blade-code 0.0.24 → 0.0.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/CHANGELOG.md +298 -0
  2. package/dist/blade.js +185 -187
  3. package/package.json +5 -2
package/dist/blade.js CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import{createRequire as cY}from"node:module";var xY=Object.create;var{getPrototypeOf:pY,defineProperty:x$,getOwnPropertyNames:h8,getOwnPropertyDescriptor:gY}=Object,x8=Object.prototype.hasOwnProperty;var H1=($,Y,X)=>{X=$!=null?xY(pY($)):{};let Z=Y||!$||!$.__esModule?x$(X,"default",{value:$,enumerable:!0}):X;for(let Q of h8($))if(!x8.call(Z,Q))x$(Z,Q,{get:()=>$[Q],enumerable:!0});return Z},f8=new WeakMap,mY=($)=>{var Y=f8.get($),X;if(Y)return Y;if(Y=x$({},"__esModule",{value:!0}),$&&typeof $==="object"||typeof $==="function")h8($).map((Z)=>!x8.call(Y,Z)&&x$(Y,Z,{get:()=>$[Z],enumerable:!(X=gY($,Z))||X.enumerable}));return f8.set($,Y),Y};var uY=($,Y)=>{for(var X in Y)x$($,X,{get:Y[X],enumerable:!0,configurable:!0,set:(Z)=>Y[X]=()=>Z})};var dY=($,Y)=>()=>($&&(Y=$($=0)),Y);var A0=cY(import.meta.url);var k9={};uY(k9,{unescapeProjectPath:()=>n6,listProjectDirectories:()=>o6,getSessionFilePath:()=>Q1,getProjectStoragePath:()=>z$,getBladeStorageRoot:()=>P1,escapeProjectPath:()=>I9,detectGitBranch:()=>o1});import{execSync as p7}from"node:child_process";import*as a6 from"node:os";import*as n1 from"node:path";function I9($){return n1.resolve($).replace(/\//g,"-")}function n6($){if($.startsWith("-"))return"/"+$.slice(1).replace(/-/g,"/");return $.replace(/-/g,"/")}function z$($){let Y=a6.homedir(),X=I9($);return n1.join(Y,".blade","projects",X)}function Q1($,Y){return n1.join(z$($),`${Y}.jsonl`)}function o1($){try{return p7("git rev-parse --abbrev-ref HEAD",{cwd:$,encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim()||void 0}catch{return}}function P1(){return n1.join(a6.homedir(),".blade")}async function o6(){let{readdir:$}=await import("node:fs/promises");try{let Y=n1.join(P1(),"projects");return(await $(Y,{withFileTypes:!0})).filter((Z)=>Z.isDirectory()).map((Z)=>Z.name)}catch{return[]}}var N$=()=>{};import{render as xG}from"ink";import pG from"react";import gG from"yargs";import{hideBin as PY}from"yargs/helpers";var p$={name:"blade-code",version:"0.0.24",private:!1,description:"🗡️ Blade Code - 智能代码助手命令行工具",type:"module",bin:{blade:"dist/blade.js"},files:["dist","bin","vendor/ripgrep/**","config.env.example","README.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/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:{"@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","string-width":"^8.1.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 L2(){return p$.version}function p8(){return p$.name}function g8(){return p$.description}function m8(){return`v${p$.version} © 2025 Blade Code`}var u8={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:"},"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:"}},l1={scriptName:"blade",usage:"$0 [command] [options]",description:g8(),version:L2(),locale:"en",showHelpOnFail:!0,demandCommand:!1,recommendCommands:!0,strict:!1};import{promises as w2}from"fs";import{merge as d8}from"lodash-es";import c8 from"os";import K$ from"path";var G$={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:{},enabledMcpjsonServers:[],disabledMcpjsonServers:[],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};class D0{static instance=null;constructor(){}static getInstance(){if(!D0.instance)D0.instance=new D0;return D0.instance}static resetInstance(){D0.instance=null}async initialize(){try{let $=await this.loadConfigFiles(),Y=await this.loadSettingsFiles(),X={...G$,...$,...Y};if(this.resolveEnvInterpolation(X),await this.ensureGitIgnore(X.debug),X.debug)console.log("[ConfigManager] Configuration loaded successfully");return X}catch($){return console.error("[ConfigManager] Failed to initialize:",$),G$}}async loadConfigFiles(){let $=K$.join(c8.homedir(),".blade","config.json"),Y=K$.join(process.cwd(),".blade","config.json"),X={},Z=await this.loadJsonFile($);if(Z)X={...X,...Z};let Q=await this.loadJsonFile(Y);if(Q)X={...X,...Q};return X}async loadSettingsFiles(){let $=K$.join(c8.homedir(),".blade","settings.json"),Y=K$.join(process.cwd(),".blade","settings.json"),X=K$.join(process.cwd(),".blade","settings.local.json"),Z={},Q=await this.loadJsonFile($);if(Q)Z=this.mergeSettings(Z,Q);let J=await this.loadJsonFile(Y);if(J)Z=this.mergeSettings(Z,J);let q=await this.loadJsonFile(X);if(q)Z=this.mergeSettings(Z,q);return Z}mergeSettings($,Y){let X=JSON.parse(JSON.stringify($));if(Y.permissions){if(!X.permissions)X.permissions={allow:[],ask:[],deny:[]};if(Y.permissions.allow){let Z=[...X.permissions.allow||[],...Y.permissions.allow];X.permissions.allow=Array.from(new Set(Z))}if(Y.permissions.ask){let Z=[...X.permissions.ask||[],...Y.permissions.ask];X.permissions.ask=Array.from(new Set(Z))}if(Y.permissions.deny){let Z=[...X.permissions.deny||[],...Y.permissions.deny];X.permissions.deny=Array.from(new Set(Z))}}if(Y.hooks)X.hooks=d8({},X.hooks,Y.hooks);if(Y.env)X.env=d8({},X.env,Y.env);if(Y.disableAllHooks!==void 0)X.disableAllHooks=Y.disableAllHooks;if(Y.permissionMode!==void 0)X.permissionMode=Y.permissionMode;if(Y.maxTurns!==void 0)X.maxTurns=Y.maxTurns;if(Y.mcpServers!==void 0)X.mcpServers=Y.mcpServers;if(Y.enabledMcpjsonServers!==void 0)X.enabledMcpjsonServers=Y.enabledMcpjsonServers;if(Y.disabledMcpjsonServers!==void 0)X.disabledMcpjsonServers=Y.disabledMcpjsonServers;return X}resolveEnvInterpolation($){let Y=/\$\{?([A-Z_][A-Z0-9_]*)(:-([^}]+))?\}?/g,X=(Z)=>{if(typeof Z==="string")return Z.replace(Y,(Q,J,q,G)=>{return process.env[J]||G||Q});return Z};for(let[Z,Q]of Object.entries($))if(typeof Q==="string")$[Z]=X(Q)}async ensureGitIgnore($){let Y=K$.join(process.cwd(),".gitignore"),X=".blade/settings.local.json";try{let Z="";if(await this.fileExists(Y))Z=await w2.readFile(Y,"utf-8");if(!Z.includes(".blade/settings.local.json")){let Q=Z.trim()+`
2
+ import{createRequire as HY}from"node:module";var qY=Object.create;var{getPrototypeOf:GY,defineProperty:r$,getOwnPropertyNames:o8,getOwnPropertyDescriptor:KY}=Object,s8=Object.prototype.hasOwnProperty;var B1=($,Y,X)=>{X=$!=null?qY(GY($)):{};let Z=Y||!$||!$.__esModule?r$(X,"default",{value:$,enumerable:!0}):X;for(let Q of o8($))if(!s8.call(Z,Q))r$(Z,Q,{get:()=>$[Q],enumerable:!0});return Z},n8=new WeakMap,WY=($)=>{var Y=n8.get($),X;if(Y)return Y;if(Y=r$({},"__esModule",{value:!0}),$&&typeof $==="object"||typeof $==="function")o8($).map((Z)=>!s8.call(Y,Z)&&r$(Y,Z,{get:()=>$[Z],enumerable:!(X=KY($,Z))||X.enumerable}));return n8.set($,Y),Y};var UY=($,Y)=>{for(var X in Y)r$($,X,{get:Y[X],enumerable:!0,configurable:!0,set:(Z)=>Y[X]=()=>Z})};var OY=($,Y)=>()=>($&&(Y=$($=0)),Y);var R0=HY(import.meta.url);var g9={};UY(g9,{unescapeProjectPath:()=>Z4,listProjectDirectories:()=>Q4,getSessionFilePath:()=>K1,getProjectStoragePath:()=>b$,getBladeStorageRoot:()=>f1,escapeProjectPath:()=>p9,detectGitBranch:()=>X$});import{execSync as GX}from"node:child_process";import*as X4 from"node:os";import*as Y$ from"node:path";function p9($){return Y$.resolve($).replace(/\//g,"-")}function Z4($){if($.startsWith("-"))return"/"+$.slice(1).replace(/-/g,"/");return $.replace(/-/g,"/")}function b$($){let Y=X4.homedir(),X=p9($);return Y$.join(Y,".blade","projects",X)}function K1($,Y){return Y$.join(b$($),`${Y}.jsonl`)}function X$($){try{return GX("git rev-parse --abbrev-ref HEAD",{cwd:$,encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim()||void 0}catch{return}}function f1(){return Y$.join(X4.homedir(),".blade")}async function Q4(){let{readdir:$}=await import("node:fs/promises");try{let Y=Y$.join(f1(),"projects");return(await $(Y,{withFileTypes:!0})).filter((Z)=>Z.isDirectory()).map((Z)=>Z.name)}catch{return[]}}var V$=()=>{};import{render as UK}from"ink";import OK from"react";import HK from"yargs";import{hideBin as e7}from"yargs/helpers";var a$={name:"blade-code",version:"0.0.28",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:{"@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","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 v2(){return a$.version}function t8(){return a$.name}function e8(){return a$.description}function $9(){return`v${a$.version} © 2025 Blade Code`}var Y9={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:"},"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:"}},s1={scriptName:"blade",usage:"$0 [command] [options]",description:e8(),version:v2(),locale:"en",showHelpOnFail:!0,demandCommand:!1,recommendCommands:!0,strict:!1};import{promises as M2}from"fs";import{merge as X9}from"lodash-es";import Z9 from"os";import z$ from"path";var F$={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};class P0{static instance=null;constructor(){}static getInstance(){if(!P0.instance)P0.instance=new P0;return P0.instance}static resetInstance(){P0.instance=null}async initialize(){try{let $=await this.loadConfigFiles(),Y=await this.loadSettingsFiles(),X={...F$,...$,...Y};if(this.resolveEnvInterpolation(X),await this.ensureGitIgnore(X.debug),X.debug)console.log("[ConfigManager] Configuration loaded successfully");return X}catch($){return console.error("[ConfigManager] Failed to initialize:",$),F$}}async loadConfigFiles(){let $=z$.join(Z9.homedir(),".blade","config.json"),Y=z$.join(process.cwd(),".blade","config.json"),X={},Z=await this.loadJsonFile($);if(Z)X={...X,...Z};let Q=await this.loadJsonFile(Y);if(Q){let J={...X.mcpServers||{},...Q.mcpServers||{}};if(X={...X,...Q},Object.keys(J).length>0)X.mcpServers=J}return X}async loadSettingsFiles(){let $=z$.join(Z9.homedir(),".blade","settings.json"),Y=z$.join(process.cwd(),".blade","settings.json"),X=z$.join(process.cwd(),".blade","settings.local.json"),Z={},Q=await this.loadJsonFile($);if(Q)Z=this.mergeSettings(Z,Q);let J=await this.loadJsonFile(Y);if(J)Z=this.mergeSettings(Z,J);let q=await this.loadJsonFile(X);if(q)Z=this.mergeSettings(Z,q);return Z}mergeSettings($,Y){let X=JSON.parse(JSON.stringify($));if(Y.permissions){if(!X.permissions)X.permissions={allow:[],ask:[],deny:[]};if(Y.permissions.allow){let Z=[...X.permissions.allow||[],...Y.permissions.allow];X.permissions.allow=Array.from(new Set(Z))}if(Y.permissions.ask){let Z=[...X.permissions.ask||[],...Y.permissions.ask];X.permissions.ask=Array.from(new Set(Z))}if(Y.permissions.deny){let Z=[...X.permissions.deny||[],...Y.permissions.deny];X.permissions.deny=Array.from(new Set(Z))}}if(Y.hooks)X.hooks=X9({},X.hooks,Y.hooks);if(Y.env)X.env=X9({},X.env,Y.env);if(Y.mcpServers)X.mcpServers={...X.mcpServers||{},...Y.mcpServers};if(Y.disableAllHooks!==void 0)X.disableAllHooks=Y.disableAllHooks;if(Y.permissionMode!==void 0)X.permissionMode=Y.permissionMode;if(Y.maxTurns!==void 0)X.maxTurns=Y.maxTurns;return X}resolveEnvInterpolation($){let Y=/\$\{?([A-Z_][A-Z0-9_]*)(:-([^}]+))?\}?/g,X=(Z)=>{if(typeof Z==="string")return Z.replace(Y,(Q,J,q,G)=>{return process.env[J]||G||Q});return Z};for(let[Z,Q]of Object.entries($))if(typeof Q==="string")$[Z]=X(Q)}async ensureGitIgnore($){let Y=z$.join(process.cwd(),".gitignore"),X=".blade/settings.local.json";try{let Z="";if(await this.fileExists(Y))Z=await M2.readFile(Y,"utf-8");if(!Z.includes(".blade/settings.local.json")){let Q=Z.trim()+`
3
3
 
4
4
  # Blade local settings
5
5
  .blade/settings.local.json
6
- `;if(await w2.writeFile(Y,Q,"utf-8"),$)console.log("[ConfigManager] Added .blade/settings.local.json to .gitignore")}}catch(Z){}}async loadJsonFile($){try{if(await this.fileExists($)){let Y=await w2.readFile($,"utf-8");return JSON.parse(Y)}}catch(Y){console.warn(`[ConfigManager] Failed to load ${$}:`,Y)}return null}async fileExists($){try{return await w2.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((Z)=>Z.id===$.currentModelId))Y.push("当前模型 ID 无效")}if(Y.length>0)throw Error(`配置验证失败:
6
+ `;if(await M2.writeFile(Y,Q,"utf-8"),$)console.log("[ConfigManager] Added .blade/settings.local.json to .gitignore")}}catch(Z){}}async loadJsonFile($){try{if(await this.fileExists($)){let Y=await M2.readFile($,"utf-8");return JSON.parse(Y)}}catch(Y){console.warn(`[ConfigManager] Failed to load ${$}:`,Y)}return null}async fileExists($){try{return await M2.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((Z)=>Z.id===$.currentModelId))Y.push("当前模型 ID 无效")}if(Y.length>0)throw Error(`配置验证失败:
7
7
  ${Y.map((X)=>` - ${X}`).join(`
8
8
  `)}
9
9
 
@@ -26,22 +26,22 @@ ${Y.map((X)=>` - ${X}`).join(`
26
26
  }
27
27
  ]
28
28
  }
29
- `)}}function A2($,Y={}){let X={...$};if(Y.fallbackModel!==void 0)X.fallbackModel=Y.fallbackModel;if(Y.debug!==void 0)X.debug=Y.debug===""?!0:Y.debug;if(Y.yolo===!0)X.permissionMode="yolo";else if(Y.permissionMode!==void 0)X.permissionMode=Y.permissionMode;if(Y.maxTurns!==void 0)X.maxTurns=Y.maxTurns;return X.systemPrompt=Y.systemPrompt,X.appendSystemPrompt=Y.appendSystemPrompt,X.resumeSessionId=Y.sessionId,X.forkSession=Y.forkSession,X.allowedTools=Y.allowedTools,X.disallowedTools=Y.disallowedTools,X.mcpConfigPaths=Y.mcpConfig,X.strictMcpConfig=Y.strictMcpConfig,X.addDirs=Y.addDir,X.outputFormat=Y.outputFormat,X.inputFormat=Y.inputFormat,X.print=Y.print,X.includePartialMessages=Y.includePartialMessages,X.replayUserMessages=Y.replayUserMessages,X.agentsConfig=Y.agents,X.settingSources=Y.settingSources,X}import{Mutex as a8}from"async-mutex";import{merge as tY}from"lodash-es";import{promises as R2}from"node:fs";import n8 from"node:os";import E1 from"node:path";import eY from"write-file-atomic";import{promises as iY}from"node:fs";import rY from"node:os";import l8 from"node:path";import aY from"pino";var r8;((Q)=>{Q[Q.DEBUG=0]="DEBUG";Q[Q.INFO=1]="INFO";Q[Q.WARN=2]="WARN";Q[Q.ERROR=3]="ERROR"})(r8||={});var nY={[0]:"debug",[1]:"info",[2]:"warn",[3]:"error"};async function oY(){let $=l8.join(rY.homedir(),".blade","logs");return await iY.mkdir($,{recursive:!0}),l8.join($,"blade.log")}var g$=null,m$=null;async function sY(){if(g$)return g$;if(m$)return m$;return m$=(async()=>{let $=await oY();return g$=aY({level:"debug",transport:{target:"pino/file",options:{destination:$}}}),g$})(),m$}function i8(){g$=null,m$=null}class S0{static globalDebugConfig=null;enabled;minLevel;category;pinoLogger=null;constructor($={}){if($.enabled!==void 0)this.enabled=$.enabled;else if(S0.globalDebugConfig!==null)this.enabled=Boolean(S0.globalDebugConfig);else this.enabled=!1;this.minLevel=$.minLevel??0,this.category=$.category??"General",this.initPino()}async initPino(){try{let $=await sY();this.pinoLogger=$.child({category:this.category})}catch($){console.error("[Logger] Failed to initialize pino:",$)}}static setGlobalDebug($){S0.globalDebugConfig=$,i8()}static clearGlobalDebug(){S0.globalDebugConfig=null,i8()}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((Z)=>Z.trim()).filter(Boolean)}}}shouldLogCategory($){if(!$)return!0;let Y=this.category.toLowerCase();if($.mode==="include")return $.categories.some((X)=>Y.includes(X.toLowerCase()));return!$.categories.some((X)=>Y.includes(X.toLowerCase()))}shouldLogToConsole($){if(S0.globalDebugConfig!==null){let{enabled:Y,filter:X}=this.parseDebugFilter(S0.globalDebugConfig);if(!Y)return!1;if($<this.minLevel)return!1;return this.shouldLogCategory(X)}return this.enabled&&$>=this.minLevel}log($,...Y){let X=Y.map((Z)=>typeof Z==="object"?JSON.stringify(Z):String(Z)).join(" ");if(this.pinoLogger){let Z=nY[$];this.pinoLogger[Z](X)}if(this.shouldLogToConsole($)){let Z=r8[$],Q=`[${this.category}] [${Z}]`;console.error(Q,...Y)}}debug(...$){this.log(0,...$)}info(...$){this.log(1,...$)}warn(...$){this.log(2,...$)}error(...$){this.log(3,...$)}}function Y0($,Y){return new S0({...Y,category:$})}var HK=new S0({category:"General"});var o8=Y0("Service"),j1={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:"settings",defaultScope:"project",mergeStrategy:"replace",persistable:!0},enabledMcpjsonServers:{target:"settings",defaultScope:"project",mergeStrategy:"replace",persistable:!0},disabledMcpjsonServers:{target:"settings",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}},RK=new Set(Object.entries(j1).filter(([$,Y])=>Y.persistable).map(([$])=>$)),bK=new Set(Object.entries(j1).filter(([$,Y])=>!Y.persistable).map(([$])=>$)),VK=new Set(Object.entries(j1).filter(([$,Y])=>Y.target==="config").map(([$])=>$)),DK=new Set(Object.entries(j1).filter(([$,Y])=>Y.target==="settings").map(([$])=>$));class D1{static instance=null;pendingUpdates=new Map;timers=new Map;fileLocks=new Map;lastSaveError=null;debounceDelay=300;constructor(){}static getInstance(){if(!D1.instance)D1.instance=new D1;return D1.instance}static resetInstance(){if(D1.instance)for(let $ of D1.instance.timers.values())clearTimeout($);D1.instance=null}async save($,Y={}){this.validatePersistableFields($);let X=this.groupUpdatesByTarget($,Y.scope);if(Y.immediate)await Promise.all(Array.from(X.entries()).map(([Z,Q])=>this.flushTarget(Z,Q)));else for(let[Z,Q]of X)this.scheduleSave(Z,Q)}async flush(){for(let Y of this.timers.values())clearTimeout(Y);this.timers.clear();let $=Array.from(this.pendingUpdates.entries()).map(([Y,X])=>this.flushTarget(Y,X));this.pendingUpdates.clear(),await Promise.all($)}getLastSaveError(){return this.lastSaveError}clearLastSaveError(){this.lastSaveError=null}async appendPermissionRule($,Y={}){let X=Y.scope??"local",Z=this.resolveFilePath("settings",X);await this.flushTargetWithModifier(Z,(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 X=j1[Y];if(!X)throw Error(`Unknown config field: ${Y}`);if(!X.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 X=new Map;for(let[Z,Q]of Object.entries($)){let J=j1[Z];if(!J)continue;let q=Y??J.defaultScope,G=this.resolveFilePath(J.target,q);if(!X.has(G))X.set(G,{});X.get(G)[Z]=Q}return X}resolveFilePath($,Y){if($==="config")return Y==="global"?E1.join(n8.homedir(),".blade","config.json"):E1.join(process.cwd(),".blade","config.json");switch(Y){case"local":return E1.join(process.cwd(),".blade","settings.local.json");case"project":return E1.join(process.cwd(),".blade","settings.json");case"global":return E1.join(n8.homedir(),".blade","settings.json");default:return E1.join(process.cwd(),".blade","settings.local.json")}}scheduleSave($,Y){let X=this.pendingUpdates.get($)??{},Z=this.mergePendingUpdates(X,Y);this.pendingUpdates.set($,Z);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,o8.error(`Failed to save config to ${$}:`,K.message),o8.error("Stack trace:",K.stack)}}},this.debounceDelay);this.timers.set($,J)}mergePendingUpdates($,Y){let X={...$};for(let[Z,Q]of Object.entries(Y)){let J=j1[Z];if(!J){X[Z]=Q;continue}switch(J.mergeStrategy){case"replace":X[Z]=Q;break;case"append-dedupe":this.applyAppendDedupe(X,Z,Q);break;case"deep-merge":this.applyDeepMerge(X,Z,Q);break}}return X}async flushTarget($,Y){let X=this.fileLocks.get($);if(!X)X=new a8,this.fileLocks.set($,X);await X.runExclusive(async()=>{await this.performWrite($,Y)})}async flushTargetWithModifier($,Y){let X=this.fileLocks.get($);if(!X)X=new a8,this.fileLocks.set($,X);await X.runExclusive(async()=>{await R2.mkdir(E1.dirname($),{recursive:!0});let Z={};try{let J=await R2.readFile($,"utf-8");Z=JSON.parse(J)}catch{Z={}}let Q=Y(Z);await this.atomicWrite($,Q)})}async performWrite($,Y){await R2.mkdir(E1.dirname($),{recursive:!0});let X={};try{let Q=await R2.readFile($,"utf-8");X=JSON.parse(Q)}catch{X={}}let Z={...X};for(let[Q,J]of Object.entries(Y)){let q=j1[Q];if(!q){Z[Q]=J;continue}switch(q.mergeStrategy){case"replace":Z[Q]=J;break;case"append-dedupe":this.applyAppendDedupe(Z,Q,J);break;case"deep-merge":this.applyDeepMerge(Z,Q,J);break}}await this.atomicWrite($,Z)}applyAppendDedupe($,Y,X){if(Y==="permissions"&&typeof X==="object"&&X!==null){let Z=$[Y]??{allow:[],ask:[],deny:[]},Q=X;$[Y]={allow:this.dedupeArray([...Z.allow||[],...Q.allow||[]]),ask:this.dedupeArray([...Z.ask||[],...Q.ask||[]]),deny:this.dedupeArray([...Z.deny||[],...Q.deny||[]])}}else if(Array.isArray(X)){let Z=Array.isArray($[Y])?$[Y]:[];$[Y]=this.dedupeArray([...Z,...X])}else $[Y]=X}applyDeepMerge($,Y,X){if(typeof X==="object"&&X!==null&&!Array.isArray(X)){let Z=typeof $[Y]==="object"&&$[Y]!==null?$[Y]:{};$[Y]=tY({},Z,X)}else $[Y]=X}dedupeArray($){return Array.from(new Set($))}async atomicWrite($,Y){await eY($,JSON.stringify(Y,null,2),{mode:384,encoding:"utf-8"})}}function I0(){return D1.getInstance()}import u$ from"picomatch";class i1{config;constructor($){this.config=$}check($){let Y=i1.buildSignature($),X=this.matchRules(Y,this.config.deny);if(X)return{result:"deny",matchedRule:X.rule,matchType:X.type,reason:`工具调用被拒绝规则阻止: ${X.rule}`};let Z=this.matchRules(Y,this.config.allow);if(Z)return{result:"allow",matchedRule:Z.rule,matchType:Z.type,reason:`工具调用符合允许规则: ${Z.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:X,tool:Z}=$;try{if(Z?.extractSignatureContent){let Q=Z.extractSignatureContent(X);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:X,tool:Z}=$;try{if(Z?.abstractPermissionRule){let Q=Z.abstractPermissionRule(X);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 X of Y){let Z=this.matchRule($,X);if(Z)return{rule:X,type:Z}}return null}matchRule($,Y){if($===Y)return"exact";if(Y==="*"||Y==="**")return"wildcard";let X=this.extractToolName($),Z=this.extractToolName(Y);if(!X||!Z)return null;if(Z.includes("*")){if(!u$.isMatch(X,Z,{dot:!0,bash:!0}))return null}else if(X!==Z)return null;if(Y===Z)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(u$.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 X=this.parseParamPairs($),Z=this.parseParamPairs(Y),Q=Object.keys(Z).length>0,J=Object.keys(X).length>0;if(Q!==J)return!1;if(!Q&&!J){if(Y==="*"||Y==="**")return!0;if(Y.includes("*")||Y.includes("{")||Y.includes("?"))return u$.isMatch($,Y,{dot:!0,bash:!0});return $===Y}for(let[q,G]of Object.entries(Z)){let K=X[q];if(K===void 0)return!1;if(G.includes("*")||G.includes("{")||G.includes("?")){if(G==="*"||G==="**")continue;if(!u$.isMatch(K,G,{dot:!0,bash:!0}))return!1}else if(K!==G)return!1}return!0}parseParamPairs($){let Y={},X=this.smartSplit($,",");for(let Z of X){let Q=this.findTopLevelDelimiter(Z,":");if(Q>0){let J=Z.slice(0,Q).trim(),q=Z.slice(Q+1).trim();Y[J]=q}}return Y}smartSplit($,Y){let X=[],Z="",Q=0,J=0,q=0,G=!1,K="",W=!1;for(let O=0;O<$.length;O++){let U=$[O];if(W){Z+=U,W=!1;continue}if(U==="\\"){Z+=U,W=!0;continue}if(!G&&U==="{")Q++;else if(!G&&U==="}")Q--;else if(!G&&U==="(")J++;else if(!G&&U===")")J--;else if(!G&&U==="[")q++;else if(!G&&U==="]")q--;if((U==='"'||U==="'")&&!G){G=!0,K=U,Z+=U;continue}else if(G&&U===K){G=!1,K="",Z+=U;continue}if(U===Y&&Q===0&&J===0&&q===0&&!G)X.push(Z.trim()),Z="";else Z+=U}if(Z)X.push(Z.trim());return X}findTopLevelDelimiter($,Y){let X=0,Z=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==="{")X++;else if(!J&&W==="}")X--;else if(!J&&W==="(")Z++;else if(!J&&W===")")Z--;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&&X===0&&Z===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}}}import{nanoid as q7}from"nanoid";import{devtools as G7,subscribeWithSelector as K7}from"zustand/middleware";import{createStore as W7}from"zustand/vanilla";var Y7={initializationStatus:"idle",initializationError:null,activeModal:"none",sessionSelectorData:void 0,modelEditorTarget:null,todos:[],awaitingSecondCtrlC:!1},y6=($)=>({...Y7,actions:{setInitializationStatus:(Y)=>{$((X)=>({app:{...X.app,initializationStatus:Y}}))},setInitializationError:(Y)=>{$((X)=>({app:{...X.app,initializationError:Y}}))},setActiveModal:(Y)=>{$((X)=>({app:{...X.app,activeModal:Y}}))},showSessionSelector:(Y)=>{$((X)=>({app:{...X.app,activeModal:"sessionSelector",sessionSelectorData:Y}}))},showModelEditWizard:(Y)=>{$((X)=>({app:{...X.app,activeModal:"modelEditWizard",modelEditorTarget:Y}}))},closeModal:()=>{$((Y)=>({app:{...Y.app,activeModal:"none",sessionSelectorData:void 0,modelEditorTarget:null}}))},setTodos:(Y)=>{$((X)=>({app:{...X.app,todos:Y}}))},updateTodo:(Y)=>{$((X)=>({app:{...X.app,todos:X.app.todos.map((Z)=>Z.id===Y.id?Y:Z)}}))},setAwaitingSecondCtrlC:(Y)=>{$((X)=>({app:{...X.app,awaitingSecondCtrlC:Y}}))}}});var X7={isProcessing:!1,abortController:null,pendingCommands:[]},E6=($,Y)=>({...X7,actions:{setProcessing:(X)=>{$((Z)=>({command:{...Z.command,isProcessing:X}}))},createAbortController:()=>{let X=new AbortController;return $((Z)=>({command:{...Z.command,abortController:X}})),X},clearAbortController:()=>{$((X)=>({command:{...X.command,abortController:null}}))},abort:()=>{let{abortController:X}=Y().command;if(X&&!X.signal.aborted)X.abort();Y().session.actions.setThinking(!1),$((Z)=>({command:{...Z.command,isProcessing:!1,abortController:null,pendingCommands:[]}}))},enqueueCommand:(X)=>{$((Z)=>({command:{...Z.command,pendingCommands:[...Z.command.pendingCommands,X]}}))},dequeueCommand:()=>{let{pendingCommands:X}=Y().command;if(X.length===0)return;let[Z,...Q]=X;return $((J)=>({command:{...J.command,pendingCommands:Q}})),Z},clearQueue:()=>{$((X)=>({command:{...X.command,pendingCommands:[]}}))}}});var Z7={config:null},j6=($)=>({...Z7,actions:{setConfig:(Y)=>{$((X)=>({config:{...X.config,config:Y}}))},updateConfig:(Y)=>{$((X)=>{if(!X.config.config)throw Error(`[ConfigSlice] Config not initialized. Cannot update: ${JSON.stringify(Y)}`);return{config:{...X.config,config:{...X.config.config,...Y}}}})}}});var Q7={currentFocus:"main-input",previousFocus:null},P6=($)=>({...Q7,actions:{setFocus:(Y)=>{$((X)=>({focus:{...X.focus,currentFocus:Y,previousFocus:X.focus.currentFocus}}))},restorePreviousFocus:()=>{$((Y)=>({focus:{...Y.focus,currentFocus:Y.focus.previousFocus||"main-input",previousFocus:null}}))}}});import{nanoid as J7}from"nanoid";var t8={inputTokens:0,outputTokens:0,totalTokens:0,maxContextTokens:200000},s8={sessionId:J7(),messages:[],isThinking:!1,isCompacting:!1,currentCommand:null,error:null,isActive:!0,tokenUsage:{...t8}},S6=($,Y)=>({...s8,actions:{addMessage:(X)=>{$((Z)=>({session:{...Z.session,messages:[...Z.session.messages,X],error:null}}))},addUserMessage:(X)=>{let Z={id:`user-${Date.now()}-${Math.random()}`,role:"user",content:X,timestamp:Date.now()};Y().session.actions.addMessage(Z)},addAssistantMessage:(X)=>{let Z={id:`assistant-${Date.now()}-${Math.random()}`,role:"assistant",content:X,timestamp:Date.now()};Y().session.actions.addMessage(Z)},addToolMessage:(X,Z)=>{let Q={id:`tool-${Date.now()}-${Math.random()}`,role:"tool",content:X,timestamp:Date.now(),metadata:Z};Y().session.actions.addMessage(Q)},setThinking:(X)=>{$((Z)=>({session:{...Z.session,isThinking:X}}))},setCompacting:(X)=>{$((Z)=>({session:{...Z.session,isCompacting:X}}))},setCommand:(X)=>{$((Z)=>({session:{...Z.session,currentCommand:X}}))},setError:(X)=>{$((Z)=>({session:{...Z.session,error:X}}))},clearMessages:()=>{$((X)=>({session:{...X.session,messages:[],error:null}}))},resetSession:()=>{$((X)=>({session:{...X.session,...s8,sessionId:X.session.sessionId,isActive:!0}}))},restoreSession:(X,Z)=>{$((Q)=>({session:{...Q.session,sessionId:X,messages:Z,error:null,isActive:!0}}))},updateTokenUsage:(X)=>{$((Z)=>({session:{...Z.session,tokenUsage:{...Z.session.tokenUsage,...X}}}))},resetTokenUsage:()=>{$((X)=>({session:{...X.session,tokenUsage:{...t8}}}))}}});var d$=W7()(G7(K7((...$)=>({session:S6(...$),app:y6(...$),config:j6(...$),focus:P6(...$),command:E6(...$)})),{name:"BladeStore",enabled:!0})),s=()=>d$.getState(),U7=d$.subscribe,o=()=>s().session.actions,X1=()=>s().app.actions;var F0=()=>s().config.config,W$=null;async function b2(){if(F0()!==null)return;if(W$)return W$;return W$=(async()=>{try{let X=await D0.getInstance().initialize();s().config.actions.setConfig(X)}catch(Y){throw W$=null,Error(`❌ Store 未初始化且无法自动初始化
29
+ `)}}function f6($,Y={}){let X={...$};if(Y.fallbackModel!==void 0)X.fallbackModel=Y.fallbackModel;if(Y.debug!==void 0)X.debug=Y.debug===""?!0:Y.debug;if(Y.yolo===!0)X.permissionMode="yolo";else if(Y.permissionMode!==void 0)X.permissionMode=Y.permissionMode;if(Y.maxTurns!==void 0)X.maxTurns=Y.maxTurns;return X.systemPrompt=Y.systemPrompt,X.appendSystemPrompt=Y.appendSystemPrompt,X.resumeSessionId=Y.sessionId,X.forkSession=Y.forkSession,X.allowedTools=Y.allowedTools,X.disallowedTools=Y.disallowedTools,X.mcpConfigPaths=Y.mcpConfig,X.strictMcpConfig=Y.strictMcpConfig,X.addDirs=Y.addDir,X.outputFormat=Y.outputFormat,X.inputFormat=Y.inputFormat,X.print=Y.print,X.includePartialMessages=Y.includePartialMessages,X.replayUserMessages=Y.replayUserMessages,X.agentsConfig=Y.agents,X.settingSources=Y.settingSources,X}import{Mutex as G9}from"async-mutex";import{merge as AY}from"lodash-es";import{promises as k2}from"node:fs";import K9 from"node:os";import T1 from"node:path";import RY from"write-file-atomic";import{promises as FY}from"node:fs";import zY from"node:os";import Q9 from"node:path";import NY from"pino";var q9;((Q)=>{Q[Q.DEBUG=0]="DEBUG";Q[Q.INFO=1]="INFO";Q[Q.WARN=2]="WARN";Q[Q.ERROR=3]="ERROR"})(q9||={});var BY={[0]:"debug",[1]:"info",[2]:"warn",[3]:"error"};async function LY(){let $=Q9.join(zY.homedir(),".blade","logs");return await FY.mkdir($,{recursive:!0}),Q9.join($,"blade.log")}var n$=null,o$=null;async function wY(){if(n$)return n$;if(o$)return o$;return o$=(async()=>{let $=await LY();return n$=NY({level:"debug",transport:{target:"pino/file",options:{destination:$}}}),n$})(),o$}function J9(){n$=null,o$=null}class J1{static globalDebugConfig=null;enabled;minLevel;category;pinoLogger=null;constructor($={}){if($.enabled!==void 0)this.enabled=$.enabled;else if(J1.globalDebugConfig!==null)this.enabled=Boolean(J1.globalDebugConfig);else this.enabled=!1;this.minLevel=$.minLevel??0,this.category=$.category??"General",this.initPino()}async initPino(){try{let $=await wY();this.pinoLogger=$.child({category:this.category})}catch($){console.error("[Logger] Failed to initialize pino:",$)}}static setGlobalDebug($){J1.globalDebugConfig=$,J9()}static clearGlobalDebug(){J1.globalDebugConfig=null,J9()}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((Z)=>Z.trim()).filter(Boolean)}}}shouldLogCategory($){if(!$)return!0;let Y=this.category.toLowerCase();if($.mode==="include")return $.categories.some((X)=>Y.includes(X.toLowerCase()));return!$.categories.some((X)=>Y.includes(X.toLowerCase()))}shouldLogToConsole($){if(J1.globalDebugConfig!==null){let{enabled:Y,filter:X}=this.parseDebugFilter(J1.globalDebugConfig);if(!Y)return!1;if($<this.minLevel)return!1;return this.shouldLogCategory(X)}return this.enabled&&$>=this.minLevel}log($,...Y){let X=Y.map((Z)=>typeof Z==="object"?JSON.stringify(Z):String(Z)).join(" ");if(this.pinoLogger){let Z=BY[$];this.pinoLogger[Z](X)}if(this.shouldLogToConsole($)){let Z=q9[$],Q=`[${this.category}] [${Z}]`;console.error(Q,...Y)}}debug(...$){this.log(0,...$)}info(...$){this.log(1,...$)}warn(...$){this.log(2,...$)}error(...$){this.log(3,...$)}}function $0($,Y){return new J1({...Y,category:$})}var xK=new J1({category:"General"});var W9=$0("Service"),C1={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}},rK=new Set(Object.entries(C1).filter(([$,Y])=>Y.persistable).map(([$])=>$)),aK=new Set(Object.entries(C1).filter(([$,Y])=>!Y.persistable).map(([$])=>$)),nK=new Set(Object.entries(C1).filter(([$,Y])=>Y.target==="config").map(([$])=>$)),oK=new Set(Object.entries(C1).filter(([$,Y])=>Y.target==="settings").map(([$])=>$));class M1{static instance=null;pendingUpdates=new Map;timers=new Map;fileLocks=new Map;lastSaveError=null;debounceDelay=300;constructor(){}static getInstance(){if(!M1.instance)M1.instance=new M1;return M1.instance}static resetInstance(){if(M1.instance)for(let $ of M1.instance.timers.values())clearTimeout($);M1.instance=null}async save($,Y={}){this.validatePersistableFields($);let X=this.groupUpdatesByTarget($,Y.scope);if(Y.immediate)await Promise.all(Array.from(X.entries()).map(([Z,Q])=>this.flushTarget(Z,Q)));else for(let[Z,Q]of X)this.scheduleSave(Z,Q)}async flush(){for(let Y of this.timers.values())clearTimeout(Y);this.timers.clear();let $=Array.from(this.pendingUpdates.entries()).map(([Y,X])=>this.flushTarget(Y,X));this.pendingUpdates.clear(),await Promise.all($)}getLastSaveError(){return this.lastSaveError}clearLastSaveError(){this.lastSaveError=null}async appendPermissionRule($,Y={}){let X=Y.scope??"local",Z=this.resolveFilePath("settings",X);await this.flushTargetWithModifier(Z,(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 X=C1[Y];if(!X)throw Error(`Unknown config field: ${Y}`);if(!X.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 X=new Map;for(let[Z,Q]of Object.entries($)){let J=C1[Z];if(!J)continue;let q=Y??J.defaultScope,G=this.resolveFilePath(J.target,q);if(!X.has(G))X.set(G,{});X.get(G)[Z]=Q}return X}resolveFilePath($,Y){if($==="config")return Y==="global"?T1.join(K9.homedir(),".blade","config.json"):T1.join(process.cwd(),".blade","config.json");switch(Y){case"local":return T1.join(process.cwd(),".blade","settings.local.json");case"project":return T1.join(process.cwd(),".blade","settings.json");case"global":return T1.join(K9.homedir(),".blade","settings.json");default:return T1.join(process.cwd(),".blade","settings.local.json")}}scheduleSave($,Y){let X=this.pendingUpdates.get($)??{},Z=this.mergePendingUpdates(X,Y);this.pendingUpdates.set($,Z);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,W9.error(`Failed to save config to ${$}:`,K.message),W9.error("Stack trace:",K.stack)}}},this.debounceDelay);this.timers.set($,J)}mergePendingUpdates($,Y){let X={...$};for(let[Z,Q]of Object.entries(Y)){let J=C1[Z];if(!J){X[Z]=Q;continue}switch(J.mergeStrategy){case"replace":X[Z]=Q;break;case"append-dedupe":this.applyAppendDedupe(X,Z,Q);break;case"deep-merge":this.applyDeepMerge(X,Z,Q);break}}return X}async flushTarget($,Y){let X=this.fileLocks.get($);if(!X)X=new G9,this.fileLocks.set($,X);await X.runExclusive(async()=>{await this.performWrite($,Y)})}async flushTargetWithModifier($,Y){let X=this.fileLocks.get($);if(!X)X=new G9,this.fileLocks.set($,X);await X.runExclusive(async()=>{await k2.mkdir(T1.dirname($),{recursive:!0});let Z={};try{let J=await k2.readFile($,"utf-8");Z=JSON.parse(J)}catch{Z={}}let Q=Y(Z);await this.atomicWrite($,Q)})}async performWrite($,Y){await k2.mkdir(T1.dirname($),{recursive:!0});let X={};try{let Q=await k2.readFile($,"utf-8");X=JSON.parse(Q)}catch{X={}}let Z={...X};for(let[Q,J]of Object.entries(Y)){let q=C1[Q];if(!q){Z[Q]=J;continue}switch(q.mergeStrategy){case"replace":Z[Q]=J;break;case"append-dedupe":this.applyAppendDedupe(Z,Q,J);break;case"deep-merge":this.applyDeepMerge(Z,Q,J);break}}await this.atomicWrite($,Z)}applyAppendDedupe($,Y,X){if(Y==="permissions"&&typeof X==="object"&&X!==null){let Z=$[Y]??{allow:[],ask:[],deny:[]},Q=X;$[Y]={allow:this.dedupeArray([...Z.allow||[],...Q.allow||[]]),ask:this.dedupeArray([...Z.ask||[],...Q.ask||[]]),deny:this.dedupeArray([...Z.deny||[],...Q.deny||[]])}}else if(Array.isArray(X)){let Z=Array.isArray($[Y])?$[Y]:[];$[Y]=this.dedupeArray([...Z,...X])}else $[Y]=X}applyDeepMerge($,Y,X){if(typeof X==="object"&&X!==null&&!Array.isArray(X)){let Z=typeof $[Y]==="object"&&$[Y]!==null?$[Y]:{};$[Y]=AY({},Z,X)}else $[Y]=X}dedupeArray($){return Array.from(new Set($))}async atomicWrite($,Y){await RY($,JSON.stringify(Y,null,2),{mode:384,encoding:"utf-8"})}}function M0(){return M1.getInstance()}import s$ from"picomatch";class t1{config;constructor($){this.config=$}check($){let Y=t1.buildSignature($),X=this.matchRules(Y,this.config.deny);if(X)return{result:"deny",matchedRule:X.rule,matchType:X.type,reason:`工具调用被拒绝规则阻止: ${X.rule}`};let Z=this.matchRules(Y,this.config.allow);if(Z)return{result:"allow",matchedRule:Z.rule,matchType:Z.type,reason:`工具调用符合允许规则: ${Z.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:X,tool:Z}=$;try{if(Z?.extractSignatureContent){let Q=Z.extractSignatureContent(X);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:X,tool:Z}=$;try{if(Z?.abstractPermissionRule){let Q=Z.abstractPermissionRule(X);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 X of Y){let Z=this.matchRule($,X);if(Z)return{rule:X,type:Z}}return null}matchRule($,Y){if($===Y)return"exact";if(Y==="*"||Y==="**")return"wildcard";let X=this.extractToolName($),Z=this.extractToolName(Y);if(!X||!Z)return null;if(Z.includes("*")){if(!s$.isMatch(X,Z,{dot:!0,bash:!0}))return null}else if(X!==Z)return null;if(Y===Z)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 X=this.parseParamPairs($),Z=this.parseParamPairs(Y),Q=Object.keys(Z).length>0,J=Object.keys(X).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(Z)){let K=X[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={},X=this.smartSplit($,",");for(let Z of X){let Q=this.findTopLevelDelimiter(Z,":");if(Q>0){let J=Z.slice(0,Q).trim(),q=Z.slice(Q+1).trim();Y[J]=q}}return Y}smartSplit($,Y){let X=[],Z="",Q=0,J=0,q=0,G=!1,K="",W=!1;for(let O=0;O<$.length;O++){let U=$[O];if(W){Z+=U,W=!1;continue}if(U==="\\"){Z+=U,W=!0;continue}if(!G&&U==="{")Q++;else if(!G&&U==="}")Q--;else if(!G&&U==="(")J++;else if(!G&&U===")")J--;else if(!G&&U==="[")q++;else if(!G&&U==="]")q--;if((U==='"'||U==="'")&&!G){G=!0,K=U,Z+=U;continue}else if(G&&U===K){G=!1,K="",Z+=U;continue}if(U===Y&&Q===0&&J===0&&q===0&&!G)X.push(Z.trim()),Z="";else Z+=U}if(Z)X.push(Z.trim());return X}findTopLevelDelimiter($,Y){let X=0,Z=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==="{")X++;else if(!J&&W==="}")X--;else if(!J&&W==="(")Z++;else if(!J&&W===")")Z--;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&&X===0&&Z===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}}}import{nanoid as kY}from"nanoid";import{devtools as yY,subscribeWithSelector as EY}from"zustand/middleware";import{createStore as jY}from"zustand/vanilla";var VY={initializationStatus:"idle",initializationError:null,activeModal:"none",sessionSelectorData:void 0,modelEditorTarget:null,todos:[],awaitingSecondCtrlC:!1,thinkingModeEnabled:!1},h6=($)=>({...VY,actions:{setInitializationStatus:(Y)=>{$((X)=>({app:{...X.app,initializationStatus:Y}}))},setInitializationError:(Y)=>{$((X)=>({app:{...X.app,initializationError:Y}}))},setActiveModal:(Y)=>{$((X)=>({app:{...X.app,activeModal:Y}}))},showSessionSelector:(Y)=>{$((X)=>({app:{...X.app,activeModal:"sessionSelector",sessionSelectorData:Y}}))},showModelEditWizard:(Y)=>{$((X)=>({app:{...X.app,activeModal:"modelEditWizard",modelEditorTarget:Y}}))},closeModal:()=>{$((Y)=>({app:{...Y.app,activeModal:"none",sessionSelectorData:void 0,modelEditorTarget:null}}))},setTodos:(Y)=>{$((X)=>({app:{...X.app,todos:Y}}))},updateTodo:(Y)=>{$((X)=>({app:{...X.app,todos:X.app.todos.map((Z)=>Z.id===Y.id?Y:Z)}}))},setAwaitingSecondCtrlC:(Y)=>{$((X)=>({app:{...X.app,awaitingSecondCtrlC:Y}}))},setThinkingModeEnabled:(Y)=>{$((X)=>({app:{...X.app,thinkingModeEnabled:Y}}))},toggleThinkingMode:()=>{$((Y)=>({app:{...Y.app,thinkingModeEnabled:!Y.app.thinkingModeEnabled}}))}}});var IY={isProcessing:!1,abortController:null,pendingCommands:[]},x6=($,Y)=>({...IY,actions:{setProcessing:(X)=>{$((Z)=>({command:{...Z.command,isProcessing:X}}))},createAbortController:()=>{let X=new AbortController;return $((Z)=>({command:{...Z.command,abortController:X}})),X},clearAbortController:()=>{$((X)=>({command:{...X.command,abortController:null}}))},abort:()=>{let{abortController:X}=Y().command;if(X&&!X.signal.aborted)X.abort();Y().session.actions.setThinking(!1),$((Z)=>({command:{...Z.command,isProcessing:!1,abortController:null,pendingCommands:[]}}))},enqueueCommand:(X)=>{$((Z)=>({command:{...Z.command,pendingCommands:[...Z.command.pendingCommands,X]}}))},dequeueCommand:()=>{let{pendingCommands:X}=Y().command;if(X.length===0)return;let[Z,...Q]=X;return $((J)=>({command:{...J.command,pendingCommands:Q}})),Z},clearQueue:()=>{$((X)=>({command:{...X.command,pendingCommands:[]}}))}}});var DY={config:null},p6=($)=>({...DY,actions:{setConfig:(Y)=>{$((X)=>({config:{...X.config,config:Y}}))},updateConfig:(Y)=>{$((X)=>{if(!X.config.config)throw Error(`[ConfigSlice] Config not initialized. Cannot update: ${JSON.stringify(Y)}`);return{config:{...X.config,config:{...X.config.config,...Y}}}})}}});var vY={currentFocus:"main-input",previousFocus:null},g6=($)=>({...vY,actions:{setFocus:(Y)=>{$((X)=>({focus:{...X.focus,currentFocus:Y,previousFocus:X.focus.currentFocus}}))},restorePreviousFocus:()=>{$((Y)=>({focus:{...Y.focus,currentFocus:Y.focus.previousFocus||"main-input",previousFocus:null}}))}}});import{nanoid as MY}from"nanoid";var O9={inputTokens:0,outputTokens:0,totalTokens:0,maxContextTokens:200000},U9={sessionId:MY(),messages:[],isThinking:!1,isCompacting:!1,currentCommand:null,error:null,isActive:!0,tokenUsage:{...O9},currentThinkingContent:null,thinkingExpanded:!1},m6=($,Y)=>({...U9,actions:{addMessage:(X)=>{$((Z)=>({session:{...Z.session,messages:[...Z.session.messages,X],error:null}}))},addUserMessage:(X)=>{let Z={id:`user-${Date.now()}-${Math.random()}`,role:"user",content:X,timestamp:Date.now()};Y().session.actions.addMessage(Z)},addAssistantMessage:(X,Z)=>{let Q={id:`assistant-${Date.now()}-${Math.random()}`,role:"assistant",content:X,timestamp:Date.now(),thinkingContent:Z};Y().session.actions.addMessage(Q)},addToolMessage:(X,Z)=>{let Q={id:`tool-${Date.now()}-${Math.random()}`,role:"tool",content:X,timestamp:Date.now(),metadata:Z};Y().session.actions.addMessage(Q)},setThinking:(X)=>{$((Z)=>({session:{...Z.session,isThinking:X}}))},setCompacting:(X)=>{$((Z)=>({session:{...Z.session,isCompacting:X}}))},setCommand:(X)=>{$((Z)=>({session:{...Z.session,currentCommand:X}}))},setError:(X)=>{$((Z)=>({session:{...Z.session,error:X}}))},clearMessages:()=>{$((X)=>({session:{...X.session,messages:[],error:null}}))},resetSession:()=>{$((X)=>({session:{...X.session,...U9,sessionId:X.session.sessionId,isActive:!0}}))},restoreSession:(X,Z)=>{$((Q)=>({session:{...Q.session,sessionId:X,messages:Z,error:null,isActive:!0}}))},updateTokenUsage:(X)=>{$((Z)=>({session:{...Z.session,tokenUsage:{...Z.session.tokenUsage,...X}}}))},resetTokenUsage:()=>{$((X)=>({session:{...X.session,tokenUsage:{...O9}}}))},setCurrentThinkingContent:(X)=>{$((Z)=>({session:{...Z.session,currentThinkingContent:X}}))},appendThinkingContent:(X)=>{$((Z)=>({session:{...Z.session,currentThinkingContent:(Z.session.currentThinkingContent||"")+X}}))},setThinkingExpanded:(X)=>{$((Z)=>({session:{...Z.session,thinkingExpanded:X}}))},toggleThinkingExpanded:()=>{$((X)=>({session:{...X.session,thinkingExpanded:!X.session.thinkingExpanded}}))}}});var t$=jY()(yY(EY((...$)=>({session:m6(...$),app:h6(...$),config:p6(...$),focus:g6(...$),command:x6(...$)})),{name:"BladeStore",enabled:!0})),o=()=>t$.getState(),PY=t$.subscribe,t=()=>o().session.actions,q1=()=>o().app.actions;var D0=()=>o().config.config,N$=null;async function y2(){if(D0()!==null)return;if(N$)return N$;return N$=(async()=>{try{let X=await P0.getInstance().initialize();o().config.actions.setConfig(X)}catch(Y){throw N$=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{W$=null}})(),W$}var c$=()=>s().config.config?.models??[],V2=()=>{let $=F0();if(!$)return;let Y=$.currentModelId;return $.models.find((Z)=>Z.id===Y)??$.models[0]},_1=()=>s().config.config?.mcpServers??{};var e=()=>({setPermissionMode:async($)=>{s().config.actions.updateConfig({permissionMode:$})},setTheme:async($,Y={})=>{s().config.actions.updateConfig({theme:$}),await I0().save({theme:$},{scope:"global",...Y})},setLanguage:async($,Y={})=>{s().config.actions.updateConfig({language:$}),await I0().save({language:$},{scope:"global",...Y})},setDebug:async($,Y={})=>{s().config.actions.updateConfig({debug:$}),await I0().save({debug:$},{scope:"global",...Y})},setTemperature:async($,Y={})=>{s().config.actions.updateConfig({temperature:$}),await I0().save({temperature:$},{scope:"global",...Y})},updateConfig:async($,Y={})=>{let X=F0();if(!X)throw Error("Config not initialized");let Z={...X};s().config.actions.updateConfig($);try{await I0().save($,Y)}catch(Q){throw s().config.actions.setConfig(Z),Q}},flush:async()=>{await I0().flush()},appendPermissionAllowRule:async($,Y={})=>{let X=F0();if(!X)throw Error("Config not initialized");let Z=X.permissions?.allow||[];if(!Z.includes($)){let Q=[...Z,$];s().config.actions.updateConfig({permissions:{...X.permissions,allow:Q}})}await I0().appendPermissionRule($,Y)},appendLocalPermissionAllowRule:async($,Y={})=>{let X=F0();if(!X)throw Error("Config not initialized");let Z=X.permissions?.allow||[];if(!Z.includes($)){let Q=[...Z,$];s().config.actions.updateConfig({permissions:{...X.permissions,allow:Q}})}await I0().appendLocalPermissionRule($,Y)},setCurrentModel:async($,Y={})=>{let X=F0();if(!X)throw Error("Config not initialized");if(!X.models.find((Q)=>Q.id===$))throw Error(`Model not found: ${$}`);s().config.actions.updateConfig({currentModelId:$}),await I0().save({currentModelId:$},{scope:"global",...Y})},addModel:async($,Y={})=>{let X=F0();if(!X)throw Error("Config not initialized");let Z="id"in $?$:{id:q7(),...$},J={models:[...X.models,Z]};if(X.models.length===0)J.currentModelId=Z.id;return s().config.actions.updateConfig(J),await I0().save(J,{scope:"global",...Y}),Z},updateModel:async($,Y,X={})=>{let Z=F0();if(!Z)throw Error("Config not initialized");let Q=Z.models.findIndex((q)=>q.id===$);if(Q===-1)throw Error(`Model not found: ${$}`);let J=[...Z.models];J[Q]={...J[Q],...Y},s().config.actions.updateConfig({models:J}),await I0().save({models:J},{scope:"global",...X})},removeModel:async($,Y={})=>{let X=F0();if(!X)throw Error("Config not initialized");if(X.models.length===1)throw Error("Cannot remove the only model");let Z=X.models.filter((J)=>J.id!==$),Q={models:Z};if(X.currentModelId===$)Q.currentModelId=Z[0].id;s().config.actions.updateConfig(Q),await I0().save(Q,{scope:"global",...Y})},addMcpServer:async($,Y,X={})=>{let Z=F0();if(!Z)throw Error("Config not initialized");let J={...Z.mcpServers??{},[$]:Y};s().config.actions.updateConfig({mcpServers:J}),await I0().save({mcpServers:J},{scope:"project",...X})},removeMcpServer:async($,Y={})=>{let X=F0();if(!X)throw Error("Config not initialized");let Q={...X.mcpServers??{}};delete Q[$],s().config.actions.updateConfig({mcpServers:Q}),await I0().save({mcpServers:Q},{scope:"project",...Y})},resetProjectChoices:async($={})=>{if(!F0())throw Error("Config not initialized");let X={enabledMcpjsonServers:[],disabledMcpjsonServers:[]};s().config.actions.updateConfig(X),await I0().save(X,{scope:"project",...$})}});var D2=Y0("General"),e8=($)=>{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((X)=>$.disallowedTools.includes(X));if(Y.length>0)throw Error(`Tools cannot be both allowed and disallowed: ${Y.join(", ")}`)}},$9=async($)=>{try{let X=await D0.getInstance().initialize();if(s().config.actions.setConfig(X),$.debug)D2.info("[CLI] Store 已初始化")}catch(Y){D2.error("[CLI] ❌ 配置初始化失败,无法继续执行命令",Y instanceof Error?Y.message:Y),console.error(`
36
+ `+"3. 配置文件权限正确")}finally{N$=null}})(),N$}var e$=()=>o().config.config?.models??[],E2=()=>{let $=D0();if(!$)return;let Y=$.currentModelId;return $.models.find((Z)=>Z.id===Y)??$.models[0]},l0=()=>o().config.config?.mcpServers??{};var W0=()=>({setPermissionMode:async($)=>{o().config.actions.updateConfig({permissionMode:$})},setTheme:async($,Y={})=>{o().config.actions.updateConfig({theme:$}),await M0().save({theme:$},{scope:"global",...Y})},setLanguage:async($,Y={})=>{o().config.actions.updateConfig({language:$}),await M0().save({language:$},{scope:"global",...Y})},setDebug:async($,Y={})=>{o().config.actions.updateConfig({debug:$}),await M0().save({debug:$},{scope:"global",...Y})},setTemperature:async($,Y={})=>{o().config.actions.updateConfig({temperature:$}),await M0().save({temperature:$},{scope:"global",...Y})},updateConfig:async($,Y={})=>{let X=D0();if(!X)throw Error("Config not initialized");let Z={...X};o().config.actions.updateConfig($);try{await M0().save($,Y)}catch(Q){throw o().config.actions.setConfig(Z),Q}},flush:async()=>{await M0().flush()},appendPermissionAllowRule:async($,Y={})=>{let X=D0();if(!X)throw Error("Config not initialized");let Z=X.permissions?.allow||[];if(!Z.includes($)){let Q=[...Z,$];o().config.actions.updateConfig({permissions:{...X.permissions,allow:Q}})}await M0().appendPermissionRule($,Y)},appendLocalPermissionAllowRule:async($,Y={})=>{let X=D0();if(!X)throw Error("Config not initialized");let Z=X.permissions?.allow||[];if(!Z.includes($)){let Q=[...Z,$];o().config.actions.updateConfig({permissions:{...X.permissions,allow:Q}})}await M0().appendLocalPermissionRule($,Y)},setCurrentModel:async($,Y={})=>{let X=D0();if(!X)throw Error("Config not initialized");if(!X.models.find((Q)=>Q.id===$))throw Error(`Model not found: ${$}`);o().config.actions.updateConfig({currentModelId:$}),await M0().save({currentModelId:$},{scope:"global",...Y})},addModel:async($,Y={})=>{let X=D0();if(!X)throw Error("Config not initialized");let Z="id"in $?$:{id:kY(),...$},J={models:[...X.models,Z]};if(X.models.length===0)J.currentModelId=Z.id;return o().config.actions.updateConfig(J),await M0().save(J,{scope:"global",...Y}),Z},updateModel:async($,Y,X={})=>{let Z=D0();if(!Z)throw Error("Config not initialized");let Q=Z.models.findIndex((q)=>q.id===$);if(Q===-1)throw Error(`Model not found: ${$}`);let J=[...Z.models];J[Q]={...J[Q],...Y},o().config.actions.updateConfig({models:J}),await M0().save({models:J},{scope:"global",...X})},removeModel:async($,Y={})=>{let X=D0();if(!X)throw Error("Config not initialized");if(X.models.length===1)throw Error("Cannot remove the only model");let Z=X.models.filter((J)=>J.id!==$),Q={models:Z};if(X.currentModelId===$)Q.currentModelId=Z[0].id;o().config.actions.updateConfig(Q),await M0().save(Q,{scope:"global",...Y})},addMcpServer:async($,Y,X={})=>{let Z=D0();if(!Z)throw Error("Config not initialized");let J={...Z.mcpServers??{},[$]:Y};o().config.actions.updateConfig({mcpServers:J}),await M0().save({mcpServers:J},{scope:"project",...X})},removeMcpServer:async($,Y={})=>{let X=D0();if(!X)throw Error("Config not initialized");let Q={...X.mcpServers??{}};delete Q[$],o().config.actions.updateConfig({mcpServers:Q}),await M0().save({mcpServers:Q},{scope:"project",...Y})}});var u6=$0("General"),H9=($)=>{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((X)=>$.disallowedTools.includes(X));if(Y.length>0)throw Error(`Tools cannot be both allowed and disallowed: ${Y.join(", ")}`)}},_9=async($)=>{try{let X=await P0.getInstance().initialize();if(o().config.actions.setConfig(X),$.debug)u6.info("[CLI] 配置已加载到 Store")}catch(Y){u6.error("[CLI] ❌ 配置初始化失败",Y instanceof Error?Y.message:Y),console.error(`
37
37
  ❌ 配置初始化失败
38
38
  `),console.error("原因:",Y instanceof Error?Y.message:"未知错误"),console.error(`
39
39
  请检查:`),console.error(" 1. 配置文件格式是否正确 (~/.blade/config.json)"),console.error(" 2. 是否需要运行 blade 进行首次配置"),console.error(` 3. 配置文件权限是否正确
40
- `),process.exit(1)}if(typeof $.settingSources==="string"){let Y=$.settingSources.split(",").map((X)=>X.trim());if($.debug)D2.info(`Loading configuration from: ${Y.join(", ")}`)}if($.continue&&$.resume)throw Error("Cannot use both --continue and --resume flags simultaneously")},Y9=($)=>{if($.outputFormat&&$.outputFormat!=="text"&&!$.print)throw Error("--output-format can only be used with --print flag");if($.inputFormat==="stream-json"&&$.print)D2.warn("⚠️ Warning: stream-json input format may not work as expected with --print")};var X9={command:"doctor",describe:"Check the health of your Blade installation",handler:async()=>{console.log(`\uD83D\uDD0D Running Blade health check...
41
- `);let $=0;try{await D0.getInstance().initialize(),console.log("✅ Configuration: OK")}catch(Z){console.log("❌ Configuration: FAILED"),console.log(` Error: ${Z instanceof Error?Z.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 Z=await import("fs/promises"),Q=process.cwd();await Z.access(Q,(await import("fs")).constants.R_OK|(await import("fs")).constants.W_OK),console.log("✅ File system permissions: OK")}catch(Z){console.log("❌ File system permissions: FAILED"),console.log(" Error: Cannot read/write in current directory"),$++}try{await import("ink"),console.log("✅ Dependencies: OK")}catch(Z){console.log("❌ Dependencies: FAILED"),console.log(" Error: Missing required dependencies"),$++}if(console.log(`
42
- \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 Z9={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)}}};import{EventEmitter as R7}from"events";import{z as c0}from"zod";function l$($){return $==="readonly"}class T6{toolName;params;context;aborted=!1;result;_internal={};constructor($,Y,X){this.toolName=$;this.params=Y;this.context=X}shouldAbort(){return this.aborted||(this.context.signal?.aborted??!1)}abort($){this.aborted=!0,this.result={success:!1,llmContent:`Tool execution aborted: ${$||"Unknown reason"}`,displayContent:`执行已中止: ${$||"未知原因"}`,error:{type:"execution_error",message:$||"Execution aborted"}}}setResult($){this.result=$}getResult(){if(!this.result)throw Error("Tool execution result not set");return this.result}}class Q9 extends Error{issues;type;constructor($,Y,X="validation_error"){super($);this.issues=Y;this.type=X;this.name="ToolValidationError"}}function O7($){let{code:Y}=$,X=$.received;switch(Y){case"invalid_type":return`类型错误:期望 ${$.expected},实际收到 ${X}`;case"too_small":{let{minimum:Z,inclusive:Q}=$;if($.type==="string")return`长度不能少于 ${Z} 个字符`;if($.type==="number")return`不能小于${Q?"等于":""} ${Z}`;if($.type==="array")return`数组长度不能少于 ${Z}`;return"值太小"}case"too_big":{let{maximum:Z,inclusive:Q}=$;if($.type==="string")return`长度不能超过 ${Z} 个字符`;if($.type==="number")return`不能大于${Q?"等于":""} ${Z}`;if($.type==="array")return`数组长度不能超过 ${Z}`;return"值太大"}case"invalid_string":{let Z=$.validation;if(Z==="email")return"必须是有效的电子邮件地址";if(Z==="url")return"必须是有效的 URL";if(Z==="uuid")return"必须是有效的 UUID";if(typeof Z==="object"&&Z.includes)return`必须包含 "${Z.includes}"`;if(typeof Z==="object"&&Z.startsWith)return`必须以 "${Z.startsWith}" 开头`;if(typeof Z==="object"&&Z.endsWith)return`必须以 "${Z.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 H7($){let Y=$.issues.map((Z)=>{let Q=Z.path.join("."),J=O7(Z),q=Z.received;return{field:Q||"root",message:J,value:q}}),X=Y.length===1?`参数验证失败 [${Y[0].field}]: ${Y[0].message}`:`参数验证失败 (${Y.length} 个错误):
40
+ `),process.exit(1)}if($.continue&&$.resume)throw Error("Cannot use both --continue and --resume flags simultaneously")},F9=($)=>{if($.outputFormat&&$.outputFormat!=="text"&&!$.print)throw Error("--output-format can only be used with --print flag");if($.inputFormat==="stream-json"&&$.print)u6.warn("⚠️ Warning: stream-json input format may not work as expected with --print")};var z9={command:"doctor",describe:"Check the health of your Blade installation",handler:async()=>{console.log(`\uD83D\uDD0D Running Blade health check...
41
+ `);let $=0;try{await P0.getInstance().initialize(),console.log("✅ Configuration: OK")}catch(Z){console.log("❌ Configuration: FAILED"),console.log(` Error: ${Z instanceof Error?Z.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 Z=await import("fs/promises"),Q=process.cwd();await Z.access(Q,(await import("fs")).constants.R_OK|(await import("fs")).constants.W_OK),console.log("✅ File system permissions: OK")}catch(Z){console.log("❌ File system permissions: FAILED"),console.log(" Error: Cannot read/write in current directory"),$++}try{await import("ink"),console.log("✅ Dependencies: OK")}catch(Z){console.log("❌ Dependencies: FAILED"),console.log(" Error: Missing required dependencies"),$++}if(console.log(`
42
+ \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 N9={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)}}};import V9 from"os";import C2 from"path";import{EventEmitter as dY}from"events";import{z as i0}from"zod";function $2($){return $==="readonly"}class d6{toolName;params;context;aborted=!1;result;_internal={};constructor($,Y,X){this.toolName=$;this.params=Y;this.context=X}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}}class B9 extends Error{issues;type;constructor($,Y,X="validation_error"){super($);this.issues=Y;this.type=X;this.name="ToolValidationError"}}function SY($){let{code:Y}=$,X=$.received;switch(Y){case"invalid_type":return`类型错误:期望 ${$.expected},实际收到 ${X}`;case"too_small":{let{minimum:Z,inclusive:Q}=$;if($.type==="string")return`长度不能少于 ${Z} 个字符`;if($.type==="number")return`不能小于${Q?"等于":""} ${Z}`;if($.type==="array")return`数组长度不能少于 ${Z}`;return"值太小"}case"too_big":{let{maximum:Z,inclusive:Q}=$;if($.type==="string")return`长度不能超过 ${Z} 个字符`;if($.type==="number")return`不能大于${Q?"等于":""} ${Z}`;if($.type==="array")return`数组长度不能超过 ${Z}`;return"值太大"}case"invalid_string":{let Z=$.validation;if(Z==="email")return"必须是有效的电子邮件地址";if(Z==="url")return"必须是有效的 URL";if(Z==="uuid")return"必须是有效的 UUID";if(typeof Z==="object"&&Z.includes)return`必须包含 "${Z.includes}"`;if(typeof Z==="object"&&Z.startsWith)return`必须以 "${Z.startsWith}" 开头`;if(typeof Z==="object"&&Z.endsWith)return`必须以 "${Z.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 TY($){let Y=$.issues.map((Z)=>{let Q=Z.path.join("."),J=SY(Z),q=Z.received;return{field:Q||"root",message:J,value:q}}),X=Y.length===1?`参数验证失败 [${Y[0].field}]: ${Y[0].message}`:`参数验证失败 (${Y.length} 个错误):
43
43
  ${Y.map((Z)=>` - ${Z.field}: ${Z.message}`).join(`
44
- `)}`;return new Q9(X,Y)}function J9($,Y){let X=$.safeParse(Y);if(!X.success)throw H7(X.error);return X.data}import{zodToJsonSchema as _7}from"zod-to-json-schema";function C6($){return _7($,{target:"jsonSchema7",$refStrategy:"none"})}class f6{toolName;params;executeFn;descriptionFn;affectedPathsFn;constructor($,Y,X,Z,Q){this.toolName=$;this.params=Y;this.executeFn=X;this.descriptionFn=Z;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,X){let Z={signal:$,updateOutput:Y,...X};return this.executeFn(this.params,Z)}}function n($){return{name:$.name,displayName:$.displayName,kind:$.kind,isReadOnly:$.isReadOnly??l$($.kind),isConcurrencySafe:$.isConcurrencySafe??!0,strict:$.strict??!1,description:$.description,version:$.version||"1.0.0",category:$.category,tags:$.tags||[],getFunctionDeclaration(){let Y=C6($.schema),X=$.description.short;if($.description.long)X+=`
44
+ `)}`;return new B9(X,Y)}function L9($,Y){let X=$.safeParse(Y);if(!X.success)throw TY(X.error);return X.data}import{zodToJsonSchema as CY}from"zod-to-json-schema";function c6($){return CY($,{target:"jsonSchema7",$refStrategy:"none"})}class l6{toolName;params;executeFn;descriptionFn;affectedPathsFn;constructor($,Y,X,Z,Q){this.toolName=$;this.params=Y;this.executeFn=X;this.descriptionFn=Z;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,X){let Z={signal:$,updateOutput:Y,...X};return this.executeFn(this.params,Z)}}function s($){return{name:$.name,displayName:$.displayName,kind:$.kind,isReadOnly:$.isReadOnly??$2($.kind),isConcurrencySafe:$.isConcurrencySafe??!0,strict:$.strict??!1,description:$.description,version:$.version||"1.0.0",category:$.category,tags:$.tags||[],getFunctionDeclaration(){let Y=c6($.schema),X=$.description.short;if($.description.long)X+=`
45
45
 
46
46
  ${$.description.long}`;if($.description.usageNotes&&$.description.usageNotes.length>0)X+=`
47
47
 
@@ -51,12 +51,12 @@ ${$.description.usageNotes.map((Z)=>`- ${Z}`).join(`
51
51
 
52
52
  Important:
53
53
  ${$.description.important.map((Z)=>`⚠️ ${Z}`).join(`
54
- `)}`;return{name:$.name,description:X,parameters:Y}},getMetadata(){return{name:$.name,displayName:$.displayName,kind:$.kind,version:$.version||"1.0.0",category:$.category,tags:$.tags||[],description:$.description,schema:C6($.schema)}},build(Y){let X=J9($.schema,Y);return new f6($.name,X,$.execute)},async execute(Y,X){return this.build(Y).execute(X||new AbortController().signal)},extractSignatureContent:$.extractSignatureContent?(Y)=>$.extractSignatureContent(Y):void 0,abstractPermissionRule:$.abstractPermissionRule?(Y)=>$.abstractPermissionRule(Y):void 0}}function I2($,Y,X,Z){let Q;try{Q=i$(X.inputSchema)}catch(q){console.warn(`[createMcpTool] Schema 转换失败,使用降级 schema: ${X.name}`,q),Q=c0.any()}let J=Z||X.name;return n({name:J,displayName:`${Y}: ${X.name}`,kind:"execute",schema:Q,description:{short:X.description||`MCP Tool: ${X.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(X.name,q),W="",O="";if(K.content&&Array.isArray(K.content)){for(let U of K.content)if(U.type==="text"&&U.text)W+=U.text,O+=U.text;else if(U.type==="image")O+=`[图片: ${U.mimeType||"unknown"}]
54
+ `)}`;return{name:$.name,description:X,parameters:Y}},getMetadata(){return{name:$.name,displayName:$.displayName,kind:$.kind,version:$.version||"1.0.0",category:$.category,tags:$.tags||[],description:$.description,schema:c6($.schema)}},build(Y){let X=L9($.schema,Y);return new l6($.name,X,$.execute)},async execute(Y,X){return this.build(Y).execute(X||new AbortController().signal)},extractSignatureContent:$.extractSignatureContent?(Y)=>$.extractSignatureContent(Y):void 0,abstractPermissionRule:$.abstractPermissionRule?(Y)=>$.abstractPermissionRule(Y):void 0}}function j2($,Y,X,Z){let Q;try{Q=Y2(X.inputSchema)}catch(q){console.warn(`[createMcpTool] Schema 转换失败,使用降级 schema: ${X.name}`,q),Q=i0.any()}let J=Z||X.name;return s({name:J,displayName:`${Y}: ${X.name}`,kind:"execute",schema:Q,description:{short:X.description||`MCP Tool: ${X.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(X.name,q),W="",O="";if(K.content&&Array.isArray(K.content)){for(let U of K.content)if(U.type==="text"&&U.text)W+=U.text,O+=U.text;else if(U.type==="image")O+=`[图片: ${U.mimeType||"unknown"}]
55
55
  `,W+=`[image: ${U.mimeType||"unknown"}]
56
56
  `;else if(U.type==="resource")O+=`[资源: ${U.mimeType||"unknown"}]
57
57
  `,W+=`[resource: ${U.mimeType||"unknown"}]
58
58
  `}if(K.isError)return{success:!1,llmContent:W||"MCP tool execution failed",displayContent:`❌ ${O||"MCP工具执行失败"}`,error:{type:"execution_error",message:W||"MCP tool execution failed"}};return{success:!0,llmContent:W||"Execution succeeded",displayContent:`✅ MCP工具 ${X.name} 执行成功
59
- ${O}`,metadata:{serverName:Y,toolName:X.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 i$($){if($.type==="object"||$.properties){let Y={},X=$.required||[];if($.properties){for(let[Z,Q]of Object.entries($.properties))if(typeof Q==="object"&&Q!==null){let J=i$(Q);if(!X.includes(Z))J=J.optional();Y[Z]=J}}return c0.object(Y)}if($.type==="array"&&$.items){if(typeof $.items==="object"&&!Array.isArray($.items)&&$.items!==null)return c0.array(i$($.items));return c0.array(c0.any())}if($.type==="string"){let Y=c0.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 c0.enum($.enum);return Y}if($.type==="number"||$.type==="integer"){let Y=c0.number();if($.minimum!==void 0)Y=Y.min($.minimum);if($.maximum!==void 0)Y=Y.max($.maximum);return Y}if($.type==="boolean")return c0.boolean();if($.oneOf&&$.oneOf.length>0){let Y=$.oneOf.filter((X)=>typeof X==="object"&&X!==null).map((X)=>i$(X));if(Y.length>=2)return c0.union(Y)}if($.anyOf&&$.anyOf.length>0){let Y=$.anyOf.filter((X)=>typeof X==="object"&&X!==null).map((X)=>i$(X));if(Y.length>=2)return c0.union(Y)}return c0.any()}import{Client as B7}from"@modelcontextprotocol/sdk/client/index.js";import{SSEClientTransport as L7}from"@modelcontextprotocol/sdk/client/sse.js";import{StdioClientTransport as w7}from"@modelcontextprotocol/sdk/client/stdio.js";import{EventEmitter as A7}from"events";import*as a$ from"crypto";import*as K9 from"http";import{spawn as z7}from"child_process";import{URL as q9}from"url";import{promises as h6}from"fs";import F7 from"os";import x6 from"path";class k2{tokenFilePath;constructor(){let $=F7.homedir(),Y=x6.join($,".blade");this.tokenFilePath=x6.join(Y,"mcp-oauth-tokens.json")}async ensureConfigDir(){let $=x6.dirname(this.tokenFilePath);try{await h6.mkdir($,{recursive:!0})}catch(Y){}}async loadAllCredentials(){let $=new Map;try{let Y=await h6.readFile(this.tokenFilePath,"utf-8"),X=JSON.parse(Y);for(let Z of X)$.set(Z.serverName,Z)}catch(Y){if(Y.code!=="ENOENT")console.warn("[OAuthTokenStorage] 加载令牌失败:",Y)}return $}async saveAllCredentials($){await this.ensureConfigDir();let Y=Array.from($.values());await h6.writeFile(this.tokenFilePath,JSON.stringify(Y,null,2),{mode:384})}async saveToken($,Y,X,Z){let Q=await this.loadAllCredentials(),J={serverName:$,token:Y,clientId:X,tokenUrl:Z,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 r$=7777,p6="/oauth/callback",G9=200;class v2{tokenStorage;constructor($=new k2){this.tokenStorage=$}generatePKCEParams(){let $=a$.randomBytes(32).toString("base64url"),Y=a$.createHash("sha256").update($).digest("base64url"),X=a$.randomBytes(16).toString("base64url");return{codeVerifier:$,codeChallenge:Y,state:X}}buildAuthorizationUrl($,Y){let X=$.redirectUri||`http://localhost:${r$}${p6}`,Z=new URLSearchParams({client_id:$.clientId,response_type:"code",redirect_uri:X,state:Y.state,code_challenge:Y.codeChallenge,code_challenge_method:"S256"});if($.scopes&&$.scopes.length>0)Z.append("scope",$.scopes.join(" "));let Q=new q9($.authorizationUrl);return Z.forEach((J,q)=>{Q.searchParams.append(q,J)}),Q.toString()}async startCallbackServer($){return new Promise((Y,X)=>{let Z=K9.createServer((Q,J)=>{try{let q=new q9(Q.url,`http://localhost:${r$}`);if(q.pathname!==p6){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(G9,{"Content-Type":"text/html"}),J.end(`
59
+ ${O}`,metadata:{serverName:Y,toolName:X.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 Y2($){if($.type==="object"||$.properties){let Y={},X=$.required||[];if($.properties){for(let[Z,Q]of Object.entries($.properties))if(typeof Q==="object"&&Q!==null){let J=Y2(Q);if(!X.includes(Z))J=J.optional();Y[Z]=J}}return i0.object(Y)}if($.type==="array"&&$.items){if(typeof $.items==="object"&&!Array.isArray($.items)&&$.items!==null)return i0.array(Y2($.items));return i0.array(i0.any())}if($.type==="string"){let Y=i0.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 i0.enum($.enum);return Y}if($.type==="number"||$.type==="integer"){let Y=i0.number();if($.minimum!==void 0)Y=Y.min($.minimum);if($.maximum!==void 0)Y=Y.max($.maximum);return Y}if($.type==="boolean")return i0.boolean();if($.oneOf&&$.oneOf.length>0){let Y=$.oneOf.filter((X)=>typeof X==="object"&&X!==null).map((X)=>Y2(X));if(Y.length>=2)return i0.union(Y)}if($.anyOf&&$.anyOf.length>0){let Y=$.anyOf.filter((X)=>typeof X==="object"&&X!==null).map((X)=>Y2(X));if(Y.length>=2)return i0.union(Y)}return i0.any()}import{Client as pY}from"@modelcontextprotocol/sdk/client/index.js";import{SSEClientTransport as gY}from"@modelcontextprotocol/sdk/client/sse.js";import{StdioClientTransport as mY}from"@modelcontextprotocol/sdk/client/stdio.js";import{EventEmitter as uY}from"events";import*as Z2 from"crypto";import*as R9 from"http";import{spawn as hY}from"child_process";import{URL as w9}from"url";import{promises as i6}from"fs";import fY from"os";import r6 from"path";class P2{tokenFilePath;constructor(){let $=fY.homedir(),Y=r6.join($,".blade");this.tokenFilePath=r6.join(Y,"mcp-oauth-tokens.json")}async ensureConfigDir(){let $=r6.dirname(this.tokenFilePath);try{await i6.mkdir($,{recursive:!0})}catch(Y){}}async loadAllCredentials(){let $=new Map;try{let Y=await i6.readFile(this.tokenFilePath,"utf-8"),X=JSON.parse(Y);for(let Z of X)$.set(Z.serverName,Z)}catch(Y){if(Y.code!=="ENOENT")console.warn("[OAuthTokenStorage] 加载令牌失败:",Y)}return $}async saveAllCredentials($){await this.ensureConfigDir();let Y=Array.from($.values());await i6.writeFile(this.tokenFilePath,JSON.stringify(Y,null,2),{mode:384})}async saveToken($,Y,X,Z){let Q=await this.loadAllCredentials(),J={serverName:$,token:Y,clientId:X,tokenUrl:Z,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 X2=7777,a6="/oauth/callback",A9=200;class S2{tokenStorage;constructor($=new P2){this.tokenStorage=$}generatePKCEParams(){let $=Z2.randomBytes(32).toString("base64url"),Y=Z2.createHash("sha256").update($).digest("base64url"),X=Z2.randomBytes(16).toString("base64url");return{codeVerifier:$,codeChallenge:Y,state:X}}buildAuthorizationUrl($,Y){let X=$.redirectUri||`http://localhost:${X2}${a6}`,Z=new URLSearchParams({client_id:$.clientId,response_type:"code",redirect_uri:X,state:Y.state,code_challenge:Y.codeChallenge,code_challenge_method:"S256"});if($.scopes&&$.scopes.length>0)Z.append("scope",$.scopes.join(" "));let Q=new w9($.authorizationUrl);return Z.forEach((J,q)=>{Q.searchParams.append(q,J)}),Q.toString()}async startCallbackServer($){return new Promise((Y,X)=>{let Z=R9.createServer((Q,J)=>{try{let q=new w9(Q.url,`http://localhost:${X2}`);if(q.pathname!==a6){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(A9,{"Content-Type":"text/html"}),J.end(`
60
60
  <html>
61
61
  <body>
62
62
  <h1>Authentication Failed</h1>
@@ -64,7 +64,7 @@ ${O}`,metadata:{serverName:Y,toolName:X.name,mcpResult:K}}}catch(K){return{succe
64
64
  <p>You can close this window.</p>
65
65
  </body>
66
66
  </html>
67
- `),Z.close(),X(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"),Z.close(),X(Error("State mismatch - possible CSRF attack"));return}J.writeHead(G9,{"Content-Type":"text/html"}),J.end(`
67
+ `),Z.close(),X(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"),Z.close(),X(Error("State mismatch - possible CSRF attack"));return}J.writeHead(A9,{"Content-Type":"text/html"}),J.end(`
68
68
  <html>
69
69
  <body>
70
70
  <h1>Authentication Successful!</h1>
@@ -72,32 +72,30 @@ ${O}`,metadata:{serverName:Y,toolName:X.name,mcpResult:K}}}catch(K){return{succe
72
72
  <script>window.close();</script>
73
73
  </body>
74
74
  </html>
75
- `),Z.close(),Y(G)}catch(q){Z.close(),X(q)}});Z.on("error",X),Z.listen(r$,()=>{console.log(`[OAuth] Callback server listening on port ${r$}`)}),setTimeout(()=>{Z.close(),X(Error("OAuth callback timeout"))},300000)})}async exchangeCodeForToken($,Y,X){let Z=$.redirectUri||`http://localhost:${r$}${p6}`,Q=new URLSearchParams({grant_type:"authorization_code",code:Y,redirect_uri:Z,code_verifier:X,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 X=new URLSearchParams({grant_type:"refresh_token",refresh_token:Y,client_id:$.clientId});if($.clientSecret)X.append("client_secret",$.clientSecret);if($.scopes&&$.scopes.length>0)X.append("scope",$.scopes.join(" "));let Z=await fetch($.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:X.toString()});if(!Z.ok){let Q=await Z.text();throw Error(`Token refresh failed: ${Z.status} - ${Q}`)}return await Z.json()}async authenticate($,Y){if(!Y.clientId||!Y.authorizationUrl||!Y.tokenUrl)throw Error("Missing required OAuth configuration");let X=this.generatePKCEParams(),Z=this.buildAuthorizationUrl(Y,X);console.log(`
75
+ `),Z.close(),Y(G)}catch(q){Z.close(),X(q)}});Z.on("error",X),Z.listen(X2,()=>{console.log(`[OAuth] Callback server listening on port ${X2}`)}),setTimeout(()=>{Z.close(),X(Error("OAuth callback timeout"))},300000)})}async exchangeCodeForToken($,Y,X){let Z=$.redirectUri||`http://localhost:${X2}${a6}`,Q=new URLSearchParams({grant_type:"authorization_code",code:Y,redirect_uri:Z,code_verifier:X,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 X=new URLSearchParams({grant_type:"refresh_token",refresh_token:Y,client_id:$.clientId});if($.clientSecret)X.append("client_secret",$.clientSecret);if($.scopes&&$.scopes.length>0)X.append("scope",$.scopes.join(" "));let Z=await fetch($.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:X.toString()});if(!Z.ok){let Q=await Z.text();throw Error(`Token refresh failed: ${Z.status} - ${Q}`)}return await Z.json()}async authenticate($,Y){if(!Y.clientId||!Y.authorizationUrl||!Y.tokenUrl)throw Error("Missing required OAuth configuration");let X=this.generatePKCEParams(),Z=this.buildAuthorizationUrl(Y,X);console.log(`
76
76
  [OAuth] Opening browser for authentication...`),console.log(`
77
- If the browser does not open automatically, copy and paste this URL:`),console.log(Z),console.log("");let Q=this.startCallbackServer(X.state);try{await this.openAuthorizationUrl(Z)}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,X.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:X}=this.getBrowserCommand($);await new Promise((Z,Q)=>{let J=z7(Y,X,{stdio:"ignore"});J.once("error",Q),J.once("close",(q)=>{if(q===0||q===null)Z();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 X=await this.tokenStorage.getCredentials($);if(!X)return null;let{token:Z}=X;if(!this.tokenStorage.isTokenExpired(Z))return Z.accessToken;if(Z.refreshToken&&Y.clientId&&X.tokenUrl)try{console.log(`[OAuth] Refreshing expired token for server: ${$}`);let Q=await this.refreshAccessToken(Y,Z.refreshToken),J={accessToken:Q.access_token,tokenType:Q.token_type,refreshToken:Q.refresh_token||Z.refreshToken,scope:Q.scope||Z.scope};if(Q.expires_in)J.expiresAt=Date.now()+Q.expires_in*1000;return await this.tokenStorage.saveToken($,J,Y.clientId,X.tokenUrl),J.accessToken}catch(Q){console.error("[OAuth] Failed to refresh token:",Q),await this.tokenStorage.deleteCredentials($)}return null}}import{EventEmitter as N7}from"events";class g6 extends N7{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 X;if(this.consecutiveFailures>=this.config.failureThreshold)X="unhealthy",this.emit("unhealthy",this.consecutiveFailures,Y),console.log("[HealthMonitor] 达到失败阈值,触发重连..."),this.triggerReconnection().catch((Q)=>{console.error("[HealthMonitor] 重连失败:",Q)});else X="degraded";this.setStatus(X);let Z={status:X,timestamp:Date.now(),consecutiveFailures:this.consecutiveFailures,lastError:Y};return this.emit("healthCheck",Z),Z}finally{this.isChecking=!1}}async pingServer(){let $=new Promise((X,Z)=>{setTimeout(()=>Z(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")}}function W9($){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:$}}class m6 extends A7{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,X){super();this.config=$;if(this.serverName=Y||"default",$.oauth?.enabled)this.oauthProvider=new v2;if(X?.enabled)this.healthMonitor=new g6(this,X),this.healthMonitor.on("unhealthy",(Z,Q)=>{this.emit("unhealthy",Z,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 X=null;for(let Z=1;Z<=$;Z++)try{await this.doConnect(),this.reconnectAttempts=0;return}catch(Q){X=Q;let J=W9(Q);if(!J.isRetryable)throw console.error("[McpClient] 检测到永久性错误,放弃重试:",J.type),Q;if(Z<$){let q=Y*Math.pow(2,Z-1);console.warn(`[McpClient] 连接失败(${Z}/${$}),${q}ms 后重试...`),await new Promise((G)=>setTimeout(G,q))}}throw X||Error("连接失败")}async doConnect(){try{this.setStatus("connecting"),this.sdkClient=new B7({name:p8(),version:L2()},{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),W9(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(X){throw console.error(`[McpClient] 调用工具 "${$}" 失败:`,X),X}}async createTransport(){let{type:$,command:Y,args:X,env:Z,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,O]of Object.entries(process.env))if(O!==void 0)K[W]=O;return new w7({command:Y,args:X||[],env:{...K,...Z},stderr:"ignore"})}else if($==="sse"){if(!Q)throw Error("sse 传输需要 url 参数");return new L7(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:""}}}class k0 extends R7{static instance=null;servers=new Map;isDiscovering=!1;constructor(){super()}static getInstance(){if(!k0.instance)k0.instance=new k0;return k0.instance}async registerServer($,Y){if(this.servers.has($))throw Error(`MCP服务器 "${$}" 已经注册`);let X=new m6(Y,$,Y.healthCheck),Z={config:Y,client:X,status:"disconnected",tools:[]};this.setupClientEventHandlers(X,Z,$),this.servers.set($,Z),this.emit("serverRegistered",$,Z);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(X){console.warn(`断开MCP服务器 "${$}" 时出错:`,X)}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(X){throw Y.lastError=X,Y.status="error",X}}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[X,Z]of this.servers)if(Z.status==="connected")for(let Q of Z.tools){let J=Y.get(Q.name)||0;Y.set(Q.name,J+1)}for(let[X,Z]of this.servers)if(Z.status==="connected")for(let Q of Z.tools){let q=(Y.get(Q.name)||0)>1?`${X}__${Q.name}`:Q.name,G=I2(Z.client,X,Q,q);$.push(G)}return $}async findTool($){for(let[Y,X]of this.servers)if(X.status==="connected"){let Z=X.tools.find((Q)=>Q.name===$);if(Z)return I2(X.client,Y,Z)}return null}getToolsByServer($){let Y=this.servers.get($);if(!Y||Y.status!=="connected")return[];return Y.tools.map((X)=>I2(Y.client,$,X))}getServerStatus($){return this.servers.get($)||null}getAllServers(){return new Map(this.servers)}async refreshAllTools(){let $=[];for(let[Y,X]of this.servers)if(X.status==="connected")$.push(this.refreshServerTools(Y));await Promise.allSettled($)}async refreshServerTools($){let Y=this.servers.get($);if(!Y||Y.status!=="connected")return;try{let X=Y.client.availableTools,Z=Y.tools.length;Y.tools=X,this.emit("toolsUpdated",$,X,Z)}catch(X){console.warn(`刷新服务器 "${$}" 工具列表失败:`,X)}}setupClientEventHandlers($,Y,X){$.on("connected",(Z)=>{Y.status="connected",Y.connectedAt=new Date,Y.tools=$.availableTools,this.emit("serverConnected",X,Z)}),$.on("disconnected",()=>{Y.status="disconnected",Y.connectedAt=void 0,Y.tools=[],this.emit("serverDisconnected",X)}),$.on("error",(Z)=>{Y.status="error",Y.lastError=Z,this.emit("serverError",X,Z)}),$.on("toolsUpdated",(Z)=>{let Q=Y.tools.length;Y.tools=Z,this.emit("toolsUpdated",X,Z,Q)}),$.on("statusChanged",(Z,Q)=>{Y.status=Z,this.emit("serverStatusChanged",X,Z,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(([X,Z])=>this.registerServer(X,Z).catch((Q)=>{return console.warn(`注册MCP服务器 "${X}" 失败:`,Q),Q}));await Promise.allSettled(Y)}getStatistics(){let $=0,Y=0,X=0;for(let Z of this.servers.values())if(Z.status==="connected")$++,Y+=Z.tools.length;else if(Z.status==="error")X++;return{totalServers:this.servers.size,connectedServers:$,errorServers:X,totalTools:Y,isDiscovering:this.isDiscovering}}async disconnectAll(){let $=[];for(let[Y,X]of this.servers)if(X.status==="connected")$.push(X.client.disconnect().catch((Z)=>{console.warn(`断开 MCP 服务器 "${Y}" 时出错:`,Z)}));await Promise.allSettled($),this.servers.clear()}}function b7(){console.log(`
77
+ If the browser does not open automatically, copy and paste this URL:`),console.log(Z),console.log("");let Q=this.startCallbackServer(X.state);try{await this.openAuthorizationUrl(Z)}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,X.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:X}=this.getBrowserCommand($);await new Promise((Z,Q)=>{let J=hY(Y,X,{stdio:"ignore"});J.once("error",Q),J.once("close",(q)=>{if(q===0||q===null)Z();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 X=await this.tokenStorage.getCredentials($);if(!X)return null;let{token:Z}=X;if(!this.tokenStorage.isTokenExpired(Z))return Z.accessToken;if(Z.refreshToken&&Y.clientId&&X.tokenUrl)try{console.log(`[OAuth] Refreshing expired token for server: ${$}`);let Q=await this.refreshAccessToken(Y,Z.refreshToken),J={accessToken:Q.access_token,tokenType:Q.token_type,refreshToken:Q.refresh_token||Z.refreshToken,scope:Q.scope||Z.scope};if(Q.expires_in)J.expiresAt=Date.now()+Q.expires_in*1000;return await this.tokenStorage.saveToken($,J,Y.clientId,X.tokenUrl),J.accessToken}catch(Q){console.error("[OAuth] Failed to refresh token:",Q),await this.tokenStorage.deleteCredentials($)}return null}}import{EventEmitter as xY}from"events";class n6 extends xY{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 X;if(this.consecutiveFailures>=this.config.failureThreshold)X="unhealthy",this.emit("unhealthy",this.consecutiveFailures,Y),console.log("[HealthMonitor] 达到失败阈值,触发重连..."),this.triggerReconnection().catch((Q)=>{console.error("[HealthMonitor] 重连失败:",Q)});else X="degraded";this.setStatus(X);let Z={status:X,timestamp:Date.now(),consecutiveFailures:this.consecutiveFailures,lastError:Y};return this.emit("healthCheck",Z),Z}finally{this.isChecking=!1}}async pingServer(){let $=new Promise((X,Z)=>{setTimeout(()=>Z(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")}}function b9($){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:$}}class o6 extends uY{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,X){super();this.config=$;if(this.serverName=Y||"default",$.oauth?.enabled)this.oauthProvider=new S2;if(X?.enabled)this.healthMonitor=new n6(this,X),this.healthMonitor.on("unhealthy",(Z,Q)=>{this.emit("unhealthy",Z,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 X=null;for(let Z=1;Z<=$;Z++)try{await this.doConnect(),this.reconnectAttempts=0;return}catch(Q){X=Q;let J=b9(Q);if(!J.isRetryable)throw console.error("[McpClient] 检测到永久性错误,放弃重试:",J.type),Q;if(Z<$){let q=Y*Math.pow(2,Z-1);console.warn(`[McpClient] 连接失败(${Z}/${$}),${q}ms 后重试...`),await new Promise((G)=>setTimeout(G,q))}}throw X||Error("连接失败")}async doConnect(){try{this.setStatus("connecting"),this.sdkClient=new pY({name:t8(),version:v2()},{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),b9(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(X){throw console.error(`[McpClient] 调用工具 "${$}" 失败:`,X),X}}async createTransport(){let{type:$,command:Y,args:X,env:Z,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,O]of Object.entries(process.env))if(O!==void 0)K[W]=O;return new mY({command:Y,args:X||[],env:{...K,...Z},stderr:"ignore"})}else if($==="sse"){if(!Q)throw Error("sse 传输需要 url 参数");return new gY(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:""}}}class v0 extends dY{static instance=null;servers=new Map;isDiscovering=!1;constructor(){super()}static getInstance(){if(!v0.instance)v0.instance=new v0;return v0.instance}async registerServer($,Y){if(this.servers.has($))throw Error(`MCP服务器 "${$}" 已经注册`);let X=new o6(Y,$,Y.healthCheck),Z={config:Y,client:X,status:"disconnected",tools:[]};this.setupClientEventHandlers(X,Z,$),this.servers.set($,Z),this.emit("serverRegistered",$,Z);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(X){console.warn(`断开MCP服务器 "${$}" 时出错:`,X)}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(X){throw Y.lastError=X,Y.status="error",X}}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[X,Z]of this.servers)if(Z.status==="connected")for(let Q of Z.tools){let J=Y.get(Q.name)||0;Y.set(Q.name,J+1)}for(let[X,Z]of this.servers)if(Z.status==="connected")for(let Q of Z.tools){let q=(Y.get(Q.name)||0)>1?`${X}__${Q.name}`:Q.name,G=j2(Z.client,X,Q,q);$.push(G)}return $}async findTool($){for(let[Y,X]of this.servers)if(X.status==="connected"){let Z=X.tools.find((Q)=>Q.name===$);if(Z)return j2(X.client,Y,Z)}return null}getToolsByServer($){let Y=this.servers.get($);if(!Y||Y.status!=="connected")return[];return Y.tools.map((X)=>j2(Y.client,$,X))}getServerStatus($){return this.servers.get($)||null}getAllServers(){return new Map(this.servers)}async refreshAllTools(){let $=[];for(let[Y,X]of this.servers)if(X.status==="connected")$.push(this.refreshServerTools(Y));await Promise.allSettled($)}async refreshServerTools($){let Y=this.servers.get($);if(!Y||Y.status!=="connected")return;try{let X=Y.client.availableTools,Z=Y.tools.length;Y.tools=X,this.emit("toolsUpdated",$,X,Z)}catch(X){console.warn(`刷新服务器 "${$}" 工具列表失败:`,X)}}setupClientEventHandlers($,Y,X){$.on("connected",(Z)=>{Y.status="connected",Y.connectedAt=new Date,Y.tools=$.availableTools,this.emit("serverConnected",X,Z)}),$.on("disconnected",()=>{Y.status="disconnected",Y.connectedAt=void 0,Y.tools=[],this.emit("serverDisconnected",X)}),$.on("error",(Z)=>{Y.status="error",Y.lastError=Z,this.emit("serverError",X,Z)}),$.on("toolsUpdated",(Z)=>{let Q=Y.tools.length;Y.tools=Z,this.emit("toolsUpdated",X,Z,Q)}),$.on("statusChanged",(Z,Q)=>{Y.status=Z,this.emit("serverStatusChanged",X,Z,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(([X,Z])=>this.registerServer(X,Z).catch((Q)=>{return console.warn(`注册MCP服务器 "${X}" 失败:`,Q),Q}));await Promise.allSettled(Y)}getStatistics(){let $=0,Y=0,X=0;for(let Z of this.servers.values())if(Z.status==="connected")$++,Y+=Z.tools.length;else if(Z.status==="error")X++;return{totalServers:this.servers.size,connectedServers:$,errorServers:X,totalTools:Y,isDiscovering:this.isDiscovering}}async disconnectAll(){let $=[];for(let[Y,X]of this.servers)if(X.status==="connected")$.push(X.client.disconnect().catch((Z)=>{console.warn(`断开 MCP 服务器 "${Y}" 时出错:`,Z)}));await Promise.allSettled($),this.servers.clear()}}function cY(){console.log(`
78
78
  blade mcp
79
79
  `),console.log(`管理 MCP 服务器
80
- `),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 字符串添加服务器"),console.log(` blade mcp reset-project-choices 重置项目级 .mcp.json 确认记录
80
+ `),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 字符串添加服务器
81
81
  `),console.log("Options:"),console.log(` -h, --help 显示帮助信息 [boolean]
82
82
  `),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
83
83
  `),console.log(`使用 blade mcp <command> --help 查看各子命令的详细帮助
84
- `)}function V7($){return $.reduce((Y,X)=>{let[Z,...Q]=X.split("=");return Y[Z]=Q.join("="),Y},{})}function D7($){return $.reduce((Y,X)=>{let[Z,...Q]=X.split(":");return Y[Z.trim()]=Q.join(":").trim(),Y},{})}var I7={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:"超时时间(毫秒)"}).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:X,args:Z,transport:Q,env:J,header:q,timeout:G}=$;if($["--"]&&$["--"].length>0)X=$["--"][0],Z=$["--"].slice(1);if(!Y||!X)console.error("❌ 缺少必需参数: name 和 commandOrUrl"),console.log(`
84
+ `)}function lY($){return $.reduce((Y,X)=>{let[Z,...Q]=X.split("=");return Y[Z]=Q.join("="),Y},{})}function iY($){return $.reduce((Y,X)=>{let[Z,...Q]=X.split(":");return Y[Z.trim()]=Q.join(":").trim(),Y},{})}var rY={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:X,args:Z,transport:Q,env:J,header:q,timeout:G}=$,K=$.global===!0;if($["--"]&&$["--"].length>0)X=$["--"][0],Z=$["--"].slice(1);if(!Y||!X)console.error("❌ 缺少必需参数: name 和 commandOrUrl"),console.log(`
85
85
  \uD83D\uDCA1 用法:`),console.log(" blade mcp add <name> <command> [args...]"),console.log(" blade mcp add <name> -- <command> [args...]"),console.log(`
86
- 示例:`),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 K={type:Q};if(Q==="stdio"){if(K.command=X,K.args=Z||[],J&&Array.isArray(J))K.env=V7(J)}else if(K.url=X,q&&Array.isArray(q))K.headers=D7(q);if(G)K.timeout=G;await e().addMcpServer(Y,K),console.log(`✅ MCP 服务器 "${Y}" 已添加到当前项目`),console.log(` 项目路径: ${process.cwd()}`)}catch(Y){console.error(`❌ 添加失败: ${Y instanceof Error?Y.message:"未知错误"}`),process.exit(1)}}},k7={command:"remove <name>",describe:"删除 MCP 服务器",aliases:["rm"],builder:($)=>{return $.positional("name",{type:"string",describe:"服务器名称",demandOption:!0}).example([["$0 mcp remove github","Remove the specified MCP server"]])},handler:async($)=>{try{if(!_1()[$.name])console.error(`❌ 服务器 "${$.name}" 不存在`),process.exit(1);await e().removeMcpServer($.name),console.log(`✅ MCP 服务器 "${$.name}" 已删除`)}catch(Y){console.error(`❌ 删除失败: ${Y instanceof Error?Y.message:"未知错误"}`),process.exit(1)}}},v7={command:"list",describe:"列出所有 MCP 服务器并检查健康状态",aliases:["ls"],handler:async()=>{try{let $=_1();if(console.log(`
87
- 当前项目: ${process.cwd()}
88
- `),Object.keys($).length===0){console.log("暂无配置的 MCP 服务器");return}console.log(`检查 MCP 服务器健康状态...
89
- `);let Y=k0.getInstance(),X=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}}}),Z=await Promise.all(X);for(let{name:Q,config:J,serverInfo:q,error:G}of Z){let K=q?.status||"disconnected",W=K==="connected"?"✓":"✗",O=K==="connected"?"Connected":"Failed";if(console.log(`${Q}: ${J.type==="stdio"?J.command:J.url} - ${W} ${O}`),G&&K!=="connected")console.log(` 错误: ${G instanceof Error?G.message:String(G)}`)}console.log("");for(let{name:Q}of Z)try{await Y.unregisterServer(Q)}catch(J){}process.exit(0)}catch($){console.error(`❌ 列表获取失败: ${$ instanceof Error?$.message:"未知错误"}`),process.exit(1)}}},M7={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 X=_1()[$.name];if(!X)console.error(`❌ 服务器 "${$.name}" 不存在`),process.exit(1);console.log(`
86
+ 示例:`),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=X,W.args=Z||[],J&&Array.isArray(J))W.env=lY(J)}else if(W.url=X,q&&Array.isArray(q))W.headers=iY(q);if(G)W.timeout=G;await W0().addMcpServer(Y,W,{scope:K?"global":"project"});let O=K?C2.join(V9.homedir(),".blade","config.json"):C2.join(process.cwd(),".blade","config.json");console.log(`✅ MCP 服务器 "${Y}" 已添加`),console.log(` 配置文件: ${O}`)}catch(Y){console.error(`❌ 添加失败: ${Y instanceof Error?Y.message:"未知错误"}`),process.exit(1)}}},aY={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=l0(),X=$.global===!0;if(!Y[$.name])console.error(`❌ 服务器 "${$.name}" 不存在`),process.exit(1);await W0().removeMcpServer($.name,{scope:X?"global":"project"}),console.log(`✅ MCP 服务器 "${$.name}" 已删除`)}catch(Y){console.error(`❌ 删除失败: ${Y instanceof Error?Y.message:"未知错误"}`),process.exit(1)}}},nY={command:"list",describe:"列出所有 MCP 服务器并检查健康状态",aliases:["ls"],handler:async()=>{try{let $=l0();if(console.log(""),Object.keys($).length===0){console.log("暂无配置的 MCP 服务器");return}console.log(`检查 MCP 服务器健康状态...
87
+ `);let Y=v0.getInstance(),X=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}}}),Z=await Promise.all(X);for(let{name:Q,config:J,serverInfo:q,error:G}of Z){let K=q?.status||"disconnected",W=K==="connected"?"✓":"✗",O=K==="connected"?"Connected":"Failed";if(console.log(`${Q}: ${J.type==="stdio"?J.command:J.url} - ${W} ${O}`),G&&K!=="connected")console.log(` 错误: ${G instanceof Error?G.message:String(G)}`)}console.log("");for(let{name:Q}of Z)try{await Y.unregisterServer(Q)}catch(J){}process.exit(0)}catch($){console.error(`❌ 列表获取失败: ${$ instanceof Error?$.message:"未知错误"}`),process.exit(1)}}},oY={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 X=l0()[$.name];if(!X)console.error(`❌ 服务器 "${$.name}" 不存在`),process.exit(1);console.log(`
90
88
  服务器: ${$.name}
91
- `),console.log(JSON.stringify(X,null,2))}catch(Y){console.error(`❌ 获取失败: ${Y instanceof Error?Y.message:"未知错误"}`),process.exit(1)}}},y7={command:"add-json <name> <json>",describe:"从 JSON 字符串添加服务器",builder:($)=>{return $.positional("name",{type:"string",describe:"服务器名称",demandOption:!0}).positional("json",{type:"string",describe:"JSON 配置字符串",demandOption:!0}).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);if(!Y.type)throw Error('配置必须包含 "type" 字段');await e().addMcpServer($.name,Y),console.log(`✅ MCP 服务器 "${$.name}" 已添加`),console.log(` 项目路径: ${process.cwd()}`)}catch(Y){console.error(`❌ 添加失败: ${Y instanceof Error?Y.message:"未知错误"}`),process.exit(1)}}},E7={command:"reset-project-choices",describe:"重置项目级 .mcp.json 确认记录",handler:async()=>{try{await e().resetProjectChoices(),console.log("✅ 已重置当前项目的 .mcp.json 确认记录"),console.log(` 项目路径: ${process.cwd()}`)}catch($){console.error(`❌ 重置失败: ${$ instanceof Error?$.message:"未知错误"}`),process.exit(1)}}},U9={command:"mcp",describe:"管理 MCP 服务器",builder:($)=>{return $.command(I7).command(k7).command(v7).command(M7).command(y7).command(E7).demandCommand(0).help(!1).option("help",{alias:"h",type:"boolean",describe:"显示帮助信息"})},handler:($)=>{let Y=["add","remove","list","ls","get","add-json","reset-project-choices"];if(!$._.some((Z)=>Y.includes(Z))||$.help)b7(),process.exit(0)}};import*as K5 from"os";import*as W5 from"path";import{nanoid as U$}from"nanoid";import O9 from"openai";var m=Y0("Chat");class y2{config;client;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 O9({apiKey:$.apiKey,baseURL:$.baseUrl,timeout:$.timeout??180000,maxRetries:3}),m.debug("✅ [ChatService] ChatService initialized successfully")}async chat($,Y,X){let Z=Date.now();m.debug("\uD83D\uDE80 [ChatService] Starting chat request"),m.debug("\uD83D\uDCDD [ChatService] Messages count:",$.length),m.debug("\uD83D\uDCDD [ChatService] Messages preview:",$.map((G)=>({role:G.role,contentLength:G.content.length})));let Q=$.map((G)=>{if(G.role==="tool")return{role:"tool",content:G.content,tool_call_id:G.tool_call_id};if(G.role==="assistant"&&G.tool_calls)return{role:"assistant",content:G.content||null,tool_calls:G.tool_calls};return{role:G.role,content:G.content}}),J=Y?.map((G)=>({type:"function",function:{name:G.name,description:G.description,parameters:G.parameters}}));if(m.debug("\uD83D\uDD27 [ChatService] Tools count:",J?.length||0),J&&J.length>0)m.debug("\uD83D\uDD27 [ChatService] Available tools:",J.map((G)=>G.type==="function"?G.function.name:"unknown"));let q={model:this.config.model,messages:Q,tools:J,tool_choice:J&&J.length>0?"auto":void 0,max_tokens:this.config.maxOutputTokens??32768,temperature:this.config.temperature??0};m.debug("\uD83D\uDCE4 [ChatService] Request params:",{model:q.model,messagesCount:q.messages.length,toolsCount:q.tools?.length||0,tool_choice:q.tool_choice,max_tokens:q.max_tokens,temperature:q.temperature});try{let G=await this.client.chat.completions.create(q,{signal:X}),K=Date.now()-Z;if(m.debug("\uD83D\uDCE5 [ChatService] Response received in",K,"ms"),!G)throw m.error("❌ [ChatService] API returned null/undefined response"),Error("API returned null/undefined response");if(!G.choices||!Array.isArray(G.choices))throw m.error("❌ [ChatService] Invalid API response format - missing choices array"),m.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 m.error("❌ [ChatService] API returned empty choices array"),Error("API returned empty choices array");m.debug("\uD83D\uDCCA [ChatService] Response usage:",G.usage),m.debug("\uD83D\uDCCA [ChatService] Response choices count:",G.choices.length);let W=G.choices[0];if(!W)throw m.error("❌ [ChatService] No completion choice returned"),Error("No completion choice returned");if(m.debug("\uD83D\uDCDD [ChatService] Response choice:",{finishReason:W.finish_reason,contentLength:W.message.content?.length||0,hasToolCalls:!!W.message.tool_calls,toolCallsCount:W.message.tool_calls?.length||0}),W.message.tool_calls)m.debug("\uD83D\uDD27 [ChatService] Tool calls:",W.message.tool_calls.map((H)=>({id:H.id,type:H.type,functionName:H.type==="function"?H.function?.name:"unknown",functionArgsLength:H.type==="function"?H.function?.arguments?.length||0:0})));let O=W.message.tool_calls?.filter((H)=>H.type==="function"),U={content:W.message.content||"",toolCalls:O,usage:{promptTokens:G.usage?.prompt_tokens||0,completionTokens:G.usage?.completion_tokens||0,totalTokens:G.usage?.total_tokens||0}};return m.debug("✅ [ChatService] Chat completed successfully"),m.debug("\uD83D\uDCCA [ChatService] Final response:",{contentLength:U.content.length,toolCallsCount:U.toolCalls?.length||0,usage:U.usage}),U}catch(G){let K=Date.now()-Z;throw m.error("❌ [ChatService] Chat request failed after",K,"ms"),m.error("❌ [ChatService] Error details:",G),G}}async*streamChat($,Y,X){let Z=Date.now();m.debug("\uD83D\uDE80 [ChatService] Starting chat stream request"),m.debug("\uD83D\uDCDD [ChatService] Messages count:",$.length),m.debug("\uD83D\uDCDD [ChatService] Messages preview:",$.map((G)=>({role:G.role,contentLength:G.content.length})));let Q=$.map((G)=>{if(G.role==="tool")return{role:"tool",content:G.content,tool_call_id:G.tool_call_id};if(G.role==="assistant"&&G.tool_calls)return{role:"assistant",content:G.content||null,tool_calls:G.tool_calls};return{role:G.role,content:G.content}}),J=Y?.map((G)=>({type:"function",function:{name:G.name,description:G.description,parameters:G.parameters}}));if(m.debug("\uD83D\uDD27 [ChatService] Stream tools count:",J?.length||0),J&&J.length>0)m.debug("\uD83D\uDD27 [ChatService] Stream available tools:",J.map((G)=>G.type==="function"?G.function.name:"unknown"));let q={model:this.config.model,messages:Q,tools:J,tool_choice:J&&J.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:q.model,messagesCount:q.messages.length,toolsCount:q.tools?.length||0,tool_choice:q.tool_choice,max_tokens:q.max_tokens,temperature:q.temperature,stream:q.stream});try{let G=await this.client.chat.completions.create(q,{signal:X}),K=Date.now()-Z;m.debug("\uD83D\uDCE5 [ChatService] Stream started in",K,"ms");let W=0,O="",U=!1;for await(let H of G){if(W++,!H||!H.choices||!Array.isArray(H.choices)){m.warn("⚠️ [ChatService] Invalid chunk format in stream",W);continue}let _=H.choices[0]?.delta;if(!_){m.warn("⚠️ [ChatService] Empty delta in chunk",W);continue}if(_.content)O+=_.content;if(_.tool_calls&&!U)U=!0,m.debug("\uD83D\uDD27 [ChatService] Tool calls detected in stream");let z=H.choices[0]?.finish_reason;if(z)m.debug("\uD83C\uDFC1 [ChatService] Stream finished with reason:",z),m.debug("\uD83D\uDCCA [ChatService] Stream summary:",{totalChunks:W,totalContentLength:O.length,hadToolCalls:U,duration:Date.now()-Z+"ms"});yield{content:_.content||void 0,toolCalls:_.tool_calls,finishReason:z||void 0}}m.debug("✅ [ChatService] Stream completed successfully")}catch(G){let K=Date.now()-Z;throw m.error("❌ [ChatService] Stream request failed after",K,"ms"),m.error("❌ [ChatService] Stream error details:",G),G}}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};this.config={...this.config,...$},this.client=new O9({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 j7=Y0("Service");function E2($){switch($.provider){case"openai-compatible":return new y2($);case"anthropic":throw Error(`❌ Anthropic provider 暂未实现
89
+ `),console.log(JSON.stringify(X,null,2))}catch(Y){console.error(`❌ 获取失败: ${Y instanceof Error?Y.message:"未知错误"}`),process.exit(1)}}},sY={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),X=$.global===!0;if(!Y.type)throw Error('配置必须包含 "type" 字段');await W0().addMcpServer($.name,Y,{scope:X?"global":"project"});let Z=X?C2.join(V9.homedir(),".blade","config.json"):C2.join(process.cwd(),".blade","config.json");console.log(`✅ MCP 服务器 "${$.name}" 已添加`),console.log(` 配置文件: ${Z}`)}catch(Y){console.error(`❌ 添加失败: ${Y instanceof Error?Y.message:"未知错误"}`),process.exit(1)}}},I9={command:"mcp",describe:"管理 MCP 服务器",builder:($)=>{return $.command(rY).command(aY).command(nY).command(oY).command(sY).demandCommand(0).help(!1).option("help",{alias:"h",type:"boolean",describe:"显示帮助信息"})},handler:($)=>{let Y=["add","remove","list","ls","get","add-json"];if(!$._.some((Z)=>Y.includes(Z))||$.help)cY(),process.exit(0)}};import*as b5 from"os";import*as V5 from"path";import{nanoid as B$}from"nanoid";import D9 from"openai";var g=$0("Chat");class f2{config;client;constructor($){this.config=$;if(g.debug("\uD83D\uDE80 [ChatService] Initializing ChatService"),g.debug("⚙️ [ChatService] Config:",{model:$.model,baseUrl:$.baseUrl,temperature:$.temperature,maxContextTokens:$.maxContextTokens,timeout:$.timeout,hasApiKey:!!$.apiKey}),!$.baseUrl)throw g.error("❌ [ChatService] baseUrl is required in ChatConfig"),Error("baseUrl is required in ChatConfig");if(!$.apiKey)throw g.error("❌ [ChatService] apiKey is required in ChatConfig"),Error("apiKey is required in ChatConfig");if(!$.model)throw g.error("❌ [ChatService] model is required in ChatConfig"),Error("model is required in ChatConfig");this.client=new D9({apiKey:$.apiKey,baseURL:$.baseUrl,timeout:$.timeout??180000,maxRetries:3}),g.debug("✅ [ChatService] ChatService initialized successfully")}async chat($,Y,X){let Z=Date.now();g.debug("\uD83D\uDE80 [ChatService] Starting chat request"),g.debug("\uD83D\uDCDD [ChatService] Messages count:",$.length),g.debug("\uD83D\uDCDD [ChatService] Messages preview:",$.map((G)=>({role:G.role,contentLength:G.content.length})));let Q=$.map((G)=>{if(G.role==="tool")return{role:"tool",content:G.content,tool_call_id:G.tool_call_id};if(G.role==="assistant"&&G.tool_calls)return{role:"assistant",content:G.content||null,tool_calls:G.tool_calls};return{role:G.role,content:G.content}}),J=Y?.map((G)=>({type:"function",function:{name:G.name,description:G.description,parameters:G.parameters}}));if(g.debug("\uD83D\uDD27 [ChatService] Tools count:",J?.length||0),J&&J.length>0)g.debug("\uD83D\uDD27 [ChatService] Available tools:",J.map((G)=>G.type==="function"?G.function.name:"unknown"));let q={model:this.config.model,messages:Q,tools:J,tool_choice:J&&J.length>0?"auto":void 0,max_tokens:this.config.maxOutputTokens??32768,temperature:this.config.temperature??0};g.debug("\uD83D\uDCE4 [ChatService] Request params:",{model:q.model,messagesCount:q.messages.length,toolsCount:q.tools?.length||0,tool_choice:q.tool_choice,max_tokens:q.max_tokens,temperature:q.temperature});try{let G=await this.client.chat.completions.create(q,{signal:X}),K=Date.now()-Z;if(g.debug("\uD83D\uDCE5 [ChatService] Response received in",K,"ms"),!G)throw g.error("❌ [ChatService] API returned null/undefined response"),Error("API returned null/undefined response");if(!G.choices||!Array.isArray(G.choices))throw g.error("❌ [ChatService] Invalid API response format - missing choices array"),g.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 g.error("❌ [ChatService] API returned empty choices array"),Error("API returned empty choices array");g.debug("\uD83D\uDCCA [ChatService] Response usage:",G.usage),g.debug("\uD83D\uDCCA [ChatService] Response choices count:",G.choices.length);let W=G.choices[0];if(!W)throw g.error("❌ [ChatService] No completion choice returned"),Error("No completion choice returned");if(g.debug("\uD83D\uDCDD [ChatService] Response choice:",{finishReason:W.finish_reason,contentLength:W.message.content?.length||0,hasToolCalls:!!W.message.tool_calls,toolCallsCount:W.message.tool_calls?.length||0}),W.message.tool_calls)g.debug("\uD83D\uDD27 [ChatService] Tool calls:",W.message.tool_calls.map((F)=>({id:F.id,type:F.type,functionName:F.type==="function"?F.function?.name:"unknown",functionArgsLength:F.type==="function"?F.function?.arguments?.length||0:0})));let O=W.message.tool_calls?.filter((F)=>F.type==="function"),H=W.message.reasoning_content||void 0,_=G.usage,z={content:W.message.content||"",reasoningContent:H,toolCalls:O,usage:{promptTokens:G.usage?.prompt_tokens||0,completionTokens:G.usage?.completion_tokens||0,totalTokens:G.usage?.total_tokens||0,reasoningTokens:_?.reasoning_tokens}};return g.debug("✅ [ChatService] Chat completed successfully"),g.debug("\uD83D\uDCCA [ChatService] Final response:",{contentLength:z.content.length,toolCallsCount:z.toolCalls?.length||0,usage:z.usage}),z}catch(G){let K=Date.now()-Z;throw g.error("❌ [ChatService] Chat request failed after",K,"ms"),g.error("❌ [ChatService] Error details:",G),G}}async*streamChat($,Y,X){let Z=Date.now();g.debug("\uD83D\uDE80 [ChatService] Starting chat stream request"),g.debug("\uD83D\uDCDD [ChatService] Messages count:",$.length),g.debug("\uD83D\uDCDD [ChatService] Messages preview:",$.map((G)=>({role:G.role,contentLength:G.content.length})));let Q=$.map((G)=>{if(G.role==="tool")return{role:"tool",content:G.content,tool_call_id:G.tool_call_id};if(G.role==="assistant"&&G.tool_calls)return{role:"assistant",content:G.content||null,tool_calls:G.tool_calls};return{role:G.role,content:G.content}}),J=Y?.map((G)=>({type:"function",function:{name:G.name,description:G.description,parameters:G.parameters}}));if(g.debug("\uD83D\uDD27 [ChatService] Stream tools count:",J?.length||0),J&&J.length>0)g.debug("\uD83D\uDD27 [ChatService] Stream available tools:",J.map((G)=>G.type==="function"?G.function.name:"unknown"));let q={model:this.config.model,messages:Q,tools:J,tool_choice:J&&J.length>0?"auto":"none",max_tokens:this.config.maxOutputTokens??32768,temperature:this.config.temperature??0,stream:!0};g.debug("\uD83D\uDCE4 [ChatService] Stream request params:",{model:q.model,messagesCount:q.messages.length,toolsCount:q.tools?.length||0,tool_choice:q.tool_choice,max_tokens:q.max_tokens,temperature:q.temperature,stream:q.stream});try{let G=await this.client.chat.completions.create(q,{signal:X}),K=Date.now()-Z;g.debug("\uD83D\uDCE5 [ChatService] Stream started in",K,"ms");let W=0,O="",U="",H=!1;for await(let _ of G){if(W++,!_||!_.choices||!Array.isArray(_.choices)){g.warn("⚠️ [ChatService] Invalid chunk format in stream",W);continue}let z=_.choices[0]?.delta;if(!z){g.warn("⚠️ [ChatService] Empty delta in chunk",W);continue}let F=z;if(z.content)O+=z.content;if(F.reasoning_content)U+=F.reasoning_content;if(z.tool_calls&&!H)H=!0,g.debug("\uD83D\uDD27 [ChatService] Tool calls detected in stream");let B=_.choices[0]?.finish_reason;if(B)g.debug("\uD83C\uDFC1 [ChatService] Stream finished with reason:",B),g.debug("\uD83D\uDCCA [ChatService] Stream summary:",{totalChunks:W,totalContentLength:O.length,totalReasoningContentLength:U.length,hadToolCalls:H,duration:Date.now()-Z+"ms"});yield{content:z.content||void 0,reasoningContent:F.reasoning_content||void 0,toolCalls:z.tool_calls,finishReason:B||void 0}}g.debug("✅ [ChatService] Stream completed successfully")}catch(G){let K=Date.now()-Z;throw g.error("❌ [ChatService] Stream request failed after",K,"ms"),g.error("❌ [ChatService] Stream error details:",G),G}}getConfig(){return{...this.config}}updateConfig($){g.debug("\uD83D\uDD04 [ChatService] Updating configuration"),g.debug("\uD83D\uDD04 [ChatService] New config:",{model:$.model,baseUrl:$.baseUrl,temperature:$.temperature,maxContextTokens:$.maxContextTokens,timeout:$.timeout,hasApiKey:!!$.apiKey});let Y={...this.config};this.config={...this.config,...$},this.client=new D9({apiKey:this.config.apiKey,baseURL:this.config.baseUrl,timeout:this.config.timeout??180000,maxRetries:2}),g.debug("✅ [ChatService] Configuration updated successfully"),g.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 tY=$0("Service");function h2($){switch($.provider){case"openai-compatible":return new f2($);case"anthropic":throw Error(`❌ Anthropic provider 暂未实现
92
90
 
93
91
  `+`请使用 "openai-compatible" 提供商,或者:
94
92
  `+`1. 等待官方实现
95
93
  `+`2. 贡献代码实现此功能: https://github.com/echoVic/blade-code
96
- `);default:return j7.warn(`⚠️ 未知的 provider: ${$.provider}, 回退到 openai-compatible`),new y2($)}}import{readFile as P7}from"node:fs/promises";class j2{static MAX_FILES=5;static MAX_LINES_PER_FILE=1000;static analyzeFiles($){let Y=new Map;return $.forEach((Z,Q)=>{if(this.extractFilePathsFromContent(Z.content||"").forEach((q)=>{this.updateFileReference(Y,q,Q,!1)}),Z.tool_calls&&Array.isArray(Z.tool_calls))Z.tool_calls.forEach((q)=>{let G=this.extractFilePathsFromToolCall(q),K=q.type==="function"&&"function"in q?q.function?.name:"",W=["Write","Edit"].includes(K||"");G.forEach((O)=>{this.updateFileReference(Y,O,Q,W)})})}),Array.from(Y.values()).sort((Z,Q)=>{if(Z.wasModified!==Q.wasModified)return Z.wasModified?-1:1;if(Z.mentions!==Q.mentions)return Q.mentions-Z.mentions;return Q.lastMentioned-Z.lastMentioned}).slice(0,this.MAX_FILES)}static async readFilesContent($){let Y=[];for(let X of $)try{let Z=await P7(X,"utf-8"),Q=Z.split(`
94
+ `);default:return tY.warn(`⚠️ 未知的 provider: ${$.provider}, 回退到 openai-compatible`),new f2($)}}import{readFile as eY}from"node:fs/promises";class x2{static MAX_FILES=5;static MAX_LINES_PER_FILE=1000;static analyzeFiles($){let Y=new Map;return $.forEach((Z,Q)=>{if(this.extractFilePathsFromContent(Z.content||"").forEach((q)=>{this.updateFileReference(Y,q,Q,!1)}),Z.tool_calls&&Array.isArray(Z.tool_calls))Z.tool_calls.forEach((q)=>{let G=this.extractFilePathsFromToolCall(q),K=q.type==="function"&&"function"in q?q.function?.name:"",W=["Write","Edit"].includes(K||"");G.forEach((O)=>{this.updateFileReference(Y,O,Q,W)})})}),Array.from(Y.values()).sort((Z,Q)=>{if(Z.wasModified!==Q.wasModified)return Z.wasModified?-1:1;if(Z.mentions!==Q.mentions)return Q.mentions-Z.mentions;return Q.lastMentioned-Z.lastMentioned}).slice(0,this.MAX_FILES)}static async readFilesContent($){let Y=[];for(let X of $)try{let Z=await eY(X,"utf-8"),Q=Z.split(`
97
95
  `),J=Q.length,q=Z,G=!1,K=J;if(J>this.MAX_LINES_PER_FILE)q=Q.slice(0,this.MAX_LINES_PER_FILE).join(`
98
96
  `),q+=`
99
97
 
100
- ... (truncated ${J-this.MAX_LINES_PER_FILE} lines)`,G=!0,K=this.MAX_LINES_PER_FILE;Y.push({path:X,content:q,truncated:G,lines:J,includedLines:K})}catch(Z){console.warn(`[FileAnalyzer] 无法读取文件: ${X}`,Z)}return Y}static extractFilePathsFromContent($){let Y=new Set,X=/```(?:\w+)?\s*\n?([\s\S]*?)```/g,Z=Array.from($.matchAll(X));for(let J of Z){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=[],X=[/(?: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 Z of X){let Q=Array.from($.matchAll(Z));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 X=$.function?.name,Z=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(X)){let J=["file_path","path","notebook_path","filePath"];for(let q of J)if(Z[q]&&typeof Z[q]==="string")Y.push(Z[q])}}catch(X){}return Y}static updateFileReference($,Y,X,Z){let Q=$.get(Y);if(Q)Q.mentions++,Q.lastMentioned=X,Q.wasModified=Q.wasModified||Z;else $.set(Y,{path:Y,mentions:1,lastMentioned:X,wasModified:Z})}static isValidFilePath($){if(!$.includes("/"))return!1;let Y=$.split("/"),X=Y[Y.length-1];if(!X.includes("."))return!1;let Z=["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=X.split(".").pop()?.toLowerCase();if(!Q||!Z.includes(Q))return!1;return!0}}import{encodingForModel as H9}from"js-tiktoken";class r1{static encodingCache=new Map;static countTokens($,Y){let X=this.getEncoding(Y),Z=0;for(let Q of $){if(Z+=4,Q.role)Z+=X.encode(Q.role).length;if(Q.content)if(typeof Q.content==="string")Z+=X.encode(Q.content).length;else Z+=X.encode(JSON.stringify(Q.content)).length;if(Q.tool_calls&&Array.isArray(Q.tool_calls))Z+=this.countToolCallTokens(Q.tool_calls,X);if(Q.name)Z+=X.encode(Q.name).length}return Z}static getTokenLimit($){return $}static shouldCompact($,Y,X,Z=0.8){let Q=this.countTokens($,Y),J=Math.floor(X*Z);return Q>=J}static getEncoding($){if(!this.encodingCache.has($))try{let Y=H9($);this.encodingCache.set($,Y)}catch{try{let Y=H9("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 X=0;for(let Z of $){if(X+=4,Z.function?.name)X+=Y.encode(Z.function.name).length;if(Z.function?.arguments){let Q=typeof Z.function.arguments==="string"?Z.function.arguments:JSON.stringify(Z.function.arguments);X+=Y.encode(Q).length}if(Z.id)X+=Y.encode(Z.id).length}return X}static clearCache(){this.encodingCache.clear()}static estimateTokens($){let Y=($.match(/[\u4e00-\u9fa5]/g)||[]).length,X=$.length-Y;return Math.ceil(Y/1.5+X/4)}}class O${static THRESHOLD_PERCENT=0.8;static RETAIN_PERCENT=0.2;static FALLBACK_RETAIN_PERCENT=0.3;static async compact($,Y){let X=Y.actualPreTokens??r1.countTokens($,Y.modelName),Z=Y.actualPreTokens?"actual (from LLM usage)":"estimated";console.log(`[CompactionService] preTokens source: ${Z}`);try{console.log("[CompactionService] 开始压缩,消息数:",$.length),console.log("[CompactionService] 压缩前 tokens:",X);let J=j2.analyzeFiles($).map((N)=>N.path);console.log("[CompactionService] 提取重点文件:",J);let q=await j2.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),O=new Set;for(let N of W)if(N.role==="assistant"&&N.tool_calls)for(let A of N.tool_calls)O.add(A.id);let U=W.filter((N)=>{if(N.role==="tool"&&N.tool_call_id)return O.has(N.tool_call_id);return!0});console.log("[CompactionService] 保留消息数:",K),console.log("[CompactionService] 过滤后保留消息数:",U.length);let H=U$(),_=this.createBoundaryMessage(H,Y.trigger,X),z=U$(),F=this.createSummaryMessage(z,G),L=[F,...U],w=r1.countTokens(L,Y.modelName);return console.log("[CompactionService] 压缩完成!"),console.log("[CompactionService] Token 变化:",X,"→",w,`(-${((1-w/X)*100).toFixed(1)}%)`),{success:!0,summary:G,preTokens:X,postTokens:w,filesIncluded:J,compactedMessages:L,boundaryMessage:_,summaryMessage:F}}catch(Q){return console.error("[CompactionService] 压缩失败,使用降级策略",Q),this.fallbackCompact($,Y,X,Q)}}static async generateSummary($,Y,X){let Z=this.buildCompactionPrompt($,Y);console.log("[CompactionService] 使用压缩模型:",X.modelName);let q=(await E2({apiKey:X.apiKey||process.env.BLADE_API_KEY||"",baseUrl:X.baseURL||process.env.BLADE_BASE_URL||"https://api.openai.com/v1",model:X.modelName,temperature:0.3,maxOutputTokens:8000,timeout:60000,provider:"openai-compatible"}).chat([{role:"user",content:Z}])).content||"",G=q.match(/<summary>([\s\S]*?)<\/summary>/);if(!G)return console.warn("[CompactionService] 总结格式不正确,使用完整响应"),q;return G[1].trim()}static buildCompactionPrompt($,Y){let X=$.map((J,q)=>{let G=J.role||"unknown",K=typeof J.content==="string"?J.content:JSON.stringify(J.content),W=5000,O=K.length>5000?K.substring(0,5000)+"...":K;return`[${q+1}] ${G}: ${O}`}).join(`
98
+ ... (truncated ${J-this.MAX_LINES_PER_FILE} lines)`,G=!0,K=this.MAX_LINES_PER_FILE;Y.push({path:X,content:q,truncated:G,lines:J,includedLines:K})}catch(Z){console.warn(`[FileAnalyzer] 无法读取文件: ${X}`,Z)}return Y}static extractFilePathsFromContent($){let Y=new Set,X=/```(?:\w+)?\s*\n?([\s\S]*?)```/g,Z=Array.from($.matchAll(X));for(let J of Z){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=[],X=[/(?: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 Z of X){let Q=Array.from($.matchAll(Z));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 X=$.function?.name,Z=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(X)){let J=["file_path","path","notebook_path","filePath"];for(let q of J)if(Z[q]&&typeof Z[q]==="string")Y.push(Z[q])}}catch(X){}return Y}static updateFileReference($,Y,X,Z){let Q=$.get(Y);if(Q)Q.mentions++,Q.lastMentioned=X,Q.wasModified=Q.wasModified||Z;else $.set(Y,{path:Y,mentions:1,lastMentioned:X,wasModified:Z})}static isValidFilePath($){if(!$.includes("/"))return!1;let Y=$.split("/"),X=Y[Y.length-1];if(!X.includes("."))return!1;let Z=["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=X.split(".").pop()?.toLowerCase();if(!Q||!Z.includes(Q))return!1;return!0}}import{encodingForModel as v9}from"js-tiktoken";class e1{static encodingCache=new Map;static countTokens($,Y){let X=this.getEncoding(Y),Z=0;for(let Q of $){if(Z+=4,Q.role)Z+=X.encode(Q.role).length;if(Q.content)if(typeof Q.content==="string")Z+=X.encode(Q.content).length;else Z+=X.encode(JSON.stringify(Q.content)).length;if(Q.tool_calls&&Array.isArray(Q.tool_calls))Z+=this.countToolCallTokens(Q.tool_calls,X);if(Q.name)Z+=X.encode(Q.name).length}return Z}static getTokenLimit($){return $}static shouldCompact($,Y,X,Z=0.8){let Q=this.countTokens($,Y),J=Math.floor(X*Z);return Q>=J}static getEncoding($){if(!this.encodingCache.has($))try{let Y=v9($);this.encodingCache.set($,Y)}catch{try{let Y=v9("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 X=0;for(let Z of $){if(X+=4,Z.function?.name)X+=Y.encode(Z.function.name).length;if(Z.function?.arguments){let Q=typeof Z.function.arguments==="string"?Z.function.arguments:JSON.stringify(Z.function.arguments);X+=Y.encode(Q).length}if(Z.id)X+=Y.encode(Z.id).length}return X}static clearCache(){this.encodingCache.clear()}static estimateTokens($){let Y=($.match(/[\u4e00-\u9fa5]/g)||[]).length,X=$.length-Y;return Math.ceil(Y/1.5+X/4)}}class L${static THRESHOLD_PERCENT=0.8;static RETAIN_PERCENT=0.2;static FALLBACK_RETAIN_PERCENT=0.3;static async compact($,Y){let X=Y.actualPreTokens??e1.countTokens($,Y.modelName),Z=Y.actualPreTokens?"actual (from LLM usage)":"estimated";console.log(`[CompactionService] preTokens source: ${Z}`);try{console.log("[CompactionService] 开始压缩,消息数:",$.length),console.log("[CompactionService] 压缩前 tokens:",X);let J=x2.analyzeFiles($).map((N)=>N.path);console.log("[CompactionService] 提取重点文件:",J);let q=await x2.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),O=new Set;for(let N of W)if(N.role==="assistant"&&N.tool_calls)for(let A of N.tool_calls)O.add(A.id);let U=W.filter((N)=>{if(N.role==="tool"&&N.tool_call_id)return O.has(N.tool_call_id);return!0});console.log("[CompactionService] 保留消息数:",K),console.log("[CompactionService] 过滤后保留消息数:",U.length);let H=B$(),_=this.createBoundaryMessage(H,Y.trigger,X),z=B$(),F=this.createSummaryMessage(z,G),B=[F,...U],L=e1.countTokens(B,Y.modelName);return console.log("[CompactionService] 压缩完成!"),console.log("[CompactionService] Token 变化:",X,"→",L,`(-${((1-L/X)*100).toFixed(1)}%)`),{success:!0,summary:G,preTokens:X,postTokens:L,filesIncluded:J,compactedMessages:B,boundaryMessage:_,summaryMessage:F}}catch(Q){return console.error("[CompactionService] 压缩失败,使用降级策略",Q),this.fallbackCompact($,Y,X,Q)}}static async generateSummary($,Y,X){let Z=this.buildCompactionPrompt($,Y);console.log("[CompactionService] 使用压缩模型:",X.modelName);let q=(await h2({apiKey:X.apiKey||process.env.BLADE_API_KEY||"",baseUrl:X.baseURL||process.env.BLADE_BASE_URL||"https://api.openai.com/v1",model:X.modelName,temperature:0.3,maxOutputTokens:8000,timeout:60000,provider:"openai-compatible"}).chat([{role:"user",content:Z}])).content||"",G=q.match(/<summary>([\s\S]*?)<\/summary>/);if(!G)return console.warn("[CompactionService] 总结格式不正确,使用完整响应"),q;return G[1].trim()}static buildCompactionPrompt($,Y){let X=$.map((J,q)=>{let G=J.role||"unknown",K=typeof J.content==="string"?J.content:JSON.stringify(J.content),W=5000,O=K.length>5000?K.substring(0,5000)+"...":K;return`[${q+1}] ${G}: ${O}`}).join(`
101
99
 
102
100
  `),Z=Y.map((J)=>{return`### ${J.path}
103
101
  \`\`\`
@@ -170,14 +168,13 @@ ${Y.length>0?`## Important Files
170
168
 
171
169
  ${Z}`:""}
172
170
 
173
- Please provide your summary following the structure specified above, with both <analysis> and <summary> sections.`}static createBoundaryMessage($,Y,X){return{id:U$(),role:"system",content:"Conversation compacted",metadata:{type:"system",subtype:"compact_boundary",parentId:$,compactMetadata:{trigger:Y,preTokens:X}}}}static createSummaryMessage($,Y){return{id:U$(),role:"user",content:Y,metadata:{parentId:$,isCompactSummary:!0}}}static fallbackCompact($,Y,X,Z){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 L of F.tool_calls)q.add(L.id);let G=J.filter((F)=>{if(F.role==="tool"&&F.tool_call_id)return q.has(F.tool_call_id);return!0}),K=U$(),W=this.createBoundaryMessage(K,Y.trigger,X),O=Z instanceof Error?Z.message:String(Z),U=U$(),H=this.createSummaryMessage(U,`[Automatic compaction failed; using fallback]
171
+ Please provide your summary following the structure specified above, with both <analysis> and <summary> sections.`}static createBoundaryMessage($,Y,X){return{id:B$(),role:"system",content:"Conversation compacted",metadata:{type:"system",subtype:"compact_boundary",parentId:$,compactMetadata:{trigger:Y,preTokens:X}}}}static createSummaryMessage($,Y){return{id:B$(),role:"user",content:Y,metadata:{parentId:$,isCompactSummary:!0}}}static fallbackCompact($,Y,X,Z){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 B of F.tool_calls)q.add(B.id);let G=J.filter((F)=>{if(F.role==="tool"&&F.tool_call_id)return q.has(F.tool_call_id);return!0}),K=B$(),W=this.createBoundaryMessage(K,Y.trigger,X),O=Z instanceof Error?Z.message:String(Z),U=B$(),H=this.createSummaryMessage(U,`[Automatic compaction failed; using fallback]
174
172
 
175
173
  An error occurred during compaction. Retained the latest ${Q} messages (~30%).
176
174
 
177
175
  Error: ${O}
178
176
 
179
- The conversation can continue, but consider retrying compaction later with /compact.`),_=[H,...G],z=r1.countTokens(_,Y.modelName);return{success:!1,summary:H.content,preTokens:X,postTokens:z,filesIncluded:[],compactedMessages:_,boundaryMessage:W,summaryMessage:H,error:O}}}import{promises as u6}from"fs";import*as n$ from"path";async function _9($={}){let{interactive:Y=!0,silent:X=!1,mcpConfig:Z,strictMcpConfig:Q=!1}=$,J=0;if(Z&&Z.length>0){if(!X)console.log(`\uD83D\uDCE6 加载来自 --mcp-config 的配置 (${Z.length} 个源)`);for(let G of Z){let K=await S7(G,{interactive:Y,silent:X,sourceType:"cli-param"});J+=K}if(!X&&J>0)console.log(`✅ 从 --mcp-config 加载了 ${J} 个服务器`)}if(Q){if(!X)console.log("\uD83D\uDD12 严格模式已启用,跳过项目级 .mcp.json");return J}let q=n$.join(process.cwd(),".mcp.json");try{await u6.access(q)}catch{return J}try{let G=await u6.readFile(q,"utf-8"),K=JSON.parse(G);if(!K.mcpServers||typeof K.mcpServers!=="object"){if(!X)console.warn("⚠️ .mcp.json 格式不正确:缺少 mcpServers 字段");return J}let W=F0();if(!W)return console.warn("⚠️ 配置未初始化"),J;let O=W.enabledMcpjsonServers||[],U=W.disabledMcpjsonServers||[],H=0,_=[...O];for(let[z,F]of Object.entries(K.mcpServers)){if(U.includes(z)){if(!X)console.log(`⏭️ 跳过已拒绝的服务器: ${z}`);continue}if(O.includes(z)){if(await e().addMcpServer(z,F),H++,!X)console.log(`✅ 加载服务器: ${z}`);continue}if(!Y){if(!X)console.log(`⏭️ 跳过未确认的服务器: ${z} (非交互模式)`);continue}if(await F9(z,F)){if(await e().addMcpServer(z,F),_.push(z),H++,!X)console.log(`✅ 已启用服务器: ${z}`)}else if(U.push(z),!X)console.log(`❌ 已拒绝服务器: ${z}`)}if(Y)await e().updateConfig({enabledMcpjsonServers:_,disabledMcpjsonServers:U});return J+=H,J}catch(G){if(!X)console.error("❌ 加载 .mcp.json 失败:",G);return J}}async function S7($,Y){let{interactive:X,silent:Z,sourceType:Q}=Y;try{let J;if($.trim().startsWith("{"))try{let G=JSON.parse($);J=G.mcpServers||G}catch(G){if(!Z)console.error(`❌ 解析 JSON 字符串失败: ${$.slice(0,50)}...`);return 0}else{let G=n$.isAbsolute($)?$:n$.join(process.cwd(),$);try{let K=await u6.readFile(G,"utf-8"),W=JSON.parse(K);J=W.mcpServers||W}catch(K){if(!Z)console.error(`❌ 加载配置文件失败: ${G}`),console.error(` 错误: ${K instanceof Error?K.message:String(K)}`);return 0}}if(!J||typeof J!=="object"){if(!Z)console.warn("⚠️ 配置格式不正确:缺少 mcpServers 对象");return 0}let q=0;for(let[G,K]of Object.entries(J))try{if(Q==="cli-param"){if(await e().addMcpServer(G,K),q++,!Z)console.log(` ✅ ${G}`)}else if(X?await F9(G,K):!1){if(await e().addMcpServer(G,K),q++,!Z)console.log(` ✅ ${G}`)}}catch(W){if(!Z)console.error(` ❌ 加载服务器 ${G} 失败:`,W)}return q}catch(J){if(!Z)console.error("❌ 加载配置源失败:",J);return 0}}async function F9($,Y){try{let{default:X}=await import("inquirer");if(console.log(`
180
- \uD83D\uDCE6 发现新的 MCP 服务器: ${$}`),console.log(` 类型: ${Y.type}`),Y.type==="stdio")console.log(` 命令: ${Y.command} ${Y.args?.join(" ")||""}`);else console.log(` URL: ${Y.url}`);let{approve:Z}=await X.prompt([{type:"confirm",name:"approve",message:"是否启用此服务器?",default:!1}]);return Z}catch(X){return console.error(`⚠️ 无法启动交互式确认,默认拒绝服务器: ${$}`),!1}}import{promises as N9}from"fs";import h7 from"path";import{execSync as T7}from"child_process";import*as _$ from"os";import*as H$ from"path";function C7(){let $=process.cwd(),Y=f7($);return{workingDirectory:$,projectRoot:Y,platform:`${_$.platform()} (${_$.arch()})`,nodeVersion:process.version,currentDate:new Date().toISOString().split("T")[0],homeDirectory:_$.homedir()}}function P2(){let $=C7();return`# Environment Context
177
+ The conversation can continue, but consider retrying compaction later with /compact.`),_=[H,...G],z=e1.countTokens(_,Y.modelName);return{success:!1,summary:H.content,preTokens:X,postTokens:z,filesIncluded:[],compactedMessages:_,boundaryMessage:W,summaryMessage:H,error:O}}}import $X from"fs/promises";import YX from"path";var M9=$0("General");async function k9($){for(let Y of $)try{let X;if(Y.trim().startsWith("{")){let J=JSON.parse(Y);if(J.name&&J.type){let{name:q,...G}=J;X={[q]:G}}else X=J}else{let J=YX.resolve(process.cwd(),Y),q=await $X.readFile(J,"utf-8"),G=JSON.parse(q);X=G.mcpServers||G}let Q={...l0(),...X};o().config.actions.updateConfig({mcpServers:Q}),M9.debug(`✅ Loaded MCP config from CLI: ${Object.keys(X).join(", ")}`)}catch(X){M9.warn(`⚠️ Failed to load MCP config "${Y}":`,X)}}import{promises as E9}from"fs";import JX from"path";import{execSync as XX}from"child_process";import*as A$ from"os";import*as w$ from"path";function ZX(){let $=process.cwd(),Y=QX($);return{workingDirectory:$,projectRoot:Y,platform:`${A$.platform()} (${A$.arch()})`,nodeVersion:process.version,currentDate:new Date().toISOString().split("T")[0],homeDirectory:A$.homedir()}}function p2(){let $=ZX();return`# Environment Context
181
178
 
182
179
  ## Working Directory
183
180
  **Current**: \`${$.workingDirectory}\`
@@ -195,7 +192,7 @@ When using file tools (read, write, edit), provide **absolute paths**:
195
192
  - ❌ Incorrect: \`/package.json\` (root directory)
196
193
  - ❌ Incorrect: \`package.json\` (relative path without context)
197
194
 
198
- **Always use** \`${$.workingDirectory}/\` as the base for file paths.`}function f7($){let Y=$;while(Y!==H$.dirname(Y)){if(z9(H$.join(Y,".git")))return Y;if(z9(H$.join(Y,"package.json")))return Y;Y=H$.dirname(Y)}return $}function z9($){try{return T7(`test -e "${$}"`,{stdio:"ignore"}),!0}catch{return!1}}var d6=`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.
195
+ **Always use** \`${$.workingDirectory}/\` as the base for file paths.`}function QX($){let Y=$;while(Y!==w$.dirname(Y)){if(y9(w$.join(Y,".git")))return Y;if(y9(w$.join(Y,"package.json")))return Y;Y=w$.dirname(Y)}return $}function y9($){try{return XX(`test -e "${$}"`,{stdio:"ignore"}),!0}catch{return!1}}var s6=`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.
199
196
 
200
197
  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.
201
198
  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.
@@ -343,7 +340,7 @@ assistant: Clients are marked as failed in the \`connectToServer\` function in s
343
340
  </example>
344
341
 
345
342
  # Language Requirement
346
- IMPORTANT: Always respond in Chinese (Simplified Chinese). Translate all your responses to Chinese before sending them to the user.`;var c6=`You are in **PLAN MODE** - a read-only research phase for designing implementation plans.
343
+ IMPORTANT: Always respond in Chinese (Simplified Chinese). Translate all your responses to Chinese before sending them to the user.`;var t6=`You are in **PLAN MODE** - a read-only research phase for designing implementation plans.
347
344
 
348
345
  ## Core Objective
349
346
 
@@ -383,23 +380,23 @@ Your plan should include:
383
380
  3. **Steps** - Detailed implementation steps with file paths
384
381
  4. **Testing** - How to verify changes
385
382
  5. **Risks** - Potential issues and mitigations
386
- `;function l6($){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>
383
+ `;function e6($){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>
387
384
 
388
- `+$}async function S2($={}){let{projectPath:Y,replaceDefault:X,append:Z,mode:Q,includeEnvironment:J=!0}=$,q=[],G=[];if(J){let U=P2();if(U)q.push(U),G.push({name:"environment",loaded:!0,length:U.length})}let K=Q==="plan",W=K?c6:X??d6;if(q.push(W),G.push({name:K?"plan_mode_prompt":X?"replace_default":"default",loaded:!0,length:W.length}),Y){let U=await x7(Y);if(U)q.push(U),G.push({name:"blade_md",loaded:!0,length:U.length});else G.push({name:"blade_md",loaded:!1})}if(Z?.trim())q.push(Z.trim()),G.push({name:"append",loaded:!0,length:Z.trim().length});return{prompt:q.join(`
385
+ `+$}async function g2($={}){let{projectPath:Y,replaceDefault:X,append:Z,mode:Q,includeEnvironment:J=!0}=$,q=[],G=[];if(J){let U=p2();if(U)q.push(U),G.push({name:"environment",loaded:!0,length:U.length})}let K=Q==="plan",W=K?t6:X??s6;if(q.push(W),G.push({name:K?"plan_mode_prompt":X?"replace_default":"default",loaded:!0,length:W.length}),Y){let U=await qX(Y);if(U)q.push(U),G.push({name:"blade_md",loaded:!0,length:U.length});else G.push({name:"blade_md",loaded:!1})}if(Z?.trim())q.push(Z.trim()),G.push({name:"append",loaded:!0,length:Z.trim().length});return{prompt:q.join(`
389
386
 
390
387
  ---
391
388
 
392
- `),sources:G}}async function x7($){let Y=h7.join($,"BLADE.md");try{return(await N9.readFile(Y,"utf-8")).trim()||null}catch{return null}}import L9 from"fast-glob";import*as F$ from"fs/promises";import*as w9 from"path";import*as T2 from"fs/promises";import*as E0 from"path";var B9=[".git",".claude","node_modules",".env",".env.local",".env.production",".env.development",".env.test"];class a1 extends Error{code;constructor($,Y){super($);this.code=Y;this.name="PathSecurityError"}}class C2{static normalize($,Y){let X=E0.isAbsolute($)?$:E0.resolve(Y,$),Z=E0.normalize(X),Q=E0.normalize(Y);if(!Z.startsWith(Q))throw new a1(`Path outside workspace: ${$} (resolved to ${Z}, workspace: ${Q})`,"PATH_OUTSIDE_WORKSPACE");return Z}static checkRestricted($){let Y=$.split(E0.sep);for(let X of B9)if(Y.includes(X))throw new a1(`Access denied: "${X}" is a protected directory`,"RESTRICTED_PATH")}static checkTraversal($){if($.includes(".."))throw new a1(`Path traversal not allowed: ${$}`,"PATH_TRAVERSAL")}static async validatePath($,Y){this.checkTraversal($);let X=this.normalize($,Y);this.checkRestricted(X);try{await T2.access(X)}catch(Z){throw new a1(`Path not found: ${$}`,"PATH_NOT_FOUND")}return X}static async resolveSymlink($,Y){try{let X=await T2.realpath($),Z=E0.normalize(Y);if(!X.startsWith(Z))throw new a1(`Symlink points outside workspace: ${$} -> ${X}`,"SYMLINK_OUTSIDE_WORKSPACE");return X}catch(X){if(X instanceof a1)throw X;return $}}static getRelativePath($,Y){return E0.relative(Y,$)}static isWithinWorkspace($,Y){let X=E0.normalize($),Z=E0.normalize(Y);return X.startsWith(Z)}static isRestricted($){let Y=$.split(E0.sep);return B9.some((X)=>Y.includes(X))}}class f2{static PATTERN=/@"([^"]+)"|@([^\s]+)/g;static LINE_RANGE_PATTERN=/#L(\d+)(?:-(\d+))?$/;static GLOB_PATTERN=/[*?[\]]/;static extract($){let Y=[],X;this.PATTERN.lastIndex=0;while((X=this.PATTERN.exec($))!==null){let Z=X[0],Q=X[1]||X[2],J=this.parseLineRange(Q);if(J)Q=Q.replace(this.LINE_RANGE_PATTERN,"");let q=this.GLOB_PATTERN.test(Q);Y.push({raw:Z,path:Q.trim(),lineRange:J,startIndex:X.index,endIndex:X.index+Z.length,isGlob:q})}return Y}static parseLineRange($){let Y=$.match(this.LINE_RANGE_PATTERN);if(!Y)return;let X=parseInt(Y[1],10),Z=Y[2]?parseInt(Y[2],10):void 0;return{start:X,end:Z}}static hasAtMentions($){return $.includes("@")}static isValidPath($){if(!$||$.trim().length===0)return!1;let Y=["<",">","|","\x00"];for(let X of Y)if($.includes(X))return!1;return!0}static removeAtMentions($){return this.PATTERN.lastIndex=0,$.replace(this.PATTERN,"")}}var Z1=Y0("Prompts");class i6{fileCache=new Map;options;constructor($){this.options={maxFileSize:1048576,maxLines:2000,maxTokens:32000,...$},Z1.debug("AttachmentCollector initialized",{maxFileSize:this.options.maxFileSize,maxLines:this.options.maxLines})}async collect($){if(!f2.hasAtMentions($))return[];let Y=f2.extract($);if(Y.length===0)return[];Z1.debug(`Found ${Y.length} @ mentions`);let X=Y.map((Q)=>this.processOne(Q));return(await Promise.allSettled(X)).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 Z1.warn(`Failed to process @${q.path}:`,G),{type:"error",path:q.path,content:"",error:G}}})}async processOne($){if($.isGlob)return Z1.debug(`Processing glob pattern: ${$.path}`),await this.processGlob($.path);let Y=await C2.validatePath($.path,this.options.cwd),X=await C2.resolveSymlink(Y,this.options.cwd);if((await F$.stat(X)).isDirectory())return Z1.debug(`Processing directory: ${$.path}`),await this.renderDirectoryTree(X,$.path);return Z1.debug(`Processing file: ${$.path}`,{lineRange:$.lineRange}),await this.readFile(X,$.path,$.lineRange)}async readFile($,Y,X){let Z=this.fileCache.get($);if(Z&&Date.now()-Z.timestamp<60000)return Z1.debug(`Cache hit: ${Y}`),this.formatFileAttachment(Y,Z.content,X);let Q=await F$.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 F$.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,X)}formatFileAttachment($,Y,X){let Z=Y.split(`
389
+ `),sources:G}}async function qX($){let Y=JX.join($,"BLADE.md");try{return(await E9.readFile(Y,"utf-8")).trim()||null}catch{return null}}import P9 from"fast-glob";import*as R$ from"fs/promises";import*as S9 from"path";import*as m2 from"fs/promises";import*as T0 from"path";var j9=[".git",".claude","node_modules",".env",".env.local",".env.production",".env.development",".env.test"];class $$ extends Error{code;constructor($,Y){super($);this.code=Y;this.name="PathSecurityError"}}class u2{static normalize($,Y){let X=T0.isAbsolute($)?$:T0.resolve(Y,$),Z=T0.normalize(X),Q=T0.normalize(Y);if(!Z.startsWith(Q))throw new $$(`Path outside workspace: ${$} (resolved to ${Z}, workspace: ${Q})`,"PATH_OUTSIDE_WORKSPACE");return Z}static checkRestricted($){let Y=$.split(T0.sep);for(let X of j9)if(Y.includes(X))throw new $$(`Access denied: "${X}" is a protected directory`,"RESTRICTED_PATH")}static checkTraversal($){if($.includes(".."))throw new $$(`Path traversal not allowed: ${$}`,"PATH_TRAVERSAL")}static async validatePath($,Y){this.checkTraversal($);let X=this.normalize($,Y);this.checkRestricted(X);try{await m2.access(X)}catch(Z){throw new $$(`Path not found: ${$}`,"PATH_NOT_FOUND")}return X}static async resolveSymlink($,Y){try{let X=await m2.realpath($),Z=T0.normalize(Y);if(!X.startsWith(Z))throw new $$(`Symlink points outside workspace: ${$} -> ${X}`,"SYMLINK_OUTSIDE_WORKSPACE");return X}catch(X){if(X instanceof $$)throw X;return $}}static getRelativePath($,Y){return T0.relative(Y,$)}static isWithinWorkspace($,Y){let X=T0.normalize($),Z=T0.normalize(Y);return X.startsWith(Z)}static isRestricted($){let Y=$.split(T0.sep);return j9.some((X)=>Y.includes(X))}}class d2{static PATTERN=/@"([^"]+)"|@([^\s]+)/g;static LINE_RANGE_PATTERN=/#L(\d+)(?:-(\d+))?$/;static GLOB_PATTERN=/[*?[\]]/;static extract($){let Y=[],X;this.PATTERN.lastIndex=0;while((X=this.PATTERN.exec($))!==null){let Z=X[0],Q=X[1]||X[2],J=this.parseLineRange(Q);if(J)Q=Q.replace(this.LINE_RANGE_PATTERN,"");let q=this.GLOB_PATTERN.test(Q);Y.push({raw:Z,path:Q.trim(),lineRange:J,startIndex:X.index,endIndex:X.index+Z.length,isGlob:q})}return Y}static parseLineRange($){let Y=$.match(this.LINE_RANGE_PATTERN);if(!Y)return;let X=parseInt(Y[1],10),Z=Y[2]?parseInt(Y[2],10):void 0;return{start:X,end:Z}}static hasAtMentions($){return $.includes("@")}static isValidPath($){if(!$||$.trim().length===0)return!1;let Y=["<",">","|","\x00"];for(let X of Y)if($.includes(X))return!1;return!0}static removeAtMentions($){return this.PATTERN.lastIndex=0,$.replace(this.PATTERN,"")}}var G1=$0("Prompts");class $4{fileCache=new Map;options;constructor($){this.options={maxFileSize:1048576,maxLines:2000,maxTokens:32000,...$},G1.debug("AttachmentCollector initialized",{maxFileSize:this.options.maxFileSize,maxLines:this.options.maxLines})}async collect($){if(!d2.hasAtMentions($))return[];let Y=d2.extract($);if(Y.length===0)return[];G1.debug(`Found ${Y.length} @ mentions`);let X=Y.map((Q)=>this.processOne(Q));return(await Promise.allSettled(X)).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 G1.warn(`Failed to process @${q.path}:`,G),{type:"error",path:q.path,content:"",error:G}}})}async processOne($){if($.isGlob)return G1.debug(`Processing glob pattern: ${$.path}`),await this.processGlob($.path);let Y=await u2.validatePath($.path,this.options.cwd),X=await u2.resolveSymlink(Y,this.options.cwd);if((await R$.stat(X)).isDirectory())return G1.debug(`Processing directory: ${$.path}`),await this.renderDirectoryTree(X,$.path);return G1.debug(`Processing file: ${$.path}`,{lineRange:$.lineRange}),await this.readFile(X,$.path,$.lineRange)}async readFile($,Y,X){let Z=this.fileCache.get($);if(Z&&Date.now()-Z.timestamp<60000)return G1.debug(`Cache hit: ${Y}`),this.formatFileAttachment(Y,Z.content,X);let Q=await R$.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 R$.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,X)}formatFileAttachment($,Y,X){let Z=Y.split(`
393
390
  `),Q=Y,J=!1,q=X;if(X){let G=Math.max(0,X.start-1),K=X.end?X.end:X.start;if(G>=Z.length)throw Error(`Line range start (${X.start}) exceeds file length (${Z.length} lines)`);let W=Math.min(K,Z.length);Q=Z.slice(G,W).join(`
394
391
  `);let O=Array.from({length:W-G},(H,_)=>G+_+1);Q=Q.split(`
395
392
  `).map((H,_)=>`${O[_]}: ${H}`).join(`
396
393
  `),q={start:X.start,end:W}}else if(Z.length>this.options.maxLines)Q=Z.slice(0,this.options.maxLines).join(`
397
394
  `),Q+=`
398
395
 
399
- [... truncated ${Z.length-this.options.maxLines} lines ...]`,J=!0;return{type:"file",path:$,content:Q,metadata:{size:Y.length,lines:Z.length,truncated:J,lineRange:q}}}async renderDirectoryTree($,Y){let X=await L9("**/*",{cwd:$,dot:!1,followSymbolicLinks:!1,onlyFiles:!0,unique:!0,ignore:["node_modules/**",".git/**","dist/**","build/**",".next/**",".cache/**","coverage/**"]});if(X.length===0)return{type:"directory",path:Y,content:"(empty directory)"};Z1.debug(`Found ${X.length} files in directory: ${Y}`);let Z=this.buildFileTree(X),Q=this.printTree(Z,Y),J=500,q=X.length>J?`
396
+ [... truncated ${Z.length-this.options.maxLines} lines ...]`,J=!0;return{type:"file",path:$,content:Q,metadata:{size:Y.length,lines:Z.length,truncated:J,lineRange:q}}}async renderDirectoryTree($,Y){let X=await P9("**/*",{cwd:$,dot:!1,followSymbolicLinks:!1,onlyFiles:!0,unique:!0,ignore:["node_modules/**",".git/**","dist/**","build/**",".next/**",".cache/**","coverage/**"]});if(X.length===0)return{type:"directory",path:Y,content:"(empty directory)"};G1.debug(`Found ${X.length} files in directory: ${Y}`);let Z=this.buildFileTree(X),Q=this.printTree(Z,Y),J=500,q=X.length>J?`
400
397
 
401
398
  [... and ${X.length-J} more files]`:"";return{type:"directory",path:Y,content:Q+q,metadata:{lines:X.length,truncated:X.length>J}}}buildFileTree($){let Y=new Map;for(let X of $){let Z=X.split("/"),Q=Y;for(let J=0;J<Z.length;J++){let q=Z[J],G=J===Z.length-1;if(!Q.has(q))Q.set(q,G?null:new Map);if(!G)Q=Q.get(q)}}return Y}printTree($,Y,X="",Z=!0){let Q=[];if(X==="")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,O=W?"└── ":"├── ",U=G instanceof Map;if(Q.push(`${X}${O}${q}${U?"/":""}`),U&&G.size>0){let H=X+(W?" ":"│ ");Q.push(this.printTree(G,"",H,W))}}),Q.filter((q)=>q).join(`
402
- `)}async processGlob($){let Y=await L9($,{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: ${$}`};Z1.debug(`Glob pattern "${$}" matched ${Y.length} files`);let X=30,Z=Y.slice(0,X),J=(await Promise.allSettled(Z.map(async(W)=>{let O=w9.join(this.options.cwd,W);try{let U=await F$.readFile(O,"utf-8"),H=U.split(`
399
+ `)}async processGlob($){let Y=await P9($,{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: ${$}`};G1.debug(`Glob pattern "${$}" matched ${Y.length} files`);let X=30,Z=Y.slice(0,X),J=(await Promise.allSettled(Z.map(async(W)=>{let O=S9.join(this.options.cwd,W);try{let U=await R$.readFile(O,"utf-8"),H=U.split(`
403
400
  `),_=200,z=U,F=!1;if(H.length>200)z=H.slice(0,200).join(`
404
401
  `),z+=`
405
402
 
@@ -408,45 +405,45 @@ ${W.content}`).join(`
408
405
 
409
406
  `),K=Y.length>X?`
410
407
 
411
- [... and ${Y.length-X} more files matched]`:"";return{type:"file",path:$,content:G+K,metadata:{lines:J.reduce((W,O)=>W+O.lines,0),truncated:Y.length>X||J.some((W)=>W.truncated)}}}clearExpiredCache(){let $=Date.now(),Y=0;for(let[X,Z]of this.fileCache.entries())if($-Z.timestamp>60000)this.fileCache.delete(X),Y++;if(Y>0)Z1.debug(`Cleared ${Y} expired cache entries`)}clearCache(){this.fileCache.clear(),Z1.debug("Cleared all cache")}getCacheStats(){return{size:this.fileCache.size,keys:Array.from(this.fileCache.keys())}}}import*as e9 from"os";import*as $5 from"path";import{promises as s6}from"fs";import{extname as g7}from"path";import{z as x2}from"zod";import{isAbsolute as A9}from"path";import{z as L0}from"zod";var G0={filePath:($)=>L0.string().min(1,"File path is required").refine((Y)=>A9(Y),{message:"Path must be absolute"}).describe($?.description||"Absolute file path"),encoding:()=>L0.enum(["utf8","base64","binary"]).default("utf8").describe("File encoding"),timeout:($=1000,Y=300000,X=30000)=>L0.number().int("Must be an integer").min($,`Cannot be less than ${$}ms`).max(Y,`Cannot exceed ${Y}ms`).default(X).describe(`Timeout in milliseconds (default ${X}ms)`),pattern:($)=>L0.string().min(1,"Pattern is required").describe($?.description||"Regex or glob pattern"),glob:($)=>L0.string().min(1,"Glob pattern is required").describe($?.description||'Glob pattern (e.g., "*.js", "**/*.ts")'),lineNumber:($)=>L0.number().int("Line number must be an integer").min($?.min??0,`Line number cannot be less than ${$?.min??0}`).describe($?.description||"Line number"),lineLimit:($)=>L0.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:()=>L0.string().min(1,"Working directory is required").refine(($)=>A9($),{message:"Path must be absolute"}).describe("Absolute working directory"),environment:()=>L0.record(L0.string(),L0.string()).describe("Environment variables (key-value)").optional(),outputMode:($,Y)=>{let X=L0.enum($);return Y?X.default(Y):X},flag:($)=>L0.boolean().default($?.defaultValue??!1).describe($?.description||"Boolean flag"),url:($)=>L0.string().url("Must be a valid URL").describe($?.description||"URL"),port:()=>L0.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:($)=>L0.string().min(1,"Command is required").describe($?.description||"Command to execute"),sessionId:()=>L0.string().min(1,"Session ID is required").uuid("Must be a valid UUID").optional().describe("Session identifier (UUID)"),nonNegativeInt:($)=>L0.number().int("Must be an integer").min(0,"Cannot be negative").describe($?.description||"Non-negative integer"),positiveInt:($)=>L0.number().int("Must be an integer").min(1,"Must be greater than 0").describe($?.description||"Positive integer")};import*as r6 from"diff";function R9($,Y,X=4){if($===Y)return null;let Z=r6.createPatch("file",$,Y,"","",{context:X}),Q=Z.split(`
408
+ [... and ${Y.length-X} more files matched]`:"";return{type:"file",path:$,content:G+K,metadata:{lines:J.reduce((W,O)=>W+O.lines,0),truncated:Y.length>X||J.some((W)=>W.truncated)}}}clearExpiredCache(){let $=Date.now(),Y=0;for(let[X,Z]of this.fileCache.entries())if($-Z.timestamp>60000)this.fileCache.delete(X),Y++;if(Y>0)G1.debug(`Cleared ${Y} expired cache entries`)}clearCache(){this.fileCache.clear(),G1.debug("Cleared all cache")}getCacheStats(){return{size:this.fileCache.size,keys:Array.from(this.fileCache.keys())}}}import*as _5 from"os";import*as F5 from"path";import{promises as J4}from"fs";import{extname as KX}from"path";import{z as l2}from"zod";import{isAbsolute as T9}from"path";import{z as w0}from"zod";var U0={filePath:($)=>w0.string().min(1,"File path is required").refine((Y)=>T9(Y),{message:"Path must be absolute"}).describe($?.description||"Absolute file path"),encoding:()=>w0.enum(["utf8","base64","binary"]).default("utf8").describe("File encoding"),timeout:($=1000,Y=300000,X=30000)=>w0.number().int("Must be an integer").min($,`Cannot be less than ${$}ms`).max(Y,`Cannot exceed ${Y}ms`).default(X).describe(`Timeout in milliseconds (default ${X}ms)`),pattern:($)=>w0.string().min(1,"Pattern is required").describe($?.description||"Regex or glob pattern"),glob:($)=>w0.string().min(1,"Glob pattern is required").describe($?.description||'Glob pattern (e.g., "*.js", "**/*.ts")'),lineNumber:($)=>w0.number().int("Line number must be an integer").min($?.min??0,`Line number cannot be less than ${$?.min??0}`).describe($?.description||"Line number"),lineLimit:($)=>w0.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:()=>w0.string().min(1,"Working directory is required").refine(($)=>T9($),{message:"Path must be absolute"}).describe("Absolute working directory"),environment:()=>w0.record(w0.string(),w0.string()).describe("Environment variables (key-value)").optional(),outputMode:($,Y)=>{let X=w0.enum($);return Y?X.default(Y):X},flag:($)=>w0.boolean().default($?.defaultValue??!1).describe($?.description||"Boolean flag"),url:($)=>w0.string().url("Must be a valid URL").describe($?.description||"URL"),port:()=>w0.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:($)=>w0.string().min(1,"Command is required").describe($?.description||"Command to execute"),sessionId:()=>w0.string().min(1,"Session ID is required").uuid("Must be a valid UUID").optional().describe("Session identifier (UUID)"),nonNegativeInt:($)=>w0.number().int("Must be an integer").min(0,"Cannot be negative").describe($?.description||"Non-negative integer"),positiveInt:($)=>w0.number().int("Must be an integer").min(1,"Must be greater than 0").describe($?.description||"Positive integer")};import*as Y4 from"diff";function C9($,Y,X=4){if($===Y)return null;let Z=Y4.createPatch("file",$,Y,"","",{context:X}),Q=Z.split(`
412
409
  `),J=1;for(let q of Q){let G=q.match(/@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@/);if(G){J=parseInt(G[1],10);break}}return`
413
410
  <<<DIFF>>>
414
411
  ${JSON.stringify({patch:Z,startLine:Math.max(1,J-X),matchLine:J})}
415
412
  <<</DIFF>>>
416
- `}function b9($,Y,X,Z,Q=4){let J=$.indexOf(X);if(J===-1)return null;let G=$.substring(0,J).split(`
413
+ `}function f9($,Y,X,Z,Q=4){let J=$.indexOf(X);if(J===-1)return null;let G=$.substring(0,J).split(`
417
414
  `).length-1,K=$.split(`
418
415
  `),W=Y.split(`
419
416
  `),O=X.split(`
420
417
  `),U=Z.split(`
421
418
  `),H=Math.max(0,G-Q),_=Math.min(K.length,G+O.length+Q),z=Math.min(W.length,G+U.length+Q),F=K.slice(H,_).join(`
422
- `),L=W.slice(H,z).join(`
423
- `),w=r6.createPatch("file",F,L,"","",{context:Q});return`
419
+ `),B=W.slice(H,z).join(`
420
+ `),L=Y4.createPatch("file",F,B,"","",{context:Q});return`
424
421
  <<<DIFF>>>
425
- ${JSON.stringify({patch:w,startLine:H+1,matchLine:G+1})}
422
+ ${JSON.stringify({patch:L,startLine:H+1,matchLine:G+1})}
426
423
  <<</DIFF>>>
427
- `}function V9($){return $.replace(/\\+(n|t|r|'|"|`|\\|\n)/g,(Y,X)=>{switch(X){case"n":return`
424
+ `}function h9($){return $.replace(/\\+(n|t|r|'|"|`|\\|\n)/g,(Y,X)=>{switch(X){case"n":return`
428
425
  `;case"t":return"\t";case"r":return"\r";case"'":return"'";case'"':return'"';case"`":return"`";case"\\":return"\\";case`
429
426
  `:return`
430
- `;default:return Y}})}function D9($,Y){let X=Y.split(`
427
+ `;default:return Y}})}function x9($,Y){let X=Y.split(`
431
428
  `);if(X.length===1)return null;let Q=X[0].match(/^(\s+)/);if(!Q)return null;let J=Q[1],G=X.map((W)=>{if(W.startsWith(J))return W.slice(J.length);return W}).join(`
432
429
  `),K=$.split(`
433
430
  `);for(let W=0;W<=K.length-X.length;W++){let O=K[W].match(/^(\s+)/),U=O?O[1]:"",H=K.slice(W,W+X.length);if(H.map((F)=>{if(F.startsWith(U))return F.slice(U.length);return F}).join(`
434
431
  `)===G)return H.join(`
435
- `)}return null}import{promises as h2}from"node:fs";var o$=Y0("Tool");class C0{static instance=null;accessedFiles=new Map;constructor(){}static getInstance(){if(!C0.instance)C0.instance=new C0;return C0.instance}async recordFileRead($,Y){try{let X=await h2.stat($),Z={filePath:$,accessTime:Date.now(),mtime:X.mtimeMs,sessionId:Y,lastOperation:"read"};this.accessedFiles.set($,Z),o$.debug(`记录文件读取: ${$}`)}catch(X){o$.warn(`记录文件读取失败: ${$}`,X)}}async recordFileEdit($,Y,X="edit"){try{let Z=await h2.stat($),Q={filePath:$,accessTime:Date.now(),mtime:Z.mtimeMs,sessionId:Y,lastOperation:X};this.accessedFiles.set($,Q),o$.debug(`记录文件${X==="edit"?"编辑":"写入"}: ${$}`)}catch(Z){o$.warn(`记录文件${X==="edit"?"编辑":"写入"}失败: ${$}`,Z)}}hasFileBeenRead($,Y){let X=this.accessedFiles.get($);if(!X)return!1;if(Y&&X.sessionId!==Y)return!1;return!0}async checkFileModification($){let Y=this.accessedFiles.get($);if(!Y)return{modified:!1,message:"文件未被跟踪"};try{let X=await h2.stat($);if(Math.abs(X.mtimeMs-Y.mtime)>1)return{modified:!0,message:`文件在访问后被修改(访问时间: ${new Date(Y.accessTime).toISOString()}, 当前修改时间: ${X.mtime.toISOString()})`};return{modified:!1}}catch(X){if(X.code==="ENOENT")return{modified:!0,message:"文件已被删除"};return{modified:!1,message:`无法检查文件状态: ${X.message}`}}}async checkExternalModification($){let Y=this.accessedFiles.get($);if(!Y)return{isExternal:!1,message:"文件未被跟踪"};try{let X=await h2.stat($);if(X.mtimeMs-Y.mtime>2000)return{isExternal:!0,message:`文件在 ${new Date(Y.accessTime).toISOString()} (${Y.lastOperation}) 之后被外部程序修改(当前修改时间: ${X.mtime.toISOString()})`};return{isExternal:!1}}catch(X){if(X.code==="ENOENT")return{isExternal:!0,message:"文件已被删除"};return o$.warn(`检查文件外部修改失败: ${$}`,X),{isExternal:!1,message:`无法检查文件状态: ${X.message}`}}}getFileRecord($){return this.accessedFiles.get($)}clearFileRecord($){this.accessedFiles.delete($)}clearAll(){this.accessedFiles.clear()}clearSession($){for(let[Y,X]of this.accessedFiles.entries())if(X.sessionId===$)this.accessedFiles.delete(Y)}getTrackedFiles(){return Array.from(this.accessedFiles.keys())}getTrackedFileCount(){return this.accessedFiles.size}static resetInstance(){C0.instance=null}}N$();import*as v9 from"node:crypto";import{promises as F1}from"node:fs";import*as s1 from"node:path";class s${sessionId;enableCheckpoints;maxSnapshots;snapshotDir;trackedFileBackups=new Map;snapshots=[];constructor($){this.sessionId=$.sessionId,this.enableCheckpoints=$.enableCheckpoints??!0,this.maxSnapshots=$.maxSnapshots??10;let Y=P1();this.snapshotDir=s1.join(Y,"file-history",this.sessionId)}async initialize(){if(!this.enableCheckpoints)return;try{await F1.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 F1.access($)}catch{return console.warn(`[SnapshotManager] 文件不存在,跳过快照: ${$}`),{backupFileName:"",version:0,backupTime:new Date}}let X=this.trackedFileBackups.get($),Z=X?X.version+1:1,Q=this.generateFileHash($,Z),J=s1.join(this.snapshotDir,`${Q}@v${Z}`);try{let q=await F1.readFile($,{encoding:"utf-8"});await F1.writeFile(J,q,{encoding:"utf-8"});let G={backupFileName:Q,version:Z,backupTime:new Date};return this.trackedFileBackups.set($,G),this.snapshots.push({messageId:Y,backupFileName:Q,timestamp:new Date,filePath:$}),console.log(`[SnapshotManager] 创建快照: ${$} -> ${Q}@v${Z}`),await this.cleanupOldSnapshots($),G}catch(q){throw console.error(`[SnapshotManager] 创建快照失败: ${$}`,q),q}}async restoreSnapshot($,Y){let X=this.snapshots.slice().reverse().find((J)=>J.messageId===Y&&J.filePath===$);if(!X)throw Error(`未找到快照: messageId=${Y}, filePath=${$}`);let Z=this.trackedFileBackups.get($);if(!Z)throw Error(`未找到文件追踪信息: ${$}`);let Q=s1.join(this.snapshotDir,`${X.backupFileName}@v${Z.version}`);try{let J=await F1.readFile(Q,{encoding:"utf-8"});await F1.writeFile($,J,{encoding:"utf-8"}),console.log(`[SnapshotManager] 恢复快照: ${$} <- ${X.backupFileName}@v${Z.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 Z=Y.sort((Q,J)=>Q.timestamp.getTime()-J.timestamp.getTime()).slice(0,Y.length-this.maxSnapshots);for(let Q of Z){let J=this.trackedFileBackups.get(Q.filePath);if(!J)continue;let q=s1.join(this.snapshotDir,`${Q.backupFileName}@v${J.version}`);try{await F1.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 F1.readdir(this.snapshotDir);if(Y.length<=$)return;let X=await Promise.all(Y.map(async(Q)=>{let J=s1.join(this.snapshotDir,Q),q=await F1.stat(J);return{file:Q,mtime:q.mtime.getTime()}}));X.sort((Q,J)=>J.mtime-Q.mtime);let Z=X.slice($);for(let{file:Q}of Z){let J=s1.join(this.snapshotDir,Q);await F1.unlink(J),console.log(`[SnapshotManager] 清理快照: ${J}`)}}catch(Y){console.warn("[SnapshotManager] 清理快照失败:",Y)}}generateFileHash($,Y){let X=v9.createHash("md5");return X.update(`${$}:${Y}`),X.digest("hex").substring(0,16)}getSnapshotDir(){return this.snapshotDir}getSessionId(){return this.sessionId}getTrackedFileCount(){return this.trackedFileBackups.size}getSnapshotCount(){return this.snapshots.length}}var t6=n({name:"Edit",displayName:"File Edit",kind:"write",strict:!0,isConcurrencySafe:!1,schema:x2.object({file_path:G0.filePath({description:"Absolute path of the file to edit"}),old_string:x2.string().min(1,"old_string cannot be empty").describe("String to replace"),new_string:x2.string().describe("Replacement string (can be empty)"),replace_all:x2.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:X,old_string:Z,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 O;try{O=await s6.readFile(X,"utf8")}catch(R){if(R.code==="ENOENT")return{success:!1,llmContent:`File not found: ${X}`,displayContent:`❌ 文件不存在: ${X}`,error:{type:"execution_error",message:"文件不存在"}};throw R}if(W.throwIfAborted(),G){let R=C0.getInstance();if(!R.hasFileBeenRead(X,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 工具读取文件
432
+ `)}return null}import{promises as c2}from"node:fs";var Q2=$0("Tool");class h0{static instance=null;accessedFiles=new Map;constructor(){}static getInstance(){if(!h0.instance)h0.instance=new h0;return h0.instance}async recordFileRead($,Y){try{let X=await c2.stat($),Z={filePath:$,accessTime:Date.now(),mtime:X.mtimeMs,sessionId:Y,lastOperation:"read"};this.accessedFiles.set($,Z),Q2.debug(`记录文件读取: ${$}`)}catch(X){Q2.warn(`记录文件读取失败: ${$}`,X)}}async recordFileEdit($,Y,X="edit"){try{let Z=await c2.stat($),Q={filePath:$,accessTime:Date.now(),mtime:Z.mtimeMs,sessionId:Y,lastOperation:X};this.accessedFiles.set($,Q),Q2.debug(`记录文件${X==="edit"?"编辑":"写入"}: ${$}`)}catch(Z){Q2.warn(`记录文件${X==="edit"?"编辑":"写入"}失败: ${$}`,Z)}}hasFileBeenRead($,Y){let X=this.accessedFiles.get($);if(!X)return!1;if(Y&&X.sessionId!==Y)return!1;return!0}async checkFileModification($){let Y=this.accessedFiles.get($);if(!Y)return{modified:!1,message:"文件未被跟踪"};try{let X=await c2.stat($);if(Math.abs(X.mtimeMs-Y.mtime)>1)return{modified:!0,message:`文件在访问后被修改(访问时间: ${new Date(Y.accessTime).toISOString()}, 当前修改时间: ${X.mtime.toISOString()})`};return{modified:!1}}catch(X){if(X.code==="ENOENT")return{modified:!0,message:"文件已被删除"};return{modified:!1,message:`无法检查文件状态: ${X.message}`}}}async checkExternalModification($){let Y=this.accessedFiles.get($);if(!Y)return{isExternal:!1,message:"文件未被跟踪"};try{let X=await c2.stat($);if(X.mtimeMs-Y.mtime>2000)return{isExternal:!0,message:`文件在 ${new Date(Y.accessTime).toISOString()} (${Y.lastOperation}) 之后被外部程序修改(当前修改时间: ${X.mtime.toISOString()})`};return{isExternal:!1}}catch(X){if(X.code==="ENOENT")return{isExternal:!0,message:"文件已被删除"};return Q2.warn(`检查文件外部修改失败: ${$}`,X),{isExternal:!1,message:`无法检查文件状态: ${X.message}`}}}getFileRecord($){return this.accessedFiles.get($)}clearFileRecord($){this.accessedFiles.delete($)}clearAll(){this.accessedFiles.clear()}clearSession($){for(let[Y,X]of this.accessedFiles.entries())if(X.sessionId===$)this.accessedFiles.delete(Y)}getTrackedFiles(){return Array.from(this.accessedFiles.keys())}getTrackedFileCount(){return this.accessedFiles.size}static resetInstance(){h0.instance=null}}V$();import*as m9 from"node:crypto";import{promises as L1}from"node:fs";import*as Z$ from"node:path";class J2{sessionId;enableCheckpoints;maxSnapshots;snapshotDir;trackedFileBackups=new Map;snapshots=[];constructor($){this.sessionId=$.sessionId,this.enableCheckpoints=$.enableCheckpoints??!0,this.maxSnapshots=$.maxSnapshots??10;let Y=f1();this.snapshotDir=Z$.join(Y,"file-history",this.sessionId)}async initialize(){if(!this.enableCheckpoints)return;try{await L1.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 L1.access($)}catch{return console.warn(`[SnapshotManager] 文件不存在,跳过快照: ${$}`),{backupFileName:"",version:0,backupTime:new Date}}let X=this.trackedFileBackups.get($),Z=X?X.version+1:1,Q=this.generateFileHash($,Z),J=Z$.join(this.snapshotDir,`${Q}@v${Z}`);try{let q=await L1.readFile($,{encoding:"utf-8"});await L1.writeFile(J,q,{encoding:"utf-8"});let G={backupFileName:Q,version:Z,backupTime:new Date};return this.trackedFileBackups.set($,G),this.snapshots.push({messageId:Y,backupFileName:Q,timestamp:new Date,filePath:$}),console.log(`[SnapshotManager] 创建快照: ${$} -> ${Q}@v${Z}`),await this.cleanupOldSnapshots($),G}catch(q){throw console.error(`[SnapshotManager] 创建快照失败: ${$}`,q),q}}async restoreSnapshot($,Y){let X=this.snapshots.slice().reverse().find((J)=>J.messageId===Y&&J.filePath===$);if(!X)throw Error(`未找到快照: messageId=${Y}, filePath=${$}`);let Z=this.trackedFileBackups.get($);if(!Z)throw Error(`未找到文件追踪信息: ${$}`);let Q=Z$.join(this.snapshotDir,`${X.backupFileName}@v${Z.version}`);try{let J=await L1.readFile(Q,{encoding:"utf-8"});await L1.writeFile($,J,{encoding:"utf-8"}),console.log(`[SnapshotManager] 恢复快照: ${$} <- ${X.backupFileName}@v${Z.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 Z=Y.sort((Q,J)=>Q.timestamp.getTime()-J.timestamp.getTime()).slice(0,Y.length-this.maxSnapshots);for(let Q of Z){let J=this.trackedFileBackups.get(Q.filePath);if(!J)continue;let q=Z$.join(this.snapshotDir,`${Q.backupFileName}@v${J.version}`);try{await L1.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 L1.readdir(this.snapshotDir);if(Y.length<=$)return;let X=await Promise.all(Y.map(async(Q)=>{let J=Z$.join(this.snapshotDir,Q),q=await L1.stat(J);return{file:Q,mtime:q.mtime.getTime()}}));X.sort((Q,J)=>J.mtime-Q.mtime);let Z=X.slice($);for(let{file:Q}of Z){let J=Z$.join(this.snapshotDir,Q);await L1.unlink(J),console.log(`[SnapshotManager] 清理快照: ${J}`)}}catch(Y){console.warn("[SnapshotManager] 清理快照失败:",Y)}}generateFileHash($,Y){let X=m9.createHash("md5");return X.update(`${$}:${Y}`),X.digest("hex").substring(0,16)}getSnapshotDir(){return this.snapshotDir}getSessionId(){return this.sessionId}getTrackedFileCount(){return this.trackedFileBackups.size}getSnapshotCount(){return this.snapshots.length}}var q4=s({name:"Edit",displayName:"File Edit",kind:"write",strict:!0,isConcurrencySafe:!1,schema:l2.object({file_path:U0.filePath({description:"Absolute path of the file to edit"}),old_string:l2.string().min(1,"old_string cannot be empty").describe("String to replace"),new_string:l2.string().describe("Replacement string (can be empty)"),replace_all:l2.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:X,old_string:Z,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 O;try{O=await J4.readFile(X,"utf8")}catch(I){if(I.code==="ENOENT")return{success:!1,llmContent:`File not found: ${X}`,displayContent:`❌ 文件不存在: ${X}`,error:{type:"execution_error",message:"文件不存在"}};throw I}if(W.throwIfAborted(),G){let I=h0.getInstance();if(!I.hasFileBeenRead(X,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 工具读取文件
436
433
 
437
- 请先用 Read 工具查看文件内容,再进行编辑。`,error:{type:"validation_error",message:"File not read before edit"}};let B=await R.checkExternalModification(X);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 editing.
434
+ 请先用 Read 工具查看文件内容,再进行编辑。`,error:{type:"validation_error",message:"File not read before edit"}};let w=await I.checkExternalModification(X);if(w.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.
438
435
 
439
- Details: ${B.message}`,displayContent:`❌ 编辑失败:文件已被外部程序修改
436
+ Details: ${w.message}`,displayContent:`❌ 编辑失败:文件已被外部程序修改
440
437
 
441
- ${B.message}
438
+ ${w.message}
442
439
 
443
- \uD83D\uDCA1 请重新使用 Read 工具读取最新内容后再编辑`,error:{type:"validation_error",message:"File modified externally",details:{externalModification:B.message}}}}if(G&&K)try{let R=new s$({sessionId:G});await R.initialize(),await R.createSnapshot(X,K)}catch(R){console.warn("[EditTool] 创建快照失败:",R)}if(Z===Q)return{success:!1,llmContent:"New string is identical; no replacement needed",displayContent:"⚠️ 新字符串与旧字符串相同,无需进行替换",error:{type:"validation_error",message:"新旧字符串相同"}};let U=m7(O,Z);if(!U.matched){let R=c7(O,Z,X);return{success:!1,llmContent:R.llmContent,displayContent:R.displayContent,error:{type:"execution_error",message:"未找到匹配内容",details:R.metadata}}}let H=U.matched;if(U.strategy!=="exact")console.log(`[SmartEdit] 使用策略: ${U.strategy}`);let _=u7(O,H);if(_.length>1&&!J){let R=O.split(`
444
- `),B=0,D=[];for(let E=0;E<R.length;E++){let M=R[E],i=B,S=B+M.length;for(let O1 of _)if(O1>=i&&O1<S){let Q0=Math.max(0,E-1),_0=Math.min(R.length-1,E+1),q$=R.slice(Q0,_0+1).map((f$)=>f$.trim()).join(" ").slice(0,80);D.push({line:E+1,column:O1-i+1,context:q$})}B=S+1}let C=[`⚠️ EDIT PAUSED: old_string matches ${_.length} locations (must be unique).`,"","**Matches found at:**",...D.map((E,M)=>` ${M+1}. Line ${E.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 ${_.length} occurrences`,"","\uD83E\uDD16 **Auto-retry expected** - This usually resolves in 1-2 attempts."].join(`
445
- `),p=["⚠️ 编辑暂停:需要更精确的定位","",`在文件中找到 ${_.length} 处相似代码:`,...D.map((E,M)=>` • 第 ${E.line} 行 (匹配 ${M+1}/${_.length})`),"","AI 正在自动调整,添加更多上下文以精确定位...","通常需要 1-2 次尝试即可成功","","\uD83D\uDCA1 如果多次失败,可能需要:"," • 包含函数/类名等独特标识符"," • 添加目标代码前后 3-5 行完整上下文",` • 或使用 replace_all=true 同时替换所有 ${_.length} 处匹配`].join(`
446
- `);return{success:!1,llmContent:C,displayContent:p,error:{type:"validation_error",message:"old_string is not unique",details:{matches:D.map((E)=>({line:E.line,column:E.column})),count:_.length}}}}else q?.(`找到 ${_.length} 个匹配项,开始替换...`);let z,F;if(J)z=O.split(H).join(Q),F=_.length;else{let R=O.indexOf(H);z=O.substring(0,R)+Q+O.substring(R+H.length),F=1}if(W.throwIfAborted(),await s6.writeFile(X,z,"utf8"),G)await C0.getInstance().recordFileEdit(X,G,"edit");let L=await s6.stat(X),w=b9(O,z,H,Q,4),N=X.split("/").pop()||X,A=F===1?`替换 1 处匹配到 ${N}`:`替换 ${F} 处匹配到 ${N}`,b={file_path:X,matches_found:_.length,replacements_made:F,replace_all:J,old_string_length:Z.length,new_string_length:Q.length,original_size:O.length,new_size:z.length,size_diff:z.length-O.length,last_modified:L.mtime.toISOString(),snapshot_created:!!(G&&K),session_id:G,message_id:K,diff_snippet:w,summary:A},y=d7(b,w);return{success:!0,llmContent:{file_path:X,replacements:F,total_matches:_.length},displayContent:y,metadata:b}}catch(O){if(O.name==="AbortError")return{success:!1,llmContent:"File edit aborted",displayContent:"⚠️ 文件编辑被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`File edit failed: ${O.message}`,displayContent:`❌ 编辑文件失败: ${O.message}`,error:{type:"execution_error",message:O.message,details:O}}}},version:"2.0.0",category:"文件操作",tags:["file","edit","replace","modify"],extractSignatureContent:($)=>$.file_path,abstractPermissionRule:($)=>{let Y=g7($.file_path);return Y?`**/*${Y}`:"**/*"}});function M9($){return $.replaceAll("‘","'").replaceAll("’","'").replaceAll("“",'"').replaceAll("”",'"')}function m7($,Y){if($.includes(Y))return{matched:Y,strategy:"exact"};let X=M9(Y),Q=M9($).indexOf(X);if(Q!==-1)return{matched:$.substring(Q,Q+Y.length),strategy:"normalize_quotes"};let J=V9(Y);if(J!==Y&&$.includes(J))return{matched:J,strategy:"unescape"};let q=D9($,Y);if(q)return{matched:q,strategy:"flexible"};return{matched:null,strategy:"failed"}}function u7($,Y){if(Y.length===0)return[];let X=[],Z=$.indexOf(Y);while(Z!==-1)X.push(Z),Z=$.indexOf(Y,Z+Y.length);return X}function d7($,Y){let{file_path:X,matches_found:Z,replacements_made:Q,replace_all:J,size_diff:q}=$,G=`✅ 成功编辑文件: ${X}`;if(G+=`
440
+ \uD83D\uDCA1 请重新使用 Read 工具读取最新内容后再编辑`,error:{type:"validation_error",message:"File modified externally",details:{externalModification:w.message}}}}if(G&&K)try{let I=new J2({sessionId:G});await I.initialize(),await I.createSnapshot(X,K)}catch(I){console.warn("[EditTool] 创建快照失败:",I)}if(Z===Q)return{success:!1,llmContent:"New string is identical; no replacement needed",displayContent:"⚠️ 新字符串与旧字符串相同,无需进行替换",error:{type:"validation_error",message:"新旧字符串相同"}};let U=WX(O,Z);if(!U.matched){let I=HX(O,Z,X);return{success:!1,llmContent:I.llmContent,displayContent:I.displayContent,error:{type:"execution_error",message:"未找到匹配内容",details:I.metadata}}}let H=U.matched;if(U.strategy!=="exact")console.log(`[SmartEdit] 使用策略: ${U.strategy}`);let _=UX(O,H);if(_.length>1&&!J){let I=O.split(`
441
+ `),w=0,b=[];for(let h=0;h<I.length;h++){let v=I[h],m=w,z1=w+v.length;for(let J0 of _)if(J0>=m&&J0<z1){let G0=Math.max(0,h-1),u=Math.min(I.length-1,h+1),Y0=I.slice(G0,u+1).map((z0)=>z0.trim()).join(" ").slice(0,80);b.push({line:h+1,column:J0-m+1,context:Y0})}w=z1+1}let E=[`⚠️ EDIT PAUSED: old_string matches ${_.length} locations (must be unique).`,"","**Matches found at:**",...b.map((h,v)=>` ${v+1}. Line ${h.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 ${_.length} occurrences`,"","\uD83E\uDD16 **Auto-retry expected** - This usually resolves in 1-2 attempts."].join(`
442
+ `),f=["⚠️ 编辑暂停:需要更精确的定位","",`在文件中找到 ${_.length} 处相似代码:`,...b.map((h,v)=>` • 第 ${h.line} 行 (匹配 ${v+1}/${_.length})`),"","AI 正在自动调整,添加更多上下文以精确定位...","通常需要 1-2 次尝试即可成功","","\uD83D\uDCA1 如果多次失败,可能需要:"," • 包含函数/类名等独特标识符"," • 添加目标代码前后 3-5 行完整上下文",` • 或使用 replace_all=true 同时替换所有 ${_.length} 处匹配`].join(`
443
+ `);return{success:!1,llmContent:E,displayContent:f,error:{type:"validation_error",message:"old_string is not unique",details:{matches:b.map((h)=>({line:h.line,column:h.column})),count:_.length}}}}else q?.(`找到 ${_.length} 个匹配项,开始替换...`);let z,F;if(J)z=O.split(H).join(Q),F=_.length;else{let I=O.indexOf(H);z=O.substring(0,I)+Q+O.substring(I+H.length),F=1}if(W.throwIfAborted(),await J4.writeFile(X,z,"utf8"),G)await h0.getInstance().recordFileEdit(X,G,"edit");let B=await J4.stat(X),L=f9(O,z,H,Q,4),N=X.split("/").pop()||X,A=F===1?`替换 1 处匹配到 ${N}`:`替换 ${F} 处匹配到 ${N}`,R={file_path:X,matches_found:_.length,replacements_made:F,replace_all:J,old_string_length:Z.length,new_string_length:Q.length,original_size:O.length,new_size:z.length,size_diff:z.length-O.length,last_modified:B.mtime.toISOString(),snapshot_created:!!(G&&K),session_id:G,message_id:K,diff_snippet:L,summary:A},k=OX(R,L);return{success:!0,llmContent:{file_path:X,replacements:F,total_matches:_.length},displayContent:k,metadata:R}}catch(O){if(O.name==="AbortError")return{success:!1,llmContent:"File edit aborted",displayContent:"⚠️ 文件编辑被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`File edit failed: ${O.message}`,displayContent:`❌ 编辑文件失败: ${O.message}`,error:{type:"execution_error",message:O.message,details:O}}}},version:"2.0.0",category:"文件操作",tags:["file","edit","replace","modify"],extractSignatureContent:($)=>$.file_path,abstractPermissionRule:($)=>{let Y=KX($.file_path);return Y?`**/*${Y}`:"**/*"}});function u9($){return $.replaceAll("‘","'").replaceAll("’","'").replaceAll("“",'"').replaceAll("”",'"')}function WX($,Y){if($.includes(Y))return{matched:Y,strategy:"exact"};let X=u9(Y),Q=u9($).indexOf(X);if(Q!==-1)return{matched:$.substring(Q,Q+Y.length),strategy:"normalize_quotes"};let J=h9(Y);if(J!==Y&&$.includes(J))return{matched:J,strategy:"unescape"};let q=x9($,Y);if(q)return{matched:q,strategy:"flexible"};return{matched:null,strategy:"failed"}}function UX($,Y){if(Y.length===0)return[];let X=[],Z=$.indexOf(Y);while(Z!==-1)X.push(Z),Z=$.indexOf(Y,Z+Y.length);return X}function OX($,Y){let{file_path:X,matches_found:Z,replacements_made:Q,replace_all:J,size_diff:q}=$,G=`✅ 成功编辑文件: ${X}`;if(G+=`
447
444
  \uD83D\uDCDD 替换了 ${Q} 个匹配项`,!J&&Z>1)G+=` (共找到 ${Z} 个匹配项)`;if(q!==0){let K=q>0?`增加${q}`:`减少${Math.abs(q)}`;G+=`
448
- \uD83D\uDCCA 文件大小${K}个字符`}if(Y)G+=Y;return G}function c7($,Y,X){let Z=$.split(`
449
- `),Q=Z.length,J=l7($,Y,3),q=0,G=Math.min(20,Q);if(J.length>0){let _=J[0];q=Math.max(0,_.lineNumber-10),G=Math.min(Q,_.lineNumber+10)}let W=Z.slice(q,G).map((_,z)=>{return` ${(q+z+1).toString().padStart(4)}: ${_}`}).join(`
445
+ \uD83D\uDCCA 文件大小${K}个字符`}if(Y)G+=Y;return G}function HX($,Y,X){let Z=$.split(`
446
+ `),Q=Z.length,J=_X($,Y,3),q=0,G=Math.min(20,Q);if(J.length>0){let _=J[0];q=Math.max(0,_.lineNumber-10),G=Math.min(Q,_.lineNumber+10)}let W=Z.slice(q,G).map((_,z)=>{return` ${(q+z+1).toString().padStart(4)}: ${_}`}).join(`
450
447
  `),O=`String not found in file.
451
448
 
452
449
  File: ${X}
@@ -492,27 +489,27 @@ ${W}
492
489
  \uD83D\uDD27 建议:
493
490
  `,H+=` 1. 使用 Read 工具重新读取文件
494
491
  `,H+=` 2. 检查空格、换行符、引号是否完全匹配
495
- `,H+=" 3. 提供更多上下文代码确保唯一性",{llmContent:O,displayContent:H,metadata:{searchStringLength:Y.length,fuzzyMatches:J.map((_)=>({line:_.lineNumber,similarity:_.similarity,preview:_.text.substring(0,100)})),excerptRange:[q+1,G],totalLines:Q}}}function l7($,Y,X=3){let Z=$.split(`
492
+ `,H+=" 3. 提供更多上下文代码确保唯一性",{llmContent:O,displayContent:H,metadata:{searchStringLength:Y.length,fuzzyMatches:J.map((_)=>({line:_.lineNumber,similarity:_.similarity,preview:_.text.substring(0,100)})),excerptRange:[q+1,G],totalLines:Q}}}function _X($,Y,X=3){let Z=$.split(`
496
493
  `),Q=Y.split(`
497
- `);if(Q.length===1)return Z.map((K,W)=>({text:K,lineNumber:W+1,similarity:y9(Y.trim(),K.trim())})).filter((K)=>K.similarity>0.5).sort((K,W)=>W.similarity-K.similarity).slice(0,X);let J=Q.length,q=[];for(let G=0;G<=Z.length-J;G++){let K=Z.slice(G,G+J).join(`
498
- `),W=y9(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,X)}function y9($,Y){let X=(H)=>H.trim().replace(/\s+/g," ").replace(/[\u201c\u201d"]/g,'"').replace(/[\u2018\u2019']/g,"'"),Z=X($),Q=X(Y);if(Z===Q)return 1;let J=Z.length,q=Q.length;if(J===0)return q===0?1:0;if(q===0)return 0;let G=200,K=Z.substring(0,G),W=Q.substring(0,G),O=i7(K,W),U=Math.max(K.length,W.length);return 1-O/U}function i7($,Y){let X=$.length,Z=Y.length,Q=Array(X+1).fill(null).map(()=>Array(Z+1).fill(0));for(let J=0;J<=X;J++)Q[J][0]=J;for(let J=0;J<=Z;J++)Q[0][J]=J;for(let J=1;J<=X;J++)for(let q=1;q<=Z;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[X][Z]}import{promises as p2}from"fs";import{extname as E9}from"path";import{z as r7}from"zod";var e6=n({name:"Read",displayName:"File Read",kind:"readonly",schema:r7.object({file_path:G0.filePath({description:"File path to read (must be absolute)"}),offset:G0.lineNumber({description:"Starting line number (0-based, text files only)"}).optional(),limit:G0.lineLimit({description:"Number of lines to read (text files only)"}).optional(),encoding:G0.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:X,offset:Z,limit:Q,encoding:J="utf8"}=$,{updateOutput:q,sessionId:G}=Y,K=Y.signal??new AbortController().signal;try{q?.("Starting file read...");try{await p2.access(X)}catch(A){return{success:!1,llmContent:`File not found: ${X}`,displayContent:`❌ 文件不存在: ${X}`,error:{type:"execution_error",message:`File not found: ${X}`}}}if(K.throwIfAborted(),G)await C0.getInstance().recordFileRead(X,G);let W=await p2.stat(X);if(W.isDirectory())return{success:!1,llmContent:`Cannot read a directory: ${X}`,displayContent:`❌ 无法读取目录: ${X}`,error:{type:"execution_error",message:"Target is a directory, not a file"}};let O=E9(X).toLowerCase(),U=a7(O),H=n7(O),_,z={file_path:X,file_size:W.size,file_type:O,last_modified:W.mtime.toISOString(),encoding:J};if(H&&J==="utf8")q?.("检测到二进制文件,使用 base64 编码..."),_=await p2.readFile(X,"base64"),z.encoding="base64",z.is_binary=!0;else{let A=await p2.readFile(X);if(J==="base64")_=A.toString("base64");else if(J==="binary")_=A.toString("binary");else _=A.toString("utf8")}if(K.throwIfAborted(),(Z!==void 0||Q!==void 0)&&J==="utf8"&&U){let A=_.split(`
499
- `),b=Z||0,y=Q!==void 0?b+Q:A.length,R=A.slice(b,y);_=R.map((B,D)=>{let C=b+D+1,p=B.length>2000?`${B.substring(0,2000)}...`:B;return`${C.toString().padStart(6)}→${p}`}).join(`
500
- `),z.lines_read=R.length,z.total_lines=A.length,z.start_line=b+1,z.end_line=Math.min(y,A.length)}let F=X.split("/").pop()||X,L=z.lines_read||z.total_lines,w=L?`读取 ${L} 行从 ${F}`:`读取 ${F}`;z.summary=w;let N=o7(X,z);return{success:!0,llmContent:_,displayContent:N,metadata:z}}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=E9($.file_path);return Y?`**/*${Y}`:"**/*"}});function a7($){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 n7($){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 o7($,Y){let X=`✅ 成功读取文件: ${$}`;if(Y.file_size!==void 0)X+=` (${s7(Y.file_size)})`;if(Y.lines_read!==void 0)X+=`
494
+ `);if(Q.length===1)return Z.map((K,W)=>({text:K,lineNumber:W+1,similarity:d9(Y.trim(),K.trim())})).filter((K)=>K.similarity>0.5).sort((K,W)=>W.similarity-K.similarity).slice(0,X);let J=Q.length,q=[];for(let G=0;G<=Z.length-J;G++){let K=Z.slice(G,G+J).join(`
495
+ `),W=d9(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,X)}function d9($,Y){let X=(H)=>H.trim().replace(/\s+/g," ").replace(/[\u201c\u201d"]/g,'"').replace(/[\u2018\u2019']/g,"'"),Z=X($),Q=X(Y);if(Z===Q)return 1;let J=Z.length,q=Q.length;if(J===0)return q===0?1:0;if(q===0)return 0;let G=200,K=Z.substring(0,G),W=Q.substring(0,G),O=FX(K,W),U=Math.max(K.length,W.length);return 1-O/U}function FX($,Y){let X=$.length,Z=Y.length,Q=Array(X+1).fill(null).map(()=>Array(Z+1).fill(0));for(let J=0;J<=X;J++)Q[J][0]=J;for(let J=0;J<=Z;J++)Q[0][J]=J;for(let J=1;J<=X;J++)for(let q=1;q<=Z;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[X][Z]}import{promises as i2}from"fs";import{extname as c9}from"path";import{z as zX}from"zod";var G4=s({name:"Read",displayName:"File Read",kind:"readonly",schema:zX.object({file_path:U0.filePath({description:"File path to read (must be absolute)"}),offset:U0.lineNumber({description:"Starting line number (0-based, text files only)"}).optional(),limit:U0.lineLimit({description:"Number of lines to read (text files only)"}).optional(),encoding:U0.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:X,offset:Z,limit:Q,encoding:J="utf8"}=$,{updateOutput:q,sessionId:G}=Y,K=Y.signal??new AbortController().signal;try{q?.("Starting file read...");try{await i2.access(X)}catch(A){return{success:!1,llmContent:`File not found: ${X}`,displayContent:`❌ 文件不存在: ${X}`,error:{type:"execution_error",message:`File not found: ${X}`}}}if(K.throwIfAborted(),G)await h0.getInstance().recordFileRead(X,G);let W=await i2.stat(X);if(W.isDirectory())return{success:!1,llmContent:`Cannot read a directory: ${X}`,displayContent:`❌ 无法读取目录: ${X}`,error:{type:"execution_error",message:"Target is a directory, not a file"}};let O=c9(X).toLowerCase(),U=NX(O),H=BX(O),_,z={file_path:X,file_size:W.size,file_type:O,last_modified:W.mtime.toISOString(),encoding:J};if(H&&J==="utf8")q?.("检测到二进制文件,使用 base64 编码..."),_=await i2.readFile(X,"base64"),z.encoding="base64",z.is_binary=!0;else{let A=await i2.readFile(X);if(J==="base64")_=A.toString("base64");else if(J==="binary")_=A.toString("binary");else _=A.toString("utf8")}if(K.throwIfAborted(),(Z!==void 0||Q!==void 0)&&J==="utf8"&&U){let A=_.split(`
496
+ `),R=Z||0,k=Q!==void 0?R+Q:A.length,I=A.slice(R,k);_=I.map((w,b)=>{let E=R+b+1,f=w.length>2000?`${w.substring(0,2000)}...`:w;return`${E.toString().padStart(6)}→${f}`}).join(`
497
+ `),z.lines_read=I.length,z.total_lines=A.length,z.start_line=R+1,z.end_line=Math.min(k,A.length)}let F=X.split("/").pop()||X,B=z.lines_read||z.total_lines,L=B?`读取 ${B} 行从 ${F}`:`读取 ${F}`;z.summary=L;let N=LX(X,z);return{success:!0,llmContent:_,displayContent:N,metadata:z}}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=c9($.file_path);return Y?`**/*${Y}`:"**/*"}});function NX($){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 BX($){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 LX($,Y){let X=`✅ 成功读取文件: ${$}`;if(Y.file_size!==void 0)X+=` (${wX(Y.file_size)})`;if(Y.lines_read!==void 0)X+=`
501
498
  \uD83D\uDCC4 读取了 ${Y.lines_read} 行 (第${Y.start_line}-${Y.end_line}行,共${Y.total_lines}行)`;if(Y.is_binary)X+=`
502
- \uD83D\uDD10 文件以 base64 编码显示`;return X}function s7($){let Y=["B","KB","MB","GB"],X=$,Z=0;while(X>=1024&&Z<Y.length-1)X/=1024,Z++;return`${X.toFixed(1)}${Y[Z]}`}import{promises as t$}from"fs";import{dirname as t7,extname as j9}from"path";import{z as $4}from"zod";var Y4=n({name:"Write",displayName:"File Write",kind:"write",strict:!0,isConcurrencySafe:!1,schema:$4.object({file_path:G0.filePath({description:"Absolute file path to write"}),content:$4.string().describe("Content to write"),encoding:G0.encoding(),create_directories:$4.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:X,content:Z,encoding:Q,create_directories:J}=$,{updateOutput:q,sessionId:G,messageId:K}=Y,W=Y.signal??new AbortController().signal;try{if(q?.("开始写入文件..."),J){let b=t7(X);try{await t$.mkdir(b,{recursive:!0})}catch(y){if(y.code!=="EEXIST")throw y}}W.throwIfAborted();let O=!1,U=null;try{if(await t$.access(X),O=!0,Q==="utf8")try{U=await t$.readFile(X,"utf8")}catch(b){console.warn("[WriteTool] 读取旧文件内容失败:",b)}}catch{}if(O&&G){let b=C0.getInstance();if(!b.hasFileBeenRead(X,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 工具读取文件
499
+ \uD83D\uDD10 文件以 base64 编码显示`;return X}function wX($){let Y=["B","KB","MB","GB"],X=$,Z=0;while(X>=1024&&Z<Y.length-1)X/=1024,Z++;return`${X.toFixed(1)}${Y[Z]}`}import{promises as q2}from"fs";import{dirname as AX,extname as l9}from"path";import{z as K4}from"zod";var W4=s({name:"Write",displayName:"File Write",kind:"write",strict:!0,isConcurrencySafe:!1,schema:K4.object({file_path:U0.filePath({description:"Absolute file path to write"}),content:K4.string().describe("Content to write"),encoding:U0.encoding(),create_directories:K4.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:X,content:Z,encoding:Q,create_directories:J}=$,{updateOutput:q,sessionId:G,messageId:K}=Y,W=Y.signal??new AbortController().signal;try{if(q?.("开始写入文件..."),J){let R=AX(X);try{await q2.mkdir(R,{recursive:!0})}catch(k){if(k.code!=="EEXIST")throw k}}W.throwIfAborted();let O=!1,U=null;try{if(await q2.access(X),O=!0,Q==="utf8")try{U=await q2.readFile(X,"utf8")}catch(R){console.warn("[WriteTool] 读取旧文件内容失败:",R)}}catch{}if(O&&G){let R=h0.getInstance();if(!R.hasFileBeenRead(X,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 工具读取文件
503
500
 
504
- 文件 ${X} 已存在,请先用 Read 工具查看其内容。`,error:{type:"validation_error",message:"File not read before write"}};let y=await b.checkExternalModification(X);if(y.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.
501
+ 文件 ${X} 已存在,请先用 Read 工具查看其内容。`,error:{type:"validation_error",message:"File not read before write"}};let k=await R.checkExternalModification(X);if(k.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.
505
502
 
506
- Details: ${y.message}`,displayContent:`❌ 写入失败:文件已被外部程序修改
503
+ Details: ${k.message}`,displayContent:`❌ 写入失败:文件已被外部程序修改
507
504
 
508
- ${y.message}
505
+ ${k.message}
509
506
 
510
- \uD83D\uDCA1 请重新使用 Read 工具读取最新内容后再写入`,error:{type:"validation_error",message:"File modified externally",details:{externalModification:y.message}}}}let H=!1;if(O&&G&&K)try{let b=new s$({sessionId:G});await b.initialize(),await b.createSnapshot(X,K),H=!0}catch(b){console.warn("[WriteTool] 创建快照失败:",b)}W.throwIfAborted();let _;if(Q==="base64")_=Buffer.from(Z,"base64");else if(Q==="binary")_=Buffer.from(Z,"binary");else _=Buffer.from(Z,"utf8");if(await t$.writeFile(X,_),G)await C0.getInstance().recordFileEdit(X,G,"write");W.throwIfAborted();let z=await t$.stat(X),F=Q==="utf8"?Z.split(`
511
- `).length:0,L=X.split("/").pop()||X,w=null;if(U&&Q==="utf8"&&U!==Z){if(U.length<1048576&&Z.length<1048576)w=R9(U,Z,4)}let N={file_path:X,content_size:Z.length,file_size:z.size,encoding:Q,created_directories:J,snapshot_created:H,session_id:G,message_id:K,last_modified:z.mtime.toISOString(),has_diff:!!w,summary:Q==="utf8"?`写入 ${F} 行到 ${L}`:`写入 ${P9(z.size)} 到 ${L}`},A=e7(X,N,Z,w);return{success:!0,llmContent:{file_path:X,size:z.size,modified:z.mtime.toISOString()},displayContent:A,metadata:N}}catch(O){if(O.name==="AbortError")return{success:!1,llmContent:"File write aborted",displayContent:"⚠️ 文件写入被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`File write failed: ${O.message}`,displayContent:`❌ 写入文件失败: ${O.message}`,error:{type:"execution_error",message:O.message,details:O}}}},version:"2.0.0",category:"文件操作",tags:["file","io","write","create"],extractSignatureContent:($)=>$.file_path,abstractPermissionRule:($)=>{let Y=j9($.file_path);return Y?`**/*${Y}`:"**/*"}});function e7($,Y,X,Z){let Q=`✅ 成功写入文件: ${$}`;if(Y.file_size!==void 0)Q+=` (${P9(Y.file_size)})`;if(Y.snapshot_created)Q+=`
507
+ \uD83D\uDCA1 请重新使用 Read 工具读取最新内容后再写入`,error:{type:"validation_error",message:"File modified externally",details:{externalModification:k.message}}}}let H=!1;if(O&&G&&K)try{let R=new J2({sessionId:G});await R.initialize(),await R.createSnapshot(X,K),H=!0}catch(R){console.warn("[WriteTool] 创建快照失败:",R)}W.throwIfAborted();let _;if(Q==="base64")_=Buffer.from(Z,"base64");else if(Q==="binary")_=Buffer.from(Z,"binary");else _=Buffer.from(Z,"utf8");if(await q2.writeFile(X,_),G)await h0.getInstance().recordFileEdit(X,G,"write");W.throwIfAborted();let z=await q2.stat(X),F=Q==="utf8"?Z.split(`
508
+ `).length:0,B=X.split("/").pop()||X,L=null;if(U&&Q==="utf8"&&U!==Z){if(U.length<1048576&&Z.length<1048576)L=C9(U,Z,4)}let N={file_path:X,content_size:Z.length,file_size:z.size,encoding:Q,created_directories:J,snapshot_created:H,session_id:G,message_id:K,last_modified:z.mtime.toISOString(),has_diff:!!L,summary:Q==="utf8"?`写入 ${F} 行到 ${B}`:`写入 ${i9(z.size)} 到 ${B}`},A=RX(X,N,Z,L);return{success:!0,llmContent:{file_path:X,size:z.size,modified:z.mtime.toISOString()},displayContent:A,metadata:N}}catch(O){if(O.name==="AbortError")return{success:!1,llmContent:"File write aborted",displayContent:"⚠️ 文件写入被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`File write failed: ${O.message}`,displayContent:`❌ 写入文件失败: ${O.message}`,error:{type:"execution_error",message:O.message,details:O}}}},version:"2.0.0",category:"文件操作",tags:["file","io","write","create"],extractSignatureContent:($)=>$.file_path,abstractPermissionRule:($)=>{let Y=l9($.file_path);return Y?`**/*${Y}`:"**/*"}});function RX($,Y,X,Z){let Q=`✅ 成功写入文件: ${$}`;if(Y.file_size!==void 0)Q+=` (${i9(Y.file_size)})`;if(Y.snapshot_created)Q+=`
512
509
  \uD83D\uDCF8 已创建快照 (可回滚)`;if(Y.encoding!=="utf8")Q+=`
513
- \uD83D\uDD10 使用编码: ${Y.encoding}`;if(Z)Q+=Z;if(X&&Y.encoding==="utf8"&&!Z){let J=$X($,X);if(J)Q+=`
510
+ \uD83D\uDD10 使用编码: ${Y.encoding}`;if(Z)Q+=Z;if(X&&Y.encoding==="utf8"&&!Z){let J=bX($,X);if(J)Q+=`
514
511
 
515
- `+J}return Q}function $X($,Y){let X=j9($).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"}[X]||"",J=100,q=5000,G=Y,K=!1,W=Y.split(`
512
+ `+J}return Q}function bX($,Y){let X=l9($).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"}[X]||"",J=100,q=5000,G=Y,K=!1,W=Y.split(`
516
513
  `);if(W.length>100)G=W.slice(0,100).join(`
517
514
  `),K=!0;if(G.length>5000)G=G.substring(0,5000),K=!0;let O=`\uD83D\uDCC4 文件内容:
518
515
 
@@ -521,11 +518,11 @@ ${y.message}
521
518
  `))O+=`
522
519
  `;if(O+="```",K)O+=`
523
520
 
524
- ⚠️ 内容已截断(完整文件共 ${W.length} 行,${Y.length} 字符)`;return O}function P9($){let Y=["B","KB","MB","GB"],X=$,Z=0;while(X>=1024&&Z<Y.length-1)X/=1024,Z++;return`${X.toFixed(1)}${Y[Z]}`}import*as g2 from"fs/promises";import{z as B$}from"zod";var X4=n({name:"NotebookEdit",displayName:"Notebook Edit",kind:"write",schema:B$.object({notebook_path:B$.string().describe("The absolute path to the Jupyter notebook file to edit (must be absolute, not relative)"),cell_id:B$.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:B$.string().describe("The new source for the cell"),cell_type:B$.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:B$.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:X,cell_id:Z,new_source:Q,cell_type:J,edit_mode:q="replace"}=$;try{let G=await g2.readFile(X,"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(Z){if(W=K.cells.findIndex((U)=>U.id===Z),W===-1&&q!=="insert")return{success:!1,llmContent:`Cell with ID "${Z}" not found`,displayContent:"Cell not found",error:{type:"validation_error",message:`Cell ID "${Z}" 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 U=K.cells[W];if(U.source=Q.split(`
521
+ ⚠️ 内容已截断(完整文件共 ${W.length} 行,${Y.length} 字符)`;return O}function i9($){let Y=["B","KB","MB","GB"],X=$,Z=0;while(X>=1024&&Z<Y.length-1)X/=1024,Z++;return`${X.toFixed(1)}${Y[Z]}`}import*as r2 from"fs/promises";import{z as I$}from"zod";var U4=s({name:"NotebookEdit",displayName:"Notebook Edit",kind:"write",schema:I$.object({notebook_path:I$.string().describe("The absolute path to the Jupyter notebook file to edit (must be absolute, not relative)"),cell_id:I$.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:I$.string().describe("The new source for the cell"),cell_type:I$.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:I$.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:X,cell_id:Z,new_source:Q,cell_type:J,edit_mode:q="replace"}=$;try{let G=await r2.readFile(X,"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(Z){if(W=K.cells.findIndex((U)=>U.id===Z),W===-1&&q!=="insert")return{success:!1,llmContent:`Cell with ID "${Z}" not found`,displayContent:"Cell not found",error:{type:"validation_error",message:`Cell ID "${Z}" 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 U=K.cells[W];if(U.source=Q.split(`
525
522
  `).map((H,_,z)=>_<z.length-1?H+`
526
523
  `:H),J)U.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 U={cell_type:J,source:Q.split(`
527
524
  `).map((_,z,F)=>z<F.length-1?_+`
528
- `:_),metadata:{},...J==="code"?{execution_count:null,outputs:[]}:{}},H=W===-1?0:W+1;K.cells.splice(H,0,U);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 g2.writeFile(X,JSON.stringify(K,null,2));let O=q==="replace"?"replaced":q==="insert"?"inserted":"deleted";return{success:!0,llmContent:`Successfully ${O} cell in ${X}`,displayContent:`Cell ${O} in notebook`,metadata:{notebook_path:X,edit_mode:q,cell_id:Z}}}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}}}}});import{z as YX}from"zod";var Z4=n({name:"EnterPlanMode",displayName:"Enter Plan Mode",kind:"readonly",schema:YX.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.
525
+ `:_),metadata:{},...J==="code"?{execution_count:null,outputs:[]}:{}},H=W===-1?0:W+1;K.cells.splice(H,0,U);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 r2.writeFile(X,JSON.stringify(K,null,2));let O=q==="replace"?"replaced":q==="insert"?"inserted":"deleted";return{success:!0,llmContent:`Successfully ${O} cell in ${X}`,displayContent:`Cell ${O} in notebook`,metadata:{notebook_path:X,edit_mode:q,cell_id:Z}}}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}}}}});import{z as VX}from"zod";var O4=s({name:"EnterPlanMode",displayName:"Enter Plan Mode",kind:"readonly",schema:VX.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.
529
526
 
530
527
  ## When to Use This Tool
531
528
 
@@ -617,7 +614,7 @@ Begin your research now.`,displayContent:"✅ Entering Plan mode",metadata:{appr
617
614
 
618
615
  `+"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(X){return{success:!1,llmContent:`Confirmation flow error: ${X instanceof Error?X.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.
619
616
 
620
- 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 S9}from"zod";import{promises as T9}from"node:fs";import*as Q4 from"node:path";import{homedir as XX}from"node:os";var J4=n({name:"ExitPlanMode",displayName:"Exit Plan Mode",kind:"readonly",schema:S9.object({plan:S9.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.
617
+ 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 r9}from"zod";import{promises as a9}from"node:fs";import*as H4 from"node:path";import{homedir as IX}from"node:os";var _4=s({name:"ExitPlanMode",displayName:"Exit Plan Mode",kind:"readonly",schema:r9.object({plan:r9.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.
621
618
 
622
619
  ## \uD83D\uDEA8 PREREQUISITES (MUST be satisfied before calling)
623
620
 
@@ -652,7 +649,7 @@ Before using this tool, ensure your plan is clear and unambiguous. If there are
652
649
  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.
653
650
  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.
654
651
  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.
655
- `},async execute($,Y){let X=$.plan||"";if(X&&Y.sessionId)try{let Z=Q4.join(XX(),".blade","plans");await T9.mkdir(Z,{recursive:!0});let Q=Q4.join(Z,`plan_${Y.sessionId}.md`);await T9.writeFile(Q,X,"utf-8")}catch(Z){console.warn("Failed to save plan file:",Z)}if(Y.confirmationHandler)try{let Z=await Y.confirmationHandler.requestConfirmation({type:"exitPlanMode",message:`The assistant has finished planning and is ready for your review.
652
+ `},async execute($,Y){let X=$.plan||"";if(X&&Y.sessionId)try{let Z=H4.join(IX(),".blade","plans");await a9.mkdir(Z,{recursive:!0});let Q=H4.join(Z,`plan_${Y.sessionId}.md`);await a9.writeFile(Q,X,"utf-8")}catch(Z){console.warn("Failed to save plan file:",Z)}if(Y.confirmationHandler)try{let Z=await Y.confirmationHandler.requestConfirmation({type:"exitPlanMode",message:`The assistant has finished planning and is ready for your review.
656
653
 
657
654
  `+`⚠️ Before approving, please verify:
658
655
  `+`1. The assistant has written a detailed plan to the plan file
@@ -665,22 +662,22 @@ please reject and ask for a proper plan.`,details:"After approval, the assistant
665
662
  `+(Z.feedback||"No specific feedback provided.")+`
666
663
 
667
664
  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:Z.feedback,awaitingUserInput:!0}}}catch(Z){return{success:!1,llmContent:`Confirmation flow error: ${Z instanceof Error?Z.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.
668
- `+"Proceeding with implementation.",displayContent:"Plan mode exit (non-interactive)",metadata:{approved:null}}}});import OX from"fast-glob";import{stat as HX}from"node:fs/promises";import{join as _X,resolve as FX}from"path";import{z as u2}from"zod";import ZX from"fast-glob";import{LRUCache as QX}from"lru-cache";import{existsSync as JX,readFileSync as qX}from"node:fs";import{readFile as GX}from"node:fs/promises";import{dirname as KX,join as f9}from"node:path";import e$ from"picomatch";var z1=["node_modules",".git","dist","build","out",".next",".nuxt",".cache",".parcel-cache","coverage",".nyc_output",".idea",".vscode",".vs","bower_components","jspm_packages"],q4=["*.log","npm-debug.log*","yarn-debug.log*","pnpm-debug.log*","*.lock","package-lock.json","yarn.lock","pnpm-lock.yaml","*.tmp","*.temp","*.swp","*.bak","*~",".DS_Store","Thumbs.db","*.pid","*.seed"];function WX($){if(!JX($))return{patterns:[],negatePatterns:[]};try{let Y=qX($,"utf-8"),X=[],Z=[];for(let Q of Y.split(`
669
- `)){let J=Q.trim();if(!J||J.startsWith("#"))continue;if(J.startsWith("!"))Z.push(J.slice(1));else X.push(J)}return{patterns:X,negatePatterns:Z}}catch(Y){return console.warn(`Failed to read .gitignore: ${Y}`),{patterns:[],negatePatterns:[]}}}var C9=new QX({max:100,ttl:30000,updateAgeOnGet:!0});async function UX($,Y){let X=[...z1.map((K)=>`${K}/**`),...Y?.scanIgnore??[]],Z=`${$}|${X.join(",")}`,Q=C9.get(Z);if(Q)return Q;let J=await ZX("**/.gitignore",{cwd:$,dot:!0,onlyFiles:!0,followSymbolicLinks:!1,unique:!0,ignore:X});J.sort((K,W)=>K.split("/").length-W.split("/").length);let q=[];for(let K of J){let W=KX(K).replace(/\\/g,"/"),O=W==="."?"":W,H=(await GX(f9($,K),"utf-8")).split(`
670
- `);for(let _ of H){let z=_.trim();if(!z||z.startsWith("#"))continue;let F=z.startsWith("!"),w=(F?z.slice(1):z).trim();if(!w)continue;let N="";if(w.startsWith("/")){let A=w.slice(1).replace(/\\/g,"/");if(N=(O?O+"/":"")+A,q.push({type:F?"negate":"ignore",pattern:N}),w.endsWith("/")){let b=N+"**";q.push({type:F?"negate":"ignore",pattern:b});let y=N.replace(/\/$/,"");if(y!==N)q.push({type:F?"negate":"ignore",pattern:y})}}else{let A=w.replace(/\\/g,"/");if(A.includes("/")){if(N=(O?O+"/":"")+A,q.push({type:F?"negate":"ignore",pattern:N}),A.endsWith("/")){let b=N+"**";q.push({type:F?"negate":"ignore",pattern:b});let y=N.replace(/\/$/,"");if(y!==N)q.push({type:F?"negate":"ignore",pattern:y})}}else N=(O?O+"/**/":"**/")+A,q.push({type:F?"negate":"ignore",pattern:N})}}}let G=Y?.cacheTTL??30000;return C9.set(Z,q,{ttl:G}),q}class m2{orderedRules=[];ignorePatterns=[];negatePatterns=[];constructor($={}){this.initialize($)}static async create($={}){let Y=new m2({...$,useGitignore:!1}),{cwd:X=process.cwd(),useGitignore:Z=!0,gitignoreScanMode:Q="root",customScanIgnore:J=[],cacheTTL:q}=$;if(Z&&Q==="recursive"){let G=await UX(X,{scanIgnore:J,cacheTTL:q});for(let K of G)if(Y.orderedRules.push({type:K.type,matcher:e$(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:X=!0,useDefaults:Z=!0,customPatterns:Q=[]}=$,J=[],q=[];if(Z){let G=[...z1.map((K)=>`${K}/**`),...z1,...q4];J.push(...G);for(let K of G)this.orderedRules.push({type:"ignore",matcher:e$(K,{dot:!0})})}if(X){let G=f9(Y,".gitignore"),{patterns:K,negatePatterns:W}=WX(G);for(let O of K)this.orderedRules.push({type:"ignore",matcher:e$(O,{dot:!0})}),J.push(O);for(let O of W)this.orderedRules.push({type:"negate",matcher:e$(O,{dot:!0})}),q.push(O)}J.push(...Q);for(let G of Q)this.orderedRules.push({type:"ignore",matcher:e$(G,{dot:!0})});this.ignorePatterns=J,this.negatePatterns=q}shouldIgnore($){let Y=$.replace(/\\/g,"/"),X=void 0;for(let Z of this.orderedRules)if(Z.matcher(Y))X=Z.type==="ignore";return X===!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}}function G4($){let Y=Error($);return Y.name="AbortError",Y}var K4=n({name:"Glob",displayName:"File Pattern Match",kind:"readonly",schema:u2.object({pattern:G0.glob({description:"Glob pattern string (supports *, ?, ** wildcards)"}),path:u2.string().optional().describe("Search path (optional, defaults to cwd)"),max_results:G0.positiveInt({description:"Maximum number of results"}).max(1000,"At most 1000 results can be returned").default(100),include_directories:u2.boolean().default(!1).describe("Include directories in results"),case_sensitive:u2.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:X,path:Z=process.cwd(),max_results:Q,include_directories:J,case_sensitive:q}=$,{updateOutput:G}=Y,K=Y.signal??new AbortController().signal;try{G?.(`Searching in ${Z} for pattern "${X}"...`);let W=FX(Z);try{if(!(await HX(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}K.throwIfAborted();let O=await m2.create({cwd:W,useGitignore:!0,useDefaults:!0,gitignoreScanMode:"recursive",customScanIgnore:[],cacheTTL:30000}),{matches:U,wasTruncated:H}=await zX(W,X,{maxResults:Q,includeDirectories:J,caseSensitive:q,signal:K},O),_=NX(U),z={search_path:W,pattern:X,total_matches:U.length,returned_matches:U.length,max_results:Q,include_directories:J,case_sensitive:q,truncated:H},F=BX(z),L;if(_.length>0)L=`${H?`Found at least ${_.length} file(s) matching "${X}" (truncated)`:`Found ${_.length} file(s) matching "${X}"`}:
665
+ `+"Proceeding with implementation.",displayContent:"Plan mode exit (non-interactive)",metadata:{approved:null}}}});import SX from"fast-glob";import{stat as TX}from"node:fs/promises";import{join as CX,resolve as fX}from"path";import{z as n2}from"zod";import DX from"fast-glob";import{LRUCache as vX}from"lru-cache";import{existsSync as MX,readFileSync as kX}from"node:fs";import{readFile as yX}from"node:fs/promises";import{dirname as EX,join as o9}from"node:path";import G2 from"picomatch";var w1=["node_modules",".git","dist","build","out",".next",".nuxt",".cache",".parcel-cache","coverage",".nyc_output",".idea",".vscode",".vs","bower_components","jspm_packages"],F4=["*.log","npm-debug.log*","yarn-debug.log*","pnpm-debug.log*","*.lock","package-lock.json","yarn.lock","pnpm-lock.yaml","*.tmp","*.temp","*.swp","*.bak","*~",".DS_Store","Thumbs.db","*.pid","*.seed"];function jX($){if(!MX($))return{patterns:[],negatePatterns:[]};try{let Y=kX($,"utf-8"),X=[],Z=[];for(let Q of Y.split(`
666
+ `)){let J=Q.trim();if(!J||J.startsWith("#"))continue;if(J.startsWith("!"))Z.push(J.slice(1));else X.push(J)}return{patterns:X,negatePatterns:Z}}catch(Y){return console.warn(`Failed to read .gitignore: ${Y}`),{patterns:[],negatePatterns:[]}}}var n9=new vX({max:100,ttl:30000,updateAgeOnGet:!0});async function PX($,Y){let X=[...w1.map((K)=>`${K}/**`),...Y?.scanIgnore??[]],Z=`${$}|${X.join(",")}`,Q=n9.get(Z);if(Q)return Q;let J=await DX("**/.gitignore",{cwd:$,dot:!0,onlyFiles:!0,followSymbolicLinks:!1,unique:!0,ignore:X});J.sort((K,W)=>K.split("/").length-W.split("/").length);let q=[];for(let K of J){let W=EX(K).replace(/\\/g,"/"),O=W==="."?"":W,H=(await yX(o9($,K),"utf-8")).split(`
667
+ `);for(let _ of H){let z=_.trim();if(!z||z.startsWith("#"))continue;let F=z.startsWith("!"),L=(F?z.slice(1):z).trim();if(!L)continue;let N="";if(L.startsWith("/")){let A=L.slice(1).replace(/\\/g,"/");if(N=(O?O+"/":"")+A,q.push({type:F?"negate":"ignore",pattern:N}),L.endsWith("/")){let R=N+"**";q.push({type:F?"negate":"ignore",pattern:R});let k=N.replace(/\/$/,"");if(k!==N)q.push({type:F?"negate":"ignore",pattern:k})}}else{let A=L.replace(/\\/g,"/");if(A.includes("/")){if(N=(O?O+"/":"")+A,q.push({type:F?"negate":"ignore",pattern:N}),A.endsWith("/")){let R=N+"**";q.push({type:F?"negate":"ignore",pattern:R});let k=N.replace(/\/$/,"");if(k!==N)q.push({type:F?"negate":"ignore",pattern:k})}}else N=(O?O+"/**/":"**/")+A,q.push({type:F?"negate":"ignore",pattern:N})}}}let G=Y?.cacheTTL??30000;return n9.set(Z,q,{ttl:G}),q}class a2{orderedRules=[];ignorePatterns=[];negatePatterns=[];constructor($={}){this.initialize($)}static async create($={}){let Y=new a2({...$,useGitignore:!1}),{cwd:X=process.cwd(),useGitignore:Z=!0,gitignoreScanMode:Q="root",customScanIgnore:J=[],cacheTTL:q}=$;if(Z&&Q==="recursive"){let G=await PX(X,{scanIgnore:J,cacheTTL:q});for(let K of G)if(Y.orderedRules.push({type:K.type,matcher:G2(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:X=!0,useDefaults:Z=!0,customPatterns:Q=[]}=$,J=[],q=[];if(Z){let G=[...w1.map((K)=>`${K}/**`),...w1,...F4];J.push(...G);for(let K of G)this.orderedRules.push({type:"ignore",matcher:G2(K,{dot:!0})})}if(X){let G=o9(Y,".gitignore"),{patterns:K,negatePatterns:W}=jX(G);for(let O of K)this.orderedRules.push({type:"ignore",matcher:G2(O,{dot:!0})}),J.push(O);for(let O of W)this.orderedRules.push({type:"negate",matcher:G2(O,{dot:!0})}),q.push(O)}J.push(...Q);for(let G of Q)this.orderedRules.push({type:"ignore",matcher:G2(G,{dot:!0})});this.ignorePatterns=J,this.negatePatterns=q}shouldIgnore($){let Y=$.replace(/\\/g,"/"),X=void 0;for(let Z of this.orderedRules)if(Z.matcher(Y))X=Z.type==="ignore";return X===!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}}function z4($){let Y=Error($);return Y.name="AbortError",Y}var N4=s({name:"Glob",displayName:"File Pattern Match",kind:"readonly",schema:n2.object({pattern:U0.glob({description:"Glob pattern string (supports *, ?, ** wildcards)"}),path:n2.string().optional().describe("Search path (optional, defaults to cwd)"),max_results:U0.positiveInt({description:"Maximum number of results"}).max(1000,"At most 1000 results can be returned").default(100),include_directories:n2.boolean().default(!1).describe("Include directories in results"),case_sensitive:n2.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:X,path:Z=process.cwd(),max_results:Q,include_directories:J,case_sensitive:q}=$,{updateOutput:G}=Y,K=Y.signal??new AbortController().signal;try{G?.(`Searching in ${Z} for pattern "${X}"...`);let W=fX(Z);try{if(!(await TX(W)).isDirectory())return{success:!1,llmContent:`Search path must be a directory: ${W}`,displayContent:`❌ 搜索路径必须是目录: ${W}`,error:{type:"validation_error",message:"搜索路径必须是目录"}}}catch(L){if(L.code==="ENOENT")return{success:!1,llmContent:`Search path does not exist: ${W}`,displayContent:`❌ 搜索路径不存在: ${W}`,error:{type:"execution_error",message:"搜索路径不存在"}};throw L}K.throwIfAborted();let O=await a2.create({cwd:W,useGitignore:!0,useDefaults:!0,gitignoreScanMode:"recursive",customScanIgnore:[],cacheTTL:30000}),{matches:U,wasTruncated:H}=await hX(W,X,{maxResults:Q,includeDirectories:J,caseSensitive:q,signal:K},O),_=xX(U),z={search_path:W,pattern:X,total_matches:U.length,returned_matches:U.length,max_results:Q,include_directories:J,case_sensitive:q,truncated:H},F=pX(z),B;if(_.length>0)B=`${H?`Found at least ${_.length} file(s) matching "${X}" (truncated)`:`Found ${_.length} file(s) matching "${X}"`}:
671
668
 
672
669
  `+_.map((N)=>`- ${N.relative_path}`).join(`
673
670
  `)+`
674
671
 
675
- Use the relative_path values above for Read/Edit operations.`;else L=`No files found matching "${X}"`;return{success:!0,llmContent:L,displayContent:F,metadata:{...z,matches:_}}}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:()=>"*"});async function zX($,Y,X,Z){let Q=Z.getIgnorePatterns(),J=[],q=!1;return await new Promise((G,K)=>{if(X.signal.aborted){K(G4("文件搜索被用户中止"));return}let W=OX.stream(Y,{cwd:$,dot:!0,followSymbolicLinks:!1,unique:!0,caseSensitiveMatch:X.caseSensitive,objectMode:!0,stats:!0,onlyFiles:!X.includeDirectories,ignore:Q}),O=!1,U=null,H=()=>{if(U){if(X.signal.removeEventListener)X.signal.removeEventListener("abort",U);else if("onabort"in X.signal)X.signal.onabort=null;U=null}},_=()=>{if(!O)O=!0,q=!0,W.destroy(),H(),G({matches:J,wasTruncated:q})},z=(F)=>{if(X.signal.aborted){if(!O)O=!0,W.destroy(G4("文件搜索被用户中止"));return}if(J.length>=X.maxResults){_();return}let L=F.path.replace(/\\/g,"/"),w=_X($,L);if(Z.shouldIgnore(L))return;let N=F.stats?F.stats.isDirectory():!1;if(N&&Z.shouldIgnoreDirectory(L))return;let A=F.stats&&F.stats.isFile()?F.stats.size:void 0,b=F.stats?F.stats.mtime.toISOString():void 0;if(J.push({path:w,relative_path:L,is_directory:N,size:A,modified:b}),J.length>=X.maxResults)_()};if(W.on("data",z),U=()=>{if(!O)O=!0,H(),W.destroy(G4("文件搜索被用户中止"))},X.signal.addEventListener)X.signal.addEventListener("abort",U);else if("onabort"in X.signal)X.signal.onabort=U;W.once("error",(F)=>{if(!O)O=!0,H(),K(F)}),W.once("end",()=>{if(!O)O=!0,H(),G({matches:J,wasTruncated:q})})})}function NX($){return $.sort((Y,X)=>{if(Y.is_directory!==X.is_directory)return Y.is_directory?1:-1;if(Y.modified&&X.modified)return new Date(X.modified).getTime()-new Date(Y.modified).getTime();return Y.relative_path.localeCompare(X.relative_path)})}function BX($){let{search_path:Y,pattern:X,total_matches:Z,returned_matches:Q,truncated:J}=$,q;if(J)q=`✅ 在 ${Y} 中找到至少 ${Z} 个匹配 "${X}" 的文件(已截断)`,q+=`
676
- \uD83D\uDCCB 显示前 ${Q} 个结果`;else q=`✅ 在 ${Y} 中找到 ${Z} 个匹配 "${X}" 的文件`;return q}import{execSync as W4,spawn as U4}from"child_process";import{existsSync as d2}from"fs";import{readdir as LX,readFile as wX}from"fs/promises";import{join as h9,relative as AX}from"path";import RX from"picomatch";import{z as S1}from"zod";function bX(){let{platform:$,arch:Y}=process,X={"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"},Z=`${$}-${Y}`,Q=X[Z];if(!Q)return null;let J=h9(process.cwd(),"vendor","ripgrep",Q);if(d2(J))return J;try{let q=new URL("../../../../vendor/ripgrep/"+Q,import.meta.url).pathname;if(d2(q))return q}catch{}return null}function x9(){try{let Y=process.platform==="win32"?"where rg":"command -v rg 2>/dev/null || which rg 2>/dev/null",X=W4(Y,{encoding:"utf8",stdio:["pipe","pipe","ignore"]}).split(/\r?\n/)[0].trim();if(X)return X}catch{}let $=bX();if($&&d2($))return $;try{let Y=A0("@vscode/ripgrep");if(Y?.rgPath&&d2(Y.rgPath))return Y.rgPath}catch{}return null}async function VX($){try{return W4("git rev-parse --git-dir",{cwd:$,stdio:"ignore"}),!0}catch{return!1}}function DX(){try{return W4("grep --version",{stdio:"ignore"}),!0}catch{return!1}}async function IX($,Y,X,Z){let Q=x9();if(!Q)throw Error("ripgrep not available");return new Promise((J,q)=>{let G=U4(Q,$,{stdio:["pipe","pipe","pipe"]}),K="",W="";G.stdout.on("data",(U)=>{K+=U.toString()}),G.stderr.on("data",(U)=>{W+=U.toString()}),G.on("close",(U)=>{J({stdout:K,stderr:W,exitCode:U||0})}),G.on("error",(U)=>{q(U)});let O=()=>{G.kill("SIGTERM"),q(Error("搜索被用户中止"))};X.addEventListener("abort",O),G.on("close",()=>{X.removeEventListener("abort",O)})})}async function kX($,Y,X,Z){let Q=["grep","-n"];if(X.caseInsensitive)Q.push("-i");if(X.contextLines!==void 0)Q.push(`-C${X.contextLines}`);if(Q.push("-e",$),X.glob)Q.push("--",X.glob);return new Promise((J,q)=>{let G=U4("git",Q,{cwd:Y,stdio:["pipe","pipe","pipe"]}),K="",W="";G.stdout.on("data",(U)=>{K+=U.toString()}),G.stderr.on("data",(U)=>{W+=U.toString()}),G.on("close",(U)=>{J({stdout:K,stderr:W,exitCode:U||0})}),G.on("error",(U)=>{q(U)});let O=()=>{G.kill("SIGTERM"),q(Error("搜索被用户中止"))};Z.addEventListener("abort",O),G.on("close",()=>{Z.removeEventListener("abort",O)})})}async function vX($,Y,X,Z){let Q=["-rn"];if(X.caseInsensitive)Q.push("-i");if(X.contextLines!==void 0)Q.push(`-C${X.contextLines}`);for(let J of z1)Q.push("--exclude-dir="+J.replace(/^\./,""));return Q.push("-e",$,Y),new Promise((J,q)=>{let G=U4("grep",Q,{stdio:["pipe","pipe","pipe"]}),K="",W="";G.stdout.on("data",(U)=>{K+=U.toString()}),G.stderr.on("data",(U)=>{W+=U.toString()}),G.on("close",(U)=>{J({stdout:K,stderr:W,exitCode:U||0})}),G.on("error",(U)=>{q(U)});let O=()=>{G.kill("SIGTERM"),q(Error("搜索被用户中止"))};Z.addEventListener("abort",O),G.on("close",()=>{Z.removeEventListener("abort",O)})})}async function MX($,Y,X,Z){let Q=[],J=new RegExp($,X.caseInsensitive?"gi":"g"),q=await yX(Y,Z),G=0;for(let K of q){if(Z.throwIfAborted(),p9(K))continue;if(X.glob&&!EX(K,X.glob))continue;try{(await wX(K,"utf-8")).split(`
677
- `).forEach((U,H)=>{if(J.test(U))Q.push({file_path:AX(Y,K),line_number:H+1,content:U})}),G++}catch(W){continue}}return{matches:Q,totalFiles:G}}async function yX($,Y){let X=[];async function Z(Q){Y.throwIfAborted();try{let J=await LX(Q,{withFileTypes:!0});for(let q of J){Y.throwIfAborted();let G=h9(Q,q.name);if(q.isDirectory()){if(!p9(G))await Z(G)}else if(q.isFile())X.push(G)}}catch(J){}}return await Z($),X}function p9($){for(let Y of z1)if($.includes(Y))return!0;return!1}function EX($,Y){return RX(Y)($)}function jX($){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 X of z1)Y.push("--glob",`!${X}/**`);if($.glob)Y.push("--glob",$.glob);if($.head_limit!==void 0){let X=($.offset??0)+$.head_limit;Y.push("-m",X.toString())}return Y.push($.pattern),Y.push($.path),Y}function PX($,Y){if(!$.trim())return[];let X=$.trim().split(`
678
- `),Z=[];switch(Y){case"files_with_matches":return X.map((Q)=>({file_path:Q.trim()}));case"count":return X.map((Q)=>{let[J,q]=Q.split(":");return{file_path:J,count:parseInt(q,10)}});case"content":for(let Q of X){let J=SX(Q);if(J)Z.push(J)}return Z;default:return[]}}function SX($){let Y=$.indexOf(":");if(Y===-1)return null;let X=$.substring(0,Y),Z=$.substring(Y+1),Q=Z.indexOf(":");if(Q!==-1&&/^\d+$/.test(Z.substring(0,Q))){let J=parseInt(Z.substring(0,Q),10),q=Z.substring(Q+1);return{file_path:X,line_number:J,content:q}}else return{file_path:X,content:Z}}function TX($){let{search_pattern:Y,search_path:X,output_mode:Z,total_matches:Q,strategy:J}=$,q=`✅ 在 ${X} 中搜索 "${Y}"`;if(J)q+=`
672
+ Use the relative_path values above for Read/Edit operations.`;else B=`No files found matching "${X}"`;return{success:!0,llmContent:B,displayContent:F,metadata:{...z,matches:_}}}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:()=>"*"});async function hX($,Y,X,Z){let Q=Z.getIgnorePatterns(),J=[],q=!1;return await new Promise((G,K)=>{if(X.signal.aborted){K(z4("文件搜索被用户中止"));return}let W=SX.stream(Y,{cwd:$,dot:!0,followSymbolicLinks:!1,unique:!0,caseSensitiveMatch:X.caseSensitive,objectMode:!0,stats:!0,onlyFiles:!X.includeDirectories,ignore:Q}),O=!1,U=null,H=()=>{if(U){if(X.signal.removeEventListener)X.signal.removeEventListener("abort",U);else if("onabort"in X.signal)X.signal.onabort=null;U=null}},_=()=>{if(!O)O=!0,q=!0,W.destroy(),H(),G({matches:J,wasTruncated:q})},z=(F)=>{if(X.signal.aborted){if(!O)O=!0,W.destroy(z4("文件搜索被用户中止"));return}if(J.length>=X.maxResults){_();return}let B=F.path.replace(/\\/g,"/"),L=CX($,B);if(Z.shouldIgnore(B))return;let N=F.stats?F.stats.isDirectory():!1;if(N&&Z.shouldIgnoreDirectory(B))return;let A=F.stats&&F.stats.isFile()?F.stats.size:void 0,R=F.stats?F.stats.mtime.toISOString():void 0;if(J.push({path:L,relative_path:B,is_directory:N,size:A,modified:R}),J.length>=X.maxResults)_()};if(W.on("data",z),U=()=>{if(!O)O=!0,H(),W.destroy(z4("文件搜索被用户中止"))},X.signal.addEventListener)X.signal.addEventListener("abort",U);else if("onabort"in X.signal)X.signal.onabort=U;W.once("error",(F)=>{if(!O)O=!0,H(),K(F)}),W.once("end",()=>{if(!O)O=!0,H(),G({matches:J,wasTruncated:q})})})}function xX($){return $.sort((Y,X)=>{if(Y.is_directory!==X.is_directory)return Y.is_directory?1:-1;if(Y.modified&&X.modified)return new Date(X.modified).getTime()-new Date(Y.modified).getTime();return Y.relative_path.localeCompare(X.relative_path)})}function pX($){let{search_path:Y,pattern:X,total_matches:Z,returned_matches:Q,truncated:J}=$,q;if(J)q=`✅ 在 ${Y} 中找到至少 ${Z} 个匹配 "${X}" 的文件(已截断)`,q+=`
673
+ \uD83D\uDCCB 显示前 ${Q} 个结果`;else q=`✅ 在 ${Y} 中找到 ${Z} 个匹配 "${X}" 的文件`;return q}import{execSync as B4,spawn as L4}from"child_process";import{existsSync as o2}from"fs";import{readdir as gX,readFile as mX}from"fs/promises";import{join as s9,relative as uX}from"path";import dX from"picomatch";import{z as h1}from"zod";function cX(){let{platform:$,arch:Y}=process,X={"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"},Z=`${$}-${Y}`,Q=X[Z];if(!Q)return null;let J=s9(process.cwd(),"vendor","ripgrep",Q);if(o2(J))return J;try{let q=new URL("../../../../vendor/ripgrep/"+Q,import.meta.url).pathname;if(o2(q))return q}catch{}return null}function t9(){try{let Y=process.platform==="win32"?"where rg":"command -v rg 2>/dev/null || which rg 2>/dev/null",X=B4(Y,{encoding:"utf8",stdio:["pipe","pipe","ignore"]}).split(/\r?\n/)[0].trim();if(X)return X}catch{}let $=cX();if($&&o2($))return $;try{let Y=R0("@vscode/ripgrep");if(Y?.rgPath&&o2(Y.rgPath))return Y.rgPath}catch{}return null}async function lX($){try{return B4("git rev-parse --git-dir",{cwd:$,stdio:"ignore"}),!0}catch{return!1}}function iX(){try{return B4("grep --version",{stdio:"ignore"}),!0}catch{return!1}}async function rX($,Y,X,Z){let Q=t9();if(!Q)throw Error("ripgrep not available");return new Promise((J,q)=>{let G=L4(Q,$,{stdio:["pipe","pipe","pipe"]}),K="",W="";G.stdout.on("data",(U)=>{K+=U.toString()}),G.stderr.on("data",(U)=>{W+=U.toString()}),G.on("close",(U)=>{J({stdout:K,stderr:W,exitCode:U||0})}),G.on("error",(U)=>{q(U)});let O=()=>{G.kill("SIGTERM"),q(Error("搜索被用户中止"))};X.addEventListener("abort",O),G.on("close",()=>{X.removeEventListener("abort",O)})})}async function aX($,Y,X,Z){let Q=["grep","-n"];if(X.caseInsensitive)Q.push("-i");if(X.contextLines!==void 0)Q.push(`-C${X.contextLines}`);if(Q.push("-e",$),X.glob)Q.push("--",X.glob);return new Promise((J,q)=>{let G=L4("git",Q,{cwd:Y,stdio:["pipe","pipe","pipe"]}),K="",W="";G.stdout.on("data",(U)=>{K+=U.toString()}),G.stderr.on("data",(U)=>{W+=U.toString()}),G.on("close",(U)=>{J({stdout:K,stderr:W,exitCode:U||0})}),G.on("error",(U)=>{q(U)});let O=()=>{G.kill("SIGTERM"),q(Error("搜索被用户中止"))};Z.addEventListener("abort",O),G.on("close",()=>{Z.removeEventListener("abort",O)})})}async function nX($,Y,X,Z){let Q=["-rn"];if(X.caseInsensitive)Q.push("-i");if(X.contextLines!==void 0)Q.push(`-C${X.contextLines}`);for(let J of w1)Q.push("--exclude-dir="+J.replace(/^\./,""));return Q.push("-e",$,Y),new Promise((J,q)=>{let G=L4("grep",Q,{stdio:["pipe","pipe","pipe"]}),K="",W="";G.stdout.on("data",(U)=>{K+=U.toString()}),G.stderr.on("data",(U)=>{W+=U.toString()}),G.on("close",(U)=>{J({stdout:K,stderr:W,exitCode:U||0})}),G.on("error",(U)=>{q(U)});let O=()=>{G.kill("SIGTERM"),q(Error("搜索被用户中止"))};Z.addEventListener("abort",O),G.on("close",()=>{Z.removeEventListener("abort",O)})})}async function oX($,Y,X,Z){let Q=[],J=new RegExp($,X.caseInsensitive?"gi":"g"),q=await sX(Y,Z),G=0;for(let K of q){if(Z.throwIfAborted(),e9(K))continue;if(X.glob&&!tX(K,X.glob))continue;try{(await mX(K,"utf-8")).split(`
674
+ `).forEach((U,H)=>{if(J.test(U))Q.push({file_path:uX(Y,K),line_number:H+1,content:U})}),G++}catch(W){continue}}return{matches:Q,totalFiles:G}}async function sX($,Y){let X=[];async function Z(Q){Y.throwIfAborted();try{let J=await gX(Q,{withFileTypes:!0});for(let q of J){Y.throwIfAborted();let G=s9(Q,q.name);if(q.isDirectory()){if(!e9(G))await Z(G)}else if(q.isFile())X.push(G)}}catch(J){}}return await Z($),X}function e9($){for(let Y of w1)if($.includes(Y))return!0;return!1}function tX($,Y){return dX(Y)($)}function eX($){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 X of w1)Y.push("--glob",`!${X}/**`);if($.glob)Y.push("--glob",$.glob);if($.head_limit!==void 0){let X=($.offset??0)+$.head_limit;Y.push("-m",X.toString())}return Y.push($.pattern),Y.push($.path),Y}function $Z($,Y){if(!$.trim())return[];let X=$.trim().split(`
675
+ `),Z=[];switch(Y){case"files_with_matches":return X.map((Q)=>({file_path:Q.trim()}));case"count":return X.map((Q)=>{let[J,q]=Q.split(":");return{file_path:J,count:parseInt(q,10)}});case"content":for(let Q of X){let J=YZ(Q);if(J)Z.push(J)}return Z;default:return[]}}function YZ($){let Y=$.indexOf(":");if(Y===-1)return null;let X=$.substring(0,Y),Z=$.substring(Y+1),Q=Z.indexOf(":");if(Q!==-1&&/^\d+$/.test(Z.substring(0,Q))){let J=parseInt(Z.substring(0,Q),10),q=Z.substring(Q+1);return{file_path:X,line_number:J,content:q}}else return{file_path:X,content:Z}}function XZ($){let{search_pattern:Y,search_path:X,output_mode:Z,total_matches:Q,strategy:J}=$,q=`✅ 在 ${X} 中搜索 "${Y}"`;if(J)q+=`
679
676
  \uD83D\uDD27 使用策略: ${J}`;switch(Z){case"files_with_matches":q+=`
680
677
  \uD83D\uDCC1 找到 ${Q} 个包含匹配内容的文件`;break;case"count":q+=`
681
678
  \uD83D\uDD22 统计了 ${Q} 个文件的匹配数量`;break;case"content":q+=`
682
- \uD83D\uDCDD 找到 ${Q} 个匹配行`;break}return q}var O4=n({name:"Grep",displayName:"内容搜索",kind:"readonly",schema:S1.object({pattern:G0.pattern({description:"The regular expression pattern to search for in file contents"}),path:S1.string().optional().describe("File or directory to search in (rg PATH). Defaults to current working directory"),glob:S1.string().optional().describe('Glob pattern to filter files (e.g. "*.js", "*.{ts,tsx}") - maps to rg --glob'),type:S1.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:S1.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":S1.boolean().optional().describe("Case insensitive search (rg -i)"),"-n":S1.boolean().default(!0).describe('Show line numbers in output (rg -n). Requires output_mode: "content", ignored otherwise. Defaults to true'),"-B":G0.nonNegativeInt().optional().describe('Number of lines to show before each match (rg -B). Requires output_mode: "content", ignored otherwise'),"-A":G0.nonNegativeInt().optional().describe('Number of lines to show after each match (rg -A). Requires output_mode: "content", ignored otherwise'),"-C":G0.nonNegativeInt().optional().describe('Number of lines to show before and after each match (rg -C). Requires output_mode: "content", ignored otherwise'),head_limit:G0.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:G0.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:S1.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:X,path:Z=process.cwd(),glob:Q,type:J,output_mode:q,"-i":G,"-n":K=!0,"-B":W,"-A":O,"-C":U,head_limit:H,offset:_,multiline:z}=$,{updateOutput:F}=Y,L=Y.signal??new AbortController().signal;try{F?.(`使用智能搜索策略查找模式 "${X}"...`);let w=null,N="ripgrep",A=[],b=x9();if(b)try{F?.(`\uD83D\uDE80 使用 ripgrep (${b})`);let D=jX({pattern:X,path:Z,glob:Q,type:J,output_mode:q,case_insensitive:G??!1,line_numbers:K,context_before:W,context_after:O,context:U,head_limit:H,offset:_,multiline:z??!1});w=await IX(D,q,L,F),N="ripgrep"}catch(D){F?.("⚠️ ripgrep 失败,尝试降级策略..."),w=null}if(!w&&await VX(Z))try{F?.("\uD83D\uDCE6 使用 git grep"),w=await kX(X,Z,{caseInsensitive:G??!1,glob:Q,contextLines:U},L),N="git-grep"}catch(D){F?.("⚠️ git grep 失败,继续尝试其他策略..."),w=null}if(!w&&DX())try{F?.("\uD83D\uDD27 使用系统 grep"),w=await vX(X,Z,{caseInsensitive:G??!1,contextLines:U},L),N="system-grep"}catch(D){F?.("⚠️ 系统 grep 失败,使用纯 JavaScript 实现..."),w=null}if(!w)F?.("\uD83D\uDCA1 使用纯 JavaScript 搜索实现"),A=(await MX(X,Z,{caseInsensitive:G??!1,glob:Q,multiline:z??!1},L)).matches,N="fallback",w={stdout:"",stderr:"",exitCode:0};else A=PX(w.stdout,q);let y=A.length;if(_!==void 0&&_>0)A=A.slice(_);if(H!==void 0&&A.length>H)A=A.slice(0,H);let R={search_pattern:X,search_path:Z,output_mode:q,case_insensitive:G??!1,total_matches:A.length,original_total:y,offset:_,head_limit:H,strategy:N,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 B=TX(R);return{success:!0,llmContent:A,displayContent:B,metadata:R}}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:()=>"*"});import{spawn as CX}from"child_process";import{randomUUID as fX}from"crypto";class f0{static instance=null;processes=new Map;static getInstance(){if(!f0.instance)f0.instance=new f0;return f0.instance}startBackgroundProcess($){let Y=`bash_${fX()}`,X={};for(let[J,q]of Object.entries({...process.env,...$.env,BLADE_CLI:"1"}))if(q!==void 0)X[J]=q;let Z=CX("bash",["-c",$.command],{cwd:$.cwd||process.cwd(),env:X,stdio:["ignore","pipe","pipe"]}),Q={id:Y,command:$.command,sessionId:$.sessionId,cwd:$.cwd,env:$.env,process:Z,pid:Z.pid,status:"running",startTime:Date.now(),pendingStdout:"",pendingStderr:""};return Z.stdout?.setEncoding("utf8"),Z.stderr?.setEncoding("utf8"),Z.stdout?.on("data",(J)=>{Q.pendingStdout+=J.toString()}),Z.stderr?.on("data",(J)=>{Q.pendingStderr+=J.toString()}),Z.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}),Z.on("error",(J)=>{Q.status="error",Q.errorMessage=J.message,Q.endTime=Date.now(),Q.process=void 0,Q.pendingStderr+=`
683
- [error] ${J.message}`}),this.processes.set(Y,Q),Q}consumeOutput($){let Y=this.processes.get($);if(!Y)return;let X={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="",X}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()}}import{spawn as hX}from"child_process";import{randomUUID as xX}from"crypto";import{z as H4}from"zod";var _4=n({name:"Bash",displayName:"Bash Command",kind:"execute",schema:H4.object({command:G0.command({description:"Bash command to execute"}),timeout:G0.timeout(1000,300000,30000),cwd:H4.string().optional().describe("Working directory (optional; applies only to this command). To persist, use cd"),env:G0.environment(),run_in_background:H4.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.
679
+ \uD83D\uDCDD 找到 ${Q} 个匹配行`;break}return q}var w4=s({name:"Grep",displayName:"内容搜索",kind:"readonly",schema:h1.object({pattern:U0.pattern({description:"The regular expression pattern to search for in file contents"}),path:h1.string().optional().describe("File or directory to search in (rg PATH). Defaults to current working directory"),glob:h1.string().optional().describe('Glob pattern to filter files (e.g. "*.js", "*.{ts,tsx}") - maps to rg --glob'),type:h1.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:h1.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":h1.boolean().optional().describe("Case insensitive search (rg -i)"),"-n":h1.boolean().default(!0).describe('Show line numbers in output (rg -n). Requires output_mode: "content", ignored otherwise. Defaults to true'),"-B":U0.nonNegativeInt().optional().describe('Number of lines to show before each match (rg -B). Requires output_mode: "content", ignored otherwise'),"-A":U0.nonNegativeInt().optional().describe('Number of lines to show after each match (rg -A). Requires output_mode: "content", ignored otherwise'),"-C":U0.nonNegativeInt().optional().describe('Number of lines to show before and after each match (rg -C). Requires output_mode: "content", ignored otherwise'),head_limit:U0.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:U0.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:h1.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:X,path:Z=process.cwd(),glob:Q,type:J,output_mode:q,"-i":G,"-n":K=!0,"-B":W,"-A":O,"-C":U,head_limit:H,offset:_,multiline:z}=$,{updateOutput:F}=Y,B=Y.signal??new AbortController().signal;try{F?.(`使用智能搜索策略查找模式 "${X}"...`);let L=null,N="ripgrep",A=[],R=t9();if(R)try{F?.(`\uD83D\uDE80 使用 ripgrep (${R})`);let b=eX({pattern:X,path:Z,glob:Q,type:J,output_mode:q,case_insensitive:G??!1,line_numbers:K,context_before:W,context_after:O,context:U,head_limit:H,offset:_,multiline:z??!1});L=await rX(b,q,B,F),N="ripgrep"}catch(b){F?.("⚠️ ripgrep 失败,尝试降级策略..."),L=null}if(!L&&await lX(Z))try{F?.("\uD83D\uDCE6 使用 git grep"),L=await aX(X,Z,{caseInsensitive:G??!1,glob:Q,contextLines:U},B),N="git-grep"}catch(b){F?.("⚠️ git grep 失败,继续尝试其他策略..."),L=null}if(!L&&iX())try{F?.("\uD83D\uDD27 使用系统 grep"),L=await nX(X,Z,{caseInsensitive:G??!1,contextLines:U},B),N="system-grep"}catch(b){F?.("⚠️ 系统 grep 失败,使用纯 JavaScript 实现..."),L=null}if(!L)F?.("\uD83D\uDCA1 使用纯 JavaScript 搜索实现"),A=(await oX(X,Z,{caseInsensitive:G??!1,glob:Q,multiline:z??!1},B)).matches,N="fallback",L={stdout:"",stderr:"",exitCode:0};else A=$Z(L.stdout,q);let k=A.length;if(_!==void 0&&_>0)A=A.slice(_);if(H!==void 0&&A.length>H)A=A.slice(0,H);let I={search_pattern:X,search_path:Z,output_mode:q,case_insensitive:G??!1,total_matches:A.length,original_total:k,offset:_,head_limit:H,strategy:N,exit_code:L?.exitCode};if(L&&L.exitCode!==0&&L.stderr)return{success:!1,llmContent:`Search execution failed: ${L.stderr}`,displayContent:`❌ 搜索执行失败: ${L.stderr}`,error:{type:"execution_error",message:L.stderr}};let w=XZ(I);return{success:!0,llmContent:A,displayContent:w,metadata:I}}catch(L){if(L.name==="AbortError")return{success:!1,llmContent:"Search aborted",displayContent:"⚠️ 搜索被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`Search failed: ${L.message}`,displayContent:`❌ 搜索失败: ${L.message}`,error:{type:"execution_error",message:L.message,details:L}}}},version:"3.0.0",category:"搜索工具",tags:["search","grep","ripgrep","regex","text","fallback"],extractSignatureContent:($)=>$.pattern,abstractPermissionRule:()=>"*"});import{spawn as ZZ}from"child_process";import{randomUUID as QZ}from"crypto";class x0{static instance=null;processes=new Map;static getInstance(){if(!x0.instance)x0.instance=new x0;return x0.instance}startBackgroundProcess($){let Y=`bash_${QZ()}`,X={};for(let[J,q]of Object.entries({...process.env,...$.env,BLADE_CLI:"1"}))if(q!==void 0)X[J]=q;let Z=ZZ("bash",["-c",$.command],{cwd:$.cwd||process.cwd(),env:X,stdio:["ignore","pipe","pipe"]}),Q={id:Y,command:$.command,sessionId:$.sessionId,cwd:$.cwd,env:$.env,process:Z,pid:Z.pid,status:"running",startTime:Date.now(),pendingStdout:"",pendingStderr:""};return Z.stdout?.setEncoding("utf8"),Z.stderr?.setEncoding("utf8"),Z.stdout?.on("data",(J)=>{Q.pendingStdout+=J.toString()}),Z.stderr?.on("data",(J)=>{Q.pendingStderr+=J.toString()}),Z.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}),Z.on("error",(J)=>{Q.status="error",Q.errorMessage=J.message,Q.endTime=Date.now(),Q.process=void 0,Q.pendingStderr+=`
680
+ [error] ${J.message}`}),this.processes.set(Y,Q),Q}consumeOutput($){let Y=this.processes.get($);if(!Y)return;let X={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="",X}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()}}import{spawn as JZ}from"child_process";import{randomUUID as qZ}from"crypto";import{z as A4}from"zod";var R4=s({name:"Bash",displayName:"Bash Command",kind:"execute",schema:A4.object({command:U0.command({description:"Bash command to execute"}),timeout:U0.timeout(1000,300000,30000),cwd:A4.string().optional().describe("Working directory (optional; applies only to this command). To persist, use cd"),env:U0.environment(),run_in_background:A4.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.
684
681
 
685
682
  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.
686
683
 
@@ -696,21 +693,21 @@ Before executing commands:
696
693
  * cd "/Users/name/My Documents" (correct)
697
694
  * cd /Users/name/My Documents (incorrect - will fail)
698
695
  * python "/path/with spaces/script.py" (correct)
699
- * 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:X,timeout:Z=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: ${X}`),q)return pX(X,Q,J);else return gX(X,Q,J,Z,K,G)}catch(W){let O=W;if(O.name==="AbortError")return{success:!1,llmContent:"Command execution aborted",displayContent:"⚠️ 命令执行被用户中止",error:{type:"execution_error",message:"Operation aborted"}};return{success:!1,llmContent:`Command execution failed: ${O.message}`,displayContent:`❌ 命令执行失败: ${O.message}`,error:{type:"execution_error",message:O.message,details:O}}}},version:"2.0.0",category:"命令工具",tags:["bash","shell","non-interactive","event-driven"],extractSignatureContent:($)=>{return $.command.trim()},abstractPermissionRule:($)=>{let X=$.command.trim().split(/\s+/);if(X.length===1)return X[0];if(["run","exec","test","start","build","dev"].includes(X[1])){if(X.length===2)return`${X[0]} ${X[1]}`;return`${X[0]} ${X[1]} *`}if(X.length===2)return`${X[0]} ${X[1]}`;return`${X[0]} ${X[1]} *`}});function pX($,Y,X){let Q=f0.getInstance().startBackgroundProcess({command:$,sessionId:xX(),cwd:Y||process.cwd(),env:X}),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=`✅ 命令已在后台启动
696
+ * 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:X,timeout:Z=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: ${X}`),q)return GZ(X,Q,J);else return KZ(X,Q,J,Z,K,G)}catch(W){let O=W;if(O.name==="AbortError")return{success:!1,llmContent:"Command execution aborted",displayContent:"⚠️ 命令执行被用户中止",error:{type:"execution_error",message:"Operation aborted"}};return{success:!1,llmContent:`Command execution failed: ${O.message}`,displayContent:`❌ 命令执行失败: ${O.message}`,error:{type:"execution_error",message:O.message,details:O}}}},version:"2.0.0",category:"命令工具",tags:["bash","shell","non-interactive","event-driven"],extractSignatureContent:($)=>{return $.command.trim()},abstractPermissionRule:($)=>{let X=$.command.trim().split(/\s+/);if(X.length===1)return X[0];if(["run","exec","test","start","build","dev"].includes(X[1])){if(X.length===2)return`${X[0]} ${X[1]}`;return`${X[0]} ${X[1]} *`}if(X.length===2)return`${X[0]} ${X[1]}`;return`${X[0]} ${X[1]} *`}});function GZ($,Y,X){let Q=x0.getInstance().startBackgroundProcess({command:$,sessionId:qZ(),cwd:Y||process.cwd(),env:X}),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=`✅ 命令已在后台启动
700
697
  `+`\uD83C\uDD94 进程 ID: ${Q.pid}
701
698
  `+`\uD83D\uDCA1 Bash ID: ${Q.id}
702
- `+"⚠️ 使用 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 gX($,Y,X,Z,Q,J){return new Promise((q)=>{let G=Date.now(),K="",W="",O=!1,U=hX("bash",["-c",$],{cwd:Y||process.cwd(),env:{...process.env,...X,BLADE_CLI:"1"},stdio:["pipe","pipe","pipe"]});U.stdout.on("data",(z)=>{K+=z.toString()}),U.stderr.on("data",(z)=>{W+=z.toString()});let H=setTimeout(()=>{O=!0,U.kill("SIGTERM"),setTimeout(()=>{if(!U.killed)U.kill("SIGKILL")},1000)},Z),_=()=>{U.kill("SIGTERM"),clearTimeout(H)};if(Q.addEventListener)Q.addEventListener("abort",_);else if("onabort"in Q)Q.onabort=_;U.on("close",(z,F)=>{if(clearTimeout(H),Q.removeEventListener)Q.removeEventListener("abort",_);else if("onabort"in Q)Q.onabort=null;let L=Date.now()-G;if(O){q({success:!1,llmContent:`Command execution timed out (${Z}ms)`,displayContent:`⏱️ 命令执行超时 (${Z}ms)
699
+ `+"⚠️ 使用 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 KZ($,Y,X,Z,Q,J){return new Promise((q)=>{let G=Date.now(),K="",W="",O=!1,U=JZ("bash",["-c",$],{cwd:Y||process.cwd(),env:{...process.env,...X,BLADE_CLI:"1"},stdio:["pipe","pipe","pipe"]});U.stdout.on("data",(z)=>{K+=z.toString()}),U.stderr.on("data",(z)=>{W+=z.toString()});let H=setTimeout(()=>{O=!0,U.kill("SIGTERM"),setTimeout(()=>{if(!U.killed)U.kill("SIGKILL")},1000)},Z),_=()=>{U.kill("SIGTERM"),clearTimeout(H)};if(Q.addEventListener)Q.addEventListener("abort",_);else if("onabort"in Q)Q.onabort=_;U.on("close",(z,F)=>{if(clearTimeout(H),Q.removeEventListener)Q.removeEventListener("abort",_);else if("onabort"in Q)Q.onabort=null;let B=Date.now()-G;if(O){q({success:!1,llmContent:`Command execution timed out (${Z}ms)`,displayContent:`⏱️ 命令执行超时 (${Z}ms)
703
700
  输出: ${K}
704
- 错误: ${W}`,error:{type:"timeout_error",message:"命令执行超时"},metadata:{command:$,timeout:!0,stdout:K,stderr:W,execution_time:L}});return}if(Q.aborted){q({success:!1,llmContent:"Command execution aborted by user",displayContent:`⚠️ 命令执行被用户中止
701
+ 错误: ${W}`,error:{type:"timeout_error",message:"命令执行超时"},metadata:{command:$,timeout:!0,stdout:K,stderr:W,execution_time:B}});return}if(Q.aborted){q({success:!1,llmContent:"Command execution aborted by user",displayContent:`⚠️ 命令执行被用户中止
705
702
  输出: ${K}
706
- 错误: ${W}`,error:{type:"execution_error",message:"操作被中止"},metadata:{command:$,aborted:!0,stdout:K,stderr:W,execution_time:L}});return}let w=$.length>30?`${$.substring(0,30)}...`:$,N=z===0?`执行命令成功 (${L}ms): ${w}`:`执行命令完成 (退出码 ${z}, ${L}ms): ${w}`,A={command:$,execution_time:L,exit_code:z,signal:F,stdout_length:K.length,stderr_length:W.length,has_stderr:W.length>0,summary:N},b=mX({stdout:K,stderr:W,command:$,execution_time:L,exit_code:z,signal:F});q({success:!0,llmContent:{stdout:K.trim(),stderr:W.trim(),execution_time:L,exit_code:z,signal:F},displayContent:b,metadata:A})}),U.on("error",(z)=>{if(clearTimeout(H),Q.removeEventListener)Q.removeEventListener("abort",_);else if("onabort"in Q)Q.onabort=null;q({success:!1,llmContent:`Command execution failed: ${z.message}`,displayContent:`❌ 命令执行失败: ${z.message}`,error:{type:"execution_error",message:z.message,details:z}})})})}function mX($){let{stdout:Y,stderr:X,command:Z,execution_time:Q,exit_code:J,signal:q}=$,G=`✅ Bash 命令执行完成: ${Z}`;if(G+=`
703
+ 错误: ${W}`,error:{type:"execution_error",message:"操作被中止"},metadata:{command:$,aborted:!0,stdout:K,stderr:W,execution_time:B}});return}let L=$.length>30?`${$.substring(0,30)}...`:$,N=z===0?`执行命令成功 (${B}ms): ${L}`:`执行命令完成 (退出码 ${z}, ${B}ms): ${L}`,A={command:$,execution_time:B,exit_code:z,signal:F,stdout_length:K.length,stderr_length:W.length,has_stderr:W.length>0,summary:N},R=WZ({stdout:K,stderr:W,command:$,execution_time:B,exit_code:z,signal:F});q({success:!0,llmContent:{stdout:K.trim(),stderr:W.trim(),execution_time:B,exit_code:z,signal:F},displayContent:R,metadata:A})}),U.on("error",(z)=>{if(clearTimeout(H),Q.removeEventListener)Q.removeEventListener("abort",_);else if("onabort"in Q)Q.onabort=null;q({success:!1,llmContent:`Command execution failed: ${z.message}`,displayContent:`❌ 命令执行失败: ${z.message}`,error:{type:"execution_error",message:z.message,details:z}})})})}function WZ($){let{stdout:Y,stderr:X,command:Z,execution_time:Q,exit_code:J,signal:q}=$,G=`✅ Bash 命令执行完成: ${Z}`;if(G+=`
707
704
  ⏱️ 执行时间: ${Q}ms`,G+=`
708
705
  \uD83D\uDCCA 退出码: ${J??"N/A"}`,q)G+=`
709
706
  ⚡ 信号: ${q}`;if(Y&&Y.trim())G+=`
710
707
  \uD83D\uDCE4 输出:
711
708
  ${Y.trim()}`;if(X&&X.trim())G+=`
712
709
  ⚠️ 错误输出:
713
- ${X.trim()}`;return G}import{z as F4}from"zod";var z4=n({name:"BashOutput",displayName:"后台命令输出",kind:"readonly",schema:F4.object({bash_id:F4.string().min(1).describe("Background bash session ID"),filter:F4.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:`
710
+ ${X.trim()}`;return G}import{z as b4}from"zod";var V4=s({name:"BashOutput",displayName:"后台命令输出",kind:"readonly",schema:b4.object({bash_id:b4.string().min(1).describe("Background bash session ID"),filter:b4.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:`
714
711
  - Retrieves output from a running or completed background bash shell
715
712
  - Takes a shell_id parameter identifying the shell
716
713
  - Always returns only new output since the last check
@@ -718,26 +715,26 @@ ${X.trim()}`;return G}import{z as F4}from"zod";var z4=n({name:"BashOutput",displ
718
715
  - Supports optional regex filtering to show only lines matching a pattern
719
716
  - Use this tool when you need to monitor or check the output of a long-running shell
720
717
  - Shell IDs can be found using the /tasks command
721
- `},async execute($,Y){let X=f0.getInstance(),Z;if($.filter)try{Z=new RegExp($.filter)}catch(W){return{success:!1,llmContent:`Invalid regular expression: ${$.filter}
718
+ `},async execute($,Y){let X=x0.getInstance(),Z;if($.filter)try{Z=new RegExp($.filter)}catch(W){return{success:!1,llmContent:`Invalid regular expression: ${$.filter}
722
719
 
723
720
  \uD83D\uDCA1 Output was not consumed; you can retry`,displayContent:`❌ 无效的正则表达式: ${$.filter}
724
721
 
725
- \uD83D\uDCA1 输出未被消费,可重新尝试`,error:{type:"validation_error",message:W.message}}}let Q=X.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}=uX(Q,Z),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=dX(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:()=>"*"});function uX($,Y){let X=g9($.stdout).filter((Q)=>{if(!Y)return!0;return Y.lastIndex=0,Y.test(Q)}),Z=g9($.stderr).filter((Q)=>{if(!Y)return!0;return Y.lastIndex=0,Y.test(Q)});return{stdoutLines:X,stderrLines:Z}}function g9($){if(!$)return[];return $.replace(/\r\n/g,`
722
+ \uD83D\uDCA1 输出未被消费,可重新尝试`,error:{type:"validation_error",message:W.message}}}let Q=X.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}=UZ(Q,Z),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=OZ(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:()=>"*"});function UZ($,Y){let X=$5($.stdout).filter((Q)=>{if(!Y)return!0;return Y.lastIndex=0,Y.test(Q)}),Z=$5($.stderr).filter((Q)=>{if(!Y)return!0;return Y.lastIndex=0,Y.test(Q)});return{stdoutLines:X,stderrLines:Z}}function $5($){if(!$)return[];return $.replace(/\r\n/g,`
726
723
  `).split(`
727
- `)}function dX($,Y,X){let Q=`${$.status==="running"?"⏳":$.status==="exited"?"✅":$.status==="killed"?"✂️":"⚠️"} BashOutput(${$.id}) - 状态: ${$.status}`;if(Q+=`
724
+ `)}function OZ($,Y,X){let Q=`${$.status==="running"?"⏳":$.status==="exited"?"✅":$.status==="killed"?"✂️":"⚠️"} BashOutput(${$.id}) - 状态: ${$.status}`;if(Q+=`
728
725
  命令: ${$.command}`,$.pid)Q+=`
729
726
  PID: ${$.pid}`;if($.exitCode!==void 0&&$.exitCode!==null)Q+=`
730
727
  退出码: ${$.exitCode}`;if($.signal)Q+=`
731
728
  信号: ${$.signal}`;if(Y===0&&X===0)Q+=`
732
729
  无新的输出`;else Q+=`
733
730
  stdout 行数: ${Y}`,Q+=`
734
- stderr 行数: ${X}`;return Q}import{z as m9}from"zod";var N4=n({name:"KillShell",displayName:"终止后台 Shell",kind:"execute",schema:m9.object({shell_id:m9.string().min(1).describe("Background Shell ID to terminate")}),description:{short:"Kills a running background bash shell by its ID",long:`
731
+ stderr 行数: ${X}`;return Q}import{z as Y5}from"zod";var I4=s({name:"KillShell",displayName:"终止后台 Shell",kind:"execute",schema:Y5.object({shell_id:Y5.string().min(1).describe("Background Shell ID to terminate")}),description:{short:"Kills a running background bash shell by its ID",long:`
735
732
  - Kills a running background bash shell by its ID
736
733
  - Takes a shell_id parameter identifying the shell to kill
737
734
  - Returns a success or failure status
738
735
  - Use this tool when you need to terminate a long-running shell
739
736
  - Shell IDs can be found using the /tasks command
740
- `},async execute($,Y){let Z=f0.getInstance().kill($.shell_id);if(!Z)return{success:!1,llmContent:`Shell not found: ${$.shell_id}`,displayContent:`❌ 未找到 Shell: ${$.shell_id}`,error:{type:"execution_error",message:"Shell ID 不存在或已清理"}};if(!Z.success&&!Z.alreadyExited)return{success:!1,llmContent:`Failed to terminate Shell: ${$.shell_id}`,displayContent:`❌ 无法终止 Shell (${$.shell_id})`,error:{type:"execution_error",message:"发送终止信号失败"},metadata:Z};let Q=Z.alreadyExited?`Shell ${$.shell_id} 已经处于 ${Z.status} 状态`:`已向 Shell ${$.shell_id} 发送终止信号`;return{success:!0,llmContent:{shell_id:$.shell_id,status:Z.status,already_exited:Z.alreadyExited,pid:Z.pid,exit_code:Z.exitCode,signal:Z.signal},displayContent:Z.alreadyExited?`ℹ️ ${Q}`:`✂️ ${Q}`,metadata:Z}},version:"1.0.0",category:"命令工具",tags:["bash","shell","terminate"],extractSignatureContent:($)=>$.shell_id,abstractPermissionRule:()=>"*"});import{z as u9}from"zod";var B4=n({name:"Skill",displayName:"Skill",kind:"execute",schema:u9.object({skill:u9.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
737
+ `},async execute($,Y){let Z=x0.getInstance().kill($.shell_id);if(!Z)return{success:!1,llmContent:`Shell not found: ${$.shell_id}`,displayContent:`❌ 未找到 Shell: ${$.shell_id}`,error:{type:"execution_error",message:"Shell ID 不存在或已清理"}};if(!Z.success&&!Z.alreadyExited)return{success:!1,llmContent:`Failed to terminate Shell: ${$.shell_id}`,displayContent:`❌ 无法终止 Shell (${$.shell_id})`,error:{type:"execution_error",message:"发送终止信号失败"},metadata:Z};let Q=Z.alreadyExited?`Shell ${$.shell_id} 已经处于 ${Z.status} 状态`:`已向 Shell ${$.shell_id} 发送终止信号`;return{success:!0,llmContent:{shell_id:$.shell_id,status:Z.status,already_exited:Z.alreadyExited,pid:Z.pid,exit_code:Z.exitCode,signal:Z.signal},displayContent:Z.alreadyExited?`ℹ️ ${Q}`:`✂️ ${Q}`,metadata:Z}},version:"1.0.0",category:"命令工具",tags:["bash","shell","terminate"],extractSignatureContent:($)=>$.shell_id,abstractPermissionRule:()=>"*"});import{z as X5}from"zod";var D4=s({name:"Skill",displayName:"Skill",kind:"execute",schema:X5.object({skill:X5.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
741
738
 
742
739
  <skills_instructions>
743
740
  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.
@@ -760,7 +757,7 @@ Important:
760
757
  <available_skills>
761
758
 
762
759
  </available_skills>
763
- `},async execute($,Y){let{skill:X}=$;return{success:!1,llmContent:`Skill system not yet implemented. The skill "${X}" could not be executed.`,displayContent:"Skill system not available",error:{type:"execution_error",message:"Skill handler not configured"}}}});import{z as d9}from"zod";var L4=n({name:"SlashCommand",displayName:"Slash Command",kind:"execute",schema:d9.object({command:d9.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
760
+ `},async execute($,Y){let{skill:X}=$;return{success:!1,llmContent:`Skill system not yet implemented. The skill "${X}" could not be executed.`,displayContent:"Skill system not available",error:{type:"execution_error",message:"Skill handler not configured"}}}});import{z as Z5}from"zod";var v4=s({name:"SlashCommand",displayName:"Slash Command",kind:"execute",schema:Z5.object({command:Z5.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
764
761
 
765
762
  How slash commands work:
766
763
  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.
@@ -778,14 +775,14 @@ Notes:
778
775
  - 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
779
776
  - 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
780
777
  - 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.
781
- `},async execute($,Y){let{command:X}=$;return{success:!1,llmContent:`Slash command system not yet implemented. The command "${X}" could not be executed.`,displayContent:"Slash command system not available",error:{type:"execution_error",message:"Slash command handler not configured"}}}});import{z as c2}from"zod";class w4{config;constructor($){this.config=$}async execute($){let Y=Date.now();try{let X=this.buildSystemPrompt($),Z=await v0.create({systemPrompt:X,toolWhitelist:this.config.tools}),Q=[{role:"user",content:$.prompt}],J="",q=0,G=0,K=await Z.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(X){let Z=Date.now()-Y;return{success:!1,message:"",error:X instanceof Error?X.message:String(X),stats:{duration:Z}}}}buildSystemPrompt($){return this.config.systemPrompt||""}}import A4 from"node:fs";import cX from"node:path";import lX from"yaml";var iX=Y0("Agent");class c9{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:
778
+ `},async execute($,Y){let{command:X}=$;return{success:!1,llmContent:`Slash command system not yet implemented. The command "${X}" could not be executed.`,displayContent:"Slash command system not available",error:{type:"execution_error",message:"Slash command handler not configured"}}}});import{z as s2}from"zod";class M4{config;constructor($){this.config=$}async execute($){let Y=Date.now();try{let X=this.buildSystemPrompt($),Z=await k0.create({systemPrompt:X,toolWhitelist:this.config.tools}),Q=[{role:"user",content:$.prompt}],J="",q=0,G=0,K=await Z.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(X){let Z=Date.now()-Y;return{success:!1,message:"",error:X instanceof Error?X.message:String(X),stats:{duration:Z}}}}buildSystemPrompt($){return this.config.systemPrompt||""}}import k4 from"node:fs";import HZ from"node:path";import _Z from"yaml";var FZ=$0("Agent");class Q5{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:
782
779
  ${$.map((X)=>{let Z=`- ${X.name}: ${X.description}`;if(X.tools&&X.tools.length>0)Z+=` (Tools: ${X.tools.join(", ")})`;return Z}).join(`
783
- `)}`}loadFromDirectory($){if(!A4.existsSync($))return;let Y=A4.readdirSync($);for(let X of Y){if(!X.endsWith(".md"))continue;let Z=cX.join($,X);try{let Q=this.parseConfigFile(Z);this.register(Q)}catch(Q){iX.warn(`Failed to load subagent config from ${Z}:`,Q)}}}parseConfigFile($){let X=A4.readFileSync($,"utf-8").match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);if(!X)throw Error(`No YAML frontmatter found in ${$}`);let[,Z,Q]=X,J=lX.parse(Z);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 $=A0("node:os"),Y=A0("node:path"),X=Y.join($.homedir(),".blade","agents");this.loadFromDirectory(X);let Z=Y.join(process.cwd(),".blade","agents");return this.loadFromDirectory(Z),this.getAllNames().length}clear(){this.subagents.clear()}}var N0=new c9;function rX(){let $=N0.getAllNames();if($.length===0)return["Explore"];return $}var R4=n({name:"Task",displayName:"Subagent Scheduler",kind:"readonly",isReadOnly:!0,schema:c2.object({subagent_type:c2.enum(rX()).describe('Subagent type to use (e.g., "Explore", "Plan")'),description:c2.string().min(3).max(100).describe("Short task description (3-5 words)"),prompt:c2.string().min(10).describe("Detailed task instructions")}),description:{short:"Launch a specialized agent to handle complex, multi-step tasks autonomously",long:`
780
+ `)}`}loadFromDirectory($){if(!k4.existsSync($))return;let Y=k4.readdirSync($);for(let X of Y){if(!X.endsWith(".md"))continue;let Z=HZ.join($,X);try{let Q=this.parseConfigFile(Z);this.register(Q)}catch(Q){FZ.warn(`Failed to load subagent config from ${Z}:`,Q)}}}parseConfigFile($){let X=k4.readFileSync($,"utf-8").match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);if(!X)throw Error(`No YAML frontmatter found in ${$}`);let[,Z,Q]=X,J=_Z.parse(Z);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 $=R0("node:os"),Y=R0("node:path"),X=Y.join($.homedir(),".blade","agents");this.loadFromDirectory(X);let Z=Y.join(process.cwd(),".blade","agents");return this.loadFromDirectory(Z),this.getAllNames().length}clear(){this.subagents.clear()}}var B0=new Q5;function zZ(){let $=B0.getAllNames();if($.length===0)return["Explore"];return $}var y4=s({name:"Task",displayName:"Subagent Scheduler",kind:"readonly",isReadOnly:!0,schema:s2.object({subagent_type:s2.enum(zZ()).describe('Subagent type to use (e.g., "Explore", "Plan")'),description:s2.string().min(3).max(100).describe("Short task description (3-5 words)"),prompt:s2.string().min(10).describe("Detailed task instructions")}),description:{short:"Launch a specialized agent to handle complex, multi-step tasks autonomously",long:`
784
781
  Launch a specialized agent to handle complex, multi-step tasks autonomously.
785
782
 
786
783
  The Task tool launches specialized agents (subprocesses) that autonomously handle complex tasks. Each agent type has specific capabilities and tools available to it.
787
784
 
788
- ${N0.getDescriptionsForPrompt()}
785
+ ${B0.getDescriptionsForPrompt()}
789
786
 
790
787
  **How to use the Task tool:**
791
788
  - Set subagent_type to ANY agent name from the list above (e.g., 'Explore', 'Plan', 'code-reviewer', etc.)
@@ -806,9 +803,9 @@ ${N0.getDescriptionsForPrompt()}
806
803
  - 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
807
804
  - 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.
808
805
  - 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.
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:X,description:Z,prompt:Q}=$,{updateOutput:J}=Y;try{let q=N0.getAllNames();console.log(`[Task] subagentRegistry 状态: registered=${q.length}, names=[${q.join(", ")}], looking for="${X}"`);let G=N0.getSubagent(X);if(!G)return{success:!1,llmContent:`Unknown subagent type: ${X}. Available types: ${q.join(", ")||"none"}`,displayContent:`❌ 未知的 subagent 类型: ${X}
806
+ `.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:X,description:Z,prompt:Q}=$,{updateOutput:J}=Y;try{let q=B0.getAllNames();console.log(`[Task] subagentRegistry 状态: registered=${q.length}, names=[${q.join(", ")}], looking for="${X}"`);let G=B0.getSubagent(X);if(!G)return{success:!1,llmContent:`Unknown subagent type: ${X}. Available types: ${q.join(", ")||"none"}`,displayContent:`❌ 未知的 subagent 类型: ${X}
810
807
 
811
- 可用类型: ${q.join(", ")||"无"}`,error:{type:"execution_error",message:`Unknown subagent type: ${X}`}};J?.(`\uD83D\uDE80 启动 ${X} subagent: ${Z}`);let K=new w4(G),W={prompt:Q,parentSessionId:Y.sessionId,permissionMode:Y.permissionMode};J?.("⚙️ 执行任务中...");let O=Date.now(),U=await K.execute(W),H=Date.now()-O;if(U.success){let _=U.message.length>1000?U.message.slice(0,1000)+`
808
+ 可用类型: ${q.join(", ")||"无"}`,error:{type:"execution_error",message:`Unknown subagent type: ${X}`}};J?.(`\uD83D\uDE80 启动 ${X} subagent: ${Z}`);let K=new M4(G),W={prompt:Q,parentSessionId:Y.sessionId,permissionMode:Y.permissionMode};J?.("⚙️ 执行任务中...");let O=Date.now(),U=await K.execute(W),H=Date.now()-O;if(U.success){let _=U.message.length>1000?U.message.slice(0,1000)+`
812
809
  ...(截断)`:U.message;return{success:!0,llmContent:U.message,displayContent:`✅ Subagent 任务完成
813
810
 
814
811
  `+`类型: ${X}
@@ -827,7 +824,7 @@ ${_}`,metadata:{subagent_type:X,description:Z,duration:H,stats:U.stats}}}else re
827
824
 
828
825
  ${G.message}
829
826
 
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:()=>""});import{randomUUID as aX}from"crypto";import*as L$ from"fs/promises";import*as l2 from"path";class T1{static instances=new Map;todos=[];filePath;loaded=!1;constructor($,Y){this.filePath=l2.join(Y,"todos",`${$}-agent-${$}.json`)}static getInstance($,Y){let X=`${$}-${Y}`;if(!T1.instances.has(X))T1.instances.set(X,new T1($,Y));return T1.instances.get(X)}validate($){if($.filter((X)=>X.status==="in_progress").length>1)return{valid:!1,error:"同时只能有一个任务处于 in_progress 状态"};return{valid:!0}}async updateTodos($){await this.ensureLoaded();let Y=new Date().toISOString(),X=$.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||aX(),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}}),Z=this.validate(X);if(!Z.valid)throw Error(Z.error);this.todos=X,await this.saveTodos()}getSortedTodos(){let $={completed:0,in_progress:1,pending:2},Y={high:0,medium:1,low:2};return[...this.todos].sort((X,Z)=>{let Q=$[X.status]-$[Z.status];if(Q!==0)return Q;return Y[X.priority]-Y[Z.priority]})}getTodos(){return this.getSortedTodos()}async ensureLoaded(){if(!this.loaded)await this.loadTodos(),this.loaded=!0}async loadTodos(){try{let $=await L$.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 L$.mkdir(l2.dirname(this.filePath),{recursive:!0}),await L$.writeFile(this.filePath,JSON.stringify(this.todos,null,2),"utf-8")}catch($){throw console.error("保存 TODO 列表失败:",$),$}}}import{z as i9}from"zod";import{z as w$}from"zod";var l9=w$.object({id:w$.string().optional(),content:w$.string().min(1,"Content cannot be empty"),status:w$.enum(["pending","in_progress","completed"]),activeForm:w$.string().min(1,"ActiveForm cannot be empty"),priority:w$.enum(["high","medium","low"]).default("medium")});function b4($){let{sessionId:Y,configDir:X}=$;return n({name:"TodoWrite",displayName:"Todo Write",kind:"readonly",schema:i9.object({todos:i9.array(l9).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.
827
+ ${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:()=>""});import{randomUUID as NZ}from"crypto";import*as D$ from"fs/promises";import*as t2 from"path";class x1{static instances=new Map;todos=[];filePath;loaded=!1;constructor($,Y){this.filePath=t2.join(Y,"todos",`${$}-agent-${$}.json`)}static getInstance($,Y){let X=`${$}-${Y}`;if(!x1.instances.has(X))x1.instances.set(X,new x1($,Y));return x1.instances.get(X)}validate($){if($.filter((X)=>X.status==="in_progress").length>1)return{valid:!1,error:"同时只能有一个任务处于 in_progress 状态"};return{valid:!0}}async updateTodos($){await this.ensureLoaded();let Y=new Date().toISOString(),X=$.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||NZ(),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}}),Z=this.validate(X);if(!Z.valid)throw Error(Z.error);this.todos=X,await this.saveTodos()}getSortedTodos(){let $={completed:0,in_progress:1,pending:2},Y={high:0,medium:1,low:2};return[...this.todos].sort((X,Z)=>{let Q=$[X.status]-$[Z.status];if(Q!==0)return Q;return Y[X.priority]-Y[Z.priority]})}getTodos(){return this.getSortedTodos()}async ensureLoaded(){if(!this.loaded)await this.loadTodos(),this.loaded=!0}async loadTodos(){try{let $=await D$.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 D$.mkdir(t2.dirname(this.filePath),{recursive:!0}),await D$.writeFile(this.filePath,JSON.stringify(this.todos,null,2),"utf-8")}catch($){throw console.error("保存 TODO 列表失败:",$),$}}}import{z as q5}from"zod";import{z as v$}from"zod";var J5=v$.object({id:v$.string().optional(),content:v$.string().min(1,"Content cannot be empty"),status:v$.enum(["pending","in_progress","completed"]),activeForm:v$.string().min(1,"ActiveForm cannot be empty"),priority:v$.enum(["high","medium","low"]).default("medium")});function E4($){let{sessionId:Y,configDir:X}=$;return s({name:"TodoWrite",displayName:"Todo Write",kind:"readonly",schema:q5.object({todos:q5.array(J5).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.
831
828
  It also helps the user understand the progress of the task and overall progress of their requests.
832
829
 
833
830
  ## When to Use This Tool
@@ -888,9 +885,9 @@ NOTE that you should not use this tool if there is only one trivial task to do.
888
885
  - activeForm: "Fixing authentication bug"
889
886
 
890
887
  When in doubt, use this tool. Being proactive with task management demonstrates attentiveness and ensures you complete all requirements successfully.
891
- `},async execute(Z,Q){let{todos:J}=Z,{updateOutput:q}=Q;try{let G=Q.sessionId||Y,K=T1.getInstance(G,X);q?.("Updating TODO list..."),await K.updateTodos(J);let W=K.getTodos(),O=nX(W),U=oX(W,O);return q?.(`✅ TODO list updated (${O.completed}/${O.total} completed)`),{success:!0,llmContent:{todos:W,stats:O},displayContent:U,metadata:{stats:O}}}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:(Z)=>`${Z.todos.length} todos`,abstractPermissionRule:()=>"*"})}function nX($){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 oX($,Y){let X=[],Z=Y.total>0?Math.round(Y.completed/Y.total*100):0;if(X.push(`\uD83D\uDCCB TODO 列表 (${Y.completed}/${Y.total} 完成,${Z}%)`),X.push(""),$.length===0)return X.push(" (暂无任务)"),X.join(`
888
+ `},async execute(Z,Q){let{todos:J}=Z,{updateOutput:q}=Q;try{let G=Q.sessionId||Y,K=x1.getInstance(G,X);q?.("Updating TODO list..."),await K.updateTodos(J);let W=K.getTodos(),O=BZ(W),U=LZ(W,O);return q?.(`✅ TODO list updated (${O.completed}/${O.total} completed)`),{success:!0,llmContent:{todos:W,stats:O},displayContent:U,metadata:{stats:O}}}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:(Z)=>`${Z.todos.length} todos`,abstractPermissionRule:()=>"*"})}function BZ($){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 LZ($,Y){let X=[],Z=Y.total>0?Math.round(Y.completed/Y.total*100):0;if(X.push(`\uD83D\uDCCB TODO 列表 (${Y.completed}/${Y.total} 完成,${Z}%)`),X.push(""),$.length===0)return X.push(" (暂无任务)"),X.join(`
892
889
  `);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"?"~~":"";X.push(` ${J} ${q} ${K}${Q.content}${K}${G}`)}return X.join(`
893
- `)}import{z as I1}from"zod";var V4=n({name:"WebFetch",displayName:"Web Fetch",kind:"readonly",schema:I1.object({url:I1.string().url().describe("URL to request"),method:I1.enum(["GET","POST","PUT","DELETE","HEAD"]).default("GET").describe("HTTP method"),headers:I1.record(I1.string()).optional().describe("Request headers (optional)"),body:I1.string().optional().describe("Request body (optional)"),timeout:G0.timeout(1000,120000,30000),follow_redirects:I1.boolean().default(!0).describe("Follow redirects"),max_redirects:I1.number().int().min(0).max(10).default(5).describe("Maximum redirect hops"),return_headers:I1.boolean().default(!1).describe("Return response headers")}),description:{short:"Fetches content from a specified URL and processes it using an AI model",long:`
890
+ `)}import{z as k1}from"zod";var j4=s({name:"WebFetch",displayName:"Web Fetch",kind:"readonly",schema:k1.object({url:k1.string().url().describe("URL to request"),method:k1.enum(["GET","POST","PUT","DELETE","HEAD"]).default("GET").describe("HTTP method"),headers:k1.record(k1.string()).optional().describe("Request headers (optional)"),body:k1.string().optional().describe("Request body (optional)"),timeout:U0.timeout(1000,120000,30000),follow_redirects:k1.boolean().default(!0).describe("Follow redirects"),max_redirects:k1.number().int().min(0).max(10).default(5).describe("Maximum redirect hops"),return_headers:k1.boolean().default(!1).describe("Return response headers")}),description:{short:"Fetches content from a specified URL and processes it using an AI model",long:`
894
891
  - Fetches content from a specified URL and processes it using an AI model
895
892
  - Takes a URL and a prompt as input
896
893
  - Fetches the URL content, converts HTML to markdown
@@ -907,14 +904,14 @@ Usage notes:
907
904
  - Results may be summarized if the content is very large
908
905
  - Includes a self-cleaning 15-minute cache for faster responses when repeatedly accessing the same URL
909
906
  - 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.
910
- `},async execute($,Y){let{url:X,method:Z="GET",headers:Q={},body:J,timeout:q=30000,follow_redirects:G=!0,max_redirects:K=5,return_headers:W=!1}=$,{updateOutput:O}=Y,U=Y.signal??new AbortController().signal;try{O?.(`发送 ${Z} 请求到: ${X}`);let H=Date.now(),_=await sX({url:X,method:Z,headers:Q,body:J,timeout:q,follow_redirects:G,max_redirects:K,signal:U}),z=Date.now()-H;if(_.response_time=z,!W)delete _.headers;let F={url:X,method:Z,status:_.status,response_time:z,content_length:Buffer.byteLength(_.body||"","utf8"),redirected:_.redirected||!1,redirect_count:_.redirect_count??0,final_url:_.url,content_type:_.content_type,redirect_chain:_.redirect_chain};if(_.status>=400)return{success:!1,llmContent:`HTTP error ${_.status}: ${_.status_text}`,displayContent:r9(_,F,!0),error:{type:"execution_error",message:`HTTP error ${_.status}: ${_.status_text}`,details:{...F,response_body:_.body}},metadata:F};return{success:!0,llmContent:_,displayContent:r9(_,F,!1),metadata:F}}catch(H){if(H.name==="AbortError")return{success:!1,llmContent:"Request aborted",displayContent:"⚠️ 请求被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`Network request failed: ${H.message}`,displayContent:`❌ 网络请求失败: ${H.message}`,error:{type:"execution_error",message:H.message,details:H}}}},version:"2.0.0",category:"网络工具",tags:["web","http","fetch","request","api"],extractSignatureContent:($)=>{try{return`domain:${new URL($.url).hostname}`}catch{return $.url}},abstractPermissionRule:($)=>{try{return`domain:${new URL($.url).hostname}`}catch{return"*"}}});async function sX($){let{url:Y,method:X,headers:Z,body:Q,timeout:J,follow_redirects:q,max_redirects:G,signal:K}=$,W={"User-Agent":"Blade-AI/1.0",...Z},O=Y,U=X,H=Q,_=0,z=[];while(!0){let F={...W};if(H&&U!=="GET"&&U!=="HEAD"&&!ZZ(F,"content-type"))F["Content-Type"]="application/json";let L=await $Z(O,{method:U,headers:F,body:H&&U!=="GET"&&U!=="HEAD"?H:void 0,redirect:"manual"},J,K),w=L.headers.get("location"),N=L.status>=300&&L.status<400,A=q&&N&&w&&_<G;if(N&&q&&!w)throw Error(`收到状态码 ${L.status} 但响应缺少 Location 头`);if(N&&q&&_>=G)throw Error(`超过最大重定向次数 (${G})`);if(A&&w){_++;let R=YZ(w,O);if(z.push(`${L.status} → ${R}`),L.status===303||(L.status===301||L.status===302)&&U!=="GET"&&U!=="HEAD")U="GET",H=void 0;O=R;continue}let b=await L.text(),y=XZ(L.headers);return{status:L.status,status_text:L.statusText,headers:y,body:b,url:L.url||O,redirected:_>0,redirect_count:_,redirect_chain:z,content_type:y["content-type"],response_time:0}}}function r9($,Y,X){let{url:Z,method:Q,status:J,response_time:q,content_length:G}=Y,K=X?`❌ ${Q} ${Z} - ${J} ${$.status_text}`:`✅ ${Q} ${Z} - ${J} ${$.status_text}`;if(K+=`
907
+ `},async execute($,Y){let{url:X,method:Z="GET",headers:Q={},body:J,timeout:q=30000,follow_redirects:G=!0,max_redirects:K=5,return_headers:W=!1}=$,{updateOutput:O}=Y,U=Y.signal??new AbortController().signal;try{O?.(`发送 ${Z} 请求到: ${X}`);let H=Date.now(),_=await wZ({url:X,method:Z,headers:Q,body:J,timeout:q,follow_redirects:G,max_redirects:K,signal:U}),z=Date.now()-H;if(_.response_time=z,!W)delete _.headers;let F={url:X,method:Z,status:_.status,response_time:z,content_length:Buffer.byteLength(_.body||"","utf8"),redirected:_.redirected||!1,redirect_count:_.redirect_count??0,final_url:_.url,content_type:_.content_type,redirect_chain:_.redirect_chain};if(_.status>=400)return{success:!1,llmContent:`HTTP error ${_.status}: ${_.status_text}`,displayContent:G5(_,F,!0),error:{type:"execution_error",message:`HTTP error ${_.status}: ${_.status_text}`,details:{...F,response_body:_.body}},metadata:F};return{success:!0,llmContent:_,displayContent:G5(_,F,!1),metadata:F}}catch(H){if(H.name==="AbortError")return{success:!1,llmContent:"Request aborted",displayContent:"⚠️ 请求被用户中止",error:{type:"execution_error",message:"操作被中止"}};return{success:!1,llmContent:`Network request failed: ${H.message}`,displayContent:`❌ 网络请求失败: ${H.message}`,error:{type:"execution_error",message:H.message,details:H}}}},version:"2.0.0",category:"网络工具",tags:["web","http","fetch","request","api"],extractSignatureContent:($)=>{try{return`domain:${new URL($.url).hostname}`}catch{return $.url}},abstractPermissionRule:($)=>{try{return`domain:${new URL($.url).hostname}`}catch{return"*"}}});async function wZ($){let{url:Y,method:X,headers:Z,body:Q,timeout:J,follow_redirects:q,max_redirects:G,signal:K}=$,W={"User-Agent":"Blade-AI/1.0",...Z},O=Y,U=X,H=Q,_=0,z=[];while(!0){let F={...W};if(H&&U!=="GET"&&U!=="HEAD"&&!DZ(F,"content-type"))F["Content-Type"]="application/json";let B=await bZ(O,{method:U,headers:F,body:H&&U!=="GET"&&U!=="HEAD"?H:void 0,redirect:"manual"},J,K),L=B.headers.get("location"),N=B.status>=300&&B.status<400,A=q&&N&&L&&_<G;if(N&&q&&!L)throw Error(`收到状态码 ${B.status} 但响应缺少 Location 头`);if(N&&q&&_>=G)throw Error(`超过最大重定向次数 (${G})`);if(A&&L){_++;let I=VZ(L,O);if(z.push(`${B.status} → ${I}`),B.status===303||(B.status===301||B.status===302)&&U!=="GET"&&U!=="HEAD")U="GET",H=void 0;O=I;continue}let R=await B.text(),k=IZ(B.headers);return{status:B.status,status_text:B.statusText,headers:k,body:R,url:B.url||O,redirected:_>0,redirect_count:_,redirect_chain:z,content_type:k["content-type"],response_time:0}}}function G5($,Y,X){let{url:Z,method:Q,status:J,response_time:q,content_length:G}=Y,K=X?`❌ ${Q} ${Z} - ${J} ${$.status_text}`:`✅ ${Q} ${Z} - ${J} ${$.status_text}`;if(K+=`
911
908
  响应时间: ${q}ms`,K+=`
912
909
  内容长度: ${G} 字节`,Y.content_type)K+=`
913
910
  Content-Type: ${Y.content_type}`;if($.redirected&&Y.final_url&&Y.final_url!==Z){if(K+=`
914
911
  最终URL: ${Y.final_url}`,Y.redirect_count)K+=`
915
- 重定向次数: ${Y.redirect_count}`}let W=tX($.body,$.content_type);if(W)K+=`
912
+ 重定向次数: ${Y.redirect_count}`}let W=AZ($.body,$.content_type);if(W)K+=`
916
913
  响应内容:
917
- ${W}`;return K}function tX($,Y){if(!$)return"(空响应)";if(eX(Y,$))return"[binary content omitted]";let X=$.trim();if(!X)return"(仅包含空白字符)";return X.length>800?`${X.slice(0,800)}...`:X}function eX($,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 X=0,Z=Math.min(Y.length,200);for(let Q=0;Q<Z;Q++){let J=Y.charCodeAt(Q);if(J===9||J===10||J===13)continue;if(J<32||J>126)X++}return X/(Z||1)>0.3}async function $Z($,Y,X,Z){let Q=new AbortController,J=setTimeout(()=>Q.abort(),X),q=()=>Q.abort();Z?.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),Z?.removeEventListener("abort",q)}}function YZ($,Y){try{return new URL($,Y).toString()}catch{return $}}function XZ($){let Y={};return $.forEach((X,Z)=>{Y[Z.toLowerCase()]=X}),Y}function ZZ($,Y){let X=Y.toLowerCase();return Object.keys($).some((Z)=>Z.toLowerCase()===X)}import{z as A$}from"zod";var QZ="https://duckduckgo.com/",JZ=15000,qZ=8,D4=n({name:"WebSearch",displayName:"Web Search",kind:"readonly",schema:A$.object({query:A$.string().min(2,"Search query must be at least 2 characters").describe("Search query"),allowed_domains:A$.array(A$.string().min(1)).optional().describe("Return results only from these domains (optional)"),blocked_domains:A$.array(A$.string().min(1)).optional().describe("Exclude results from these domains (optional)")}),description:{short:"Search the web and use the results to inform responses",long:`
914
+ ${W}`;return K}function AZ($,Y){if(!$)return"(空响应)";if(RZ(Y,$))return"[binary content omitted]";let X=$.trim();if(!X)return"(仅包含空白字符)";return X.length>800?`${X.slice(0,800)}...`:X}function RZ($,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 X=0,Z=Math.min(Y.length,200);for(let Q=0;Q<Z;Q++){let J=Y.charCodeAt(Q);if(J===9||J===10||J===13)continue;if(J<32||J>126)X++}return X/(Z||1)>0.3}async function bZ($,Y,X,Z){let Q=new AbortController,J=setTimeout(()=>Q.abort(),X),q=()=>Q.abort();Z?.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),Z?.removeEventListener("abort",q)}}function VZ($,Y){try{return new URL($,Y).toString()}catch{return $}}function IZ($){let Y={};return $.forEach((X,Z)=>{Y[Z.toLowerCase()]=X}),Y}function DZ($,Y){let X=Y.toLowerCase();return Object.keys($).some((Z)=>Z.toLowerCase()===X)}import{z as M$}from"zod";var vZ="https://duckduckgo.com/",MZ=15000,kZ=8,P4=s({name:"WebSearch",displayName:"Web Search",kind:"readonly",schema:M$.object({query:M$.string().min(2,"Search query must be at least 2 characters").describe("Search query"),allowed_domains:M$.array(M$.string().min(1)).optional().describe("Return results only from these domains (optional)"),blocked_domains:M$.array(M$.string().min(1)).optional().describe("Exclude results from these domains (optional)")}),description:{short:"Search the web and use the results to inform responses",long:`
918
915
  - Search the web and use the results to inform responses
919
916
  - Provides up-to-date information for current events and recent data
920
917
  - Returns search result information formatted as search result blocks, including links as markdown hyperlinks
@@ -939,18 +936,18 @@ Usage notes:
939
936
  IMPORTANT - Use the correct year in search queries:
940
937
  - You MUST use the current year when searching for recent information, documentation, or current events.
941
938
  - Example: If the user asks for "latest React docs", search for "React documentation 2025", NOT "React documentation 2024"
942
- `},async execute($,Y){let{query:X}=$,Z=a9($.allowed_domains),Q=a9($.blocked_domains),{updateOutput:J}=Y,q=Y.signal??new AbortController().signal;J?.(`\uD83D\uDD0E Searching: "${X}"`);try{let G=await KZ(GZ(X),{headers:{Accept:"application/json, text/plain;q=0.9","User-Agent":"Blade-AI-WebSearch/1.0"}},JZ,q);if(!G.ok)throw Error(`Search request failed with status ${G.status}`);let K=await G.text(),W;try{W=JSON.parse(K)}catch{throw Error("Failed to parse search result JSON")}let O=WZ(W),U=_Z(O,Z,Q),H=U.slice(0,qZ),_={query:X,results:H,provider:"duckduckgo",total_results:U.length,fetched_at:new Date().toISOString()},z={query:X,provider:"duckduckgo",fetched_at:_.fetched_at,total_results:U.length,returned_results:H.length,allowed_domains:Z,blocked_domains:Q};if(H.length===0)return{success:!0,llmContent:_,displayContent:`\uD83D\uDD0D WebSearch("${X}") 未找到匹配结果`,metadata:z};return{success:!0,llmContent:_,displayContent:FZ(X,H,U.length),metadata:z}}catch(G){return{success:!1,llmContent:`WebSearch call failed: ${G.message}`,displayContent:`❌ WebSearch 调用失败: ${G.message}`,error:{type:"execution_error",message:G.message,details:{query:X,allowedDomains:Z,blockedDomains:Q}}}}},version:"1.0.0",category:"网络工具",tags:["web","search","internet","news"],extractSignatureContent:($)=>`search:${zZ($.query)}`,abstractPermissionRule:()=>"search:*"});function GZ($){let Y=new URL(QZ);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()}async function KZ($,Y,X,Z){let Q=new AbortController,J=setTimeout(()=>Q.abort(),X),q=()=>Q.abort();Z?.addEventListener("abort",q);try{return await fetch($,{...Y,signal:Q.signal})}catch(G){if(G.name==="AbortError")throw Error("搜索请求超时或被中止");throw G}finally{clearTimeout(J),Z?.removeEventListener("abort",q)}}function WZ($){let Y=($.Results??[]).map((Z)=>UZ(Z)).filter((Z)=>Z!==null),X=o9($.RelatedTopics??[]);return[...Y,...X]}function UZ($){if(!$.FirstURL||!$.Text)return null;let{title:Y,snippet:X}=s9($.Text);return{title:Y,snippet:X,url:$.FirstURL,display_url:t9($.FirstURL),source:I4($.FirstURL)??""}}function o9($){let Y=[];for(let X of $){if(X.Topics&&X.Topics.length>0){Y.push(...o9(X.Topics));continue}if(X.FirstURL&&X.Text){let{title:Z,snippet:Q}=s9(X.Text);Y.push({title:Z,snippet:Q,url:X.FirstURL,display_url:t9(X.FirstURL),source:I4(X.FirstURL)??""})}}return Y}function s9($){let Y=OZ($).trim();if(!Y.includes(" - "))return{title:Y,snippet:Y};let[X,...Z]=Y.split(" - "),Q=X.trim(),J=Z.join(" - ").trim()||Y;return{title:Q,snippet:J}}function OZ($){return $.replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#39;/g,"'")}function t9($){try{let Y=new URL($),X=Y.pathname==="/"?"":Y.pathname;return`${Y.hostname}${X}`}catch{return $}}function I4($){try{return new URL($).hostname.toLowerCase()}catch{return null}}function HZ($){return $.trim().toLowerCase()}function a9($){if(!$||$.length===0)return[];return $.map(HZ).filter(Boolean)}function n9($,Y){return $===Y||$.endsWith(`.${Y}`)}function _Z($,Y,X){return $.filter((Z)=>{let Q=I4(Z.url);if(!Q)return!1;if(X.length>0&&X.some((J)=>n9(Q,J)))return!1;if(Y.length>0&&!Y.some((J)=>n9(Q,J)))return!1;return!0})}function FZ($,Y,X){let Z=`\uD83D\uDD0E WebSearch("${$}") - 返回 ${Y.length}/${X} 条结果`,Q=Y.map((J,q)=>`${q+1}. ${J.title}
939
+ `},async execute($,Y){let{query:X}=$,Z=K5($.allowed_domains),Q=K5($.blocked_domains),{updateOutput:J}=Y,q=Y.signal??new AbortController().signal;J?.(`\uD83D\uDD0E Searching: "${X}"`);try{let G=await EZ(yZ(X),{headers:{Accept:"application/json, text/plain;q=0.9","User-Agent":"Blade-AI-WebSearch/1.0"}},MZ,q);if(!G.ok)throw Error(`Search request failed with status ${G.status}`);let K=await G.text(),W;try{W=JSON.parse(K)}catch{throw Error("Failed to parse search result JSON")}let O=jZ(W),U=CZ(O,Z,Q),H=U.slice(0,kZ),_={query:X,results:H,provider:"duckduckgo",total_results:U.length,fetched_at:new Date().toISOString()},z={query:X,provider:"duckduckgo",fetched_at:_.fetched_at,total_results:U.length,returned_results:H.length,allowed_domains:Z,blocked_domains:Q};if(H.length===0)return{success:!0,llmContent:_,displayContent:`\uD83D\uDD0D WebSearch("${X}") 未找到匹配结果`,metadata:z};return{success:!0,llmContent:_,displayContent:fZ(X,H,U.length),metadata:z}}catch(G){return{success:!1,llmContent:`WebSearch call failed: ${G.message}`,displayContent:`❌ WebSearch 调用失败: ${G.message}`,error:{type:"execution_error",message:G.message,details:{query:X,allowedDomains:Z,blockedDomains:Q}}}}},version:"1.0.0",category:"网络工具",tags:["web","search","internet","news"],extractSignatureContent:($)=>`search:${hZ($.query)}`,abstractPermissionRule:()=>"search:*"});function yZ($){let Y=new URL(vZ);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()}async function EZ($,Y,X,Z){let Q=new AbortController,J=setTimeout(()=>Q.abort(),X),q=()=>Q.abort();Z?.addEventListener("abort",q);try{return await fetch($,{...Y,signal:Q.signal})}catch(G){if(G.name==="AbortError")throw Error("搜索请求超时或被中止");throw G}finally{clearTimeout(J),Z?.removeEventListener("abort",q)}}function jZ($){let Y=($.Results??[]).map((Z)=>PZ(Z)).filter((Z)=>Z!==null),X=U5($.RelatedTopics??[]);return[...Y,...X]}function PZ($){if(!$.FirstURL||!$.Text)return null;let{title:Y,snippet:X}=O5($.Text);return{title:Y,snippet:X,url:$.FirstURL,display_url:H5($.FirstURL),source:S4($.FirstURL)??""}}function U5($){let Y=[];for(let X of $){if(X.Topics&&X.Topics.length>0){Y.push(...U5(X.Topics));continue}if(X.FirstURL&&X.Text){let{title:Z,snippet:Q}=O5(X.Text);Y.push({title:Z,snippet:Q,url:X.FirstURL,display_url:H5(X.FirstURL),source:S4(X.FirstURL)??""})}}return Y}function O5($){let Y=SZ($).trim();if(!Y.includes(" - "))return{title:Y,snippet:Y};let[X,...Z]=Y.split(" - "),Q=X.trim(),J=Z.join(" - ").trim()||Y;return{title:Q,snippet:J}}function SZ($){return $.replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#39;/g,"'")}function H5($){try{let Y=new URL($),X=Y.pathname==="/"?"":Y.pathname;return`${Y.hostname}${X}`}catch{return $}}function S4($){try{return new URL($).hostname.toLowerCase()}catch{return null}}function TZ($){return $.trim().toLowerCase()}function K5($){if(!$||$.length===0)return[];return $.map(TZ).filter(Boolean)}function W5($,Y){return $===Y||$.endsWith(`.${Y}`)}function CZ($,Y,X){return $.filter((Z)=>{let Q=S4(Z.url);if(!Q)return!1;if(X.length>0&&X.some((J)=>W5(Q,J)))return!1;if(Y.length>0&&!Y.some((J)=>W5(Q,J)))return!1;return!0})}function fZ($,Y,X){let Z=`\uD83D\uDD0E WebSearch("${$}") - 返回 ${Y.length}/${X} 条结果`,Q=Y.map((J,q)=>`${q+1}. ${J.title}
943
940
  ${J.display_url}
944
941
  ${J.snippet}`);return[Z,...Q].join(`
945
- `)}function zZ($){let Y=$.trim().toLowerCase();return Y.length>80?Y.slice(0,80):Y}async function NZ(){try{return await k0.getInstance().getAvailableTools()}catch($){return console.warn("MCP协议工具加载失败:",$),[]}}async function Y5($){let Y=$?.sessionId||`session_${Date.now()}`,X=$?.configDir||$5.join(e9.homedir(),".blade"),Z=[e6,t6,Y4,X4,K4,O4,_4,z4,N4,V4,D4,R4,b4({sessionId:Y,configDir:X}),Z4,J4,B4,L4],Q=await NZ();return[...Z,...Q]}import{EventEmitter as SZ}from"events";import{nanoid as EZ}from"nanoid";import{nanoid as Q5}from"nanoid";var i2;((Z)=>{Z.PreToolUse="PreToolUse";Z.PostToolUse="PostToolUse";Z.Stop="Stop"})(i2||={});var k4;((Z)=>{Z.Approve="approve";Z.Block="block";Z.Async="async"})(k4||={});var v4;((Z)=>{Z.Allow="allow";Z.Deny="deny";Z.Ask="ask"})(v4||={});var M4={enabled:!1,defaultTimeout:60,timeoutBehavior:"ignore",failureBehavior:"ignore",maxConcurrentHooks:5,PreToolUse:[],PostToolUse:[],Stop:[]};function y4($,Y){return{...$,...Y,PreToolUse:Y.PreToolUse??$.PreToolUse,PostToolUse:Y.PostToolUse??$.PostToolUse,Stop:Y.Stop??$.Stop}}function X5(){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 $}import{spawn as BZ}from"child_process";class E4{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 j4{MAX_STDOUT_SIZE=1048576;MAX_STDERR_SIZE=1048576;MAX_INPUT_SIZE=102400;async execute($,Y,X,Z){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=BZ($,[],{shell:!0,env:J,cwd:X.projectDir,timeout:Z}),G=new E4(this.MAX_STDOUT_SIZE),K=new E4(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,O)=>{let U=!1,H=setTimeout(()=>{U=!0,q.kill("SIGKILL")},Z);if(q.on("close",(_)=>{clearTimeout(H),W({stdout:G.getContent(),stderr:K.getContent(),exitCode:U?124:_??1,timedOut:U})}),q.on("error",(_)=>{clearTimeout(H),O(_)}),X.abortSignal)X.abortSignal.addEventListener("abort",()=>{clearTimeout(H),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"}}}import{z as j}from"zod";var S4=j.object({hook_event_name:j.nativeEnum(i2),hook_execution_id:j.string(),timestamp:j.string(),project_dir:j.string(),session_id:j.string(),permission_mode:j.enum(["default","autoEdit","yolo","plan"]),_metadata:j.object({blade_version:j.string(),hook_timeout_ms:j.number()}).optional()}),wZ=S4.extend({hook_event_name:j.literal("PreToolUse"),tool_name:j.string(),tool_use_id:j.string(),tool_input:j.record(j.unknown())}),AZ=S4.extend({hook_event_name:j.literal("PostToolUse"),tool_name:j.string(),tool_use_id:j.string(),tool_input:j.record(j.unknown()),tool_response:j.unknown()}),RZ=S4.extend({hook_event_name:j.literal("Stop"),reason:j.string().optional()}),zF=j.discriminatedUnion("hook_event_name",[wZ,AZ,RZ]),bZ=j.object({hookEventName:j.literal("PreToolUse"),permissionDecision:j.nativeEnum(v4).optional(),permissionDecisionReason:j.string().optional(),updatedInput:j.record(j.unknown()).optional()}),VZ=j.object({hookEventName:j.literal("PostToolUse"),additionalContext:j.string().optional(),updatedOutput:j.unknown().optional()}),DZ=j.object({decision:j.object({behavior:j.nativeEnum(k4)}).optional(),systemMessage:j.string().optional(),hookSpecificOutput:j.discriminatedUnion("hookEventName",[bZ,VZ]).optional(),suppressOutput:j.boolean().optional()}),IZ=j.object({type:j.literal("command"),command:j.string(),timeout:j.number().positive().optional(),statusMessage:j.string().optional()}),kZ=j.object({type:j.literal("prompt"),prompt:j.string(),timeout:j.number().positive().optional()}),vZ=j.discriminatedUnion("type",[IZ,kZ]),MZ=j.object({tools:j.string().optional(),paths:j.string().optional(),commands:j.string().optional()}),P4=j.object({name:j.string().optional(),matcher:MZ.optional(),hooks:j.array(vZ)}),NF=j.object({enabled:j.boolean().optional(),defaultTimeout:j.number().positive().optional(),timeoutBehavior:j.enum(["ignore","deny","ask"]).optional(),failureBehavior:j.enum(["ignore","deny","ask"]).optional(),maxConcurrentHooks:j.number().positive().optional(),PreToolUse:j.array(P4).optional(),PostToolUse:j.array(P4).optional(),Stop:j.array(P4).optional()});function Z5($){let Y=DZ.safeParse($);if(Y.success)return{success:!0,data:Y.data};return{success:!1,error:Y.error}}class T4{parse($,Y,X){if($.timedOut){let Q=X?.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 Z=this.tryParseJSON($.stdout);if(Z){let Q=Z5(Z);if(!Q.success){let q="error"in Q?Q.error.message:"Unknown validation error",G=X?.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,X)}parseByExitCode($,Y,X){let Z=$.exitCode;switch(Z){case 0:return{success:!0,stdout:$.stdout,stderr:$.stderr,exitCode:Z,hook:Y};case 2:return{success:!1,blocking:!0,error:$.stderr||$.stdout||"Hook returned exit code 2",stdout:$.stdout,stderr:$.stderr,exitCode:Z,hook:Y};case 124:{let Q=X?.timeoutBehavior||"ignore",J="Hook timeout";if(Q==="deny")return{success:!1,blocking:!0,error:"Hook timeout",stdout:$.stdout,stderr:$.stderr,exitCode:Z,hook:Y};else if(Q==="ask")return{success:!1,blocking:!1,needsConfirmation:!0,warning:"Hook timeout. Continue?",stdout:$.stdout,stderr:$.stderr,exitCode:Z,hook:Y};else return{success:!1,blocking:!1,warning:"Hook timeout",stdout:$.stdout,stderr:$.stderr,exitCode:Z,hook:Y}}default:{let Q=X?.failureBehavior||"ignore",J=$.stderr||$.stdout||`Hook failed with exit code ${Z}`;if(Q==="deny")return{success:!1,blocking:!0,error:J,stdout:$.stdout,stderr:$.stderr,exitCode:Z,hook:Y};else if(Q==="ask")return{success:!1,blocking:!1,needsConfirmation:!0,warning:`${J}. Continue?`,stdout:$.stdout,stderr:$.stderr,exitCode:Z,hook:Y};else return{success:!1,blocking:!1,warning:J,stdout:$.stdout,stderr:$.stderr,exitCode:Z,hook:Y}}}}tryParseJSON($){try{let Y=$.trim();if(!Y)return null;let X=Y.match(/^\s*(\{[\s\S]*\})\s*$/);if(!X)return null;return JSON.parse(X[1])}catch{return null}}}class C4{processExecutor=new j4;outputParser=new T4;async executePreToolHooks($,Y,X){if($.length===0)return{decision:"allow"};let Z="tool_input"in Y?Y.tool_input:{},Q=[];for(let J of $)try{let q={...Y,...Z&&{tool_input:Z}},G=await this.executeHook(J,q,X);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)Z={...Z,...K.updatedInput}}}catch(q){let G=q instanceof Error?q.message:String(q);if(Q.push(`Hook failed: ${G}`),X.config.failureBehavior==="deny")return{decision:"deny",reason:G};else if(X.config.failureBehavior==="ask")return{decision:"ask",reason:`Hook failed: ${G}. Continue?`}}return{decision:"allow",modifiedInput:Z,warning:Q.length>0?Q.join(`
942
+ `)}function hZ($){let Y=$.trim().toLowerCase();return Y.length>80?Y.slice(0,80):Y}async function xZ(){try{return await v0.getInstance().getAvailableTools()}catch($){return console.warn("MCP协议工具加载失败:",$),[]}}async function z5($){let Y=$?.sessionId||`session_${Date.now()}`,X=$?.configDir||F5.join(_5.homedir(),".blade"),Z=[G4,q4,W4,U4,N4,w4,R4,V4,I4,j4,P4,y4,E4({sessionId:Y,configDir:X}),O4,_4,D4,v4],Q=await xZ();return[...Z,...Q]}import{EventEmitter as YQ}from"events";import{nanoid as tZ}from"nanoid";import{nanoid as L5}from"nanoid";var e2;((Z)=>{Z.PreToolUse="PreToolUse";Z.PostToolUse="PostToolUse";Z.Stop="Stop"})(e2||={});var T4;((Z)=>{Z.Approve="approve";Z.Block="block";Z.Async="async"})(T4||={});var C4;((Z)=>{Z.Allow="allow";Z.Deny="deny";Z.Ask="ask"})(C4||={});var f4={enabled:!1,defaultTimeout:60,timeoutBehavior:"ignore",failureBehavior:"ignore",maxConcurrentHooks:5,PreToolUse:[],PostToolUse:[],Stop:[]};function h4($,Y){return{...$,...Y,PreToolUse:Y.PreToolUse??$.PreToolUse,PostToolUse:Y.PostToolUse??$.PostToolUse,Stop:Y.Stop??$.Stop}}function N5(){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 $}import{spawn as pZ}from"child_process";class x4{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 p4{MAX_STDOUT_SIZE=1048576;MAX_STDERR_SIZE=1048576;MAX_INPUT_SIZE=102400;async execute($,Y,X,Z){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=pZ($,[],{shell:!0,env:J,cwd:X.projectDir,timeout:Z}),G=new x4(this.MAX_STDOUT_SIZE),K=new x4(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,O)=>{let U=!1,H=setTimeout(()=>{U=!0,q.kill("SIGKILL")},Z);if(q.on("close",(_)=>{clearTimeout(H),W({stdout:G.getContent(),stderr:K.getContent(),exitCode:U?124:_??1,timedOut:U})}),q.on("error",(_)=>{clearTimeout(H),O(_)}),X.abortSignal)X.abortSignal.addEventListener("abort",()=>{clearTimeout(H),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"}}}import{z as j}from"zod";var m4=j.object({hook_event_name:j.nativeEnum(e2),hook_execution_id:j.string(),timestamp:j.string(),project_dir:j.string(),session_id:j.string(),permission_mode:j.enum(["default","autoEdit","yolo","plan"]),_metadata:j.object({blade_version:j.string(),hook_timeout_ms:j.number()}).optional()}),mZ=m4.extend({hook_event_name:j.literal("PreToolUse"),tool_name:j.string(),tool_use_id:j.string(),tool_input:j.record(j.unknown())}),uZ=m4.extend({hook_event_name:j.literal("PostToolUse"),tool_name:j.string(),tool_use_id:j.string(),tool_input:j.record(j.unknown()),tool_response:j.unknown()}),dZ=m4.extend({hook_event_name:j.literal("Stop"),reason:j.string().optional()}),lF=j.discriminatedUnion("hook_event_name",[mZ,uZ,dZ]),cZ=j.object({hookEventName:j.literal("PreToolUse"),permissionDecision:j.nativeEnum(C4).optional(),permissionDecisionReason:j.string().optional(),updatedInput:j.record(j.unknown()).optional()}),lZ=j.object({hookEventName:j.literal("PostToolUse"),additionalContext:j.string().optional(),updatedOutput:j.unknown().optional()}),iZ=j.object({decision:j.object({behavior:j.nativeEnum(T4)}).optional(),systemMessage:j.string().optional(),hookSpecificOutput:j.discriminatedUnion("hookEventName",[cZ,lZ]).optional(),suppressOutput:j.boolean().optional()}),rZ=j.object({type:j.literal("command"),command:j.string(),timeout:j.number().positive().optional(),statusMessage:j.string().optional()}),aZ=j.object({type:j.literal("prompt"),prompt:j.string(),timeout:j.number().positive().optional()}),nZ=j.discriminatedUnion("type",[rZ,aZ]),oZ=j.object({tools:j.string().optional(),paths:j.string().optional(),commands:j.string().optional()}),g4=j.object({name:j.string().optional(),matcher:oZ.optional(),hooks:j.array(nZ)}),iF=j.object({enabled:j.boolean().optional(),defaultTimeout:j.number().positive().optional(),timeoutBehavior:j.enum(["ignore","deny","ask"]).optional(),failureBehavior:j.enum(["ignore","deny","ask"]).optional(),maxConcurrentHooks:j.number().positive().optional(),PreToolUse:j.array(g4).optional(),PostToolUse:j.array(g4).optional(),Stop:j.array(g4).optional()});function B5($){let Y=iZ.safeParse($);if(Y.success)return{success:!0,data:Y.data};return{success:!1,error:Y.error}}class u4{parse($,Y,X){if($.timedOut){let Q=X?.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 Z=this.tryParseJSON($.stdout);if(Z){let Q=B5(Z);if(!Q.success){let q="error"in Q?Q.error.message:"Unknown validation error",G=X?.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,X)}parseByExitCode($,Y,X){let Z=$.exitCode;switch(Z){case 0:return{success:!0,stdout:$.stdout,stderr:$.stderr,exitCode:Z,hook:Y};case 2:return{success:!1,blocking:!0,error:$.stderr||$.stdout||"Hook returned exit code 2",stdout:$.stdout,stderr:$.stderr,exitCode:Z,hook:Y};case 124:{let Q=X?.timeoutBehavior||"ignore",J="Hook timeout";if(Q==="deny")return{success:!1,blocking:!0,error:"Hook timeout",stdout:$.stdout,stderr:$.stderr,exitCode:Z,hook:Y};else if(Q==="ask")return{success:!1,blocking:!1,needsConfirmation:!0,warning:"Hook timeout. Continue?",stdout:$.stdout,stderr:$.stderr,exitCode:Z,hook:Y};else return{success:!1,blocking:!1,warning:"Hook timeout",stdout:$.stdout,stderr:$.stderr,exitCode:Z,hook:Y}}default:{let Q=X?.failureBehavior||"ignore",J=$.stderr||$.stdout||`Hook failed with exit code ${Z}`;if(Q==="deny")return{success:!1,blocking:!0,error:J,stdout:$.stdout,stderr:$.stderr,exitCode:Z,hook:Y};else if(Q==="ask")return{success:!1,blocking:!1,needsConfirmation:!0,warning:`${J}. Continue?`,stdout:$.stdout,stderr:$.stderr,exitCode:Z,hook:Y};else return{success:!1,blocking:!1,warning:J,stdout:$.stdout,stderr:$.stderr,exitCode:Z,hook:Y}}}}tryParseJSON($){try{let Y=$.trim();if(!Y)return null;let X=Y.match(/^\s*(\{[\s\S]*\})\s*$/);if(!X)return null;return JSON.parse(X[1])}catch{return null}}}class d4{processExecutor=new p4;outputParser=new u4;async executePreToolHooks($,Y,X){if($.length===0)return{decision:"allow"};let Z="tool_input"in Y?Y.tool_input:{},Q=[];for(let J of $)try{let q={...Y,...Z&&{tool_input:Z}},G=await this.executeHook(J,q,X);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)Z={...Z,...K.updatedInput}}}catch(q){let G=q instanceof Error?q.message:String(q);if(Q.push(`Hook failed: ${G}`),X.config.failureBehavior==="deny")return{decision:"deny",reason:G};else if(X.config.failureBehavior==="ask")return{decision:"ask",reason:`Hook failed: ${G}. Continue?`}}return{decision:"allow",modifiedInput:Z,warning:Q.length>0?Q.join(`
946
943
  `):void 0}}async executePostToolHooks($,Y,X){if($.length===0)return{};let Z=X.config.maxConcurrentHooks||5,Q=await this.executeHooksConcurrently($,Y,X,Z),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(`
947
944
 
948
945
  `):void 0,modifiedOutput:q,warning:G.length>0?G.join(`
949
- `):void 0}}async executeHook($,Y,X){if($.type==="command")return this.executeCommandHook($,Y,X);throw Error(`Hook type ${$.type} not yet implemented`)}async executeCommandHook($,Y,X){let Z=($.timeout??X.config.defaultTimeout??60)*1000;try{let Q=await this.processExecutor.execute($.command,Y,X,Z);return this.outputParser.parse(Q,$,{timeoutBehavior:X.config.timeoutBehavior,failureBehavior:X.config.failureBehavior})}catch(Q){return{success:!1,blocking:!1,error:Q instanceof Error?Q.message:String(Q),hook:$}}}async executeHooksConcurrently($,Y,X,Z){let Q=[],J=new Set;for(let q of $){if(J.size>=Z)await Promise.race(J);let G=this.executeHook(q,Y,X).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)}}class f4{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 X=this.executedHooks.get($);if(X)X.add(Y)}cleanup($){this.executedHooks.delete($)}cleanupAll(){this.executedHooks.clear()}}import yZ from"picomatch";class h4{matches($,Y){if(!$)return!0;if($.tools&&Y.toolName){if(!this.matchPattern(Y.toolName,$.tools))return!1}if($.paths&&Y.filePath){if(!yZ($.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((Z)=>Z.trim()).includes($);try{return new RegExp(Y).test($)}catch{return $===Y}}}class l0{static instance=null;config=M4;executor=new C4;guard=new f4;matcher=new h4;sessionDisabled=!1;constructor(){}static getInstance(){if(!l0.instance)l0.instance=new l0;return l0.instance}loadConfig($){let Y=y4(M4,$),X=X5();Y=y4(Y,X),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,X,Z){if(!this.isEnabled())return{decision:"allow"};if(Z.permissionMode==="plan")return{decision:"allow"};if(!this.guard.canExecute(Y,"PreToolUse"))return{decision:"allow"};let Q={hook_event_name:"PreToolUse",hook_execution_id:Q5(),timestamp:new Date().toISOString(),tool_name:$,tool_use_id:Y,tool_input:X,project_dir:Z.projectDir,session_id:Z.sessionId,permission_mode:Z.permissionMode},J=this.getMatchingHooks("PreToolUse",{toolName:$,filePath:this.extractFilePath(X),command:this.extractCommand($,X)});if(J.length===0)return{decision:"allow"};let q={projectDir:Z.projectDir,sessionId:Z.sessionId,permissionMode:Z.permissionMode,config:this.config,abortSignal:Z.abortSignal};try{let G=await this.executor.executePreToolHooks(J,Q,q);if(this.guard.markExecuted(Y,"PreToolUse"),Z.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,X,Z,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:Q5(),timestamp:new Date().toISOString(),tool_name:$,tool_use_id:Y,tool_input:X,tool_response:Z,project_dir:Q.projectDir,session_id:Q.sessionId,permission_mode:Q.permissionMode},q=this.getMatchingHooks("PostToolUse",{toolName:$,filePath:this.extractFilePath(X),command:this.extractCommand($,X)});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 X=this.config[$]||[],Z=[];for(let Q of X)if(this.matcher.matches(Q.matcher,Y))Z.push(...Q.hooks);return Z}extractFilePath($){let Y=["file_path","path","filePath","source","target"];for(let X of Y){let Z=$[X];if(typeof Z==="string")return Z}return}extractCommand($,Y){if($==="Bash"||$==="BashTool"){let X=Y.command;if(typeof X==="string")return X}return}cleanup(){this.guard.cleanupAll()}}class x4{name="hook";hookManager;constructor(){this.hookManager=l0.getInstance()}async process($){if(!this.hookManager.isEnabled())return;let Y=$._internal.tool;if(!Y)return;try{let X=$.context.messageId||`tool_${EZ()}`;$._internal.hookToolUseId=X;let Z=$.context.workspaceRoot||process.cwd(),Q=await this.hookManager.executePreToolHooks(Y.name,X,$.params,{projectDir:Z,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(X){console.error("[HookStage] Error executing hooks:",X)}}}import{nanoid as jZ}from"nanoid";class p4{name="post-hook";hookManager;constructor(){this.hookManager=l0.getInstance()}async process($){if(!this.hookManager.isEnabled())return;let Y=$._internal.tool;if(!Y)return;let X=$.getResult();if(!X)return;try{let Z=$._internal.hookToolUseId||$.context.messageId||`tool_${jZ()}`,Q=$.context.workspaceRoot||process.cwd(),J=await this.hookManager.executePostToolHooks(Y.name,Z,$.params,X,{projectDir:Q,sessionId:$.context.sessionId||"unknown",permissionMode:$.context.permissionMode||"default"});if(J.additionalContext){let q=X.llmContent||X.displayContent||"";X.llmContent=`${q}
946
+ `):void 0}}async executeHook($,Y,X){if($.type==="command")return this.executeCommandHook($,Y,X);throw Error(`Hook type ${$.type} not yet implemented`)}async executeCommandHook($,Y,X){let Z=($.timeout??X.config.defaultTimeout??60)*1000;try{let Q=await this.processExecutor.execute($.command,Y,X,Z);return this.outputParser.parse(Q,$,{timeoutBehavior:X.config.timeoutBehavior,failureBehavior:X.config.failureBehavior})}catch(Q){return{success:!1,blocking:!1,error:Q instanceof Error?Q.message:String(Q),hook:$}}}async executeHooksConcurrently($,Y,X,Z){let Q=[],J=new Set;for(let q of $){if(J.size>=Z)await Promise.race(J);let G=this.executeHook(q,Y,X).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)}}class c4{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 X=this.executedHooks.get($);if(X)X.add(Y)}cleanup($){this.executedHooks.delete($)}cleanupAll(){this.executedHooks.clear()}}import sZ from"picomatch";class l4{matches($,Y){if(!$)return!0;if($.tools&&Y.toolName){if(!this.matchPattern(Y.toolName,$.tools))return!1}if($.paths&&Y.filePath){if(!sZ($.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((Z)=>Z.trim()).includes($);try{return new RegExp(Y).test($)}catch{return $===Y}}}class r0{static instance=null;config=f4;executor=new d4;guard=new c4;matcher=new l4;sessionDisabled=!1;constructor(){}static getInstance(){if(!r0.instance)r0.instance=new r0;return r0.instance}loadConfig($){let Y=h4(f4,$),X=N5();Y=h4(Y,X),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,X,Z){if(!this.isEnabled())return{decision:"allow"};if(Z.permissionMode==="plan")return{decision:"allow"};if(!this.guard.canExecute(Y,"PreToolUse"))return{decision:"allow"};let Q={hook_event_name:"PreToolUse",hook_execution_id:L5(),timestamp:new Date().toISOString(),tool_name:$,tool_use_id:Y,tool_input:X,project_dir:Z.projectDir,session_id:Z.sessionId,permission_mode:Z.permissionMode},J=this.getMatchingHooks("PreToolUse",{toolName:$,filePath:this.extractFilePath(X),command:this.extractCommand($,X)});if(J.length===0)return{decision:"allow"};let q={projectDir:Z.projectDir,sessionId:Z.sessionId,permissionMode:Z.permissionMode,config:this.config,abortSignal:Z.abortSignal};try{let G=await this.executor.executePreToolHooks(J,Q,q);if(this.guard.markExecuted(Y,"PreToolUse"),Z.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,X,Z,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:L5(),timestamp:new Date().toISOString(),tool_name:$,tool_use_id:Y,tool_input:X,tool_response:Z,project_dir:Q.projectDir,session_id:Q.sessionId,permission_mode:Q.permissionMode},q=this.getMatchingHooks("PostToolUse",{toolName:$,filePath:this.extractFilePath(X),command:this.extractCommand($,X)});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 X=this.config[$]||[],Z=[];for(let Q of X)if(this.matcher.matches(Q.matcher,Y))Z.push(...Q.hooks);return Z}extractFilePath($){let Y=["file_path","path","filePath","source","target"];for(let X of Y){let Z=$[X];if(typeof Z==="string")return Z}return}extractCommand($,Y){if($==="Bash"||$==="BashTool"){let X=Y.command;if(typeof X==="string")return X}return}cleanup(){this.guard.cleanupAll()}}class i4{name="hook";hookManager;constructor(){this.hookManager=r0.getInstance()}async process($){if(!this.hookManager.isEnabled())return;let Y=$._internal.tool;if(!Y)return;try{let X=$.context.messageId||`tool_${tZ()}`;$._internal.hookToolUseId=X;let Z=$.context.workspaceRoot||process.cwd(),Q=await this.hookManager.executePreToolHooks(Y.name,X,$.params,{projectDir:Z,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(X){console.error("[HookStage] Error executing hooks:",X)}}}import{nanoid as eZ}from"nanoid";class r4{name="post-hook";hookManager;constructor(){this.hookManager=r0.getInstance()}async process($){if(!this.hookManager.isEnabled())return;let Y=$._internal.tool;if(!Y)return;let X=$.getResult();if(!X)return;try{let Z=$._internal.hookToolUseId||$.context.messageId||`tool_${eZ()}`,Q=$.context.workspaceRoot||process.cwd(),J=await this.hookManager.executePostToolHooks(Y.name,Z,$.params,X,{projectDir:Q,sessionId:$.context.sessionId||"unknown",permissionMode:$.context.permissionMode||"default"});if(J.additionalContext){let q=X.llmContent||X.displayContent||"";X.llmContent=`${q}
950
947
 
951
948
  ---
952
949
  **Hook Context:**
953
- ${J.additionalContext}`}if(J.modifiedOutput!==void 0){let q=J.modifiedOutput;if(typeof q==="object"&&q!==null)Object.assign(X,q)}if(J.warning)console.warn(`[PostToolUseHook Warning] ${J.warning}`)}catch(Z){console.error("[PostToolUseHookStage] Error executing post-tool hooks:",Z)}}}var g4=Y0("Execution");class C1{static instance=null;locks=new Map;constructor(){}static getInstance(){if(!C1.instance)C1.instance=new C1;return C1.instance}async acquireLock($,Y){let X=this.locks.get($);if(X)try{await X}catch{}let Z=this.executeWithLock($,Y);return this.locks.set($,Z.then(()=>{return})),Z}async executeWithLock($,Y){g4.debug(`获取文件锁: ${$}`);try{let X=await Y();return g4.debug(`释放文件锁: ${$}`),X}catch(X){throw g4.debug(`操作失败,释放文件锁: ${$}`),X}}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(){C1.instance=null}}import PZ from"node:os";import m4 from"node:path";class u4{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($),X=m4.basename(Y);for(let Z of this.SENSITIVE_PATTERNS)if(this.matchPattern(X,Z.pattern))return{isSensitive:!0,level:Z.level,matchedPattern:Z.pattern instanceof RegExp?Z.pattern.source:Z.pattern,reason:Z.description};for(let Z of this.SENSITIVE_PATHS)if(this.matchPattern(Y,Z.path))return{isSensitive:!0,level:Z.level,matchedPattern:Z.path instanceof RegExp?Z.path.source:Z.path,reason:Z.description};return{isSensitive:!1}}static checkMultiple($){let Y=new Map;for(let X of $)Y.set(X,this.check(X));return Y}static filterSensitive($,Y="low"){let X={["high"]:3,["medium"]:2,["low"]:1},Z=X[Y];return $.map((Q)=>({path:Q,result:this.check(Q)})).filter(({result:Q})=>Q.isSensitive&&Q.level&&X[Q.level]>=Z)}static normalizePath($){if($.startsWith("~/")||$==="~")return m4.join(PZ.homedir(),$.slice(1));return m4.resolve($)}static matchPattern($,Y){if(Y instanceof RegExp)return Y.test($);let X=Y.replace(/\*/g,".*");return new RegExp(`^${X}$`,"i").test($)}static getSensitivePatterns(){return[...this.SENSITIVE_PATTERNS]}static getSensitivePaths(){return[...this.SENSITIVE_PATHS]}}var t1=Y0("Execution");class d4{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 c4{name="permission";permissionChecker;sessionApprovals;defaultPermissionMode;constructor($,Y,X){this.permissionChecker=new i1($),this.sessionApprovals=Y,this.defaultPermissionMode=X}getPermissionChecker(){return this.permissionChecker}async process($){let Y=$._internal.tool;if(!Y){$.abort("Discovery stage failed; cannot perform permission check");return}try{let X=Y.build($.params),Z=X.getAffectedPaths(),Q={toolName:Y.name,params:$.params,affectedPaths:Z,tool:Y},J=i1.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(Z.length>0){let K=["/etc/","/sys/","/proc/","/dev/","/boot/","/root/","C:\\Windows\\System32","C:\\Program Files","C:\\ProgramData"],W=Z.filter((U)=>{if(U.includes(".."))return!0;return K.some((H)=>U.includes(H))});if(W.length>0){$.abort(`Access to dangerous system paths denied: ${W.join(", ")}`);return}let O=u4.filterSensitive(Z,"medium");if(O.length>0){let U=O.map(({path:_,result:z})=>`${_} (${z.level}: ${z.reason})`);if(O.filter(({result:_})=>_.level==="high").length>0&&q.result!=="allow"){$.abort(`Access to highly sensitive files denied:
950
+ ${J.additionalContext}`}if(J.modifiedOutput!==void 0){let q=J.modifiedOutput;if(typeof q==="object"&&q!==null)Object.assign(X,q)}if(J.warning)console.warn(`[PostToolUseHook Warning] ${J.warning}`)}catch(Z){console.error("[PostToolUseHookStage] Error executing post-tool hooks:",Z)}}}var a4=$0("Execution");class p1{static instance=null;locks=new Map;constructor(){}static getInstance(){if(!p1.instance)p1.instance=new p1;return p1.instance}async acquireLock($,Y){let X=this.locks.get($);if(X)try{await X}catch{}let Z=this.executeWithLock($,Y);return this.locks.set($,Z.then(()=>{return})),Z}async executeWithLock($,Y){a4.debug(`获取文件锁: ${$}`);try{let X=await Y();return a4.debug(`释放文件锁: ${$}`),X}catch(X){throw a4.debug(`操作失败,释放文件锁: ${$}`),X}}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(){p1.instance=null}}import $Q from"node:os";import n4 from"node:path";class o4{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($),X=n4.basename(Y);for(let Z of this.SENSITIVE_PATTERNS)if(this.matchPattern(X,Z.pattern))return{isSensitive:!0,level:Z.level,matchedPattern:Z.pattern instanceof RegExp?Z.pattern.source:Z.pattern,reason:Z.description};for(let Z of this.SENSITIVE_PATHS)if(this.matchPattern(Y,Z.path))return{isSensitive:!0,level:Z.level,matchedPattern:Z.path instanceof RegExp?Z.path.source:Z.path,reason:Z.description};return{isSensitive:!1}}static checkMultiple($){let Y=new Map;for(let X of $)Y.set(X,this.check(X));return Y}static filterSensitive($,Y="low"){let X={["high"]:3,["medium"]:2,["low"]:1},Z=X[Y];return $.map((Q)=>({path:Q,result:this.check(Q)})).filter(({result:Q})=>Q.isSensitive&&Q.level&&X[Q.level]>=Z)}static normalizePath($){if($.startsWith("~/")||$==="~")return n4.join($Q.homedir(),$.slice(1));return n4.resolve($)}static matchPattern($,Y){if(Y instanceof RegExp)return Y.test($);let X=Y.replace(/\*/g,".*");return new RegExp(`^${X}$`,"i").test($)}static getSensitivePatterns(){return[...this.SENSITIVE_PATTERNS]}static getSensitivePaths(){return[...this.SENSITIVE_PATHS]}}var Q$=$0("Execution");class s4{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 t4{name="permission";permissionChecker;sessionApprovals;defaultPermissionMode;constructor($,Y,X){this.permissionChecker=new t1($),this.sessionApprovals=Y,this.defaultPermissionMode=X}getPermissionChecker(){return this.permissionChecker}async process($){let Y=$._internal.tool;if(!Y){$.abort("Discovery stage failed; cannot perform permission check");return}try{let X=Y.build($.params),Z=X.getAffectedPaths(),Q={toolName:Y.name,params:$.params,affectedPaths:Z,tool:Y},J=t1.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(Z.length>0){let K=["/etc/","/sys/","/proc/","/dev/","/boot/","/root/","C:\\Windows\\System32","C:\\Program Files","C:\\ProgramData"],W=Z.filter((U)=>{if(U.includes(".."))return!0;return K.some((H)=>U.includes(H))});if(W.length>0){$.abort(`Access to dangerous system paths denied: ${W.join(", ")}`);return}let O=o4.filterSensitive(Z,"medium");if(O.length>0){let U=O.map(({path:_,result:z})=>`${_} (${z.level}: ${z.reason})`);if(O.filter(({result:_})=>_.level==="high").length>0&&q.result!=="allow"){$.abort(`Access to highly sensitive files denied:
954
951
  ${U.join(`
955
952
  `)}
956
953
 
@@ -958,7 +955,7 @@ If access is required, add an explicit allow rule in permissions.`);return}if(q.
958
955
  ${U.join(`
959
956
  `)}
960
957
 
961
- Confirm to proceed?`,$._internal.needsConfirmation=!0}}$._internal.invocation=X,$._internal.permissionCheckResult=q}catch(X){$.abort(`Permission check failed: ${X.message}`)}}applyModeOverrides($,Y,X){if(X==="yolo")return{result:"allow",matchedRule:"mode:yolo",reason:"YOLO mode: automatically approve all tool invocations"};if(X==="plan"){if(!l$($))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(l$($))return{result:"allow",matchedRule:`mode:${X}:readonly`,reason:"Read-only tools do not require confirmation"};if(X==="autoEdit"&&$==="write")return{result:"allow",matchedRule:"mode:autoEdit:write",reason:"AUTO_EDIT mode: automatically approve write tools"};return Y}}class l4{sessionApprovals;name="confirmation";permissionChecker;constructor($,Y){this.sessionApprovals=$;this.permissionChecker=Y}async process($){let{tool:Y,invocation:X,needsConfirmation:Z,confirmationReason:Q,permissionCheckResult:J}=$._internal;if(!Y||!X){$.abort("Pre-confirmation stage failed; cannot request user approval");return}if(!Z)return;try{let G={title:`权限确认: ${Y.extractSignatureContent?Y.extractSignatureContent($.params):Y.name}`,message:Q||"此操作需要用户确认",details:this.generatePreviewForTool(Y.name,$.params),risks:this.extractRisksFromPermissionCheck(Y,$.params,J),affectedFiles:X.getAffectedPaths()||[]};if(t1.warn(`工具 "${Y.name}" 需要用户确认: ${G.title}`),t1.warn(`详情: ${G.message}`),G.risks&&G.risks.length>0)t1.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"}`);return}if((W.scope||"once")==="session"&&$._internal.permissionSignature){let U=$._internal.permissionSignature;this.sessionApprovals.add(U);let H={toolName:Y.name,params:$.params,affectedPaths:X.getAffectedPaths()||[],tool:Y};await this.persistSessionApproval(U,H)}}else t1.warn("⚠️ No ConfirmationHandler; auto-approving tool execution (non-interactive environment only)")}catch(q){$.abort(`User confirmation failed: ${q.message}`)}}async persistSessionApproval($,Y){try{let X=i1.abstractPattern(Y);t1.debug(`保存权限规则: "${X}"`),await e().appendLocalPermissionAllowRule(X,{immediate:!0});let Z=F0();if(Z?.permissions)t1.debug("同步权限配置到 PermissionChecker:",Z.permissions),this.permissionChecker.replaceConfig(Z.permissions)}catch(X){t1.warn(`Failed to persist permission rule "${$}": ${X instanceof Error?X.message:"Unknown error"}`)}}generatePreviewForTool($,Y){switch($){case"Edit":{let{old_string:X,new_string:Z}=Y;if(!X&&!Z)return;let Q=20,J=(q)=>{let G=q.split(`
958
+ Confirm to proceed?`,$._internal.needsConfirmation=!0}}$._internal.invocation=X,$._internal.permissionCheckResult=q}catch(X){$.abort(`Permission check failed: ${X.message}`)}}applyModeOverrides($,Y,X){if(X==="yolo")return{result:"allow",matchedRule:"mode:yolo",reason:"YOLO mode: automatically approve all tool invocations"};if(X==="plan"){if(!$2($))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($2($))return{result:"allow",matchedRule:`mode:${X}:readonly`,reason:"Read-only tools do not require confirmation"};if(X==="autoEdit"&&$==="write")return{result:"allow",matchedRule:"mode:autoEdit:write",reason:"AUTO_EDIT mode: automatically approve write tools"};return Y}}class e4{sessionApprovals;name="confirmation";permissionChecker;constructor($,Y){this.sessionApprovals=$;this.permissionChecker=Y}async process($){let{tool:Y,invocation:X,needsConfirmation:Z,confirmationReason:Q,permissionCheckResult:J}=$._internal;if(!Y||!X){$.abort("Pre-confirmation stage failed; cannot request user approval");return}if(!Z)return;try{let G={title:`权限确认: ${Y.extractSignatureContent?Y.extractSignatureContent($.params):Y.name}`,message:Q||"此操作需要用户确认",details:this.generatePreviewForTool(Y.name,$.params),risks:this.extractRisksFromPermissionCheck(Y,$.params,J),affectedFiles:X.getAffectedPaths()||[]};if(Q$.warn(`工具 "${Y.name}" 需要用户确认: ${G.title}`),Q$.warn(`详情: ${G.message}`),G.risks&&G.risks.length>0)Q$.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 U=$._internal.permissionSignature;this.sessionApprovals.add(U);let H={toolName:Y.name,params:$.params,affectedPaths:X.getAffectedPaths()||[],tool:Y};await this.persistSessionApproval(U,H)}}else Q$.warn("⚠️ No ConfirmationHandler; auto-approving tool execution (non-interactive environment only)")}catch(q){$.abort(`User confirmation failed: ${q.message}`)}}async persistSessionApproval($,Y){try{let X=t1.abstractPattern(Y);Q$.debug(`保存权限规则: "${X}"`),await W0().appendLocalPermissionAllowRule(X,{immediate:!0});let Z=D0();if(Z?.permissions)Q$.debug("同步权限配置到 PermissionChecker:",Z.permissions),this.permissionChecker.replaceConfig(Z.permissions)}catch(X){Q$.warn(`Failed to persist permission rule "${$}": ${X instanceof Error?X.message:"Unknown error"}`)}}generatePreviewForTool($,Y){switch($){case"Edit":{let{old_string:X,new_string:Z}=Y;if(!X&&!Z)return;let Q=20,J=(q)=>{let G=q.split(`
962
959
  `);if(G.length<=Q)return q;return`${G.slice(0,Q).join(`
963
960
  `)}
964
961
  ... (还有 ${G.length-Q} 行)`};return`**变更前:**
@@ -979,44 +976,44 @@ ${X}
979
976
  ${q}
980
977
  \`\`\`
981
978
 
982
- ... (还有 ${J.length-Q} 行)`}case"Bash":case"Shell":return;default:return}}extractRisksFromPermissionCheck($,Y,X){let Z=[];if(X?.reason)Z.push(X.reason);if($.name==="Bash"){let Q=Y.command||"",J=Q.trim().split(/\s+/)[0];if(J==="cat"||J==="head"||J==="tail")Z.push(`\uD83D\uDCA1 建议使用 Read 工具代替 ${J} 命令(性能更好,支持大文件分页)`);else if(J==="grep"||J==="rg")Z.push("\uD83D\uDCA1 建议使用 Grep 工具代替 grep/rg 命令(支持更强大的过滤和上下文)");else if(J==="find")Z.push("\uD83D\uDCA1 建议使用 Glob 工具代替 find 命令(更快,支持 glob 模式)");else if(J==="sed"||J==="awk")Z.push(`\uD83D\uDCA1 建议使用 Edit 工具代替 ${J} 命令(更安全,支持预览和回滚)`);if(Q.includes("rm"))Z.push("⚠️ 此命令可能删除文件");if(Q.includes("sudo"))Z.push("⚠️ 此命令需要管理员权限");if(Q.includes("git push"))Z.push("⚠️ 此命令将推送代码到远程仓库")}else if($.name==="Write"||$.name==="Edit")Z.push("此操作将修改文件内容");else if($.name==="Delete")Z.push("此操作将永久删除文件");return Z}}class i4{name="execution";async process($){let Y=$._internal.invocation;if(!Y){$.abort("Pre-execution stage failed; cannot run tool");return}try{let X=await Y.execute($.context.signal,$.context.onProgress,$.context);$.setResult(X)}catch(X){$.abort(`Tool execution failed: ${X.message}`)}}}class r4{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}`)}}}class a4 extends SZ{registry;stages;executionHistory=[];maxHistorySize;sessionApprovals=new Set;constructor($,Y={}){super();this.registry=$;this.maxHistorySize=Y.maxHistorySize||1000;let X=Y.permissionConfig||{allow:[],ask:[],deny:[]},Z=Y.permissionMode??"default",Q=new c4(X,this.sessionApprovals,Z);this.stages=[new d4(this.registry),Q,new x4,new l4(this.sessionApprovals,Q.getPermissionChecker()),new i4,new p4,new r4]}async execute($,Y,X){let Z=Date.now(),Q=this.generateExecutionId(),J=new T6($,Y,{...X,sessionId:X.sessionId||Q});this.emit("executionStarted",{executionId:Q,toolName:$,params:Y,context:X,timestamp:Z});let q=this.registry.get($),G=q&&!q.isConcurrencySafe,K=G&&Y.file_path?String(Y.file_path):null;if(G&&K)return C1.getInstance().acquireLock(K,()=>this.executeWithPipeline(J,Q,Z));return this.executeWithPipeline(J,Q,Z)}async executeWithPipeline($,Y,X){try{for(let J of this.stages)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 Z=$.getResult(),Q=Date.now();return this.addToHistory({executionId:Y,toolName:$.toolName,params:$.params,result:Z,startTime:X,endTime:Q,context:$.context}),this.emit("executionCompleted",{executionId:Y,toolName:$.toolName,result:Z,duration:Q-X,timestamp:Q}),Z}catch(Z){let Q={success:!1,llmContent:`Tool execution failed: ${Z.message}`,displayContent:`错误: ${Z.message}`,error:{type:"execution_error",message:Z.message}},J=Date.now();return this.addToHistory({executionId:Y,toolName:$.toolName,params:$.params,result:Q,startTime:X,endTime:J,context:$.context}),this.emit("executionFailed",{executionId:Y,toolName:$.toolName,error:Z,duration:J-X,timestamp:J}),Q}}async executeAll($){let Y=$.map((X)=>this.execute(X.toolName,X.params,X.context));return Promise.all(Y)}async executeParallel($,Y=5){let X=[],Z=[];for(let Q=0;Q<$.length;Q++){let J=$[Q],q=this.execute(J.toolName,J.params,J.context);if(Z.push(q),Z.length>=Y||Q===$.length-1){let G=await Promise.all(Z);X.push(...G),Z.length=0}}return X}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 X of this.executionHistory){if(X.result.success)$.successfulExecutions++;else $.failedExecutions++;let Z=X.endTime-X.startTime;Y+=Z;let Q=$.toolUsage.get(X.toolName)||0;$.toolUsage.set(X.toolName,Q+1)}return $.averageDuration=$.totalExecutions>0?Y/$.totalExecutions:0,$}addStage($,Y=-1){if(Y===-1){let X=this.stages.findIndex((Z)=>Z.name==="execution");this.stages.splice(X,0,$)}else this.stages.splice(Y,0,$);this.emit("stageAdded",{stageName:$.name,position:Y,timestamp:Date.now()})}removeStage($){let Y=this.stages.findIndex((X)=>X.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 TZ}from"events";class n4 extends TZ{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 X of $)try{this.register(X)}catch(Z){Y.push(`${X.name}: ${Z.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((X)=>this.get(X)).filter((X)=>X!==void 0)}getByTag($){let Y=this.tags.get($);if(!Y)return[];return Array.from(Y).map((X)=>this.get(X)).filter((X)=>X!==void 0)}search($){let Y=$.toLowerCase();return this.getAll().filter((X)=>{let Z=typeof X.description==="string"?X.description:X.description.short;return X.name.toLowerCase().includes(Y)||Z.toLowerCase().includes(Y)||X.displayName.toLowerCase().includes(Y)||X.category&&X.category.toLowerCase().includes(Y)||X.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,X=`mcp__${$}__`;for(let[Z,Q]of this.mcpTools.entries())if(Z.startsWith(X))this.mcpTools.delete(Z),this.removeFromIndexes(Q),Y++,this.emit("toolUnregistered",{type:"mcp",toolName:Z,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 X=this.tags.get(Y);if(X){if(X.delete($.name),X.size===0)this.tags.delete(Y)}}}}import*as G5 from"crypto";import{nanoid as q5}from"nanoid";class o4{maxSummaryLength;keyPointsLimit;recentMessagesLimit;constructor($=500,Y=10,X=20){this.maxSummaryLength=$,this.keyPointsLimit=Y,this.recentMessagesLimit=X}async compress($){let Y=$.layers.conversation.messages,X=$.layers.tool.recentCalls,Z=Y.filter((U)=>U.role==="system"),Q=Y.filter((U)=>U.role!=="system"),J=this.getRecentMessages(Q),q=Q.slice(0,-this.recentMessagesLimit),G=await this.generateSummary(q),K=this.extractKeyPoints(q,X),W=this.generateToolSummary(X),O=this.estimateTokenCount(G,K,J,W);return{summary:G,keyPoints:K,recentMessages:[...Z,...J],toolSummary:W,tokenCount:O}}getRecentMessages($){return $.slice(-this.recentMessagesLimit)}async generateSummary($){if($.length===0)return"";let Y=new Set,X=new Set,Z=new Set;for(let J of $){let q=J.content.toLowerCase();["关于","讨论","问题","项目","功能","需求"].forEach((O)=>{if(q.includes(O)){let U=this.extractContext(q,O,50);if(U)Y.add(U)}}),["创建","删除","修改","更新","实现","开发"].forEach((O)=>{if(q.includes(O)){let U=this.extractContext(q,O,30);if(U)X.add(U)}}),["决定","选择","确定","采用","使用"].forEach((O)=>{if(q.includes(O)){let U=this.extractContext(q,O,40);if(U)Z.add(U)}})}let Q=`对话涉及 ${$.length} 条消息。`;if(Y.size>0)Q+=` 主要讨论:${Array.from(Y).slice(0,3).join("、")}。`;if(X.size>0)Q+=` 执行操作:${Array.from(X).slice(0,3).join("、")}。`;if(Z.size>0)Q+=` 关键决策:${Array.from(Z).slice(0,2).join("、")}。`;return Q.length>this.maxSummaryLength?Q.substring(0,this.maxSummaryLength)+"...":Q}extractKeyPoints($,Y){let X=new Set;for(let Q of $)if(Q.role==="user")this.extractQuestions(Q.content).forEach((G)=>X.add(`用户问题:${G}`)),this.extractRequests(Q.content).forEach((G)=>X.add(`用户请求:${G}`));else if(Q.role==="assistant")this.extractSolutions(Q.content).forEach((q)=>X.add(`解决方案:${q}`));return this.summarizeToolUsage(Y).forEach((Q)=>X.add(`工具使用:${Q}`)),Array.from(X).slice(0,this.keyPointsLimit)}generateToolSummary($){if($.length===0)return"";let Y=new Map,X=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>X)J.recent++;Y.set(Q.name,J)}let Z=[];for(let[Q,J]of Array.from(Y.entries())){let q=Math.round(J.success/J.count*100);Z.push(`${Q}(${J.count}次,成功率${q}%)`)}return`工具调用:${Z.join("、")}`}estimateTokenCount($,Y,X,Z){let Q=$.length+Y.join(" ").length;if(Z)Q+=Z.length;for(let J of X)Q+=J.content.length;return Math.ceil(Q/4)}extractContext($,Y,X){let Z=$.indexOf(Y);if(Z===-1)return null;let Q=Math.max(0,Z-X/2),J=Math.min($.length,Z+X/2);return $.substring(Q,J).trim()}extractQuestions($){let Y=[],X=["?","?","如何","怎么","什么","为什么"],Z=$.split(/[。!.!]/);for(let Q of Z)if(X.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=[],X=["请","帮我","需要","想要","希望","能否"],Z=$.split(/[。!.!]/);for(let Q of Z)if(X.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=[],X=["可以","建议","推荐","应该","最好","解决方案"],Z=$.split(/[。!.!]/);for(let Q of Z)if(X.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=[],X=$.filter((Z)=>Date.now()-Z.timestamp<1800000);if(X.length>0){let Z=new Map;X.forEach((Q)=>{let J=Z.get(Q.name)||[];J.push(Q),Z.set(Q.name,J)});for(let[Q,J]of Array.from(Z.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 X=$.layers.conversation.messages.reduce((Z,Q)=>Z+Q.content.length,0);return Math.ceil(X/4)}}class e1{defaultOptions;constructor($){this.defaultOptions={maxTokens:32000,maxMessages:50,timeWindow:86400000,priority:1,includeTools:!0,includeWorkspace:!0,...$}}filter($,Y){let X={...this.defaultOptions,...Y},Z={layers:{system:$.layers.system,session:$.layers.session,conversation:this.filterConversation($.layers.conversation,X),tool:X.includeTools?this.filterTools($.layers.tool,X):{recentCalls:[],toolStates:{},dependencies:{}},workspace:X.includeWorkspace?$.layers.workspace:{currentFiles:[],recentFiles:[],environment:{}}},metadata:{...$.metadata,lastUpdated:Date.now()}};return Z.metadata.totalTokens=this.estimateTokens(Z),Z}filterConversation($,Y){let X=[...$.messages];if(Y.timeWindow>0){let Z=Date.now()-Y.timeWindow;X=X.filter((Q)=>Q.timestamp>=Z||Q.role==="system")}if(Y.priority>1)X=this.filterByPriority(X,Y.priority);if(Y.maxMessages>0)X=this.limitMessages(X,Y.maxMessages);if(Y.maxTokens>0)X=this.limitByTokens(X,Y.maxTokens);return{messages:X,summary:$.summary,topics:this.updateTopics(X,$.topics),lastActivity:$.lastActivity}}filterTools($,Y){let X=[...$.recentCalls];if(Y.timeWindow>0){let K=Date.now()-Y.timeWindow;X=X.filter((W)=>W.timestamp>=K)}let Z=X.filter((K)=>K.status==="success"),Q=X.filter((K)=>K.status==="error"),J=Math.min(20,Z.length),q=Math.min(10,Q.length);return{recentCalls:[...Z.slice(-J),...Q.slice(-q)].sort((K,W)=>K.timestamp-W.timestamp),toolStates:$.toolStates,dependencies:$.dependencies}}filterByPriority($,Y){return $.filter((X)=>{if(X.role==="system")return!0;return this.calculateMessagePriority(X)>=Y})}calculateMessagePriority($){let Y=1;if($.role==="system")Y+=3;else if($.role==="assistant")Y+=1;let X=$.content.toLowerCase();if(["错误","警告","重要","关键","问题","解决"].some((J)=>X.includes(J)))Y+=2;if(X.includes("```")||X.includes("function")||X.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 X=$.filter((q)=>q.role==="system"),Z=$.filter((q)=>q.role!=="system"),Q=Y-X.length,J=Q>0?Z.slice(-Q):[];return[...X,...J].sort((q,G)=>q.timestamp-G.timestamp)}limitByTokens($,Y){if(Y<=0)return $;let X=0,Z=[];for(let Q=$.length-1;Q>=0;Q--){let J=$[Q],q=this.estimateMessageTokens(J);if(J.role==="system")if(X+q<=Y)Z.unshift(J),X+=q;else{let G=this.compressMessage(J,Y-X);Z.unshift(G),X+=this.estimateMessageTokens(G)}else if(X+q<=Y)Z.unshift(J),X+=q;else break}return Z.sort((Q,J)=>Q.timestamp-J.timestamp)}estimateMessageTokens($){return Math.ceil($.content.length/4)}compressMessage($,Y){let X=Y*4;if($.content.length<=X)return $;let Z=$.content.substring(0,X-3)+"...";return{...$,content:Z,metadata:{...$.metadata,compressed:!0,originalLength:$.content.length}}}updateTopics($,Y){let X=new Set(Y);for(let Z of $)this.extractTopicsFromMessage(Z).forEach((J)=>X.add(J));return Array.from(X).slice(0,10)}extractTopicsFromMessage($){let Y=$.content.toLowerCase(),X=[];return["项目","功能","模块","组件","服务","接口","数据库","前端","后端","算法","架构","设计"].forEach((Q)=>{if(Y.includes(Q))X.push(Q)}),X}estimateTokens($){let Y=0;for(let Z of $.layers.conversation.messages)Y+=this.estimateMessageTokens(Z);let X=JSON.stringify($.layers.system);if(Y+=Math.ceil(X.length/4),$.layers.tool.recentCalls.length>0){let Z=JSON.stringify($.layers.tool);Y+=Math.ceil(Z.length/8)}return Y}static createPresets(){return{lightweight:new e1({maxTokens:1000,maxMessages:10,timeWindow:7200000,includeTools:!1,includeWorkspace:!1}),standard:new e1({maxTokens:4000,maxMessages:30,timeWindow:43200000,includeTools:!0,includeWorkspace:!0}),comprehensive:new e1({maxTokens:8000,maxMessages:100,timeWindow:86400000,includeTools:!0,includeWorkspace:!0}),debug:new e1({maxTokens:2000,maxMessages:20,timeWindow:21600000,priority:2,includeTools:!0,includeWorkspace:!1})}}}class s4{cache=new Map;maxSize;defaultTTL;constructor($=100,Y=300000){this.maxSize=$,this.defaultTTL=Y}set($,Y,X){let Z=Date.now(),Q={data:Y,timestamp:Z,accessCount:0,lastAccess:Z,ttl:X||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 X=Date.now();if(X-Y.timestamp>Y.ttl)return this.cache.delete($),null;return Y.accessCount++,Y.lastAccess=X,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,X){let Z=`summary:${$}:${Y.length}`;this.set(Z,{summary:X,messageCount:Y.length,lastMessage:Y[Y.length-1]?.timestamp||0},600000)}getMessageSummary($,Y){let X=`summary:${$}:${Y}`;return this.get(X)}cacheToolResult($,Y,X){let Z=this.hashInput(Y),Q=`tool:${$}:${Z}`;this.set(Q,X,1800000)}getToolResult($,Y){let X=this.hashInput(Y),Z=`tool:${$}:${X}`;return this.get(Z)}cacheCompressedContext($,Y){let X=`compressed:${$}`;this.set(X,Y,900000)}getCompressedContext($){let Y=`compressed:${$}`;return this.get(Y)}getStats(){this.cleanExpired();let $=0,Y=0,X=[];for(let[Z,Q]of Array.from(this.cache.entries()))$+=Q.accessCount,Y+=this.estimateItemSize(Q),X.push({key:Z,accessCount:Q.accessCount,lastAccess:Q.lastAccess});return X.sort((Z,Q)=>Q.accessCount-Z.accessCount),{size:this.cache.size,maxSize:this.maxSize,hitRate:$>0?$/($+this.cache.size):0,memoryUsage:Y,topKeys:X.slice(0,10)}}cleanExpired(){let $=Date.now(),Y=[];for(let[X,Z]of Array.from(this.cache.entries()))if($-Z.timestamp>Z.ttl)Y.push(X);Y.forEach((X)=>this.cache.delete(X))}evictLeastUsed(){let $=null,Y=1/0,X=Date.now();for(let[Z,Q]of Array.from(this.cache.entries())){let J=1/(X-Q.lastAccess+1),q=Q.accessCount,G=J*q;if(G<Y)Y=G,$=Z}if($)this.cache.delete($)}hashInput($){let Y=JSON.stringify($),X=0;for(let Z=0;Z<Y.length;Z++){let Q=Y.charCodeAt(Z);X=(X<<5)-X+Q,X=X&X}return Math.abs(X).toString(36)}estimateItemSize($){try{return JSON.stringify($).length*2}catch{return 1000}}setTTL($,Y){let X=this.cache.get($);if(X)return X.ttl=Y,X.timestamp=Date.now(),!0;return!1}getRemainingTTL($){let Y=this.cache.get($);if(!Y)return-1;let X=Y.ttl-(Date.now()-Y.timestamp);return Math.max(0,X)}warmup($){$.forEach(({key:Y,value:X,ttl:Z})=>{this.set(Y,X,Z)})}}class t4{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}}N$();import{nanoid as R$}from"nanoid";import*as k1 from"node:fs/promises";import*as J5 from"node:path";import*as r2 from"node:fs";import{createReadStream as CZ}from"node:fs";import*as j0 from"node:fs/promises";import*as e4 from"node:path";import{createInterface as fZ}from"node:readline";class J1{filePath;constructor($){this.filePath=$}async append($){try{await j0.mkdir(e4.dirname(this.filePath),{recursive:!0});let Y=JSON.stringify($)+`
983
- `;await j0.appendFile(this.filePath,Y,"utf-8")}catch(Y){throw console.error(`[JSONLStore] 追加写入失败: ${this.filePath}`,Y),Y}}async appendBatch($){try{await j0.mkdir(e4.dirname(this.filePath),{recursive:!0});let Y=$.map((X)=>JSON.stringify(X)).join(`
979
+ ... (还有 ${J.length-Q} 行)`}case"Bash":case"Shell":return;default:return}}extractRisksFromPermissionCheck($,Y,X){let Z=[];if(X?.reason)Z.push(X.reason);if($.name==="Bash"){let Q=Y.command||"",J=Q.trim().split(/\s+/)[0];if(J==="cat"||J==="head"||J==="tail")Z.push(`\uD83D\uDCA1 建议使用 Read 工具代替 ${J} 命令(性能更好,支持大文件分页)`);else if(J==="grep"||J==="rg")Z.push("\uD83D\uDCA1 建议使用 Grep 工具代替 grep/rg 命令(支持更强大的过滤和上下文)");else if(J==="find")Z.push("\uD83D\uDCA1 建议使用 Glob 工具代替 find 命令(更快,支持 glob 模式)");else if(J==="sed"||J==="awk")Z.push(`\uD83D\uDCA1 建议使用 Edit 工具代替 ${J} 命令(更安全,支持预览和回滚)`);if(Q.includes("rm"))Z.push("⚠️ 此命令可能删除文件");if(Q.includes("sudo"))Z.push("⚠️ 此命令需要管理员权限");if(Q.includes("git push"))Z.push("⚠️ 此命令将推送代码到远程仓库")}else if($.name==="Write"||$.name==="Edit")Z.push("此操作将修改文件内容");else if($.name==="Delete")Z.push("此操作将永久删除文件");return Z}}class $8{name="execution";async process($){let Y=$._internal.invocation;if(!Y){$.abort("Pre-execution stage failed; cannot run tool");return}try{let X=await Y.execute($.context.signal,$.context.onProgress,$.context);$.setResult(X)}catch(X){$.abort(`Tool execution failed: ${X.message}`)}}}class Y8{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}`)}}}class X8 extends YQ{registry;stages;executionHistory=[];maxHistorySize;sessionApprovals=new Set;constructor($,Y={}){super();this.registry=$;this.maxHistorySize=Y.maxHistorySize||1000;let X=Y.permissionConfig||{allow:[],ask:[],deny:[]},Z=Y.permissionMode??"default",Q=new t4(X,this.sessionApprovals,Z);this.stages=[new s4(this.registry),Q,new i4,new e4(this.sessionApprovals,Q.getPermissionChecker()),new $8,new r4,new Y8]}async execute($,Y,X){let Z=Date.now(),Q=this.generateExecutionId(),J=new d6($,Y,{...X,sessionId:X.sessionId||Q});this.emit("executionStarted",{executionId:Q,toolName:$,params:Y,context:X,timestamp:Z});let q=this.registry.get($),G=q&&!q.isConcurrencySafe,K=G&&Y.file_path?String(Y.file_path):null;if(G&&K)return p1.getInstance().acquireLock(K,()=>this.executeWithPipeline(J,Q,Z));return this.executeWithPipeline(J,Q,Z)}async executeWithPipeline($,Y,X){try{for(let J of this.stages)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 Z=$.getResult(),Q=Date.now();return this.addToHistory({executionId:Y,toolName:$.toolName,params:$.params,result:Z,startTime:X,endTime:Q,context:$.context}),this.emit("executionCompleted",{executionId:Y,toolName:$.toolName,result:Z,duration:Q-X,timestamp:Q}),Z}catch(Z){let Q={success:!1,llmContent:`Tool execution failed: ${Z.message}`,displayContent:`错误: ${Z.message}`,error:{type:"execution_error",message:Z.message}},J=Date.now();return this.addToHistory({executionId:Y,toolName:$.toolName,params:$.params,result:Q,startTime:X,endTime:J,context:$.context}),this.emit("executionFailed",{executionId:Y,toolName:$.toolName,error:Z,duration:J-X,timestamp:J}),Q}}async executeAll($){let Y=$.map((X)=>this.execute(X.toolName,X.params,X.context));return Promise.all(Y)}async executeParallel($,Y=5){let X=[],Z=[];for(let Q=0;Q<$.length;Q++){let J=$[Q],q=this.execute(J.toolName,J.params,J.context);if(Z.push(q),Z.length>=Y||Q===$.length-1){let G=await Promise.all(Z);X.push(...G),Z.length=0}}return X}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 X of this.executionHistory){if(X.result.success)$.successfulExecutions++;else $.failedExecutions++;let Z=X.endTime-X.startTime;Y+=Z;let Q=$.toolUsage.get(X.toolName)||0;$.toolUsage.set(X.toolName,Q+1)}return $.averageDuration=$.totalExecutions>0?Y/$.totalExecutions:0,$}addStage($,Y=-1){if(Y===-1){let X=this.stages.findIndex((Z)=>Z.name==="execution");this.stages.splice(X,0,$)}else this.stages.splice(Y,0,$);this.emit("stageAdded",{stageName:$.name,position:Y,timestamp:Date.now()})}removeStage($){let Y=this.stages.findIndex((X)=>X.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 XQ}from"events";class Z8 extends XQ{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 X of $)try{this.register(X)}catch(Z){Y.push(`${X.name}: ${Z.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((X)=>this.get(X)).filter((X)=>X!==void 0)}getByTag($){let Y=this.tags.get($);if(!Y)return[];return Array.from(Y).map((X)=>this.get(X)).filter((X)=>X!==void 0)}search($){let Y=$.toLowerCase();return this.getAll().filter((X)=>{let Z=typeof X.description==="string"?X.description:X.description.short;return X.name.toLowerCase().includes(Y)||Z.toLowerCase().includes(Y)||X.displayName.toLowerCase().includes(Y)||X.category&&X.category.toLowerCase().includes(Y)||X.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,X=`mcp__${$}__`;for(let[Z,Q]of this.mcpTools.entries())if(Z.startsWith(X))this.mcpTools.delete(Z),this.removeFromIndexes(Q),Y++,this.emit("toolUnregistered",{type:"mcp",toolName:Z,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 X=this.tags.get(Y);if(X){if(X.delete($.name),X.size===0)this.tags.delete(Y)}}}}import*as R5 from"crypto";import{nanoid as A5}from"nanoid";class Q8{maxSummaryLength;keyPointsLimit;recentMessagesLimit;constructor($=500,Y=10,X=20){this.maxSummaryLength=$,this.keyPointsLimit=Y,this.recentMessagesLimit=X}async compress($){let Y=$.layers.conversation.messages,X=$.layers.tool.recentCalls,Z=Y.filter((U)=>U.role==="system"),Q=Y.filter((U)=>U.role!=="system"),J=this.getRecentMessages(Q),q=Q.slice(0,-this.recentMessagesLimit),G=await this.generateSummary(q),K=this.extractKeyPoints(q,X),W=this.generateToolSummary(X),O=this.estimateTokenCount(G,K,J,W);return{summary:G,keyPoints:K,recentMessages:[...Z,...J],toolSummary:W,tokenCount:O}}getRecentMessages($){return $.slice(-this.recentMessagesLimit)}async generateSummary($){if($.length===0)return"";let Y=new Set,X=new Set,Z=new Set;for(let J of $){let q=J.content.toLowerCase();["关于","讨论","问题","项目","功能","需求"].forEach((O)=>{if(q.includes(O)){let U=this.extractContext(q,O,50);if(U)Y.add(U)}}),["创建","删除","修改","更新","实现","开发"].forEach((O)=>{if(q.includes(O)){let U=this.extractContext(q,O,30);if(U)X.add(U)}}),["决定","选择","确定","采用","使用"].forEach((O)=>{if(q.includes(O)){let U=this.extractContext(q,O,40);if(U)Z.add(U)}})}let Q=`对话涉及 ${$.length} 条消息。`;if(Y.size>0)Q+=` 主要讨论:${Array.from(Y).slice(0,3).join("、")}。`;if(X.size>0)Q+=` 执行操作:${Array.from(X).slice(0,3).join("、")}。`;if(Z.size>0)Q+=` 关键决策:${Array.from(Z).slice(0,2).join("、")}。`;return Q.length>this.maxSummaryLength?Q.substring(0,this.maxSummaryLength)+"...":Q}extractKeyPoints($,Y){let X=new Set;for(let Q of $)if(Q.role==="user")this.extractQuestions(Q.content).forEach((G)=>X.add(`用户问题:${G}`)),this.extractRequests(Q.content).forEach((G)=>X.add(`用户请求:${G}`));else if(Q.role==="assistant")this.extractSolutions(Q.content).forEach((q)=>X.add(`解决方案:${q}`));return this.summarizeToolUsage(Y).forEach((Q)=>X.add(`工具使用:${Q}`)),Array.from(X).slice(0,this.keyPointsLimit)}generateToolSummary($){if($.length===0)return"";let Y=new Map,X=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>X)J.recent++;Y.set(Q.name,J)}let Z=[];for(let[Q,J]of Array.from(Y.entries())){let q=Math.round(J.success/J.count*100);Z.push(`${Q}(${J.count}次,成功率${q}%)`)}return`工具调用:${Z.join("、")}`}estimateTokenCount($,Y,X,Z){let Q=$.length+Y.join(" ").length;if(Z)Q+=Z.length;for(let J of X)Q+=J.content.length;return Math.ceil(Q/4)}extractContext($,Y,X){let Z=$.indexOf(Y);if(Z===-1)return null;let Q=Math.max(0,Z-X/2),J=Math.min($.length,Z+X/2);return $.substring(Q,J).trim()}extractQuestions($){let Y=[],X=["?","?","如何","怎么","什么","为什么"],Z=$.split(/[。!.!]/);for(let Q of Z)if(X.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=[],X=["请","帮我","需要","想要","希望","能否"],Z=$.split(/[。!.!]/);for(let Q of Z)if(X.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=[],X=["可以","建议","推荐","应该","最好","解决方案"],Z=$.split(/[。!.!]/);for(let Q of Z)if(X.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=[],X=$.filter((Z)=>Date.now()-Z.timestamp<1800000);if(X.length>0){let Z=new Map;X.forEach((Q)=>{let J=Z.get(Q.name)||[];J.push(Q),Z.set(Q.name,J)});for(let[Q,J]of Array.from(Z.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 X=$.layers.conversation.messages.reduce((Z,Q)=>Z+Q.content.length,0);return Math.ceil(X/4)}}class J${defaultOptions;constructor($){this.defaultOptions={maxTokens:32000,maxMessages:50,timeWindow:86400000,priority:1,includeTools:!0,includeWorkspace:!0,...$}}filter($,Y){let X={...this.defaultOptions,...Y},Z={layers:{system:$.layers.system,session:$.layers.session,conversation:this.filterConversation($.layers.conversation,X),tool:X.includeTools?this.filterTools($.layers.tool,X):{recentCalls:[],toolStates:{},dependencies:{}},workspace:X.includeWorkspace?$.layers.workspace:{currentFiles:[],recentFiles:[],environment:{}}},metadata:{...$.metadata,lastUpdated:Date.now()}};return Z.metadata.totalTokens=this.estimateTokens(Z),Z}filterConversation($,Y){let X=[...$.messages];if(Y.timeWindow>0){let Z=Date.now()-Y.timeWindow;X=X.filter((Q)=>Q.timestamp>=Z||Q.role==="system")}if(Y.priority>1)X=this.filterByPriority(X,Y.priority);if(Y.maxMessages>0)X=this.limitMessages(X,Y.maxMessages);if(Y.maxTokens>0)X=this.limitByTokens(X,Y.maxTokens);return{messages:X,summary:$.summary,topics:this.updateTopics(X,$.topics),lastActivity:$.lastActivity}}filterTools($,Y){let X=[...$.recentCalls];if(Y.timeWindow>0){let K=Date.now()-Y.timeWindow;X=X.filter((W)=>W.timestamp>=K)}let Z=X.filter((K)=>K.status==="success"),Q=X.filter((K)=>K.status==="error"),J=Math.min(20,Z.length),q=Math.min(10,Q.length);return{recentCalls:[...Z.slice(-J),...Q.slice(-q)].sort((K,W)=>K.timestamp-W.timestamp),toolStates:$.toolStates,dependencies:$.dependencies}}filterByPriority($,Y){return $.filter((X)=>{if(X.role==="system")return!0;return this.calculateMessagePriority(X)>=Y})}calculateMessagePriority($){let Y=1;if($.role==="system")Y+=3;else if($.role==="assistant")Y+=1;let X=$.content.toLowerCase();if(["错误","警告","重要","关键","问题","解决"].some((J)=>X.includes(J)))Y+=2;if(X.includes("```")||X.includes("function")||X.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 X=$.filter((q)=>q.role==="system"),Z=$.filter((q)=>q.role!=="system"),Q=Y-X.length,J=Q>0?Z.slice(-Q):[];return[...X,...J].sort((q,G)=>q.timestamp-G.timestamp)}limitByTokens($,Y){if(Y<=0)return $;let X=0,Z=[];for(let Q=$.length-1;Q>=0;Q--){let J=$[Q],q=this.estimateMessageTokens(J);if(J.role==="system")if(X+q<=Y)Z.unshift(J),X+=q;else{let G=this.compressMessage(J,Y-X);Z.unshift(G),X+=this.estimateMessageTokens(G)}else if(X+q<=Y)Z.unshift(J),X+=q;else break}return Z.sort((Q,J)=>Q.timestamp-J.timestamp)}estimateMessageTokens($){return Math.ceil($.content.length/4)}compressMessage($,Y){let X=Y*4;if($.content.length<=X)return $;let Z=$.content.substring(0,X-3)+"...";return{...$,content:Z,metadata:{...$.metadata,compressed:!0,originalLength:$.content.length}}}updateTopics($,Y){let X=new Set(Y);for(let Z of $)this.extractTopicsFromMessage(Z).forEach((J)=>X.add(J));return Array.from(X).slice(0,10)}extractTopicsFromMessage($){let Y=$.content.toLowerCase(),X=[];return["项目","功能","模块","组件","服务","接口","数据库","前端","后端","算法","架构","设计"].forEach((Q)=>{if(Y.includes(Q))X.push(Q)}),X}estimateTokens($){let Y=0;for(let Z of $.layers.conversation.messages)Y+=this.estimateMessageTokens(Z);let X=JSON.stringify($.layers.system);if(Y+=Math.ceil(X.length/4),$.layers.tool.recentCalls.length>0){let Z=JSON.stringify($.layers.tool);Y+=Math.ceil(Z.length/8)}return Y}static createPresets(){return{lightweight:new J$({maxTokens:1000,maxMessages:10,timeWindow:7200000,includeTools:!1,includeWorkspace:!1}),standard:new J$({maxTokens:4000,maxMessages:30,timeWindow:43200000,includeTools:!0,includeWorkspace:!0}),comprehensive:new J$({maxTokens:8000,maxMessages:100,timeWindow:86400000,includeTools:!0,includeWorkspace:!0}),debug:new J$({maxTokens:2000,maxMessages:20,timeWindow:21600000,priority:2,includeTools:!0,includeWorkspace:!1})}}}class J8{cache=new Map;maxSize;defaultTTL;constructor($=100,Y=300000){this.maxSize=$,this.defaultTTL=Y}set($,Y,X){let Z=Date.now(),Q={data:Y,timestamp:Z,accessCount:0,lastAccess:Z,ttl:X||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 X=Date.now();if(X-Y.timestamp>Y.ttl)return this.cache.delete($),null;return Y.accessCount++,Y.lastAccess=X,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,X){let Z=`summary:${$}:${Y.length}`;this.set(Z,{summary:X,messageCount:Y.length,lastMessage:Y[Y.length-1]?.timestamp||0},600000)}getMessageSummary($,Y){let X=`summary:${$}:${Y}`;return this.get(X)}cacheToolResult($,Y,X){let Z=this.hashInput(Y),Q=`tool:${$}:${Z}`;this.set(Q,X,1800000)}getToolResult($,Y){let X=this.hashInput(Y),Z=`tool:${$}:${X}`;return this.get(Z)}cacheCompressedContext($,Y){let X=`compressed:${$}`;this.set(X,Y,900000)}getCompressedContext($){let Y=`compressed:${$}`;return this.get(Y)}getStats(){this.cleanExpired();let $=0,Y=0,X=[];for(let[Z,Q]of Array.from(this.cache.entries()))$+=Q.accessCount,Y+=this.estimateItemSize(Q),X.push({key:Z,accessCount:Q.accessCount,lastAccess:Q.lastAccess});return X.sort((Z,Q)=>Q.accessCount-Z.accessCount),{size:this.cache.size,maxSize:this.maxSize,hitRate:$>0?$/($+this.cache.size):0,memoryUsage:Y,topKeys:X.slice(0,10)}}cleanExpired(){let $=Date.now(),Y=[];for(let[X,Z]of Array.from(this.cache.entries()))if($-Z.timestamp>Z.ttl)Y.push(X);Y.forEach((X)=>this.cache.delete(X))}evictLeastUsed(){let $=null,Y=1/0,X=Date.now();for(let[Z,Q]of Array.from(this.cache.entries())){let J=1/(X-Q.lastAccess+1),q=Q.accessCount,G=J*q;if(G<Y)Y=G,$=Z}if($)this.cache.delete($)}hashInput($){let Y=JSON.stringify($),X=0;for(let Z=0;Z<Y.length;Z++){let Q=Y.charCodeAt(Z);X=(X<<5)-X+Q,X=X&X}return Math.abs(X).toString(36)}estimateItemSize($){try{return JSON.stringify($).length*2}catch{return 1000}}setTTL($,Y){let X=this.cache.get($);if(X)return X.ttl=Y,X.timestamp=Date.now(),!0;return!1}getRemainingTTL($){let Y=this.cache.get($);if(!Y)return-1;let X=Y.ttl-(Date.now()-Y.timestamp);return Math.max(0,X)}warmup($){$.forEach(({key:Y,value:X,ttl:Z})=>{this.set(Y,X,Z)})}}class q8{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}}V$();import{nanoid as k$}from"nanoid";import*as y1 from"node:fs/promises";import*as w5 from"node:path";import*as $6 from"node:fs";import{createReadStream as ZQ}from"node:fs";import*as C0 from"node:fs/promises";import*as G8 from"node:path";import{createInterface as QQ}from"node:readline";class W1{filePath;constructor($){this.filePath=$}async append($){try{await C0.mkdir(G8.dirname(this.filePath),{recursive:!0});let Y=JSON.stringify($)+`
980
+ `;await C0.appendFile(this.filePath,Y,"utf-8")}catch(Y){throw console.error(`[JSONLStore] 追加写入失败: ${this.filePath}`,Y),Y}}async appendBatch($){try{await C0.mkdir(G8.dirname(this.filePath),{recursive:!0});let Y=$.map((X)=>JSON.stringify(X)).join(`
984
981
  `)+`
985
- `;await j0.appendFile(this.filePath,Y,"utf-8")}catch(Y){throw console.error(`[JSONLStore] 批量追加写入失败: ${this.filePath}`,Y),Y}}async readAll(){try{if(!r2.existsSync(this.filePath))return[];let Y=(await j0.readFile(this.filePath,"utf-8")).split(`
986
- `).filter((Z)=>Z.trim().length>0),X=[];for(let Z of Y)try{X.push(JSON.parse(Z))}catch(Q){console.warn(`[JSONLStore] 解析 JSON 行失败: ${Z}`,Q)}return X}catch($){return console.error(`[JSONLStore] 读取文件失败: ${this.filePath}`,$),[]}}async readStream($){return new Promise((Y,X)=>{if(!r2.existsSync(this.filePath)){Y();return}let Z=CZ(this.filePath,"utf-8"),Q=fZ({input:Z,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",X),Z.on("error",X)})}async filter($){let Y=[];return await this.readStream((X)=>{if($(X))Y.push(X)}),Y}async readLast($){return(await this.readAll()).slice(-$)}async getStats(){try{if(!r2.existsSync(this.filePath))return{exists:!1,size:0,lineCount:0};let $=await j0.stat(this.filePath),X=(await j0.readFile(this.filePath,"utf-8")).split(`
987
- `).filter((Z)=>Z.trim().length>0).length;return{exists:!0,size:$.size,lineCount:X}}catch($){return console.error(`[JSONLStore] 获取统计信息失败: ${this.filePath}`,$),{exists:!1,size:0,lineCount:0}}}async exists(){try{return await j0.access(this.filePath),!0}catch{return!1}}async delete(){try{if(await this.exists())await j0.unlink(this.filePath)}catch($){throw console.error(`[JSONLStore] 删除文件失败: ${this.filePath}`,$),$}}getFilePath(){return this.filePath}}class $8{projectPath;maxSessions;version;constructor($=process.cwd(),Y=100,X="0.0.10"){this.projectPath=$,this.maxSessions=Y,this.version=X}async initialize(){try{let $=z$(this.projectPath);await k1.mkdir($,{recursive:!0}),console.log(`[PersistentStore] 初始化存储目录: ${$}`)}catch($){console.warn("[PersistentStore] 无法创建持久化存储目录:",$)}}async saveMessage($,Y,X,Z=null,Q){try{let J=Q1(this.projectPath,$),q=new J1(J),G={uuid:R$(),parentUuid:Z,sessionId:$,timestamp:new Date().toISOString(),type:Y==="user"?"user":Y==="assistant"?"assistant":"system",cwd:this.projectPath,gitBranch:o1(this.projectPath),version:this.version,message:{role:Y,content:X,...Q||{}}};return await q.append(G),G.uuid}catch(J){throw console.error(`[PersistentStore] 保存消息失败 (session: ${$}):`,J),J}}async saveToolUse($,Y,X,Z=null){try{let Q=Q1(this.projectPath,$),J=new J1(Q),q={uuid:R$(),parentUuid:Z,sessionId:$,timestamp:new Date().toISOString(),type:"tool_use",cwd:this.projectPath,gitBranch:o1(this.projectPath),version:this.version,message:{role:"assistant",content:""},tool:{id:R$(),name:Y,input:X}};return await J.append(q),q.uuid}catch(Q){throw console.error(`[PersistentStore] 保存工具调用失败 (session: ${$}):`,Q),Q}}async saveToolResult($,Y,X,Z=null,Q){try{let J=Q1(this.projectPath,$),q=new J1(J),G={uuid:R$(),parentUuid:Z,sessionId:$,timestamp:new Date().toISOString(),type:"tool_result",cwd:this.projectPath,gitBranch:o1(this.projectPath),version:this.version,message:{role:"assistant",content:""},toolResult:{id:Y,output:X,error:Q}};return await q.append(G),G.uuid}catch(J){throw console.error(`[PersistentStore] 保存工具结果失败 (session: ${$}):`,J),J}}async saveCompaction($,Y,X,Z=null){try{let Q=Q1(this.projectPath,$),J=new J1(Q),q={uuid:R$(),parentUuid:Z,sessionId:$,timestamp:new Date().toISOString(),type:"system",subtype:"compact_boundary",cwd:this.projectPath,gitBranch:o1(this.projectPath),version:this.version,message:{role:"system",content:"=== 上下文压缩边界 ==="},compactMetadata:X};await J.append(q),console.log("[PersistentStore] 保存压缩边界标记");let G={uuid:R$(),parentUuid:q.uuid,logicalParentUuid:Z??void 0,sessionId:$,timestamp:new Date().toISOString(),type:"user",isCompactSummary:!0,cwd:this.projectPath,gitBranch:o1(this.projectPath),version:this.version,message:{role:"user",content:Y},compactMetadata:X};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:X}=Y.layers;for(let Z of X.messages)await this.saveMessage($,Z.role,Z.content,null)}catch(X){console.warn(`[PersistentStore] 保存上下文失败 (session: ${$}):`,X)}}async saveSession($,Y){console.warn("[PersistentStore] saveSession 方法已废弃,请使用 saveMessage")}async saveConversation($,Y){console.warn("[PersistentStore] saveConversation 方法已废弃,请使用 saveMessage")}async loadSession($){try{let Y=Q1(this.projectPath,$),Z=await new J1(Y).readAll();if(Z.length===0)return null;let Q=Z[0];return{sessionId:$,userId:void 0,preferences:{},configuration:{},startTime:new Date(Q.timestamp).getTime()}}catch{return null}}async loadConversation($){try{let Y=Q1(this.projectPath,$),Z=await new J1(Y).readAll();if(Z.length===0)return null;let Q=Z.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=Z[Z.length-1],q=new Date(J.timestamp).getTime();return{messages:Q,topics:[],lastActivity:q}}catch{return null}}async listSessions(){try{let $=z$(this.projectPath);return(await k1.readdir($)).filter((X)=>X.endsWith(".jsonl")).map((X)=>X.replace(".jsonl","")).sort()}catch{return[]}}async getSessionSummary($){try{let Y=Q1(this.projectPath,$),X=new J1(Y);if(!(await X.getStats()).exists)return null;let Q=await X.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=Q1(this.projectPath,$);await new J1(Y).delete()}catch(Y){console.warn(`[PersistentStore] 删除会话失败 (session: ${$}):`,Y)}}async cleanupOldSessions(){try{let $=await this.listSessions();if($.length<=this.maxSessions)return;let Z=(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(Z.map((Q)=>this.deleteSession(Q))),console.log(`[PersistentStore] 已清理 ${Z.length} 个旧会话`)}catch($){console.error("[PersistentStore] 清理旧会话失败:",$)}}async getStorageStats(){try{let $=await this.listSessions(),Y=0;for(let X of $){let Z=Q1(this.projectPath,X),J=await new J1(Z).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 $=z$(this.projectPath);await k1.mkdir($,{recursive:!0});let Y=J5.join($,".health-check");return await k1.writeFile(Y,"test","utf-8"),await k1.unlink(Y),{isAvailable:!0,canWrite:!0}}catch($){return{isAvailable:!1,canWrite:!1,error:$ instanceof Error?$.message:String($)}}}static async listAllProjects(){return o6()}}N$();class $2{memory;persistent;cache;compressor;filter;options;currentSessionId=null;initialized=!1;constructor($={}){let Y=$.storage?.persistentPath||P1();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 t4(this.options.storage.maxMemorySize),this.persistent=new $8(process.cwd(),100),this.cache=new s4(this.options.storage.cacheSize,300000),this.compressor=new o4,this.filter=new e1(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={},X={}){let Z=X.sessionId||this.generateSessionId(),Q=Date.now(),J={layers:{system:await this.createSystemContext(),session:{sessionId:Z,userId:$,preferences:Y,configuration:X,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(Z,J),this.currentSessionId=Z,console.log(`新会话已创建: ${Z}`),Z}async loadSession($){try{let Y=this.memory.getContext();if(!Y||Y.layers.session.sessionId!==$){let[X,Z]=await Promise.all([this.persistent.loadSession($),this.persistent.loadConversation($)]);if(!X||!Z)return!1;Y={layers:{system:await this.createSystemContext(),session:X,conversation:Z,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,X){if(!this.currentSessionId)throw Error("没有活动会话");let Z={id:this.generateMessageId(),role:$,content:Y,timestamp:Date.now(),metadata:X};this.memory.addMessage(Z);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,X,Z=null,Q){return this.persistent.saveMessage($,Y,X,Z,Q)}async saveToolUse($,Y,X,Z=null){return this.persistent.saveToolUse($,Y,X,Z)}async saveToolResult($,Y,X,Z=null,Q){return this.persistent.saveToolResult($,Y,X,Z,Q)}async saveCompaction($,Y,X,Z=null){return this.persistent.saveCompaction($,Y,X,Z)}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 X=this.filter.filter(Y,$),Z=this.shouldCompress(X),Q;if(Z){let J=this.hashContext(X);if(Q=this.cache.getCompressedContext(J),!Q)Q=await this.compressor.compress(X),this.cache.cacheCompressedContext(J,Q)}return{context:X,compressed:Q,tokenCount:Q?Q.tokenCount:X.metadata.totalTokens}}async searchSessions($,Y=10){let X=await this.persistent.listSessions(),Z=[];for(let Q of X){let J=await this.persistent.getSessionSummary(Q);if(J){let q=this.calculateRelevance($,J.topics);if(q>0)Z.push({sessionId:Q,summary:`${J.messageCount}条消息,主题:${J.topics.join("、")}`,lastActivity:J.lastActivity,relevanceScore:q})}}return Z.sort((Q,J)=>J.relevanceScore-Q.relevanceScore).slice(0,Y)}getCachedToolResult($,Y){return this.cache.getToolResult($,Y)}async getStats(){let[$,Y,X]=await Promise.all([Promise.resolve(this.memory.getMemoryInfo()),Promise.resolve(this.cache.getStats()),this.persistent.getStorageStats()]);return{currentSession:this.currentSessionId,memory:$,cache:Y,storage:X}}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 q5()}generateMessageId(){return q5()}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 G5.createHash("md5").update(Y).digest("hex")}calculateRelevance($,Y){let X=$.toLowerCase(),Z=0;for(let Q of Y)if(X.includes(Q.toLowerCase())||Q.toLowerCase().includes(X))Z+=1;return Z}}class Y8{chatService;contextManager;memoryAdapter;constructor($,Y){this.chatService=$,this.contextManager=Y||new $2,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}],X=await this.chatService.chat(Y);return{taskId:$.id,content:X.content,metadata:{executionMode:"simple",taskType:$.type}}}async executeParallelTask($){let Y=this.decomposeTask($),X=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}}})),Z=this.combineSubTaskResults(X);return{taskId:$.id,content:Z,metadata:{executionMode:"parallel",taskType:$.type,subTaskCount:Y.length,failedSubTasks:X.filter((Q)=>!Q.success).length}}}async executeSteeringTask($){let Y=await this.generateExecutionSteps($),X="",Z={};for(let Q=0;Q<Y.length;Q++){let J=Y[Q];try{let q=await this.executeStep(J,$);X+=q.content+`
982
+ `;await C0.appendFile(this.filePath,Y,"utf-8")}catch(Y){throw console.error(`[JSONLStore] 批量追加写入失败: ${this.filePath}`,Y),Y}}async readAll(){try{if(!$6.existsSync(this.filePath))return[];let Y=(await C0.readFile(this.filePath,"utf-8")).split(`
983
+ `).filter((Z)=>Z.trim().length>0),X=[];for(let Z of Y)try{X.push(JSON.parse(Z))}catch(Q){console.warn(`[JSONLStore] 解析 JSON 行失败: ${Z}`,Q)}return X}catch($){return console.error(`[JSONLStore] 读取文件失败: ${this.filePath}`,$),[]}}async readStream($){return new Promise((Y,X)=>{if(!$6.existsSync(this.filePath)){Y();return}let Z=ZQ(this.filePath,"utf-8"),Q=QQ({input:Z,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",X),Z.on("error",X)})}async filter($){let Y=[];return await this.readStream((X)=>{if($(X))Y.push(X)}),Y}async readLast($){return(await this.readAll()).slice(-$)}async getStats(){try{if(!$6.existsSync(this.filePath))return{exists:!1,size:0,lineCount:0};let $=await C0.stat(this.filePath),X=(await C0.readFile(this.filePath,"utf-8")).split(`
984
+ `).filter((Z)=>Z.trim().length>0).length;return{exists:!0,size:$.size,lineCount:X}}catch($){return console.error(`[JSONLStore] 获取统计信息失败: ${this.filePath}`,$),{exists:!1,size:0,lineCount:0}}}async exists(){try{return await C0.access(this.filePath),!0}catch{return!1}}async delete(){try{if(await this.exists())await C0.unlink(this.filePath)}catch($){throw console.error(`[JSONLStore] 删除文件失败: ${this.filePath}`,$),$}}getFilePath(){return this.filePath}}class K8{projectPath;maxSessions;version;constructor($=process.cwd(),Y=100,X="0.0.10"){this.projectPath=$,this.maxSessions=Y,this.version=X}async initialize(){try{let $=b$(this.projectPath);await y1.mkdir($,{recursive:!0}),console.log(`[PersistentStore] 初始化存储目录: ${$}`)}catch($){console.warn("[PersistentStore] 无法创建持久化存储目录:",$)}}async saveMessage($,Y,X,Z=null,Q){try{let J=K1(this.projectPath,$),q=new W1(J),G={uuid:k$(),parentUuid:Z,sessionId:$,timestamp:new Date().toISOString(),type:Y==="user"?"user":Y==="assistant"?"assistant":"system",cwd:this.projectPath,gitBranch:X$(this.projectPath),version:this.version,message:{role:Y,content:X,...Q||{}}};return await q.append(G),G.uuid}catch(J){throw console.error(`[PersistentStore] 保存消息失败 (session: ${$}):`,J),J}}async saveToolUse($,Y,X,Z=null){try{let Q=K1(this.projectPath,$),J=new W1(Q),q={uuid:k$(),parentUuid:Z,sessionId:$,timestamp:new Date().toISOString(),type:"tool_use",cwd:this.projectPath,gitBranch:X$(this.projectPath),version:this.version,message:{role:"assistant",content:""},tool:{id:k$(),name:Y,input:X}};return await J.append(q),q.uuid}catch(Q){throw console.error(`[PersistentStore] 保存工具调用失败 (session: ${$}):`,Q),Q}}async saveToolResult($,Y,X,Z=null,Q){try{let J=K1(this.projectPath,$),q=new W1(J),G={uuid:k$(),parentUuid:Z,sessionId:$,timestamp:new Date().toISOString(),type:"tool_result",cwd:this.projectPath,gitBranch:X$(this.projectPath),version:this.version,message:{role:"assistant",content:""},toolResult:{id:Y,output:X,error:Q}};return await q.append(G),G.uuid}catch(J){throw console.error(`[PersistentStore] 保存工具结果失败 (session: ${$}):`,J),J}}async saveCompaction($,Y,X,Z=null){try{let Q=K1(this.projectPath,$),J=new W1(Q),q={uuid:k$(),parentUuid:Z,sessionId:$,timestamp:new Date().toISOString(),type:"system",subtype:"compact_boundary",cwd:this.projectPath,gitBranch:X$(this.projectPath),version:this.version,message:{role:"system",content:"=== 上下文压缩边界 ==="},compactMetadata:X};await J.append(q),console.log("[PersistentStore] 保存压缩边界标记");let G={uuid:k$(),parentUuid:q.uuid,logicalParentUuid:Z??void 0,sessionId:$,timestamp:new Date().toISOString(),type:"user",isCompactSummary:!0,cwd:this.projectPath,gitBranch:X$(this.projectPath),version:this.version,message:{role:"user",content:Y},compactMetadata:X};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:X}=Y.layers;for(let Z of X.messages)await this.saveMessage($,Z.role,Z.content,null)}catch(X){console.warn(`[PersistentStore] 保存上下文失败 (session: ${$}):`,X)}}async saveSession($,Y){console.warn("[PersistentStore] saveSession 方法已废弃,请使用 saveMessage")}async saveConversation($,Y){console.warn("[PersistentStore] saveConversation 方法已废弃,请使用 saveMessage")}async loadSession($){try{let Y=K1(this.projectPath,$),Z=await new W1(Y).readAll();if(Z.length===0)return null;let Q=Z[0];return{sessionId:$,userId:void 0,preferences:{},configuration:{},startTime:new Date(Q.timestamp).getTime()}}catch{return null}}async loadConversation($){try{let Y=K1(this.projectPath,$),Z=await new W1(Y).readAll();if(Z.length===0)return null;let Q=Z.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=Z[Z.length-1],q=new Date(J.timestamp).getTime();return{messages:Q,topics:[],lastActivity:q}}catch{return null}}async listSessions(){try{let $=b$(this.projectPath);return(await y1.readdir($)).filter((X)=>X.endsWith(".jsonl")).map((X)=>X.replace(".jsonl","")).sort()}catch{return[]}}async getSessionSummary($){try{let Y=K1(this.projectPath,$),X=new W1(Y);if(!(await X.getStats()).exists)return null;let Q=await X.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=K1(this.projectPath,$);await new W1(Y).delete()}catch(Y){console.warn(`[PersistentStore] 删除会话失败 (session: ${$}):`,Y)}}async cleanupOldSessions(){try{let $=await this.listSessions();if($.length<=this.maxSessions)return;let Z=(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(Z.map((Q)=>this.deleteSession(Q))),console.log(`[PersistentStore] 已清理 ${Z.length} 个旧会话`)}catch($){console.error("[PersistentStore] 清理旧会话失败:",$)}}async getStorageStats(){try{let $=await this.listSessions(),Y=0;for(let X of $){let Z=K1(this.projectPath,X),J=await new W1(Z).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 $=b$(this.projectPath);await y1.mkdir($,{recursive:!0});let Y=w5.join($,".health-check");return await y1.writeFile(Y,"test","utf-8"),await y1.unlink(Y),{isAvailable:!0,canWrite:!0}}catch($){return{isAvailable:!1,canWrite:!1,error:$ instanceof Error?$.message:String($)}}}static async listAllProjects(){return Q4()}}V$();class K2{memory;persistent;cache;compressor;filter;options;currentSessionId=null;initialized=!1;constructor($={}){let Y=$.storage?.persistentPath||f1();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 q8(this.options.storage.maxMemorySize),this.persistent=new K8(process.cwd(),100),this.cache=new J8(this.options.storage.cacheSize,300000),this.compressor=new Q8,this.filter=new J$(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={},X={}){let Z=X.sessionId||this.generateSessionId(),Q=Date.now(),J={layers:{system:await this.createSystemContext(),session:{sessionId:Z,userId:$,preferences:Y,configuration:X,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(Z,J),this.currentSessionId=Z,console.log(`新会话已创建: ${Z}`),Z}async loadSession($){try{let Y=this.memory.getContext();if(!Y||Y.layers.session.sessionId!==$){let[X,Z]=await Promise.all([this.persistent.loadSession($),this.persistent.loadConversation($)]);if(!X||!Z)return!1;Y={layers:{system:await this.createSystemContext(),session:X,conversation:Z,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,X){if(!this.currentSessionId)throw Error("没有活动会话");let Z={id:this.generateMessageId(),role:$,content:Y,timestamp:Date.now(),metadata:X};this.memory.addMessage(Z);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,X,Z=null,Q){return this.persistent.saveMessage($,Y,X,Z,Q)}async saveToolUse($,Y,X,Z=null){return this.persistent.saveToolUse($,Y,X,Z)}async saveToolResult($,Y,X,Z=null,Q){return this.persistent.saveToolResult($,Y,X,Z,Q)}async saveCompaction($,Y,X,Z=null){return this.persistent.saveCompaction($,Y,X,Z)}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 X=this.filter.filter(Y,$),Z=this.shouldCompress(X),Q;if(Z){let J=this.hashContext(X);if(Q=this.cache.getCompressedContext(J),!Q)Q=await this.compressor.compress(X),this.cache.cacheCompressedContext(J,Q)}return{context:X,compressed:Q,tokenCount:Q?Q.tokenCount:X.metadata.totalTokens}}async searchSessions($,Y=10){let X=await this.persistent.listSessions(),Z=[];for(let Q of X){let J=await this.persistent.getSessionSummary(Q);if(J){let q=this.calculateRelevance($,J.topics);if(q>0)Z.push({sessionId:Q,summary:`${J.messageCount}条消息,主题:${J.topics.join("、")}`,lastActivity:J.lastActivity,relevanceScore:q})}}return Z.sort((Q,J)=>J.relevanceScore-Q.relevanceScore).slice(0,Y)}getCachedToolResult($,Y){return this.cache.getToolResult($,Y)}async getStats(){let[$,Y,X]=await Promise.all([Promise.resolve(this.memory.getMemoryInfo()),Promise.resolve(this.cache.getStats()),this.persistent.getStorageStats()]);return{currentSession:this.currentSessionId,memory:$,cache:Y,storage:X}}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 A5()}generateMessageId(){return A5()}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 R5.createHash("md5").update(Y).digest("hex")}calculateRelevance($,Y){let X=$.toLowerCase(),Z=0;for(let Q of Y)if(X.includes(Q.toLowerCase())||Q.toLowerCase().includes(X))Z+=1;return Z}}class W8{chatService;contextManager;memoryAdapter;constructor($,Y){this.chatService=$,this.contextManager=Y||new K2,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}],X=await this.chatService.chat(Y);return{taskId:$.id,content:X.content,metadata:{executionMode:"simple",taskType:$.type}}}async executeParallelTask($){let Y=this.decomposeTask($),X=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}}})),Z=this.combineSubTaskResults(X);return{taskId:$.id,content:Z,metadata:{executionMode:"parallel",taskType:$.type,subTaskCount:Y.length,failedSubTasks:X.filter((Q)=>!Q.success).length}}}async executeSteeringTask($){let Y=await this.generateExecutionSteps($),X="",Z={};for(let Q=0;Q<Y.length;Q++){let J=Y[Q];try{let q=await this.executeStep(J,$);X+=q.content+`
988
985
 
989
986
  `,Z[`step_${Q}_type`]=J.type,Z[`step_${Q}_result`]=q}catch(q){throw Error(`步骤 ${J.id} 执行失败: ${q instanceof Error?q.message:"未知错误"}`)}}return{taskId:$.id,content:X.trim(),metadata:{executionMode:"steering",taskType:$.type,steps:Y.length,...Z}}}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 X=`Step: ${$.description}
990
987
  Task: ${Y.prompt}`;return{content:(await this.chatService.chat([{role:"user",content:X}])).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(`
991
988
 
992
- `)}}var k=Y0("Agent");class v0{config;runtimeOptions;isInitialized=!1;activeTask;executionPipeline;systemPrompt;chatService;executionEngine;attachmentCollector;constructor($,Y={},X){this.config=$,this.runtimeOptions=Y,this.executionPipeline=X||this.createDefaultPipeline()}createDefaultPipeline(){let $=new n4,Y={...this.config.permissions,...this.runtimeOptions.permissions},X=this.runtimeOptions.permissionMode??this.config.permissionMode??"default";return new a4($,{permissionConfig:Y,permissionMode:X,maxHistorySize:1000})}static async create($={}){if(await b2(),c$().length===0)throw Error(`❌ 没有可用的模型配置
989
+ `)}}var M=$0("Agent");class k0{config;runtimeOptions;isInitialized=!1;activeTask;executionPipeline;systemPrompt;chatService;executionEngine;attachmentCollector;constructor($,Y={},X){this.config=$,this.runtimeOptions=Y,this.executionPipeline=X||this.createDefaultPipeline()}createDefaultPipeline(){let $=new Z8,Y={...this.config.permissions,...this.runtimeOptions.permissions},X=this.runtimeOptions.permissionMode??this.config.permissionMode??"default";return new X8($,{permissionConfig:Y,permissionMode:X,maxHistorySize:1000})}static async create($={}){if(await y2(),e$().length===0)throw Error(`❌ 没有可用的模型配置
993
990
 
994
991
  `+`请先使用以下命令添加模型:
995
992
  `+` /model add
996
993
 
997
994
  `+`或运行初始化向导:
998
- `+" /init");let X=F0();if(!X)throw Error("❌ 配置未初始化,请确保应用已正确启动");D0.getInstance().validateConfig(X);let Q=new v0(X,$);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 $=V2();if(!$)throw Error("❌ 当前模型配置未找到");this.log(`\uD83D\uDE80 使用模型: ${$.name} (${$.model})`),this.chatService=E2({provider:$.provider,apiKey:$.apiKey,model:$.model,baseUrl:$.baseUrl,temperature:$.temperature??this.config.temperature,maxContextTokens:$.maxContextTokens??this.config.maxContextTokens,maxOutputTokens:this.config.maxOutputTokens,timeout:this.config.timeout}),this.executionEngine=new Y8(this.chatService),this.attachmentCollector=new i6({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,X){if(!this.isInitialized)throw Error("Agent未初始化");let Z=await this.processAtMentions($);if(Y){let q={signal:Y.signal,...X},G=Y.permissionMode==="plan"?await this.runPlanLoop(Z,Y,q):await this.runLoop(Z,Y,q);if(!G.success){if(G.error?.type==="aborted")return"";throw Error(G.error?.message||"执行失败")}if(G.metadata?.targetMode&&Y.permissionMode==="plan"){let K=G.metadata.targetMode,W=G.metadata.planContent;k.debug(`\uD83D\uDD04 Plan 模式已批准,切换到 ${K} 模式并重新执行`),await e().setPermissionMode(K),k.debug(`✅ 权限模式已更新: ${K}`);let O={...Y,permissionMode:K},U=Z;if(W)U=`${Z}
995
+ `+" /init");let X=D0();if(!X)throw Error("❌ 配置未初始化,请确保应用已正确启动");P0.getInstance().validateConfig(X);let Q=new k0(X,$);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 $=E2();if(!$)throw Error("❌ 当前模型配置未找到");this.log(`\uD83D\uDE80 使用模型: ${$.name} (${$.model})`),this.chatService=h2({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}),this.executionEngine=new W8(this.chatService),this.attachmentCollector=new $4({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,X){if(!this.isInitialized)throw Error("Agent未初始化");let Z=await this.processAtMentions($);if(Y){let q={signal:Y.signal,...X},G=Y.permissionMode==="plan"?await this.runPlanLoop(Z,Y,q):await this.runLoop(Z,Y,q);if(!G.success){if(G.error?.type==="aborted"||G.metadata?.shouldExitLoop)return"";throw Error(G.error?.message||"执行失败")}if(G.metadata?.targetMode&&Y.permissionMode==="plan"){let K=G.metadata.targetMode,W=G.metadata.planContent;M.debug(`\uD83D\uDD04 Plan 模式已批准,切换到 ${K} 模式并重新执行`),await W0().setPermissionMode(K),M.debug(`✅ 权限模式已更新: ${K}`);let O={...Y,permissionMode:K},U=Z;if(W)U=`${Z}
999
996
 
1000
997
  <approved-plan>
1001
998
  ${W}
1002
999
  </approved-plan>
1003
1000
 
1004
- IMPORTANT: Execute according to the approved plan above. Follow the steps exactly as specified.`,k.debug(`\uD83D\uDCCB 已将 plan 内容注入到消息中 (${W.length} 字符)`);return this.runLoop(U,O,q).then((H)=>{if(!H.success)throw Error(H.error?.message||"执行失败");return H.finalMessage||""})}return G.finalMessage||""}let Q={id:this.generateTaskId(),type:"simple",prompt:Z};return(await this.executeTask(Q)).content}async runPlanLoop($,Y,X){k.debug("\uD83D\uDD35 Processing Plan mode message...");let{prompt:Z}=await S2({projectPath:process.cwd(),mode:"plan",includeEnvironment:!0}),Q=l6($);return this.executeLoop(Q,Y,X,Z)}async runLoop($,Y,X){k.debug("\uD83D\uDCAC Processing enhanced chat message...");let Z=P2(),Q=this.systemPrompt?`${Z}
1001
+ IMPORTANT: Execute according to the approved plan above. Follow the steps exactly as specified.`,M.debug(`\uD83D\uDCCB 已将 plan 内容注入到消息中 (${W.length} 字符)`);return this.runLoop(U,O,q).then((H)=>{if(!H.success)throw Error(H.error?.message||"执行失败");return H.finalMessage||""})}return G.finalMessage||""}let Q={id:this.generateTaskId(),type:"simple",prompt:Z};return(await this.executeTask(Q)).content}async runPlanLoop($,Y,X){M.debug("\uD83D\uDD35 Processing Plan mode message...");let{prompt:Z}=await g2({projectPath:process.cwd(),mode:"plan",includeEnvironment:!0}),Q=e6($);return this.executeLoop(Q,Y,X,Z)}async runLoop($,Y,X){M.debug("\uD83D\uDCAC Processing enhanced chat message...");let Z=p2(),Q=this.systemPrompt?`${Z}
1005
1002
 
1006
1003
  ---
1007
1004
 
1008
- ${this.systemPrompt}`:Z;return this.executeLoop($,Y,X,Q)}async executeLoop($,Y,X,Z){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 A=J.getReadOnlyTools();k.debug(`\uD83D\uDD12 Plan mode: 使用只读工具 (${A.length} 个): ${A.map((b)=>b.name).join(", ")}`)}let W=Y.messages.length===0||!Y.messages.some((A)=>A.role==="system"),O=[];if(W&&Z)O.push({role:"system",content:Z});O.push(...Y.messages,{role:"user",content:$});let U=null;try{let A=this.executionEngine?.getContextManager();if(A&&Y.sessionId&&$.trim()!=="")U=await A.saveMessage(Y.sessionId,"user",$);else if($.trim()==="")k.debug("[Agent] 跳过保存空用户消息")}catch(A){k.warn("[Agent] 保存用户消息失败:",A)}let H=100,_=this.runtimeOptions.maxTurns??X?.maxTurns??this.config.maxTurns??-1;if(_===0)return{success:!1,error:{type:"chat_disabled",message:`对话功能已被禁用 (maxTurns=0)。如需启用,请调整配置:
1005
+ ${this.systemPrompt}`:Z;return this.executeLoop($,Y,X,Q)}async executeLoop($,Y,X,Z){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 R=J.getReadOnlyTools();M.debug(`\uD83D\uDD12 Plan mode: 使用只读工具 (${R.length} 个): ${R.map((k)=>k.name).join(", ")}`)}let W=Y.messages.length===0||!Y.messages.some((R)=>R.role==="system"),O=[];if(W&&Z)O.push({role:"system",content:Z});O.push(...Y.messages,{role:"user",content:$});let U=null;try{let R=this.executionEngine?.getContextManager();if(R&&Y.sessionId&&$.trim()!=="")U=await R.saveMessage(Y.sessionId,"user",$);else if($.trim()==="")M.debug("[Agent] 跳过保存空用户消息")}catch(R){M.warn("[Agent] 保存用户消息失败:",R)}let H=100,_=Y.permissionMode==="yolo",z=this.runtimeOptions.maxTurns??X?.maxTurns??this.config.maxTurns??-1;if(z===0)return{success:!1,error:{type:"chat_disabled",message:`对话功能已被禁用 (maxTurns=0)。如需启用,请调整配置:
1009
1006
  `+` • CLI 参数: blade --max-turns -1
1010
1007
  `+` • 配置文件: ~/.blade/config.json 中设置 "maxTurns": -1
1011
- `+" • 环境变量: export BLADE_MAX_TURNS=-1"},metadata:{turnsCount:0,toolCallsCount:0,duration:0}};let z=_===-1?H:Math.min(_,H);if(this.config.debug)k.debug(`[MaxTurns] 配置值: ${_}, 实际限制: ${z}, 安全上限: ${H}`);let F=0,L=[],w=0,N;while(!0){if(X?.signal?.aborted)return{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:F,toolCallsCount:L.length,duration:Date.now()-Q}};let A=Y.messages.length;if(await this.checkAndCompactInLoop(O,Y,F,N,X?.onCompacting)){k.debug(`[Agent] [轮次 ${F}] 检测到压缩发生,重建 messages 数组 (${A} → ${Y.messages.length} 条历史消息)`);let B=W&&Z?1:0,D=B+A,C=O.slice(0,B),p=O.slice(D);O.length=0,O.push(...C,...Y.messages,...p),k.debug(`[Agent] [轮次 ${F}] messages 重建完成: ${C.length} system + ${Y.messages.length} 历史 + ${p.length} 新增 = ${O.length} 总计`)}if(F++,k.debug(`\uD83D\uDD04 [轮次 ${F}/${z}] 调用 LLM...`),X?.signal?.aborted)return{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:F-1,toolCallsCount:L.length,duration:Date.now()-Q}};X?.onTurnStart?.({turn:F,maxTurns:z}),k.debug(`
1012
- ========== 发送给 LLM ==========`),k.debug("轮次:",F+1),k.debug("消息数量:",O.length),k.debug("最后 3 条消息:"),O.slice(-3).forEach((B,D)=>{if(k.debug(` [${D}] ${B.role}:`,typeof B.content==="string"?B.content.substring(0,100)+(B.content.length>100?"...":""):JSON.stringify(B.content).substring(0,100)),B.tool_calls)k.debug(" tool_calls:",B.tool_calls.map((C)=>("function"in C)?C.function.name:C.type).join(", "))}),k.debug("可用工具数量:",G.length),k.debug(`================================
1013
- `);let y=this.filterOrphanToolMessages(O);if(y.length<O.length)k.debug(`\uD83D\uDD27 过滤掉 ${O.length-y.length} 条孤儿 tool 消息`);let R=await this.chatService.chat(y,G,X?.signal);if(R.usage){if(R.usage.totalTokens)w+=R.usage.totalTokens;if(N=R.usage.promptTokens,k.debug(`[Agent] LLM usage: prompt=${N}, completion=${R.usage.completionTokens}, total=${R.usage.totalTokens}`),X?.onTokenUsage)X.onTokenUsage({inputTokens:R.usage.promptTokens??0,outputTokens:R.usage.completionTokens??0,totalTokens:w,maxContextTokens:this.config.maxContextTokens})}if(X?.signal?.aborted)return{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:F-1,toolCallsCount:L.length,duration:Date.now()-Q}};if(k.debug(`
1014
- ========== LLM 返回 ==========`),k.debug("Content:",R.content),k.debug("Tool Calls:",JSON.stringify(R.toolCalls,null,2)),k.debug("当前权限模式:",Y.permissionMode),k.debug(`================================
1015
- `),R.content&&R.content.trim()&&X?.onContent)X.onContent(R.content);if(!R.toolCalls||R.toolCalls.length===0){let B=[/:\s*$/,/:\s*$/,/\.\.\.\s*$/,/让我(先|来|开始|查看|检查|修复)/,/Let me (first|start|check|look|fix)/i],D=R.content||"",C=B.some((M)=>M.test(D)),p="请执行你提到的操作,不要只是描述。",E=O.slice(-10).filter((M)=>M.role==="user"&&M.content==="请执行你提到的操作,不要只是描述。").length;if(C&&E<2){k.debug(`⚠️ 检测到意图未完成(重试 ${E+1}/2): "${D.slice(-50)}"`),O.push({role:"user",content:"请执行你提到的操作,不要只是描述。"});continue}k.debug("✅ 任务完成 - LLM 未请求工具调用");try{let M=this.executionEngine?.getContextManager();if(M&&Y.sessionId&&R.content)if(R.content.trim()!=="")U=await M.saveMessage(Y.sessionId,"assistant",R.content,U);else k.debug("[Agent] 跳过保存空响应(任务完成时)")}catch(M){k.warn("[Agent] 保存助手消息失败:",M)}return{success:!0,finalMessage:R.content,metadata:{turnsCount:F,toolCallsCount:L.length,duration:Date.now()-Q,tokensUsed:w}}}O.push({role:"assistant",content:R.content||"",tool_calls:R.toolCalls});try{let B=this.executionEngine?.getContextManager();if(B&&Y.sessionId&&R.content)if(R.content.trim()!=="")U=await B.saveMessage(Y.sessionId,"assistant",R.content,U);else k.debug("[Agent] 跳过保存空响应(工具调用时)")}catch(B){k.warn("[Agent] 保存助手工具调用消息失败:",B)}for(let B of R.toolCalls){if(B.type!=="function")continue;try{if(X?.onToolStart)X.onToolStart(B);let D=JSON.parse(B.function.arguments);if(D.todos&&typeof D.todos==="string")try{D.todos=JSON.parse(D.todos),this.log("[Agent] 自动修复了字符串化的 todos 参数")}catch{this.error("[Agent] todos 参数格式异常,将由验证层处理")}let C=null;try{let S=this.executionEngine?.getContextManager();if(S&&Y.sessionId)C=await S.saveToolUse(Y.sessionId,B.function.name,D,U)}catch(S){k.warn("[Agent] 保存工具调用失败:",S)}let p=X?.signal;if(!p)k.error("[Agent] Missing signal in tool execution, this should not happen");k.debug("[Agent] Passing confirmationHandler to ExecutionPipeline.execute:",{toolName:B.function.name,hasHandler:!!Y.confirmationHandler,hasMethod:!!Y.confirmationHandler?.requestConfirmation,methodType:typeof Y.confirmationHandler?.requestConfirmation});let E=await this.executionPipeline.execute(B.function.name,D,{sessionId:Y.sessionId,userId:Y.userId||"default",workspaceRoot:Y.workspaceRoot||process.cwd(),signal:p,confirmationHandler:Y.confirmationHandler,permissionMode:Y.permissionMode});if(L.push(E),k.debug(`
1016
- ========== 工具执行结果 ==========`),k.debug("工具名称:",B.function.name),k.debug("成功:",E.success),k.debug("LLM Content:",E.llmContent),k.debug("Display Content:",E.displayContent),E.error)k.debug("错误:",E.error);if(k.debug(`==================================
1017
- `),E.metadata?.shouldExitLoop){k.debug("\uD83D\uDEAA 检测到退出循环标记,结束 Agent 循环");let S=typeof E.llmContent==="string"?E.llmContent:"循环已退出";return{success:E.success,finalMessage:S,metadata:{turnsCount:F,toolCallsCount:L.length,duration:Date.now()-Q,shouldExitLoop:!0,targetMode:E.metadata.targetMode}}}if(X?.onToolResult){k.debug("[Agent] Calling onToolResult:",{toolName:B.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 X.onToolResult(B,E),k.debug("[Agent] onToolResult callback completed successfully")}catch(S){k.error("[Agent] onToolResult callback error:",S)}}else k.debug("[Agent] No onToolResult callback provided");try{let S=this.executionEngine?.getContextManager();if(S&&Y.sessionId)U=await S.saveToolResult(Y.sessionId,B.id,E.success?E.llmContent:void 0,C,E.success?void 0:E.error?.message)}catch(S){k.warn("[Agent] 保存工具结果失败:",S)}if(B.function.name==="TodoWrite"&&E.success&&E.llmContent){let S=typeof E.llmContent==="object"?E.llmContent:{},O1=Array.isArray(S)?S:S.todos||[];X1().setTodos(O1)}let M=E.success?E.llmContent||E.displayContent||"":E.error?.message||"执行失败";if(typeof M==="object"&&M!==null)M=JSON.stringify(M,null,2);let i=typeof M==="string"?M:JSON.stringify(M);O.push({role:"tool",tool_call_id:B.id,name:B.function.name,content:i})}catch(D){k.error(`Tool execution failed for ${B.function.name}:`,D),O.push({role:"tool",tool_call_id:B.id,name:B.function.name,content:`Execution failed: ${D instanceof Error?D.message:"Unknown error"}`})}}if(X?.signal?.aborted)return{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:F,toolCallsCount:L.length,duration:Date.now()-Q}};if(F>=z){let B=_===-1||_>H,D=B?H:_;k.warn(`⚠️ 达到${B?"安全上限":"最大轮次限制"} ${D},自动压缩上下文...`);try{let C=this.chatService.getConfig(),p=await O$.compact(Y.messages,{trigger:"auto",modelName:C.model,maxContextTokens:C.maxContextTokens??this.config.maxContextTokens,apiKey:C.apiKey,baseURL:C.baseUrl,actualPreTokens:N});Y.messages=p.compactedMessages;let E=O.find((i)=>i.role==="system");if(O.length=0,E)O.push(E);O.push(...Y.messages);let M={role:"user",content:`This session is being continued from a previous conversation that ran out of context. The conversation is summarized above.
1008
+ `+" • 环境变量: export BLADE_MAX_TURNS=-1"},metadata:{turnsCount:0,toolCallsCount:0,duration:0}};let F=z===-1?H:Math.min(z,H);if(this.config.debug)M.debug(`[MaxTurns] runtimeOptions: ${this.runtimeOptions.maxTurns}, options: ${X?.maxTurns}, config: ${this.config.maxTurns}, 最终: ${z} → ${F}, YOLO: ${_}`);let B=0,L=[],N=0,A;while(!0){if(X?.signal?.aborted)return{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:B,toolCallsCount:L.length,duration:Date.now()-Q}};let R=Y.messages.length;if(await this.checkAndCompactInLoop(Y,B,A,X?.onCompacting)){M.debug(`[Agent] [轮次 ${B}] 检测到压缩发生,重建 messages 数组 (${R} → ${Y.messages.length} 条历史消息)`);let b=W&&Z?1:0,E=b+R,f=O.slice(0,b),h=O.slice(E);O.length=0,O.push(...f,...Y.messages,...h),M.debug(`[Agent] [轮次 ${B}] messages 重建完成: ${f.length} system + ${Y.messages.length} 历史 + ${h.length} 新增 = ${O.length} 总计`)}if(B++,M.debug(`\uD83D\uDD04 [轮次 ${B}/${F}] 调用 LLM...`),X?.signal?.aborted)return{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:B-1,toolCallsCount:L.length,duration:Date.now()-Q}};X?.onTurnStart?.({turn:B,maxTurns:F}),M.debug(`
1009
+ ========== 发送给 LLM ==========`),M.debug("轮次:",B+1),M.debug("消息数量:",O.length),M.debug("最后 3 条消息:"),O.slice(-3).forEach((b,E)=>{if(M.debug(` [${E}] ${b.role}:`,typeof b.content==="string"?b.content.substring(0,100)+(b.content.length>100?"...":""):JSON.stringify(b.content).substring(0,100)),b.tool_calls)M.debug(" tool_calls:",b.tool_calls.map((f)=>("function"in f)?f.function.name:f.type).join(", "))}),M.debug("可用工具数量:",G.length),M.debug(`================================
1010
+ `);let I=this.filterOrphanToolMessages(O);if(I.length<O.length)M.debug(`\uD83D\uDD27 过滤掉 ${O.length-I.length} 条孤儿 tool 消息`);let w=await this.chatService.chat(I,G,X?.signal);if(w.usage){if(w.usage.totalTokens)N+=w.usage.totalTokens;if(A=w.usage.promptTokens,M.debug(`[Agent] LLM usage: prompt=${A}, completion=${w.usage.completionTokens}, total=${w.usage.totalTokens}`),X?.onTokenUsage)X.onTokenUsage({inputTokens:w.usage.promptTokens??0,outputTokens:w.usage.completionTokens??0,totalTokens:N,maxContextTokens:this.config.maxContextTokens})}if(X?.signal?.aborted)return{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:B-1,toolCallsCount:L.length,duration:Date.now()-Q}};if(M.debug(`
1011
+ ========== LLM 返回 ==========`),M.debug("Content:",w.content),M.debug("Tool Calls:",JSON.stringify(w.toolCalls,null,2)),M.debug("当前权限模式:",Y.permissionMode),M.debug(`================================
1012
+ `),w.reasoningContent&&X?.onThinking)X.onThinking(w.reasoningContent);if(w.content&&w.content.trim()&&X?.onContent)X.onContent(w.content);if(!w.toolCalls||w.toolCalls.length===0){let b=[/:\s*$/,/:\s*$/,/\.\.\.\s*$/,/让我(先|来|开始|查看|检查|修复)/,/Let me (first|start|check|look|fix)/i],E=w.content||"",f=b.some((m)=>m.test(E)),h="请执行你提到的操作,不要只是描述。",v=O.slice(-10).filter((m)=>m.role==="user"&&m.content==="请执行你提到的操作,不要只是描述。").length;if(f&&v<2){M.debug(`⚠️ 检测到意图未完成(重试 ${v+1}/2): "${E.slice(-50)}"`),O.push({role:"user",content:"请执行你提到的操作,不要只是描述。"});continue}M.debug("✅ 任务完成 - LLM 未请求工具调用");try{let m=this.executionEngine?.getContextManager();if(m&&Y.sessionId&&w.content)if(w.content.trim()!=="")U=await m.saveMessage(Y.sessionId,"assistant",w.content,U);else M.debug("[Agent] 跳过保存空响应(任务完成时)")}catch(m){M.warn("[Agent] 保存助手消息失败:",m)}return{success:!0,finalMessage:w.content,metadata:{turnsCount:B,toolCallsCount:L.length,duration:Date.now()-Q,tokensUsed:N}}}O.push({role:"assistant",content:w.content||"",tool_calls:w.toolCalls});try{let b=this.executionEngine?.getContextManager();if(b&&Y.sessionId&&w.content)if(w.content.trim()!=="")U=await b.saveMessage(Y.sessionId,"assistant",w.content,U);else M.debug("[Agent] 跳过保存空响应(工具调用时)")}catch(b){M.warn("[Agent] 保存助手工具调用消息失败:",b)}for(let b of w.toolCalls){if(b.type!=="function")continue;try{if(X?.onToolStart)X.onToolStart(b);let E=JSON.parse(b.function.arguments);if(E.todos&&typeof E.todos==="string")try{E.todos=JSON.parse(E.todos),this.log("[Agent] 自动修复了字符串化的 todos 参数")}catch{this.error("[Agent] todos 参数格式异常,将由验证层处理")}let f=null;try{let J0=this.executionEngine?.getContextManager();if(J0&&Y.sessionId)f=await J0.saveToolUse(Y.sessionId,b.function.name,E,U)}catch(J0){M.warn("[Agent] 保存工具调用失败:",J0)}let h=X?.signal;if(!h)M.error("[Agent] Missing signal in tool execution, this should not happen");M.debug("[Agent] Passing confirmationHandler to ExecutionPipeline.execute:",{toolName:b.function.name,hasHandler:!!Y.confirmationHandler,hasMethod:!!Y.confirmationHandler?.requestConfirmation,methodType:typeof Y.confirmationHandler?.requestConfirmation});let v=await this.executionPipeline.execute(b.function.name,E,{sessionId:Y.sessionId,userId:Y.userId||"default",workspaceRoot:Y.workspaceRoot||process.cwd(),signal:h,confirmationHandler:Y.confirmationHandler,permissionMode:Y.permissionMode});if(L.push(v),M.debug(`
1013
+ ========== 工具执行结果 ==========`),M.debug("工具名称:",b.function.name),M.debug("成功:",v.success),M.debug("LLM Content:",v.llmContent),M.debug("Display Content:",v.displayContent),v.error)M.debug("错误:",v.error);if(M.debug(`==================================
1014
+ `),v.metadata?.shouldExitLoop){M.debug("\uD83D\uDEAA 检测到退出循环标记,结束 Agent 循环");let J0=typeof v.llmContent==="string"?v.llmContent:"循环已退出";return{success:v.success,finalMessage:J0,metadata:{turnsCount:B,toolCallsCount:L.length,duration:Date.now()-Q,shouldExitLoop:!0,targetMode:v.metadata.targetMode}}}if(X?.onToolResult){M.debug("[Agent] Calling onToolResult:",{toolName:b.function.name,hasCallback:!0,resultSuccess:v.success,resultKeys:Object.keys(v),hasMetadata:!!v.metadata,metadataKeys:v.metadata?Object.keys(v.metadata):[],hasSummary:!!v.metadata?.summary,summary:v.metadata?.summary});try{await X.onToolResult(b,v),M.debug("[Agent] onToolResult callback completed successfully")}catch(J0){M.error("[Agent] onToolResult callback error:",J0)}}else M.debug("[Agent] No onToolResult callback provided");try{let J0=this.executionEngine?.getContextManager();if(J0&&Y.sessionId)U=await J0.saveToolResult(Y.sessionId,b.id,v.success?v.llmContent:void 0,f,v.success?void 0:v.error?.message)}catch(J0){M.warn("[Agent] 保存工具结果失败:",J0)}if(b.function.name==="TodoWrite"&&v.success&&v.llmContent){let J0=typeof v.llmContent==="object"?v.llmContent:{},G0=Array.isArray(J0)?J0:J0.todos||[];q1().setTodos(G0)}let m=v.success?v.llmContent||v.displayContent||"":v.error?.message||"执行失败";if(typeof m==="object"&&m!==null)m=JSON.stringify(m,null,2);let z1=typeof m==="string"?m:JSON.stringify(m);O.push({role:"tool",tool_call_id:b.id,name:b.function.name,content:z1})}catch(E){M.error(`Tool execution failed for ${b.function.name}:`,E),O.push({role:"tool",tool_call_id:b.id,name:b.function.name,content:`Execution failed: ${E instanceof Error?E.message:"Unknown error"}`})}}if(X?.signal?.aborted)return{success:!1,error:{type:"aborted",message:"任务已被用户中止"},metadata:{turnsCount:B,toolCallsCount:L.length,duration:Date.now()-Q}};if(B>=F&&!_){if(M.info(`⚠️ 达到轮次上限 ${F} 轮,等待用户确认...`),X?.onTurnLimitReached){let b=await X.onTurnLimitReached({turnsCount:B});if(b?.continue){M.info("✅ 用户选择继续,压缩上下文...");try{let E=this.chatService.getConfig(),f=await L$.compact(Y.messages,{trigger:"auto",modelName:E.model,maxContextTokens:E.maxContextTokens??this.config.maxContextTokens,apiKey:E.apiKey,baseURL:E.baseUrl,actualPreTokens:A});Y.messages=f.compactedMessages;let h=O.find((m)=>m.role==="system");if(O.length=0,h)O.push(h);O.push(...Y.messages);let v={role:"user",content:`This session is being continued from a previous conversation. The conversation is summarized above.
1018
1015
 
1019
- 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.`};O.push(M),Y.messages.push(M);try{let i=this.executionEngine?.getContextManager();if(i&&Y.sessionId)await i.saveCompaction(Y.sessionId,p.summary,{trigger:"auto",preTokens:p.preTokens,postTokens:p.postTokens,filesIncluded:p.filesIncluded},null)}catch(i){k.warn("[Agent] 保存压缩数据失败:",i)}F=0,k.info(`✅ 上下文已压缩 (${p.preTokens} → ${p.postTokens} tokens),重置轮次计数,继续对话`)}catch(C){k.error("[Agent] 压缩失败,使用降级策略:",C);let p=O.find((M)=>M.role==="system"),E=O.slice(-80);if(O.length=0,p&&!E.some((M)=>M.role==="system"))O.push(p);O.push(...E),Y.messages=O.filter((M)=>M.role!=="system"),F=0,k.warn(`⚠️ 降级压缩完成,保留 ${O.length} 条消息,继续对话`)}}}}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 k.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,X){if(!this.isInitialized)throw Error("Agent未初始化");let Z={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($,Z,X)}filterOrphanToolMessages($){let Y=new Set;for(let X of $)if(X.role==="assistant"&&X.tool_calls)for(let Z of X.tool_calls)Y.add(Z.id);return $.filter((X)=>{if(X.role==="tool"){if(!X.tool_call_id)return!1;return Y.has(X.tool_call_id)}return!0})}async chatWithSystem($,Y){if(!this.isInitialized)throw Error("Agent未初始化");let X=[{role:"system",content:$},{role:"user",content:Y}];return(await this.chatService.chat(X)).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(),Z=Y.getAll().filter((Q)=>!$.includes(Q.name));for(let Q of Z)Y.unregister(Q.name);k.debug(`\uD83D\uDD12 Applied tool whitelist: ${$.join(", ")} (removed ${Z.length} tools)`)}getToolStats(){let $=this.getAvailableTools(),Y=new Map;return $.forEach((X)=>{let Z=Y.get(X.kind)||0;Y.set(X.kind,Z+1)}),{totalTools:$.length,toolsByKind:Object.fromEntries(Y),toolNames:$.map((X)=>X.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){k.debug(`[MainAgent] ${$}`,Y||"")}error($,Y){k.error(`[MainAgent] ${$}`,Y||"")}async initializeSystemPrompt(){try{let $=this.runtimeOptions.systemPrompt,Y=this.runtimeOptions.appendSystemPrompt,X=await S2({projectPath:process.cwd(),replaceDefault:$,append:Y,includeEnvironment:!1});if(this.systemPrompt=X.prompt,this.systemPrompt)this.log("系统提示已加载"),k.debug(`[SystemPrompt] 加载来源: ${X.sources.filter((Z)=>Z.loaded).map((Z)=>Z.name).join(", ")}`)}catch($){this.error("初始化系统提示失败",$)}}getSystemPrompt(){return this.systemPrompt}async checkAndCompactInLoop($,Y,X,Z,Q){if(Z===void 0)return k.debug(`[Agent] [轮次 ${X}] 压缩检查: 跳过(无历史 usage 数据)`),!1;let J=this.chatService.getConfig(),q=J.model,G=J.maxContextTokens??this.config.maxContextTokens,K=J.maxOutputTokens??this.config.maxOutputTokens,W=G-K,O=Math.floor(W*0.8);if(k.debug(`[Agent] [轮次 ${X}] 压缩检查:`,{promptTokens:Z,maxContextTokens:G,maxOutputTokens:K,availableForInput:W,threshold:O,shouldCompact:Z>=O}),Z<O)return!1;let U=X===0?"[Agent] 触发自动压缩":`[Agent] [轮次 ${X}] 触发循环内自动压缩`;k.debug(U),Q?.(!0);try{let H=await O$.compact(Y.messages,{trigger:"auto",modelName:q,maxContextTokens:G,apiKey:J.apiKey,baseURL:J.baseUrl,actualPreTokens:Z});if(H.success)Y.messages=H.compactedMessages,k.debug(`[Agent] [轮次 ${X}] 压缩完成: ${H.preTokens} → ${H.postTokens} tokens (-${((1-H.postTokens/H.preTokens)*100).toFixed(1)}%)`);else Y.messages=H.compactedMessages,k.warn(`[Agent] [轮次 ${X}] 压缩使用降级策略: ${H.preTokens} → ${H.postTokens} tokens`);try{let _=this.executionEngine?.getContextManager();if(_&&Y.sessionId)await _.saveCompaction(Y.sessionId,H.summary,{trigger:"auto",preTokens:H.preTokens,postTokens:H.postTokens,filesIncluded:H.filesIncluded},null),k.debug(`[Agent] [轮次 ${X}] 压缩数据已保存到 JSONL`)}catch(_){k.warn(`[Agent] [轮次 ${X}] 保存压缩数据失败:`,_)}return Q?.(!1),!0}catch(H){return Q?.(!1),k.error(`[Agent] [轮次 ${X}] 压缩失败,继续执行`,H),!1}}async registerBuiltinTools(){try{let $=await Y5({sessionId:"default",configDir:W5.join(K5.homedir(),".blade")});k.debug(`\uD83D\uDCE6 Registering ${$.length} builtin tools...`),this.executionPipeline.getRegistry().registerAll($);let Y=this.executionPipeline.getRegistry().getAll().length;k.debug(`✅ Builtin tools registered: ${Y} tools`),k.debug(`[Tools] ${this.executionPipeline.getRegistry().getAll().map((X)=>X.name).join(", ")}`),await this.registerMcpTools()}catch($){throw k.error("Failed to register builtin tools:",$),$}}async registerMcpTools(){try{let $=await _9({interactive:!1,silent:!0,mcpConfig:this.runtimeOptions.mcpConfig,strictMcpConfig:this.runtimeOptions.strictMcpConfig});if($>0)k.debug(`✅ Loaded ${$} servers from .mcp.json`);let Y=_1();if(Object.keys(Y).length===0){k.debug("\uD83D\uDCE6 No MCP servers configured");return}let X=k0.getInstance();for(let[Q,J]of Object.entries(Y))try{k.debug(`\uD83D\uDD0C Connecting to MCP server: ${Q}`),await X.registerServer(Q,J),k.debug(`✅ MCP server "${Q}" connected`)}catch(q){k.warn(`⚠️ MCP server "${Q}" connection failed:`,q)}let Z=await X.getAvailableTools();if(Z.length>0)this.executionPipeline.getRegistry().registerAll(Z),k.debug(`✅ Registered ${Z.length} MCP tools`),k.debug(`[MCP Tools] ${Z.map((Q)=>Q.name).join(", ")}`)}catch($){k.warn("Failed to register MCP tools:",$)}}async loadSubagents(){if(N0.getAllNames().length>0){k.debug(`\uD83D\uDCE6 Subagents already loaded: ${N0.getAllNames().join(", ")}`);return}try{let $=N0.loadFromStandardLocations();if($>0)k.debug(`✅ Loaded ${$} subagents: ${N0.getAllNames().join(", ")}`);else k.debug("\uD83D\uDCE6 No subagents configured")}catch($){k.warn("Failed to load subagents:",$)}}async processAtMentions($){if(!this.attachmentCollector)return $;try{let Y=await this.attachmentCollector.collect($);if(Y.length===0)return $;return k.debug(`✅ Processed ${Y.length} @ file mentions`),this.appendAttachments($,Y)}catch(Y){return k.error("Failed to process @ mentions:",Y),$}}appendAttachments($,Y){let X=[],Z=[];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}`:""})`:"";X.push(`<file path="${J.path}"${q?` range="${q}"`:""}>`,J.content,"</file>")}else if(J.type==="directory")X.push(`<directory path="${J.path}">`,J.content,"</directory>");else if(J.type==="error")Z.push(`- @${J.path}: ${J.error}`);let Q=$;if(X.length>0)Q+=`
1016
+ 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.`};O.push(v),Y.messages.push(v);try{let m=this.executionEngine?.getContextManager();if(m&&Y.sessionId)await m.saveCompaction(Y.sessionId,f.summary,{trigger:"auto",preTokens:f.preTokens,postTokens:f.postTokens,filesIncluded:f.filesIncluded},null)}catch(m){M.warn("[Agent] 保存压缩数据失败:",m)}M.info(`✅ 上下文已压缩 (${f.preTokens} → ${f.postTokens} tokens),重置轮次计数`)}catch(E){M.error("[Agent] 压缩失败,使用降级策略:",E);let f=O.find((v)=>v.role==="system"),h=O.slice(-80);if(O.length=0,f&&!h.some((v)=>v.role==="system"))O.push(f);O.push(...h),Y.messages=O.filter((v)=>v.role!=="system"),M.warn(`⚠️ 降级压缩完成,保留 ${O.length} 条消息`)}B=0;continue}return{success:!0,finalMessage:b?.reason||"已达到对话轮次上限,用户选择停止",metadata:{turnsCount:B,toolCallsCount:L.length,duration:Date.now()-Q,tokensUsed:N}}}return{success:!1,error:{type:"max_turns_exceeded",message:`已达到轮次上限 (${F} 轮)。使用 --permission-mode yolo 跳过此限制。`},metadata:{turnsCount:B,toolCallsCount:L.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 M.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,X){if(!this.isInitialized)throw Error("Agent未初始化");let Z={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($,Z,X)}filterOrphanToolMessages($){let Y=new Set;for(let X of $)if(X.role==="assistant"&&X.tool_calls)for(let Z of X.tool_calls)Y.add(Z.id);return $.filter((X)=>{if(X.role==="tool"){if(!X.tool_call_id)return!1;return Y.has(X.tool_call_id)}return!0})}async chatWithSystem($,Y){if(!this.isInitialized)throw Error("Agent未初始化");let X=[{role:"system",content:$},{role:"user",content:Y}];return(await this.chatService.chat(X)).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(),Z=Y.getAll().filter((Q)=>!$.includes(Q.name));for(let Q of Z)Y.unregister(Q.name);M.debug(`\uD83D\uDD12 Applied tool whitelist: ${$.join(", ")} (removed ${Z.length} tools)`)}getToolStats(){let $=this.getAvailableTools(),Y=new Map;return $.forEach((X)=>{let Z=Y.get(X.kind)||0;Y.set(X.kind,Z+1)}),{totalTools:$.length,toolsByKind:Object.fromEntries(Y),toolNames:$.map((X)=>X.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){M.debug(`[MainAgent] ${$}`,Y||"")}error($,Y){M.error(`[MainAgent] ${$}`,Y||"")}async initializeSystemPrompt(){try{let $=this.runtimeOptions.systemPrompt,Y=this.runtimeOptions.appendSystemPrompt,X=await g2({projectPath:process.cwd(),replaceDefault:$,append:Y,includeEnvironment:!1});if(this.systemPrompt=X.prompt,this.systemPrompt)this.log("系统提示已加载"),M.debug(`[SystemPrompt] 加载来源: ${X.sources.filter((Z)=>Z.loaded).map((Z)=>Z.name).join(", ")}`)}catch($){this.error("初始化系统提示失败",$)}}getSystemPrompt(){return this.systemPrompt}async checkAndCompactInLoop($,Y,X,Z){if(X===void 0)return M.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(M.debug(`[Agent] [轮次 ${Y}] 压缩检查:`,{promptTokens:X,maxContextTokens:q,maxOutputTokens:G,availableForInput:K,threshold:W,shouldCompact:X>=W}),X<W)return!1;let O=Y===0?"[Agent] 触发自动压缩":`[Agent] [轮次 ${Y}] 触发循环内自动压缩`;M.debug(O),Z?.(!0);try{let U=await L$.compact($.messages,{trigger:"auto",modelName:J,maxContextTokens:q,apiKey:Q.apiKey,baseURL:Q.baseUrl,actualPreTokens:X});if(U.success)$.messages=U.compactedMessages,M.debug(`[Agent] [轮次 ${Y}] 压缩完成: ${U.preTokens} → ${U.postTokens} tokens (-${((1-U.postTokens/U.preTokens)*100).toFixed(1)}%)`);else $.messages=U.compactedMessages,M.warn(`[Agent] [轮次 ${Y}] 压缩使用降级策略: ${U.preTokens} → ${U.postTokens} tokens`);try{let H=this.executionEngine?.getContextManager();if(H&&$.sessionId)await H.saveCompaction($.sessionId,U.summary,{trigger:"auto",preTokens:U.preTokens,postTokens:U.postTokens,filesIncluded:U.filesIncluded},null),M.debug(`[Agent] [轮次 ${Y}] 压缩数据已保存到 JSONL`)}catch(H){M.warn(`[Agent] [轮次 ${Y}] 保存压缩数据失败:`,H)}return Z?.(!1),!0}catch(U){return Z?.(!1),M.error(`[Agent] [轮次 ${Y}] 压缩失败,继续执行`,U),!1}}async registerBuiltinTools(){try{let $=await z5({sessionId:"default",configDir:V5.join(b5.homedir(),".blade")});M.debug(`\uD83D\uDCE6 Registering ${$.length} builtin tools...`),this.executionPipeline.getRegistry().registerAll($);let Y=this.executionPipeline.getRegistry().getAll().length;M.debug(`✅ Builtin tools registered: ${Y} tools`),M.debug(`[Tools] ${this.executionPipeline.getRegistry().getAll().map((X)=>X.name).join(", ")}`),await this.registerMcpTools()}catch($){throw M.error("Failed to register builtin tools:",$),$}}async registerMcpTools(){try{if(this.runtimeOptions.mcpConfig&&this.runtimeOptions.mcpConfig.length>0)await k9(this.runtimeOptions.mcpConfig);let $=l0();if(Object.keys($).length===0){M.debug("\uD83D\uDCE6 No MCP servers configured");return}let Y=v0.getInstance();for(let[Z,Q]of Object.entries($))try{M.debug(`\uD83D\uDD0C Connecting to MCP server: ${Z}`),await Y.registerServer(Z,Q),M.debug(`✅ MCP server "${Z}" connected`)}catch(J){M.warn(`⚠️ MCP server "${Z}" connection failed:`,J)}let X=await Y.getAvailableTools();if(X.length>0)this.executionPipeline.getRegistry().registerAll(X),M.debug(`✅ Registered ${X.length} MCP tools`),M.debug(`[MCP Tools] ${X.map((Z)=>Z.name).join(", ")}`)}catch($){M.warn("Failed to register MCP tools:",$)}}async loadSubagents(){if(B0.getAllNames().length>0){M.debug(`\uD83D\uDCE6 Subagents already loaded: ${B0.getAllNames().join(", ")}`);return}try{let $=B0.loadFromStandardLocations();if($>0)M.debug(`✅ Loaded ${$} subagents: ${B0.getAllNames().join(", ")}`);else M.debug("\uD83D\uDCE6 No subagents configured")}catch($){M.warn("Failed to load subagents:",$)}}async processAtMentions($){if(!this.attachmentCollector)return $;try{let Y=await this.attachmentCollector.collect($);if(Y.length===0)return $;return M.debug(`✅ Processed ${Y.length} @ file mentions`),this.appendAttachments($,Y)}catch(Y){return M.error("Failed to process @ mentions:",Y),$}}appendAttachments($,Y){let X=[],Z=[];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}`:""})`:"";X.push(`<file path="${J.path}"${q?` range="${q}"`:""}>`,J.content,"</file>")}else if(J.type==="directory")X.push(`<directory path="${J.path}">`,J.content,"</directory>");else if(J.type==="error")Z.push(`- @${J.path}: ${J.error}`);let Q=$;if(X.length>0)Q+=`
1020
1017
 
1021
1018
  <system-reminder>
1022
1019
  `,Q+=`The following files were mentioned with @ syntax:
@@ -1027,15 +1024,14 @@ Please continue the conversation from where we left it off without asking the us
1027
1024
 
1028
1025
  ⚠️ Some files could not be loaded:
1029
1026
  `,Q+=Z.join(`
1030
- `);return Q}}function hZ($){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"})},async(Y)=>{if(!Y.print)return;try{let X=await v0.create({systemPrompt:Y.systemPrompt,appendSystemPrompt:Y.appendSystemPrompt}),Z="",Q=Y._?.[0];if(Q&&typeof Q==="string")Z=Q;else if(!process.stdin.isTTY){let q=[];for await(let G of process.stdin)q.push(G);Z=Buffer.concat(q).toString("utf-8").trim()}else Z="Hello";let J;if(Y.appendSystemPrompt)J=await X.chatWithSystem(Y.appendSystemPrompt,Z);else J=await X.chat(Z,{messages:[],userId:"cli-user",sessionId:`print-${Date.now()}`,workspaceRoot:process.cwd()});if(Y.outputFormat==="json")console.log(JSON.stringify({response:J,input:Z,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(X){console.error(`Error: ${X instanceof Error?X.message:"未知错误"}`),process.exit(1)}})}async function U5(){if(process.argv.slice(2).findIndex((X)=>X==="--print"||X==="-p")===-1)return!1;try{let X=(await import("yargs")).default,{hideBin:Z}=await import("yargs/helpers"),Q=X(Z(process.argv)).scriptName("blade").strict(!1);return hZ(Q),await Q.parse(),!0}catch(X){console.error(`Print mode error: ${X instanceof Error?X.message:"未知错误"}`),process.exit(1)}}import{execSync as iZ}from"child_process";import*as $$ from"fs/promises";import*as f1 from"path";import{fileURLToPath as xZ}from"url";var X8="blade-code",H5=f1.join(process.env.HOME||process.env.USERPROFILE||".",".blade"),_5=f1.join(H5,"version-cache.json"),pZ=86400000,gZ=`https://registry.npmmirror.com/${X8}/latest`;async function mZ(){try{if(process.env.BLADE_VERSION)return process.env.BLADE_VERSION;let $=xZ(import.meta.url),Y=f1.dirname($),X=[f1.join(Y,"..","..","package.json"),f1.join(Y,"..","package.json"),f1.join(process.cwd(),"package.json")];for(let Z of X)try{let Q=await $$.readFile(Z,"utf-8"),J=JSON.parse(Q);if(J.name===X8&&J.version)return J.version}catch{}return"unknown"}catch{return"unknown"}}async function uZ(){try{let $=await $$.readFile(_5,"utf-8"),Y=JSON.parse($);if(Date.now()-Y.checkedAt<pZ)return Y;return null}catch{return null}}async function dZ($){try{await $$.mkdir(H5,{recursive:!0}),await $$.writeFile(_5,JSON.stringify($,null,2))}catch{}}async function cZ(){try{let $=new AbortController,Y=setTimeout(()=>$.abort(),5000),X=await fetch(gZ,{signal:$.signal,headers:{Accept:"application/json"}});if(clearTimeout(Y),!X.ok)return null;return(await X.json()).version||null}catch{return null}}function O5($,Y){let X=$.split(".").map(Number),Z=Y.split(".").map(Number);for(let Q=0;Q<Math.max(X.length,Z.length);Q++){let J=X[Q]||0,q=Z[Q]||0;if(J>q)return 1;if(J<q)return-1}return 0}async function Z8($=!1){let Y=await mZ();if(Y==="unknown")return{currentVersion:Y,latestVersion:null,hasUpdate:!1,error:"Unable to determine current version"};if(!$){let Z=await uZ();if(Z)return{currentVersion:Y,latestVersion:Z.latestVersion,hasUpdate:O5(Z.latestVersion,Y)>0}}let X=await cZ();if(X)return await dZ({latestVersion:X,checkedAt:Date.now()}),{currentVersion:Y,latestVersion:X,hasUpdate:O5(X,Y)>0};return{currentVersion:Y,latestVersion:null,hasUpdate:!1,error:"Unable to check for updates"}}function lZ($){if(!$.hasUpdate||!$.latestVersion)return null;return`\x1B[33m⚠️ Update available: ${$.currentVersion} ${$.latestVersion}\x1B[0m
1031
- Run \x1B[36mnpm install -g ${X8}@latest\x1B[0m to update`}async function F5(){try{let $=await Z8();return lZ($)}catch{return null}}var z5={command:"update",describe:"Check for updates and install if available",handler:async()=>{console.log("\uD83D\uDD0D Checking for updates...");try{let $=await Z8(!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{iZ("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)}}};var v1=Y0("Service");class b${static instance=null;cleanupHandlers=[];isShuttingDown=!1;initialized=!1;constructor(){}static getInstance(){if(!b$.instance)b$.instance=new b$;return b$.instance}initialize(){if(this.initialized){v1.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",()=>{v1.info("[GracefulShutdown] 收到 SIGTERM 信号"),this.shutdown("SIGTERM",0)}),process.env.BLADE_NON_INTERACTIVE==="true")process.on("SIGINT",()=>{v1.info("[GracefulShutdown] 收到 SIGINT 信号(非交互模式)"),this.shutdown("SIGINT",0)});this.initialized=!0,v1.debug("[GracefulShutdown] 全局错误处理器已初始化")}registerCleanup($){return this.cleanupHandlers.push($),v1.debug(`[GracefulShutdown] 注册清理函数,当前共 ${this.cleanupHandlers.length} 个`),()=>{let Y=this.cleanupHandlers.indexOf($);if(Y!==-1)this.cleanupHandlers.splice(Y,1),v1.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){v1.debug("[GracefulShutdown] 已在退出过程中,跳过重复退出");return}this.isShuttingDown=!0,v1.info(`[GracefulShutdown] 开始优雅退出 (原因: ${$})`);let X=5000,Z=new Promise((Q,J)=>{setTimeout(()=>{J(Error(`清理超时 (${X}ms)`))},X)});try{let Q=this.runCleanupHandlers();await Promise.race([Q,Z]),v1.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 X=Y();if(X instanceof Promise)await X}catch(X){console.error("[GracefulShutdown] 清理函数执行失败:",X)}}isExiting(){return this.isShuttingDown}reset(){this.isShuttingDown=!1,this.cleanupHandlers=[],this.initialized=!1}}var a2=()=>{return b$.getInstance()},N5=($)=>{return a2().registerCleanup($)},B5=()=>{a2().initialize()};import{useMemoizedFn as CG}from"ahooks";import{useEffect as fG,useState as hG}from"react";import{useMemoizedFn as g0}from"ahooks";import{Box as B2,useApp as jG}from"ink";import{useEffect as J$,useRef as I6}from"react";N$();import{readdir as L5,readFile as w5}from"node:fs/promises";import*as n2 from"node:path";var Y$=Y0("Service");class N1{static async listSessions(){let $=[],Y=n2.join(P1(),"projects");try{let X=await L5(Y,{withFileTypes:!0});for(let Z of X){if(!Z.isDirectory())continue;let Q=n2.join(Y,Z.name),J=n6(Z.name),G=(await L5(Q)).filter((K)=>K.endsWith(".jsonl"));for(let K of G){let W=n2.join(Q,K),O=K.replace(".jsonl","");try{let U=await this.extractMetadata(W,O,J);$.push(U)}catch(U){Y$.warn(`[SessionService] 跳过损坏的会话文件: ${W}`,U)}}}return $.sort((Z,Q)=>new Date(Q.lastMessageTime).getTime()-new Date(Z.lastMessageTime).getTime()),$}catch(X){return Y$.error("[SessionService] 列出会话失败:",X),[]}}static async extractMetadata($,Y,X){let Q=(await w5($,"utf-8")).trim().split(`
1032
- `).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:X,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 Z=(await this.listSessions()).find((Q)=>Q.sessionId===$);if(!Z)throw Error(`未找到会话: ${$}`);return await this.loadSessionFromFile(Z.filePath)}catch(X){throw Y$.error(`[SessionService] 加载会话失败 (${$}):`,X),X}}static async loadSessionFromFile($){let Z=(await w5($,"utf-8")).trim().split(`
1033
- `).filter((Q)=>Q.trim()).map((Q)=>JSON.parse(Q));return this.convertJSONLToMessages(Z)}static convertJSONLToMessages($){let Y=[],X=-1;for(let Q=$.length-1;Q>=0;Q--)if($[Q].subtype==="compact_boundary"){X=Q,Y$.debug(`[SessionService] 检测到压缩边界 at index ${Q}`);break}let Z=X>=0?X:0;for(let Q=Z;Q<$.length;Q++){let J=$[Q];if(J.subtype==="compact_boundary"){Y$.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)Y$.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(X>=0)Y$.debug(`[SessionService] 会话已压缩,跳过前 ${X} 条历史,加载 ${Y.length} 条消息`);return Y}static getSessionFilePath($,Y){let{getSessionFilePath:X}=(N$(),mY(k9));return X($,Y)}}import{useShallow as BN}from"zustand/react/shallow";import{useStore as rZ}from"zustand";function K0($){return rZ(d$,$)}var aZ=[],A5=()=>K0(($)=>$.session.sessionId),o2=()=>K0(($)=>$.session.messages),h1=()=>K0(($)=>$.session.isThinking),R5=()=>K0(($)=>$.session.isCompacting);var V$=()=>K0(($)=>$.session.actions);var b5=()=>K0(($)=>{let{inputTokens:Y,maxContextTokens:X}=$.session.tokenUsage;if(X<=0)return 100;let Z=Math.max(0,100-Y/X*100);return Math.round(Z)});var V5=()=>K0(($)=>$.app.initializationStatus),D5=()=>K0(($)=>$.app.initializationError),s2=()=>K0(($)=>$.app.activeModal),I5=()=>K0(($)=>$.app.todos),k5=()=>K0(($)=>$.app.modelEditorTarget),v5=()=>K0(($)=>$.app.sessionSelectorData),M5=()=>K0(($)=>$.app.awaitingSecondCtrlC),D$=()=>K0(($)=>$.app.actions),t2=()=>K0(($)=>$.app.initializationStatus==="ready");var y5=()=>K0(($)=>$.app.todos.length>0);var I$=()=>K0(($)=>$.config.config?.permissionMode||"default"),E5=()=>K0(($)=>$.config.config?.models??aZ),j5=()=>K0(($)=>{let Y=$.config.config;if(!Y)return;let X=Y.currentModelId;return Y.models.find((Q)=>Q.id===X)??Y.models[0]}),P5=()=>K0(($)=>$.config.config?.currentModelId);var i0=()=>K0(($)=>$.focus.currentFocus);var S5=()=>K0(($)=>$.focus.actions);var T5=()=>K0(($)=>$.command.isProcessing);var C5=()=>K0(($)=>$.command.actions),f5=()=>K0(($)=>$.command.pendingCommands);import{useMemoizedFn as W8}from"ahooks";import{useEffect as lQ,useRef as iQ}from"react";import mQ from"fuse.js";import nZ from"node:os";import h5 from"node:path";var x5={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 X=$[0],Z=o().addAssistantMessage;if(!X)return{success:!0,message:"show_agents_manager",data:{action:"show_agents_manager"}};if(X==="list"){let J=N0.getAllNames().map((U)=>N0.getSubagent(U)).filter((U)=>U!==void 0);if(J.length===0){let U=`\uD83D\uDCCB **Agents 管理**
1027
+ `);return Q}}function JQ($){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 X=await k0.create({systemPrompt:Y.systemPrompt,appendSystemPrompt:Y.appendSystemPrompt,maxTurns:Y.maxTurns}),Z="",Q=Y._?.[0];if(Q&&typeof Q==="string")Z=Q;else if(!process.stdin.isTTY){let q=[];for await(let G of process.stdin)q.push(G);Z=Buffer.concat(q).toString("utf-8").trim()}else Z="Hello";let J;if(Y.appendSystemPrompt)J=await X.chatWithSystem(Y.appendSystemPrompt,Z);else J=await X.chat(Z,{messages:[],userId:"cli-user",sessionId:`print-${Date.now()}`,workspaceRoot:process.cwd()});if(Y.outputFormat==="json")console.log(JSON.stringify({response:J,input:Z,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(X){console.error(`Error: ${X instanceof Error?X.message:"未知错误"}`),process.exit(1)}})}async function I5(){if(process.argv.slice(2).findIndex((X)=>X==="--print"||X==="-p")===-1)return!1;try{let X=(await import("yargs")).default,{hideBin:Z}=await import("yargs/helpers"),Q=X(Z(process.argv)).scriptName("blade").strict(!1);return JQ(Q),await Q.parse(),!0}catch(X){console.error(`Print mode error: ${X instanceof Error?X.message:"未知错误"}`),process.exit(1)}}import{execSync as HQ}from"child_process";import*as q$ from"fs/promises";import*as g1 from"path";import D5 from"semver";import{fileURLToPath as qQ}from"url";var U8="blade-code",GQ="https://cdn.jsdelivr.net/npm/blade-code@latest/CHANGELOG.md",v5=g1.join(process.env.HOME||process.env.USERPROFILE||".",".blade"),M5=g1.join(v5,"version-cache.json"),KQ=3600000,WQ=`https://registry.npmjs.org/${U8}/latest`;async function UQ(){try{if(process.env.BLADE_VERSION)return process.env.BLADE_VERSION;let $=qQ(import.meta.url),Y=g1.dirname($),X=[g1.join(Y,"..","..","package.json"),g1.join(Y,"..","package.json"),g1.join(process.cwd(),"package.json")];for(let Z of X)try{let Q=await q$.readFile(Z,"utf-8"),J=JSON.parse(Q);if(J.name===U8&&J.version)return J.version}catch{}return"unknown"}catch{return"unknown"}}async function k5(){try{let $=await q$.readFile(M5,"utf-8"),Y=JSON.parse($);if(Date.now()-Y.checkedAt<KQ)return Y;return{...Y,checkedAt:0}}catch{return null}}async function y5($){try{await q$.mkdir(v5,{recursive:!0}),await q$.writeFile(M5,JSON.stringify($,null,2))}catch{}}async function OQ(){try{let $=new AbortController,Y=setTimeout(()=>$.abort(),5000),X=await fetch(WQ,{signal:$.signal,headers:{Accept:"application/json"}});if(clearTimeout(Y),!X.ok)return null;return(await X.json()).version||null}catch{return null}}async function O8($=!1){let Y=await UQ(),X=GQ;if(Y==="unknown")return{currentVersion:Y,latestVersion:null,hasUpdate:!1,shouldPrompt:!1,releaseNotesUrl:X,error:"Unable to determine current version"};let Z=await k5(),Q=Z?.skipUntilVersion,J=null;if(!$&&Z&&Z.checkedAt>0)J=Z.latestVersion;else if(J=await OQ(),J)await y5({latestVersion:J,checkedAt:Date.now(),skipUntilVersion:Q});if(!J)return{currentVersion:Y,latestVersion:null,hasUpdate:!1,shouldPrompt:!1,releaseNotesUrl:X,error:"Unable to check for updates"};let q=D5.gt(J,Y),G=q;if(q&&Q)G=D5.gt(J,Q);return{currentVersion:Y,latestVersion:J,hasUpdate:q,shouldPrompt:G,releaseNotesUrl:X}}async function E5($){let Y=await k5();await y5({latestVersion:Y?.latestVersion||$,checkedAt:Y?.checkedAt||Date.now(),skipUntilVersion:$})}function H8(){return`npm install -g ${U8}@latest`}async function j5(){let{spawn:$}=await import("child_process");return new Promise((Y)=>{let X=H8(),Z=$(X,{stdio:"inherit",shell:!0});Z.on("close",(Q)=>{if(Q===0)Y({success:!0,message:"✅ 升级成功!请重新启动 blade。"});else Y({success:!1,message:`❌ 升级失败 (exit code: ${Q})`})}),Z.on("error",(Q)=>{Y({success:!1,message:`❌ 升级失败: ${Q.message}`})})})}async function P5(){try{let $=await O8();return $.shouldPrompt?$:null}catch{return null}}var S5={command:"update",describe:"Check for updates and install if available",handler:async()=>{console.log("\uD83D\uDD0D Checking for updates...");try{let $=await O8(!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{HQ("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)}}};var E1=$0("Service");class y${static instance=null;cleanupHandlers=[];isShuttingDown=!1;initialized=!1;constructor(){}static getInstance(){if(!y$.instance)y$.instance=new y$;return y$.instance}initialize(){if(this.initialized){E1.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",()=>{E1.info("[GracefulShutdown] 收到 SIGTERM 信号"),this.shutdown("SIGTERM",0)}),process.env.BLADE_NON_INTERACTIVE==="true")process.on("SIGINT",()=>{E1.info("[GracefulShutdown] 收到 SIGINT 信号(非交互模式)"),this.shutdown("SIGINT",0)});this.initialized=!0,E1.debug("[GracefulShutdown] 全局错误处理器已初始化")}registerCleanup($){return this.cleanupHandlers.push($),E1.debug(`[GracefulShutdown] 注册清理函数,当前共 ${this.cleanupHandlers.length} 个`),()=>{let Y=this.cleanupHandlers.indexOf($);if(Y!==-1)this.cleanupHandlers.splice(Y,1),E1.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){E1.debug("[GracefulShutdown] 已在退出过程中,跳过重复退出");return}this.isShuttingDown=!0,E1.info(`[GracefulShutdown] 开始优雅退出 (原因: ${$})`);let X=5000,Z=new Promise((Q,J)=>{setTimeout(()=>{J(Error(`清理超时 (${X}ms)`))},X)});try{let Q=this.runCleanupHandlers();await Promise.race([Q,Z]),E1.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 X=Y();if(X instanceof Promise)await X}catch(X){console.error("[GracefulShutdown] 清理函数执行失败:",X)}}isExiting(){return this.isShuttingDown}reset(){this.isShuttingDown=!1,this.cleanupHandlers=[],this.initialized=!1}}var G$=()=>{return y$.getInstance()},T5=($)=>{return G$().registerCleanup($)},C5=()=>{G$().initialize()};import{useMemoizedFn as o7}from"ahooks";import{useEffect as KK,useState as a8}from"react";import{useMemoizedFn as g0}from"ahooks";import{Box as D2,useApp as ZK}from"ink";import{useEffect as H$,useRef as P6}from"react";V$();import{readdir as f5,readFile as h5}from"node:fs/promises";import*as Y6 from"node:path";var K$=$0("Service");class A1{static async listSessions(){let $=[],Y=Y6.join(f1(),"projects");try{let X=await f5(Y,{withFileTypes:!0});for(let Z of X){if(!Z.isDirectory())continue;let Q=Y6.join(Y,Z.name),J=Z4(Z.name),G=(await f5(Q)).filter((K)=>K.endsWith(".jsonl"));for(let K of G){let W=Y6.join(Q,K),O=K.replace(".jsonl","");try{let U=await this.extractMetadata(W,O,J);$.push(U)}catch(U){K$.warn(`[SessionService] 跳过损坏的会话文件: ${W}`,U)}}}return $.sort((Z,Q)=>new Date(Q.lastMessageTime).getTime()-new Date(Z.lastMessageTime).getTime()),$}catch(X){return K$.error("[SessionService] 列出会话失败:",X),[]}}static async extractMetadata($,Y,X){let Q=(await h5($,"utf-8")).trim().split(`
1028
+ `).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:X,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 Z=(await this.listSessions()).find((Q)=>Q.sessionId===$);if(!Z)throw Error(`未找到会话: ${$}`);return await this.loadSessionFromFile(Z.filePath)}catch(X){throw K$.error(`[SessionService] 加载会话失败 (${$}):`,X),X}}static async loadSessionFromFile($){let Z=(await h5($,"utf-8")).trim().split(`
1029
+ `).filter((Q)=>Q.trim()).map((Q)=>JSON.parse(Q));return this.convertJSONLToMessages(Z)}static convertJSONLToMessages($){let Y=[],X=-1;for(let Q=$.length-1;Q>=0;Q--)if($[Q].subtype==="compact_boundary"){X=Q,K$.debug(`[SessionService] 检测到压缩边界 at index ${Q}`);break}let Z=X>=0?X:0;for(let Q=Z;Q<$.length;Q++){let J=$[Q];if(J.subtype==="compact_boundary"){K$.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)K$.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(X>=0)K$.debug(`[SessionService] 会话已压缩,跳过前 ${X} 条历史,加载 ${Y.length} 条消息`);return Y}static getSessionFilePath($,Y){let{getSessionFilePath:X}=(V$(),WY(g9));return X($,Y)}}import{useShallow as aN}from"zustand/react/shallow";import{useStore as _Q}from"zustand";function Z0($){return _Q(t$,$)}var FQ=[],x5=()=>Z0(($)=>$.session.sessionId),X6=()=>Z0(($)=>$.session.messages),m1=()=>Z0(($)=>$.session.isThinking),p5=()=>Z0(($)=>$.session.isCompacting);var E$=()=>Z0(($)=>$.session.actions);var g5=()=>Z0(($)=>{let{inputTokens:Y,maxContextTokens:X}=$.session.tokenUsage;if(X<=0)return 100;let Z=Math.max(0,100-Y/X*100);return Math.round(Z)});var m5=()=>Z0(($)=>$.app.initializationStatus),u5=()=>Z0(($)=>$.app.initializationError),Z6=()=>Z0(($)=>$.app.activeModal),d5=()=>Z0(($)=>$.app.todos),c5=()=>Z0(($)=>$.app.modelEditorTarget),l5=()=>Z0(($)=>$.app.sessionSelectorData),i5=()=>Z0(($)=>$.app.awaitingSecondCtrlC),u1=()=>Z0(($)=>$.app.actions),Q6=()=>Z0(($)=>$.app.initializationStatus==="ready");var r5=()=>Z0(($)=>$.app.todos.length>0);var j$=()=>Z0(($)=>$.config.config?.permissionMode||"default"),a5=()=>Z0(($)=>$.config.config?.models??FQ),J6=()=>Z0(($)=>{let Y=$.config.config;if(!Y)return;let X=Y.currentModelId;return Y.models.find((Q)=>Q.id===X)??Y.models[0]}),n5=()=>Z0(($)=>$.config.config?.currentModelId);var a0=()=>Z0(($)=>$.focus.currentFocus);var o5=()=>Z0(($)=>$.focus.actions);var s5=()=>Z0(($)=>$.command.isProcessing);var t5=()=>Z0(($)=>$.command.actions),e5=()=>Z0(($)=>$.command.pendingCommands);var $3=()=>Z0(($)=>$.app.thinkingModeEnabled),Y3=()=>Z0(($)=>$.session.currentThinkingContent),X3=()=>Z0(($)=>$.session.thinkingExpanded);import{useMemoizedFn as L8}from"ahooks";import{useEffect as OJ,useRef as HJ}from"react";import GJ from"fuse.js";import zQ from"node:os";import Z3 from"node:path";var Q3={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 X=$[0],Z=t().addAssistantMessage;if(!X)return{success:!0,message:"show_agents_manager",data:{action:"show_agents_manager"}};if(X==="list"){let J=B0.getAllNames().map((U)=>B0.getSubagent(U)).filter((U)=>U!==void 0);if(J.length===0){let U=`\uD83D\uDCCB **Agents 管理**
1034
1030
 
1035
1031
  `+`❌ 没有找到任何 agent 配置
1036
1032
 
1037
1033
  `+`**配置文件位置:**
1038
- `+"- 项目级: `.blade/agents/`\n"+"- 用户级: `~/.blade/agents/`\n\n"+"\uD83D\uDCA1 使用 `/agents` 打开管理对话框";return Z(U),{success:!0,message:"No agents found"}}let q=h5.join(process.cwd(),".blade","agents"),G=h5.join(nZ.homedir(),".blade","agents"),K=J.filter((U)=>U.configPath?.startsWith(q)),W=J.filter((U)=>U.configPath?.startsWith(G)),O=`\uD83D\uDCCB **Agents 管理**
1034
+ `+"- 项目级: `.blade/agents/`\n"+"- 用户级: `~/.blade/agents/`\n\n"+"\uD83D\uDCA1 使用 `/agents` 打开管理对话框";return Z(U),{success:!0,message:"No agents found"}}let q=Z3.join(process.cwd(),".blade","agents"),G=Z3.join(zQ.homedir(),".blade","agents"),K=J.filter((U)=>U.configPath?.startsWith(q)),W=J.filter((U)=>U.configPath?.startsWith(G)),O=`\uD83D\uDCCB **Agents 管理**
1039
1035
 
1040
1036
  找到 **${J.length}** 个 agent:
1041
1037
 
@@ -1075,11 +1071,11 @@ Please continue the conversation from where we left it off without asking the us
1075
1071
  `+"- 项目级 (`.blade/agents/`) - 最高优先级\n"+"- 用户级 (`~/.blade/agents/`) - 较低优先级\n\n"+`**可用工具:**
1076
1072
  `+"- `Glob` - 文件搜索\n"+"- `Grep` - 内容搜索\n"+"- `Read` - 读取文件\n"+"- `Write` - 写入文件\n"+"- `Edit` - 编辑文件\n"+"- `Bash` - 执行命令\n"+"- 省略 `tools` 字段 = 继承所有工具\n\n"+"\uD83D\uDCA1 **提示:** 创建文件后,重启 Blade 使配置生效";return Z(J),{success:!0,message:"Help displayed"}}if(X==="create")return{success:!0,message:"show_agent_creation_wizard",data:{action:"show_agent_creation_wizard"}};let Q=`❌ 未知子命令: \`${X}\`
1077
1073
 
1078
- `+"使用 `/agents help` 查看可用命令";return Z(Q),{success:!1,error:`Unknown subcommand: ${X}`}}};async function oZ($,Y){let X=o().addAssistantMessage;try{let Z=F0(),Q=V2();if(!Z||!Q)return{success:!1,error:"配置未初始化"};let J=s().session,q=J.messages,G=J.sessionId;if(!q||q.length===0)return X("⚠️ 当前会话没有消息,无需压缩"),{success:!1,error:"没有消息需要压缩"};let K=q.map((_)=>({role:_.role,content:_.content})),W=r1.countTokens(K,Q.model),O=Q.maxContextTokens??Z.maxContextTokens,U=(W/O*100).toFixed(1);if(X("\uD83D\uDCCA **当前上下文统计**"),X(` • 消息数量: ${K.length}`),X(` • Token 数量: ${W.toLocaleString()}`),X(` • Token 限制: ${O.toLocaleString()}`),X(` • 使用率: ${U}%`),X(""),W<O*0.5)return X(`\uD83D\uDCA1 提示: 当前 token 使用率较低(${U}%),可以暂时不压缩。`),X(" 系统会在达到 80% 时自动触发压缩。"),{success:!0,message:"无需压缩"};X("⏳ **正在压缩上下文...**");let H=await O$.compact(K,{trigger:"manual",modelName:Q.model,maxContextTokens:O,apiKey:Q.apiKey,baseURL:Q.baseUrl});if(H.success){try{if(G)await new $2().saveCompaction(G,H.summary,{trigger:"manual",preTokens:H.preTokens,postTokens:H.postTokens,filesIncluded:H.filesIncluded},null),console.log("[/compact] 压缩数据已保存到 JSONL")}catch(_){console.warn("[/compact] 保存压缩数据失败:",_)}if(X(""),X("✅ **压缩完成!**"),X(""),X("\uD83D\uDCC9 **Token 变化**"),X(` • 压缩前: ${H.preTokens.toLocaleString()} tokens`),X(` • 压缩后: ${H.postTokens.toLocaleString()} tokens`),X(` • 压缩率: ${((1-H.postTokens/H.preTokens)*100).toFixed(1)}%`),H.filesIncluded.length>0)X(""),X(`\uD83D\uDCC1 **包含文件** (${H.filesIncluded.length})`),H.filesIncluded.forEach((_,z)=>{X(` ${z+1}. ${_}`)});return X(""),X("\uD83D\uDCA1 对话历史已压缩,但完整记录仍保存在会话文件中。"),{success:!0,message:"compact_completed",data:{compactedMessages:H.compactedMessages,boundaryMessage:H.boundaryMessage,summaryMessage:H.summaryMessage,preTokens:H.preTokens,postTokens:H.postTokens,filesIncluded:H.filesIncluded}}}else return X(""),X("⚠️ **压缩使用降级策略**"),X(""),X("\uD83D\uDCC9 **Token 变化**"),X(` • 压缩前: ${H.preTokens.toLocaleString()} tokens`),X(` • 压缩后: ${H.postTokens.toLocaleString()} tokens`),X(""),X("\uD83D\uDCA1 由于压缩过程出现错误,已使用简单截断策略。"),X(` 错误信息: ${H.error}`),{success:!1,message:"compact_fallback",error:H.error,data:{compactedMessages:H.compactedMessages,boundaryMessage:H.boundaryMessage,summaryMessage:H.summaryMessage,preTokens:H.preTokens,postTokens:H.postTokens}}}catch(Z){let Q=Z instanceof Error?Z.message:String(Z);return X(`❌ **压缩失败**: ${Q}`),{success:!1,error:Q}}}var sZ={name:"compact",description:"手动压缩当前会话的上下文",fullDescription:"压缩当前对话历史,生成详细的技术总结,保留最近的消息。压缩后的上下文可以节省 token 使用量,同时保留关键信息。",usage:"/compact",examples:["/compact"],category:"context",handler:oZ},p5=sZ;function m5($){let Y=Math.floor((Date.now()-$.getTime())/1000);if(Y<60)return`${Y}s ago`;let X=Math.floor(Y/60);if(X<60)return`${X}m ago`;let Z=Math.floor(X/60);if(Z<24)return`${Z}h ago`;return`${Math.floor(Z/24)}d ago`}async function tZ(){let $=o().addAssistantMessage,Y=k0.getInstance(),X=_1();if(Object.keys(X).length===0){$(`\uD83D\uDD0C **MCP 服务器状态**
1074
+ `+"使用 `/agents help` 查看可用命令";return Z(Q),{success:!1,error:`Unknown subcommand: ${X}`}}};async function NQ($,Y){let X=t().addAssistantMessage;try{let Z=D0(),Q=E2();if(!Z||!Q)return{success:!1,error:"配置未初始化"};let J=o().session,q=J.messages,G=J.sessionId;if(!q||q.length===0)return X("⚠️ 当前会话没有消息,无需压缩"),{success:!1,error:"没有消息需要压缩"};let K=q.map((_)=>({role:_.role,content:_.content})),W=e1.countTokens(K,Q.model),O=Q.maxContextTokens??Z.maxContextTokens,U=(W/O*100).toFixed(1);if(X("\uD83D\uDCCA **当前上下文统计**"),X(` • 消息数量: ${K.length}`),X(` • Token 数量: ${W.toLocaleString()}`),X(` • Token 限制: ${O.toLocaleString()}`),X(` • 使用率: ${U}%`),X(""),W<O*0.5)return X(`\uD83D\uDCA1 提示: 当前 token 使用率较低(${U}%),可以暂时不压缩。`),X(" 系统会在达到 80% 时自动触发压缩。"),{success:!0,message:"无需压缩"};X("⏳ **正在压缩上下文...**");let H=await L$.compact(K,{trigger:"manual",modelName:Q.model,maxContextTokens:O,apiKey:Q.apiKey,baseURL:Q.baseUrl});if(H.success){try{if(G)await new K2().saveCompaction(G,H.summary,{trigger:"manual",preTokens:H.preTokens,postTokens:H.postTokens,filesIncluded:H.filesIncluded},null),console.log("[/compact] 压缩数据已保存到 JSONL")}catch(_){console.warn("[/compact] 保存压缩数据失败:",_)}if(X(""),X("✅ **压缩完成!**"),X(""),X("\uD83D\uDCC9 **Token 变化**"),X(` • 压缩前: ${H.preTokens.toLocaleString()} tokens`),X(` • 压缩后: ${H.postTokens.toLocaleString()} tokens`),X(` • 压缩率: ${((1-H.postTokens/H.preTokens)*100).toFixed(1)}%`),H.filesIncluded.length>0)X(""),X(`\uD83D\uDCC1 **包含文件** (${H.filesIncluded.length})`),H.filesIncluded.forEach((_,z)=>{X(` ${z+1}. ${_}`)});return X(""),X("\uD83D\uDCA1 对话历史已压缩,但完整记录仍保存在会话文件中。"),{success:!0,message:"compact_completed",data:{compactedMessages:H.compactedMessages,boundaryMessage:H.boundaryMessage,summaryMessage:H.summaryMessage,preTokens:H.preTokens,postTokens:H.postTokens,filesIncluded:H.filesIncluded}}}else return X(""),X("⚠️ **压缩使用降级策略**"),X(""),X("\uD83D\uDCC9 **Token 变化**"),X(` • 压缩前: ${H.preTokens.toLocaleString()} tokens`),X(` • 压缩后: ${H.postTokens.toLocaleString()} tokens`),X(""),X("\uD83D\uDCA1 由于压缩过程出现错误,已使用简单截断策略。"),X(` 错误信息: ${H.error}`),{success:!1,message:"compact_fallback",error:H.error,data:{compactedMessages:H.compactedMessages,boundaryMessage:H.boundaryMessage,summaryMessage:H.summaryMessage,preTokens:H.preTokens,postTokens:H.postTokens}}}catch(Z){let Q=Z instanceof Error?Z.message:String(Z);return X(`❌ **压缩失败**: ${Q}`),{success:!1,error:Q}}}var BQ={name:"compact",description:"手动压缩当前会话的上下文",fullDescription:"压缩当前对话历史,生成详细的技术总结,保留最近的消息。压缩后的上下文可以节省 token 使用量,同时保留关键信息。",usage:"/compact",examples:["/compact"],category:"context",handler:NQ},J3=BQ;function G3($){let Y=Math.floor((Date.now()-$.getTime())/1000);if(Y<60)return`${Y}s ago`;let X=Math.floor(Y/60);if(X<60)return`${X}m ago`;let Z=Math.floor(X/60);if(Z<24)return`${Z}h ago`;return`${Math.floor(Z/24)}d ago`}async function LQ(){let $=t().addAssistantMessage,Y=v0.getInstance(),X=l0();if(Object.keys(X).length===0){$(`\uD83D\uDD0C **MCP 服务器状态**
1079
1075
 
1080
1076
  ⚠️ 暂无配置的 MCP 服务器
1081
1077
 
1082
- \uD83D\uDCA1 使用 \`blade mcp add\` 命令添加 MCP 服务器`);return}$("\uD83D\uDD0D 正在检查 MCP 服务器状态...");let Z=Object.entries(X).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(Z),eZ(Y.getAllServers())}function eZ($){let Y=o().addAssistantMessage,X=`\uD83D\uDD0C **MCP 服务器状态**
1078
+ \uD83D\uDCA1 使用 \`blade mcp add\` 命令添加 MCP 服务器`);return}$("\uD83D\uDD0D 正在检查 MCP 服务器状态...");let Z=Object.entries(X).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(Z),wQ(Y.getAllServers())}function wQ($){let Y=t().addAssistantMessage,X=`\uD83D\uDD0C **MCP 服务器状态**
1083
1079
 
1084
1080
  `,Z=0,Q=0,J=0;for(let[q,G]of $){let{config:K,status:W,connectedAt:O,lastError:U,tools:H}=G,_=W==="connected"?"✓":"✗",z=W==="connected"?"Connected":"Disconnected";if(W==="connected")Z++,J+=H.length;else Q++;if(X+=`\uD83D\uDCE6 **${q}**
1085
1081
  `,X+=` 状态: ${_} ${z}
@@ -1087,20 +1083,20 @@ Please continue the conversation from where we left it off without asking the us
1087
1083
  `,K.type==="stdio")X+=` 命令: ${K.command}${K.args?.length?" "+K.args.join(" "):""}
1088
1084
  `;else X+=` URL: ${K.url}
1089
1085
  `;if(X+=` 工具: ${H.length} 个
1090
- `,O&&W==="connected")X+=` 连接时间: ${m5(O)}
1086
+ `,O&&W==="connected")X+=` 连接时间: ${G3(O)}
1091
1087
  `;if(U&&W!=="connected")X+=` 错误: ${U.message}
1092
1088
  `;X+=`
1093
1089
  `}X+=`**总计:**
1094
1090
  `,X+=`- 服务器: ${$.size} 个 (${Z} 连接, ${Q} 断开)
1095
1091
  `,X+=`- 可用工具: ${J} 个
1096
1092
 
1097
- `,X+="\uD83D\uDCA1 使用 `/mcp <server-name>` 查看详细信息\n",X+="\uD83D\uDCA1 使用 `/mcp tools` 查看所有工具",Y(X)}async function $Q($){let Y=o().addAssistantMessage,X=k0.getInstance(),Q=_1()[$];if(!Q){Y(`❌ 服务器 "${$}" 不存在
1093
+ `,X+="\uD83D\uDCA1 使用 `/mcp <server-name>` 查看详细信息\n",X+="\uD83D\uDCA1 使用 `/mcp tools` 查看所有工具",Y(X)}async function AQ($){let Y=t().addAssistantMessage,X=v0.getInstance(),Q=l0()[$];if(!Q){Y(`❌ 服务器 "${$}" 不存在
1098
1094
 
1099
- \uD83D\uDCA1 使用 \`/mcp\` 查看所有可用服务器`);return}try{let J=X.getServerStatus($);if(!J)Y(`\uD83D\uDD0D 正在连接 ${$}...`),await X.registerServer($,Q),J=X.getServerStatus($);else if(J.status==="disconnected")Y(`\uD83D\uDD0D 正在重新连接 ${$}...`),await X.connectServer($),J=X.getServerStatus($);if(J)YQ($,J);else g5($,Q)}catch(J){g5($,Q),Y(`
1100
- ⚠️ 连接失败: ${J instanceof Error?J.message:"未知错误"}`)}}function YQ($,Y){let X=o().addAssistantMessage,{config:Z,status:Q,connectedAt:J,lastError:q,tools:G}=Y,K=Q==="connected"?"✓":"✗",W=Q==="connected"?"Connected":"Disconnected",O=`\uD83D\uDCE6 **${$}**
1095
+ \uD83D\uDCA1 使用 \`/mcp\` 查看所有可用服务器`);return}try{let J=X.getServerStatus($);if(!J)Y(`\uD83D\uDD0D 正在连接 ${$}...`),await X.registerServer($,Q),J=X.getServerStatus($);else if(J.status==="disconnected")Y(`\uD83D\uDD0D 正在重新连接 ${$}...`),await X.connectServer($),J=X.getServerStatus($);if(J)RQ($,J);else q3($,Q)}catch(J){q3($,Q),Y(`
1096
+ ⚠️ 连接失败: ${J instanceof Error?J.message:"未知错误"}`)}}function RQ($,Y){let X=t().addAssistantMessage,{config:Z,status:Q,connectedAt:J,lastError:q,tools:G}=Y,K=Q==="connected"?"✓":"✗",W=Q==="connected"?"Connected":"Disconnected",O=`\uD83D\uDCE6 **${$}**
1101
1097
 
1102
1098
  `;if(O+=`**连接状态:**
1103
- `,O+=` ${K} ${W}`,J&&Q==="connected")O+=` (连接于 ${m5(J)})`;if(O+=`
1099
+ `,O+=` ${K} ${W}`,J&&Q==="connected")O+=` (连接于 ${G3(J)})`;if(O+=`
1104
1100
 
1105
1101
  `,O+=`**配置信息:**
1106
1102
  `,O+=` 类型: ${Z.type}
@@ -1118,7 +1114,7 @@ Please continue the conversation from where we left it off without asking the us
1118
1114
  ⚠️ 服务器未连接,无法获取工具列表
1119
1115
  `;if(q)O+=`
1120
1116
  **错误信息:**
1121
- `,O+=` ${q.message}`;X(O)}function g5($,Y){let X=o().addAssistantMessage,Z=`\uD83D\uDCE6 **${$}**
1117
+ `,O+=` ${q.message}`;X(O)}function q3($,Y){let X=t().addAssistantMessage,Z=`\uD83D\uDCE6 **${$}**
1122
1118
 
1123
1119
  `;if(Z+=`**连接状态:**
1124
1120
  `,Z+=` ⏸️ 未启动 (等待 Agent 连接)
@@ -1132,7 +1128,7 @@ Please continue the conversation from where we left it off without asking the us
1132
1128
  `,Y.headers&&Object.keys(Y.headers).length>0)Z+=` Headers: ${Object.keys(Y.headers).join(", ")}
1133
1129
  `;if(Y.timeout)Z+=` 超时: ${Y.timeout}ms
1134
1130
  `;Z+=`
1135
- \uD83D\uDCA1 服务器将在 Agent 启动时自动连接`,X(Z)}async function XQ(){let $=o().addAssistantMessage,Y=k0.getInstance(),X=_1();if(Object.keys(X).length===0){$(`\uD83D\uDD27 **可用的 MCP 工具**
1131
+ \uD83D\uDCA1 服务器将在 Agent 启动时自动连接`,X(Z)}async function bQ(){let $=t().addAssistantMessage,Y=v0.getInstance(),X=l0();if(Object.keys(X).length===0){$(`\uD83D\uDD27 **可用的 MCP 工具**
1136
1132
 
1137
1133
  ⚠️ 暂无配置的 MCP 服务器
1138
1134
 
@@ -1145,9 +1141,9 @@ Please continue the conversation from where we left it off without asking the us
1145
1141
 
1146
1142
  `;continue}q+=O.length;for(let U of O){if(J+=` • ${U.name}`,U.description){let H=U.description.length>60?U.description.substring(0,57)+"...":U.description;J+=` - ${H}`}J+=`
1147
1143
  `}J+=`
1148
- `}J+=`**总计:** ${q} 个工具可用`,$(J)}var ZQ={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){try{if(console.log("[MCP Command] Received args:",$),$.length===0)return await tZ(),{success:!0,message:"MCP 服务器概览已显示"};let X=$[0];if(console.log("[MCP Command] Subcommand:",X),X==="tools")return await XQ(),{success:!0,message:"MCP 工具列表已显示"};return await $Q(X),{success:!0,message:`服务器 "${X}" 详情已显示`}}catch(X){return{success:!1,error:`显示 MCP 信息失败: ${X instanceof Error?X.message:"未知错误"}`}}}},u5=ZQ;async function QQ($,Y){return{success:!0,message:"show_permissions_manager",data:{action:"show_permissions_manager"}}}var JQ={name:"permissions",description:"管理项目的本地权限规则",fullDescription:"打开权限管理器,管理 .blade/settings.local.json 中的权限规则",usage:"/permissions",aliases:["perm"],category:"ui",handler:QQ},e2=JQ;var qQ={name:"resume",description:"Resume a conversation",fullDescription:"恢复历史会话。可以指定 sessionId 直接恢复,或不带参数打开会话选择器",usage:"/resume [sessionId]",aliases:["r"],category:"Session",examples:["/resume - 打开会话选择器","/resume abc123xyz - 直接恢复指定的会话"],async handler($,Y){let X=o().addAssistantMessage,Z=o().restoreSession;if($.length>0){let Q=$[0];try{let J=await N1.loadSession(Q);if(J.length===0)return X(`❌ 会话 \`${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 Z(Q,q),X(`✅ 已恢复会话 \`${Q}\`
1144
+ `}J+=`**总计:** ${q} 个工具可用`,$(J)}var VQ={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){try{if(console.log("[MCP Command] Received args:",$),$.length===0)return await LQ(),{success:!0,message:"MCP 服务器概览已显示"};let X=$[0];if(console.log("[MCP Command] Subcommand:",X),X==="tools")return await bQ(),{success:!0,message:"MCP 工具列表已显示"};return await AQ(X),{success:!0,message:`服务器 "${X}" 详情已显示`}}catch(X){return{success:!1,error:`显示 MCP 信息失败: ${X instanceof Error?X.message:"未知错误"}`}}}},K3=VQ;async function IQ($,Y){return{success:!0,message:"show_permissions_manager",data:{action:"show_permissions_manager"}}}var DQ={name:"permissions",description:"管理项目的本地权限规则",fullDescription:"打开权限管理器,管理 .blade/settings.local.json 中的权限规则",usage:"/permissions",aliases:["perm"],category:"ui",handler:IQ},q6=DQ;var vQ={name:"resume",description:"Resume a conversation",fullDescription:"恢复历史会话。可以指定 sessionId 直接恢复,或不带参数打开会话选择器",usage:"/resume [sessionId]",aliases:["r"],category:"Session",examples:["/resume - 打开会话选择器","/resume abc123xyz - 直接恢复指定的会话"],async handler($,Y){let X=t().addAssistantMessage,Z=t().restoreSession;if($.length>0){let Q=$[0];try{let J=await A1.loadSession(Q);if(J.length===0)return X(`❌ 会话 \`${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 Z(Q,q),X(`✅ 已恢复会话 \`${Q}\`
1149
1145
 
1150
- 共 ${q.length} 条消息已加载,可以继续对话`),{success:!0,message:"session_restored",data:{sessionId:Q,messageCount:q.length}}}catch(J){let q=J instanceof Error?J.message:"未知错误";return X(`❌ 加载会话失败: ${q}`),{success:!1,error:`加载会话失败: ${q}`}}}try{let Q=await N1.listSessions();if(Q.length===0)return X("\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 X(`❌ 获取会话列表失败: ${J}`),{success:!1,error:`获取会话列表失败: ${J}`}}}},d5=qQ;var GQ={name:"help",description:"Show all available slash commands",fullDescription:"显示所有可用的 slash commands 及其使用方法",usage:"/help",aliases:["h"],async handler($,Y){return o().addAssistantMessage(`\uD83D\uDD27 **可用的 Slash Commands:**
1146
+ 共 ${q.length} 条消息已加载,可以继续对话`),{success:!0,message:"session_restored",data:{sessionId:Q,messageCount:q.length}}}catch(J){let q=J instanceof Error?J.message:"未知错误";return X(`❌ 加载会话失败: ${q}`),{success:!1,error:`加载会话失败: ${q}`}}}try{let Q=await A1.listSessions();if(Q.length===0)return X("\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 X(`❌ 获取会话列表失败: ${J}`),{success:!1,error:`获取会话列表失败: ${J}`}}}},W3=vQ;var MQ={name:"help",description:"Show all available slash commands",fullDescription:"显示所有可用的 slash commands 及其使用方法",usage:"/help",aliases:["h"],async handler($,Y){return t().addAssistantMessage(`\uD83D\uDD27 **可用的 Slash Commands:**
1151
1147
 
1152
1148
  **/init** - 分析当前项目并生成 BLADE.md 配置文件
1153
1149
  **/git** - Git 仓库查询和 AI 辅助 (status/log/diff/review/commit)
@@ -1165,7 +1161,7 @@ Please continue the conversation from where we left it off without asking the us
1165
1161
  - 在命令前加上 \`/\` 即可执行 slash command
1166
1162
  - 普通消息会发送给 AI 助手处理
1167
1163
  - 按 Ctrl+C 退出程序
1168
- - 按 Ctrl+L 快速清屏`),{success:!0,message:"帮助信息已显示"}}},KQ={name:"clear",description:"Clear conversation history and free up context",fullDescription:"清除屏幕内容和对话历史",usage:"/clear",aliases:["cls"],async handler($,Y){return{success:!0,message:"clear_screen"}}},WQ={name:"version",description:"Show Blade Code version information",fullDescription:"显示 Blade Code 版本信息和构建详情",usage:"/version",aliases:["v"],async handler($,Y){try{let Q=`\uD83D\uDDE1️ **Blade Code v${(()=>{throw new Error("Cannot require module "+"../../../package.json");})().version||"1.3.0"}**
1164
+ - 按 Ctrl+L 快速清屏`),{success:!0,message:"帮助信息已显示"}}},kQ={name:"clear",description:"Clear conversation history and free up context",fullDescription:"清除屏幕内容和对话历史",usage:"/clear",aliases:["cls"],async handler($,Y){return{success:!0,message:"clear_screen"}}},yQ={name:"version",description:"Show Blade Code version information",fullDescription:"显示 Blade Code 版本信息和构建详情",usage:"/version",aliases:["v"],async handler($,Y){try{let Q=`\uD83D\uDDE1️ **Blade Code v${(()=>{throw new Error("Cannot require module "+"../../../package.json");})().version||"1.3.0"}**
1169
1165
 
1170
1166
  **构建信息:**
1171
1167
  - Node.js: ${process.version}
@@ -1176,9 +1172,9 @@ Please continue the conversation from where we left it off without asking the us
1176
1172
  - \uD83E\uDD16 智能 AI 对话
1177
1173
  - \uD83D\uDD27 项目自动分析
1178
1174
  - \uD83D\uDCDD 自定义系统提示
1179
- - \uD83C\uDFAF 多工具集成支持`;return o().addAssistantMessage(Q),{success:!0,message:"版本信息已显示"}}catch(X){return o().addAssistantMessage(`\uD83D\uDDE1️ **Blade Code**
1175
+ - \uD83C\uDFAF 多工具集成支持`;return t().addAssistantMessage(Q),{success:!0,message:"版本信息已显示"}}catch(X){return t().addAssistantMessage(`\uD83D\uDDE1️ **Blade Code**
1180
1176
 
1181
- 版本信息获取失败`),{success:!0,message:"版本信息已显示"}}}},UQ={name:"status",description:"Show current configuration status",fullDescription:"显示当前项目配置状态和环境信息",usage:"/status",async handler($,Y){let{cwd:X}=Y,Z=A0("path"),Q=A0("fs").promises;try{let J=Z.join(X,"BLADE.md"),q=await Q.access(J).then(()=>!0).catch(()=>!1),G=Z.join(X,"package.json"),K="未知项目",W="未知类型";try{let U=await Q.readFile(G,"utf-8"),H=JSON.parse(U);K=H.name||"未知项目";let _={...H.dependencies,...H.devDependencies};if(_.react)W="React 项目";else if(_.vue)W="Vue 项目";else if(_.next)W="Next.js 项目";else if(_.express)W="Express 项目";else W="Node.js 项目"}catch{}let O=`\uD83D\uDCCA **当前状态**
1177
+ 版本信息获取失败`),{success:!0,message:"版本信息已显示"}}}},EQ={name:"status",description:"Show current configuration status",fullDescription:"显示当前项目配置状态和环境信息",usage:"/status",async handler($,Y){let{cwd:X}=Y,Z=R0("path"),Q=R0("fs").promises;try{let J=Z.join(X,"BLADE.md"),q=await Q.access(J).then(()=>!0).catch(()=>!1),G=Z.join(X,"package.json"),K="未知项目",W="未知类型";try{let U=await Q.readFile(G,"utf-8"),H=JSON.parse(U);K=H.name||"未知项目";let _={...H.dependencies,...H.devDependencies};if(_.react)W="React 项目";else if(_.vue)W="Vue 项目";else if(_.next)W="Next.js 项目";else if(_.express)W="Express 项目";else W="Node.js 项目"}catch{}let O=`\uD83D\uDCCA **当前状态**
1182
1178
 
1183
1179
  **项目信息:**
1184
1180
  - 名称: ${K}
@@ -1192,7 +1188,7 @@ Please continue the conversation from where we left it off without asking the us
1192
1188
  - 工作目录: ${process.cwd()}
1193
1189
  - Node.js: ${process.version}
1194
1190
 
1195
- ${!q?"\n\uD83D\uDCA1 **建议:** 运行 `/init` 命令来创建项目配置文件":""}`;return o().addAssistantMessage(O),{success:!0,message:"状态信息已显示"}}catch(J){return{success:!1,error:`获取状态信息失败: ${J instanceof Error?J.message:"未知错误"}`}}}},OQ={name:"exit",description:"Exit the REPL",fullDescription:"退出 Blade Code 命令行界面",usage:"/exit",aliases:["quit","q"],async handler($,Y){return{success:!0,message:"exit_application"}}},HQ={name:"config",description:"Open config panel",fullDescription:"打开配置面板,管理 Blade Code 设置",usage:"/config [theme]",async handler($,Y){return o().addAssistantMessage(`⚙️ **配置面板**
1191
+ ${!q?"\n\uD83D\uDCA1 **建议:** 运行 `/init` 命令来创建项目配置文件":""}`;return t().addAssistantMessage(O),{success:!0,message:"状态信息已显示"}}catch(J){return{success:!1,error:`获取状态信息失败: ${J instanceof Error?J.message:"未知错误"}`}}}},jQ={name:"exit",description:"Exit the REPL",fullDescription:"退出 Blade Code 命令行界面",usage:"/exit",aliases:["quit","q"],async handler($,Y){return{success:!0,message:"exit_application"}}},PQ={name:"config",description:"Open config panel",fullDescription:"打开配置面板,管理 Blade Code 设置",usage:"/config [theme]",async handler($,Y){return t().addAssistantMessage(`⚙️ **配置面板**
1196
1192
 
1197
1193
  **当前配置:**
1198
1194
  - 主题: Default
@@ -1204,7 +1200,7 @@ ${!q?"\n\uD83D\uDCA1 **建议:** 运行 `/init` 命令来创建项目配置文
1204
1200
  - \`/config lang\` - 切换语言
1205
1201
  - \`/config debug\` - 切换调试模式
1206
1202
 
1207
- \uD83D\uDCA1 **提示:** 配置更改会在下次启动时生效`),{success:!0,message:"配置面板已显示"}}},_Q={name:"context",description:"Visualize current context usage as a colored grid",fullDescription:"可视化显示当前上下文使用情况",usage:"/context",async handler($,Y){let X=`\uD83D\uDCCA **上下文使用情况**
1203
+ \uD83D\uDCA1 **提示:** 配置更改会在下次启动时生效`),{success:!0,message:"配置面板已显示"}}},SQ={name:"context",description:"Visualize current context usage as a colored grid",fullDescription:"可视化显示当前上下文使用情况",usage:"/context",async handler($,Y){let X=`\uD83D\uDCCA **上下文使用情况**
1208
1204
 
1209
1205
  **当前会话:**
1210
1206
  - 消息数量: ${Math.floor(Math.random()*20)+5}
@@ -1216,7 +1212,7 @@ ${!q?"\n\uD83D\uDCA1 **建议:** 运行 `/init` 命令来创建项目配置文
1216
1212
  - 系统提示: ${Math.floor(Math.random()*500)+200} tokens
1217
1213
  - 项目上下文: ${Math.floor(Math.random()*1000)+300} tokens
1218
1214
 
1219
- \uD83D\uDFE2 正常 \uD83D\uDFE1 中等 \uD83D\uDD34 高负载`;return o().addAssistantMessage(X),{success:!0,message:"上下文信息已显示"}}},FQ={name:"cost",description:"Show the total cost and duration of the current session",fullDescription:"显示当前会话的成本和持续时间",usage:"/cost",async handler($,Y){let X=`\uD83D\uDCB0 **会话成本统计**
1215
+ \uD83D\uDFE2 正常 \uD83D\uDFE1 中等 \uD83D\uDD34 高负载`;return t().addAssistantMessage(X),{success:!0,message:"上下文信息已显示"}}},TQ={name:"cost",description:"Show the total cost and duration of the current session",fullDescription:"显示当前会话的成本和持续时间",usage:"/cost",async handler($,Y){let X=`\uD83D\uDCB0 **会话成本统计**
1220
1216
 
1221
1217
  **时间统计:**
1222
1218
  - 开始时间: ${new Date().toLocaleTimeString()}
@@ -1231,8 +1227,8 @@ ${!q?"\n\uD83D\uDCA1 **建议:** 运行 `/init` 命令来创建项目配置文
1231
1227
  - 当前会话: $${(Math.random()*0.5+0.1).toFixed(3)}
1232
1228
  - 今日总计: $${(Math.random()*2+0.5).toFixed(3)}
1233
1229
 
1234
- \uD83D\uDCA1 **提示:** 成本基于当前 AI 模型定价估算`;return o().addAssistantMessage(X),{success:!0,message:"成本信息已显示"}}},c5={help:GQ,clear:KQ,version:WQ,status:UQ,exit:OQ,config:HQ,context:_Q,cost:FQ,permissions:e2,resume:d5,compact:p5,mcp:u5,agents:x5};import{execFile as l5,spawn as zQ}from"child_process";import{promisify as NQ}from"util";var aN=NQ(l5);async function Y2($,Y){return new Promise((X)=>{l5("git",Y,{cwd:$,maxBuffer:10485760},(Z,Q,J)=>{X({code:Z?Z.code||1:0,stdout:Q||"",stderr:J||""})})})}async function BQ($,Y){let{code:X}=await Y2($,Y);return X===0}async function B1($,Y){let{stdout:X}=await Y2($,Y);return X.trim()}async function X2($){return BQ($,["rev-parse","--is-inside-work-tree"])}async function Q8($){return(await B1($,["status","--porcelain"])).length>0}async function i5($){return B1($,["branch","--show-current"])}async function J8($,Y=10){return B1($,["log","-n",String(Y),"--pretty=format:%s"])}async function r5($){let{code:Y,stderr:X}=await Y2($,["add","."]);if(Y!==0){let Z=X||"Unknown error";if(Z.includes("fatal: pathspec"))throw Error("Failed to stage files: Invalid file path or pattern");throw Error(`Failed to stage files: ${Z}`)}}async function a5($,Y,X=!1,Z){let Q=["commit","-m",Y];if(X)Q.push("--no-verify");if(!Z){let{code:J,stderr:q}=await Y2($,Q);if(J!==0)throw Error(q||"Commit failed");return}return new Promise((J,q)=>{let G=zQ("git",Q,{cwd:$}),K="",W=(H,_,z)=>{let L=(z+H.toString()).split(`
1235
- `),w=L.pop()||"";for(let N of L)if(N.trim())Z(N,_);return w},O="",U="";G.stdout?.on("data",(H)=>{O=W(H,"stdout",O)}),G.stderr?.on("data",(H)=>{K+=H.toString(),U=W(H,"stderr",U)}),G.on("error",(H)=>{q(H)}),G.on("close",(H)=>{if(O.trim())Z(O,"stdout");if(U.trim())Z(U,"stderr");if(H===0)J();else q(Error(K||"Commit failed"))})})}async function n5($){let{cwd:Y}=$;if(!await X2(Y))return null;let[X,Z,Q,J,q]=await Promise.all([B1(Y,["branch","--show-current"]),B1(Y,["rev-parse","--abbrev-ref","origin/HEAD"]).then((K)=>K.replace("origin/","")).catch(()=>"main"),B1(Y,["status","--short"]),B1(Y,["log","--oneline","-n","5"]),B1(Y,["config","user.email"])]),G=q?await B1(Y,["log","--author",q,"--oneline","-n","5"]):"";return{branch:X,mainBranch:Z,status:Q,log:J,author:q,authorLog:G}}function o5($){if(!$)return null;return`
1230
+ \uD83D\uDCA1 **提示:** 成本基于当前 AI 模型定价估算`;return t().addAssistantMessage(X),{success:!0,message:"成本信息已显示"}}},U3={help:MQ,clear:kQ,version:yQ,status:EQ,exit:jQ,config:PQ,context:SQ,cost:TQ,permissions:q6,resume:W3,compact:J3,mcp:K3,agents:Q3};import{execFile as O3,spawn as CQ}from"child_process";import{promisify as fQ}from"util";var DB=fQ(O3);async function W2($,Y){return new Promise((X)=>{O3("git",Y,{cwd:$,maxBuffer:10485760},(Z,Q,J)=>{X({code:Z?Z.code||1:0,stdout:Q||"",stderr:J||""})})})}async function hQ($,Y){let{code:X}=await W2($,Y);return X===0}async function R1($,Y){let{stdout:X}=await W2($,Y);return X.trim()}async function U2($){return hQ($,["rev-parse","--is-inside-work-tree"])}async function _8($){return(await R1($,["status","--porcelain"])).length>0}async function H3($){return R1($,["branch","--show-current"])}async function F8($,Y=10){return R1($,["log","-n",String(Y),"--pretty=format:%s"])}async function _3($){let{code:Y,stderr:X}=await W2($,["add","."]);if(Y!==0){let Z=X||"Unknown error";if(Z.includes("fatal: pathspec"))throw Error("Failed to stage files: Invalid file path or pattern");throw Error(`Failed to stage files: ${Z}`)}}async function F3($,Y,X=!1,Z){let Q=["commit","-m",Y];if(X)Q.push("--no-verify");if(!Z){let{code:J,stderr:q}=await W2($,Q);if(J!==0)throw Error(q||"Commit failed");return}return new Promise((J,q)=>{let G=CQ("git",Q,{cwd:$}),K="",W=(H,_,z)=>{let B=(z+H.toString()).split(`
1231
+ `),L=B.pop()||"";for(let N of B)if(N.trim())Z(N,_);return L},O="",U="";G.stdout?.on("data",(H)=>{O=W(H,"stdout",O)}),G.stderr?.on("data",(H)=>{K+=H.toString(),U=W(H,"stderr",U)}),G.on("error",(H)=>{q(H)}),G.on("close",(H)=>{if(O.trim())Z(O,"stdout");if(U.trim())Z(U,"stderr");if(H===0)J();else q(Error(K||"Commit failed"))})})}async function z3($){let{cwd:Y}=$;if(!await U2(Y))return null;let[X,Z,Q,J,q]=await Promise.all([R1(Y,["branch","--show-current"]),R1(Y,["rev-parse","--abbrev-ref","origin/HEAD"]).then((K)=>K.replace("origin/","")).catch(()=>"main"),R1(Y,["status","--short"]),R1(Y,["log","--oneline","-n","5"]),R1(Y,["config","user.email"])]),G=q?await R1(Y,["log","--author",q,"--oneline","-n","5"]):"";return{branch:X,mainBranch:Z,status:Q,log:J,author:q,authorLog:G}}function N3($){if(!$)return null;return`
1236
1232
  Git repository status (snapshot at conversation start):
1237
1233
  Current branch: ${$.branch}
1238
1234
  Main branch (target for PRs): ${$.mainBranch}
@@ -1245,14 +1241,14 @@ ${$.log||"(no commits)"}
1245
1241
 
1246
1242
  Your recent commits:
1247
1243
  ${$.authorLog||"(no recent commits)"}
1248
- `.trim()}async function $6($){return B1($,["diff","--cached","--name-status"])}async function Y6($){let X=["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:Z,stdout:Q,stderr:J}=await Y2($,X);if(Z!==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)+`
1244
+ `.trim()}async function G6($){return R1($,["diff","--cached","--name-status"])}async function K6($){let X=["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:Z,stdout:Q,stderr:J}=await W2($,X);if(Z!==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)+`
1249
1245
 
1250
- [Diff truncated due to size. Total diff size: `+(Q.length/1024).toFixed(2)+"KB]";return Q}var LQ={name:"git",description:"Git 仓库查询和 AI 辅助",usage:"/git [status|log|diff|review|commit]",aliases:["g"],examples:["/git","/git status","/git log 10","/git review","/git commit"],async handler($,Y){let{cwd:X}=Y,Z=$[0]?.toLowerCase();if(!await X2(X))return{success:!1,error:"❌ 当前目录不在 Git 仓库中"};try{switch(Z){case"status":case"s":return s5(X);case"log":case"l":return wQ(X,$[1]);case"diff":case"d":return AQ(X);case"review":case"r":return RQ(X);case"commit":case"c":return bQ(X);default:return s5(X)}}catch(Q){return{success:!1,error:`Git 命令失败: ${Q instanceof Error?Q.message:"未知错误"}`}}}};async function s5($){let Y=await n5({cwd:$});if(!Y)return{success:!1,error:"无法获取 Git 状态"};let X=o5(Y);if(X)o().addAssistantMessage(`\`\`\`
1246
+ [Diff truncated due to size. Total diff size: `+(Q.length/1024).toFixed(2)+"KB]";return Q}var xQ={name:"git",description:"Git 仓库查询和 AI 辅助",usage:"/git [status|log|diff|review|commit]",aliases:["g"],examples:["/git","/git status","/git log 10","/git review","/git commit"],async handler($,Y){let{cwd:X}=Y,Z=$[0]?.toLowerCase();if(!await U2(X))return{success:!1,error:"❌ 当前目录不在 Git 仓库中"};try{switch(Z){case"status":case"s":return B3(X);case"log":case"l":return pQ(X,$[1]);case"diff":case"d":return gQ(X);case"review":case"r":return mQ(X);case"commit":case"c":return uQ(X);default:return B3(X)}}catch(Q){return{success:!1,error:`Git 命令失败: ${Q instanceof Error?Q.message:"未知错误"}`}}}};async function B3($){let Y=await z3({cwd:$});if(!Y)return{success:!1,error:"无法获取 Git 状态"};let X=N3(Y);if(X)t().addAssistantMessage(`\`\`\`
1251
1247
  ${X}
1252
- \`\`\``);else o().addAssistantMessage("\uD83D\uDCED 无法获取 Git 状态信息");return{success:!0}}async function wQ($,Y){let X=Math.min(Math.max(parseInt(Y||"5",10)||5,1),50),Z=await J8($,X);if(!Z)o().addAssistantMessage("\uD83D\uDCED 暂无提交记录");else o().addAssistantMessage(`**最近 ${X} 条提交:**
1248
+ \`\`\``);else t().addAssistantMessage("\uD83D\uDCED 无法获取 Git 状态信息");return{success:!0}}async function pQ($,Y){let X=Math.min(Math.max(parseInt(Y||"5",10)||5,1),50),Z=await F8($,X);if(!Z)t().addAssistantMessage("\uD83D\uDCED 暂无提交记录");else t().addAssistantMessage(`**最近 ${X} 条提交:**
1253
1249
  \`\`\`
1254
1250
  ${Z}
1255
- \`\`\``);return{success:!0}}async function AQ($){let Y=await $6($);if(!Y)return o().addAssistantMessage("\uD83D\uDCED 暂存区为空,没有待提交的改动"),{success:!0};let X=await Y6($),Z=`**暂存文件:**
1251
+ \`\`\``);return{success:!0}}async function gQ($){let Y=await G6($);if(!Y)return t().addAssistantMessage("\uD83D\uDCED 暂存区为空,没有待提交的改动"),{success:!0};let X=await K6($),Z=`**暂存文件:**
1256
1252
  \`\`\`
1257
1253
  ${Y}
1258
1254
  \`\`\`
@@ -1260,7 +1256,7 @@ ${Y}
1260
1256
  **Diff:**
1261
1257
  \`\`\`diff
1262
1258
  ${X||"(无差异)"}
1263
- \`\`\``;return o().addAssistantMessage(Z),{success:!0}}async function RQ($){let Y=o().addAssistantMessage;if(!await Q8($))return Y("\uD83D\uDCED 没有未提交的改动,无需 Review"),{success:!0};Y("\uD83D\uDD0D 正在分析代码改动...");let X=await $6($),Z=await Y6($);if(!Z&&!X)return Y("\uD83D\uDCA1 请先使用 `git add` 暂存要 Review 的文件"),{success:!0};let Q=await v0.create(),J=s().session.sessionId,q=`请对以下 Git 改动进行 Code Review。
1259
+ \`\`\``;return t().addAssistantMessage(Z),{success:!0}}async function mQ($){let Y=t().addAssistantMessage;if(!await _8($))return Y("\uD83D\uDCED 没有未提交的改动,无需 Review"),{success:!0};Y("\uD83D\uDD0D 正在分析代码改动...");let X=await G6($),Z=await K6($);if(!Z&&!X)return Y("\uD83D\uDCA1 请先使用 `git add` 暂存要 Review 的文件"),{success:!0};let Q=await k0.create(),J=o().session.sessionId,q=`请对以下 Git 改动进行 Code Review。
1264
1260
 
1265
1261
  **暂存文件:**
1266
1262
  ${X||"(无)"}
@@ -1276,7 +1272,7 @@ ${Z||"(无差异)"}
1276
1272
  3. **潜在问题**:指出可能的 bug、安全问题或性能问题
1277
1273
  4. **改进建议**:具体的代码改进建议
1278
1274
 
1279
- 如果改动很好,也请说明优点。保持简洁专业。`,G=await Q.chat(q,{messages:[],userId:"cli-user",sessionId:J||"git-review",workspaceRoot:$});return Y(G),{success:!0}}async function bQ($){let Y=o().addAssistantMessage;if(!await Q8($))return Y("\uD83D\uDCED 没有未提交的改动"),{success:!0};Y("\uD83D\uDCE6 暂存所有改动..."),await r5($);let X=await $6($),Z=await Y6($);if(!X)return Y("\uD83D\uDCED 没有需要提交的改动"),{success:!0};Y("\uD83E\uDD16 正在生成 commit message...");let Q=await J8($,5),J=await v0.create(),q=s().session.sessionId,G=`请根据以下 Git 改动生成一条简洁的 commit message。
1275
+ 如果改动很好,也请说明优点。保持简洁专业。`,G=await Q.chat(q,{messages:[],userId:"cli-user",sessionId:J||"git-review",workspaceRoot:$});return Y(G),{success:!0}}async function uQ($){let Y=t().addAssistantMessage;if(!await _8($))return Y("\uD83D\uDCED 没有未提交的改动"),{success:!0};Y("\uD83D\uDCE6 暂存所有改动..."),await _3($);let X=await G6($),Z=await K6($);if(!X)return Y("\uD83D\uDCED 没有需要提交的改动"),{success:!0};Y("\uD83E\uDD16 正在生成 commit message...");let Q=await F8($,5),J=await k0.create(),q=o().session.sessionId,G=`请根据以下 Git 改动生成一条简洁的 commit message。
1280
1276
 
1281
1277
  **暂存文件:**
1282
1278
  ${X}
@@ -1302,13 +1298,13 @@ feat: add user authentication module
1302
1298
  - Implement JWT token handling`,W=(await J.chat(G,{messages:[],userId:"cli-user",sessionId:q||"git-commit",workspaceRoot:$})).replace(/^```\w*\n?/,"").replace(/\n?```$/,"").trim();Y(`**生成的 Commit Message:**
1303
1299
  \`\`\`
1304
1300
  ${W}
1305
- \`\`\``);try{await a5($,W),Y("✅ 提交成功!")}catch(O){let U=O instanceof Error?O.message:"未知错误";return Y(`❌ 提交失败: ${U}`),{success:!1,error:U}}return{success:!0}}var t5=LQ;import{existsSync as vQ,readFileSync as MQ}from"fs";import{homedir as yQ}from"os";import{join as EQ}from"path";import{exec as VQ}from"child_process";import{promisify as DQ}from"util";var e5=DQ(VQ);class q8{static async detectIde(){let $=process.env.TERM_PROGRAM,Y=process.env.VSCODE_INJECTION,X=process.env.VSCODE_IPC_HOOK;if($==="vscode"||Y||X)return await this.detectVsCode();let Z=await this.detectVsCode();if(Z)return Z;return null}static async detectVsCode(){try{let{stdout:$}=await e5("code --version"),X=$.trim().split(`
1306
- `)[0]||"unknown",Z=[];try{let{stdout:Q}=await e5("code --list-extensions");Z=Q.trim().split(`
1307
- `).filter(Boolean)}catch{}return{name:"VS Code",version:X,extensions:Z}}catch{return null}}static isRunningInIdeTerminal(){let $=process.env.TERM_PROGRAM,Y=process.env.VSCODE_INJECTION,X=process.env.VSCODE_IPC_HOOK;return $==="vscode"||!!Y||!!X}}import{exec as IQ}from"child_process";import{promisify as kQ}from"util";var X6=kQ(IQ);class Z2{static async getInstalledIdes(){let $=[],Y=await this.checkVsCode();if(Y)$.push(Y);let X=await this.checkVsCodeInsiders();if(X)$.push(X);let Z=await this.checkCursor();if(Z)$.push(Z);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 X6(Y),{success:!0,message:"扩展安装成功"}}catch(X){return{success:!1,message:"安装失败: "+(X instanceof Error?X.message:"未知错误")}}}static async checkVsCode(){try{let{stdout:$}=await X6("code --version");return{id:"vscode",name:"VS Code",version:$.trim().split(`
1308
- `)[0]||"unknown"}}catch{return null}}static async checkVsCodeInsiders(){try{let{stdout:$}=await X6("code-insiders --version");return{id:"vscode-insiders",name:"VS Code Insiders",version:$.trim().split(`
1309
- `)[0]||"unknown"}}catch{return null}}static async checkCursor(){try{let{stdout:$}=await X6("cursor --version");return{id:"cursor",name:"Cursor",version:$.trim().split(`
1310
- `)[0]||"unknown"}}catch{return null}}}var $3=EQ(yQ(),".blade","ide-port");var k$="disconnected",G8=null,K8=null;function jQ(){switch(k$){case"connected":return{type:"info",content:`\uD83D\uDFE2 已连接到 ${G8||"IDE"} (端口: ${K8})`};case"connecting":return{type:"info",content:"\uD83D\uDFE1 正在连接..."};default:return{type:"error",content:"\uD83D\uDD34 未连接到 IDE"}}}function Y3(){try{if(vQ($3)){let $=MQ($3,"utf-8");return JSON.parse($)}}catch{}return null}function X3(){let $=process.env.BLADE_IDE_PORT;if($)return parseInt($,10);let Y=Y3();if(Y)return Y.port;return null}async function PQ(){let $=[],Y=jQ();$.push(Y.content),$.push(""),$.push("\uD83D\uDCE6 已安装的 IDE:");let X=await Z2.getInstalledIdes();if(X.length===0)$.push(" (未检测到支持的 IDE)");else for(let q of X)$.push(` • ${q.name} ${q.version}`);$.push("");let Z=await q8.detectIde();if(Z){if($.push(`\uD83D\uDDA5️ 当前环境: ${Z.name} ${Z.version}`),Z.extensions.length>0)$.push(` 已安装扩展: ${Z.extensions.length} 个`)}let Q=X3(),J=Y3();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(`
1311
- `)}async function SQ(){let $=X3();if(!$)return`❌ 未检测到 IDE 端口
1301
+ \`\`\``);try{await F3($,W),Y("✅ 提交成功!")}catch(O){let U=O instanceof Error?O.message:"未知错误";return Y(`❌ 提交失败: ${U}`),{success:!1,error:U}}return{success:!0}}var L3=xQ;import{existsSync as rQ,readFileSync as aQ}from"fs";import{homedir as nQ}from"os";import{join as oQ}from"path";import{exec as dQ}from"child_process";import{promisify as cQ}from"util";var w3=cQ(dQ);class z8{static async detectIde(){let $=process.env.TERM_PROGRAM,Y=process.env.VSCODE_INJECTION,X=process.env.VSCODE_IPC_HOOK;if($==="vscode"||Y||X)return await this.detectVsCode();let Z=await this.detectVsCode();if(Z)return Z;return null}static async detectVsCode(){try{let{stdout:$}=await w3("code --version"),X=$.trim().split(`
1302
+ `)[0]||"unknown",Z=[];try{let{stdout:Q}=await w3("code --list-extensions");Z=Q.trim().split(`
1303
+ `).filter(Boolean)}catch{}return{name:"VS Code",version:X,extensions:Z}}catch{return null}}static isRunningInIdeTerminal(){let $=process.env.TERM_PROGRAM,Y=process.env.VSCODE_INJECTION,X=process.env.VSCODE_IPC_HOOK;return $==="vscode"||!!Y||!!X}}import{exec as lQ}from"child_process";import{promisify as iQ}from"util";var W6=iQ(lQ);class O2{static async getInstalledIdes(){let $=[],Y=await this.checkVsCode();if(Y)$.push(Y);let X=await this.checkVsCodeInsiders();if(X)$.push(X);let Z=await this.checkCursor();if(Z)$.push(Z);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 W6(Y),{success:!0,message:"扩展安装成功"}}catch(X){return{success:!1,message:"安装失败: "+(X instanceof Error?X.message:"未知错误")}}}static async checkVsCode(){try{let{stdout:$}=await W6("code --version");return{id:"vscode",name:"VS Code",version:$.trim().split(`
1304
+ `)[0]||"unknown"}}catch{return null}}static async checkVsCodeInsiders(){try{let{stdout:$}=await W6("code-insiders --version");return{id:"vscode-insiders",name:"VS Code Insiders",version:$.trim().split(`
1305
+ `)[0]||"unknown"}}catch{return null}}static async checkCursor(){try{let{stdout:$}=await W6("cursor --version");return{id:"cursor",name:"Cursor",version:$.trim().split(`
1306
+ `)[0]||"unknown"}}catch{return null}}}var A3=oQ(nQ(),".blade","ide-port");var P$="disconnected",N8=null,B8=null;function sQ(){switch(P$){case"connected":return{type:"info",content:`\uD83D\uDFE2 已连接到 ${N8||"IDE"} (端口: ${B8})`};case"connecting":return{type:"info",content:"\uD83D\uDFE1 正在连接..."};default:return{type:"error",content:"\uD83D\uDD34 未连接到 IDE"}}}function R3(){try{if(rQ(A3)){let $=aQ(A3,"utf-8");return JSON.parse($)}}catch{}return null}function b3(){let $=process.env.BLADE_IDE_PORT;if($)return parseInt($,10);let Y=R3();if(Y)return Y.port;return null}async function tQ(){let $=[],Y=sQ();$.push(Y.content),$.push(""),$.push("\uD83D\uDCE6 已安装的 IDE:");let X=await O2.getInstalledIdes();if(X.length===0)$.push(" (未检测到支持的 IDE)");else for(let q of X)$.push(` • ${q.name} ${q.version}`);$.push("");let Z=await z8.detectIde();if(Z){if($.push(`\uD83D\uDDA5️ 当前环境: ${Z.name} ${Z.version}`),Z.extensions.length>0)$.push(` 已安装扩展: ${Z.extensions.length} 个`)}let Q=b3(),J=R3();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(`
1307
+ `)}async function eQ(){let $=b3();if(!$)return`❌ 未检测到 IDE 端口
1312
1308
 
1313
1309
  请确保:
1314
1310
  1. 已在 VS Code 中安装 Blade Code 插件
@@ -1316,25 +1312,25 @@ ${W}
1316
1312
  3. 在 VS Code 终端中运行 blade
1317
1313
 
1318
1314
  或手动设置端口:
1319
- export BLADE_IDE_PORT=9527`;k$="connecting";try{let X=new(await import("ws")).default(`ws://127.0.0.1:${$}`);return await new Promise((Z,Q)=>{let J=setTimeout(()=>{X.close(),Q(Error("连接超时"))},5000);X.on("open",()=>{clearTimeout(J),k$="connected",K8=$,G8="VS Code",X.close(),Z()}),X.on("error",(q)=>{clearTimeout(J),Q(q)})}),`✅ 成功连接到 IDE (端口: ${$})
1315
+ export BLADE_IDE_PORT=9527`;P$="connecting";try{let X=new(await import("ws")).default(`ws://127.0.0.1:${$}`);return await new Promise((Z,Q)=>{let J=setTimeout(()=>{X.close(),Q(Error("连接超时"))},5000);X.on("open",()=>{clearTimeout(J),P$="connected",B8=$,N8="VS Code",X.close(),Z()}),X.on("error",(q)=>{clearTimeout(J),Q(q)})}),`✅ 成功连接到 IDE (端口: ${$})
1320
1316
 
1321
1317
  现在可以使用以下功能:
1322
1318
  • 在 IDE 中打开文件
1323
1319
  • 获取当前选中的代码
1324
- • 查看打开的编辑器列表`}catch(Y){return k$="disconnected",`❌ 连接失败: ${Y instanceof Error?Y.message:"未知错误"}
1320
+ • 查看打开的编辑器列表`}catch(Y){return P$="disconnected",`❌ 连接失败: ${Y instanceof Error?Y.message:"未知错误"}
1325
1321
 
1326
1322
  请检查:
1327
1323
  1. VS Code 插件是否正在运行
1328
1324
  2. 端口 ${$} 是否正确
1329
- 3. 防火墙设置`}}async function TQ(){let $=[];if($.push("\uD83D\uDCE6 安装 Blade Code VS Code 插件"),$.push(""),!await Z2.isIdeInstalled("vscode"))return $.push("❌ 未检测到 VS Code"),$.push(""),$.push("请先安装 VS Code:"),$.push(" https://code.visualstudio.com/"),$.join(`
1325
+ 3. 防火墙设置`}}async function $J(){let $=[];if($.push("\uD83D\uDCE6 安装 Blade Code VS Code 插件"),$.push(""),!await O2.isIdeInstalled("vscode"))return $.push("❌ 未检测到 VS Code"),$.push(""),$.push("请先安装 VS Code:"),$.push(" https://code.visualstudio.com/"),$.join(`
1330
1326
  `);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(`
1331
- `)}async function CQ(){if(k$==="disconnected")return"⚠️ 当前未连接到任何 IDE";return k$="disconnected",G8=null,K8=null,"✅ 已断开与 IDE 的连接"}var fQ={name:"ide",aliases:[],description:"Manage IDE integrations and show status",usage:"/ide [status|connect|install|disconnect]",category:"system",async handler($,Y){let X=($[0]||"").toLowerCase(),Z;switch(X){case"":case"status":Z=await PQ();break;case"connect":Z=await SQ();break;case"install":Z=await TQ();break;case"disconnect":Z=await CQ();break;default:Z=`未知的子命令: ${X}
1327
+ `)}async function YJ(){if(P$==="disconnected")return"⚠️ 当前未连接到任何 IDE";return P$="disconnected",N8=null,B8=null,"✅ 已断开与 IDE 的连接"}var XJ={name:"ide",aliases:[],description:"Manage IDE integrations and show status",usage:"/ide [status|connect|install|disconnect]",category:"system",async handler($,Y){let X=($[0]||"").toLowerCase(),Z;switch(X){case"":case"status":Z=await tQ();break;case"connect":Z=await eQ();break;case"install":Z=await $J();break;case"disconnect":Z=await YJ();break;default:Z=`未知的子命令: ${X}
1332
1328
 
1333
1329
  可用命令:
1334
1330
  /ide status - 显示连接状态
1335
1331
  /ide connect - 连接到 IDE
1336
1332
  /ide install - 安装 VS Code 插件
1337
- /ide disconnect - 断开连接`}return{success:!0,message:Z}}},Z3=fQ;import{promises as J2}from"fs";import*as J3 from"path";function Q2($,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 X=Y.command;return`Bash(${X?X.substring(0,50):"command"}${X&&X.length>50?"...":""})`}case"Glob":return`Glob(${Y.pattern||"*"})`;case"Grep":{let{pattern:X,path:Z}=Y;if(Z)return`Grep("${X}" in ${Z})`;return`Grep("${X}")`}case"WebFetch":{let X=Y.url;if(X)try{return`WebFetch(${new URL(X).hostname})`}catch{return`WebFetch(${X.substring(0,30)}${X.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 Q3($,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}}var hQ={name:"init",description:"分析当前项目并生成 BLADE.md 配置文件",usage:"/init",async handler($,Y){try{let{cwd:X}=Y,Z=o().addAssistantMessage,Q=o().addToolMessage,J=s().session.sessionId,q=J3.join(X,"BLADE.md"),G=!1,K=!1;try{if(G=(await J2.stat(q)).isFile(),G)K=(await J2.readFile(q,"utf-8")).trim().length===0}catch{G=!1}if(G&&!K){Z("⚠️ BLADE.md 已存在。"),Z("\uD83D\uDCA1 正在分析现有文件并提供改进建议...");let H=await v0.create(),_=`Please analyze the existing BLADE.md file and provide improvement suggestions.
1333
+ /ide disconnect - 断开连接`}return{success:!0,message:Z}}},V3=XJ;import{promises as _2}from"fs";import*as D3 from"path";function H2($,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 X=Y.command;return`Bash(${X?X.substring(0,50):"command"}${X&&X.length>50?"...":""})`}case"Glob":return`Glob(${Y.pattern||"*"})`;case"Grep":{let{pattern:X,path:Z}=Y;if(Z)return`Grep("${X}" in ${Z})`;return`Grep("${X}")`}case"WebFetch":{let X=Y.url;if(X)try{return`WebFetch(${new URL(X).hostname})`}catch{return`WebFetch(${X.substring(0,30)}${X.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 I3($,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}}var ZJ={name:"init",description:"分析当前项目并生成 BLADE.md 配置文件",usage:"/init",async handler($,Y){try{let{cwd:X}=Y,Z=t().addAssistantMessage,Q=t().addToolMessage,J=o().session.sessionId,q=D3.join(X,"BLADE.md"),G=!1,K=!1;try{if(G=(await _2.stat(q)).isFile(),G)K=(await _2.readFile(q,"utf-8")).trim().length===0}catch{G=!1}if(G&&!K){Z("⚠️ BLADE.md 已存在。"),Z("\uD83D\uDCA1 正在分析现有文件并提供改进建议...");let H=await k0.create(),_=`Please analyze the existing BLADE.md file and provide improvement suggestions.
1338
1334
 
1339
1335
  **Important**:
1340
1336
  - After each step, briefly describe what you found before proceeding
@@ -1361,7 +1357,7 @@ ${W}
1361
1357
  - 具体的改进建议(附带示例)
1362
1358
  - 如果需要重大修改,提供完整的改进版本内容
1363
1359
 
1364
- **Final output**: Return your analysis and suggestions as plain text. Do NOT use Write tool.`,z=await H.chat(_,{messages:[],userId:"cli-user",sessionId:J||"init-session",workspaceRoot:X},{onToolStart:(F)=>{if(F.type!=="function")return;try{let L=JSON.parse(F.function.arguments),w=Q2(F.function.name,L);Q(w,{toolName:F.function.name,phase:"start",summary:w,params:L})}catch{}},onToolResult:async(F,L)=>{if(F.type!=="function")return;if(L?.metadata?.summary)Q(L.metadata.summary,{toolName:F.function.name,phase:"complete",summary:L.metadata.summary})}});return Z(z),{success:!0,message:"✅ 分析完成"}}if(K)Z("⚠️ 检测到空的 BLADE.md 文件,将重新生成...");Z("\uD83D\uDD0D 正在分析项目结构...");let W=await v0.create(),O=`Please analyze this codebase and generate BLADE.md content.
1360
+ **Final output**: Return your analysis and suggestions as plain text. Do NOT use Write tool.`,z=await H.chat(_,{messages:[],userId:"cli-user",sessionId:J||"init-session",workspaceRoot:X},{onToolStart:(F)=>{if(F.type!=="function")return;try{let B=JSON.parse(F.function.arguments),L=H2(F.function.name,B);Q(L,{toolName:F.function.name,phase:"start",summary:L,params:B})}catch{}},onToolResult:async(F,B)=>{if(F.type!=="function")return;if(B?.metadata?.summary)Q(B.metadata.summary,{toolName:F.function.name,phase:"complete",summary:B.metadata.summary})}});return Z(z),{success:!0,message:"✅ 分析完成"}}if(K)Z("⚠️ 检测到空的 BLADE.md 文件,将重新生成...");Z("\uD83D\uDD0D 正在分析项目结构...");let W=await k0.create(),O=`Please analyze this codebase and generate BLADE.md content.
1365
1361
 
1366
1362
  **Important**: After each step, briefly describe what you found before proceeding.
1367
1363
 
@@ -1394,7 +1390,7 @@ ${W}
1394
1390
  - Focus on non-obvious insights
1395
1391
  - Be concise but comprehensive
1396
1392
 
1397
- **Final output**: Return ONLY the complete BLADE.md content (markdown format), ready to be written to the file.`,U=await W.chat(O,{messages:[],userId:"cli-user",sessionId:J||"init-session",workspaceRoot:X},{onToolStart:(H)=>{if(H.type!=="function")return;try{let _=JSON.parse(H.function.arguments),z=Q2(H.function.name,_);Q(z,{toolName:H.function.name,phase:"start",summary:z,params:_})}catch{}},onToolResult:async(H,_)=>{if(H.type!=="function")return;if(_?.metadata?.summary)Q(_.metadata.summary,{toolName:H.function.name,phase:"complete",summary:_.metadata.summary})}});if(!U||U.trim().length===0)throw Error("Agent 未能生成有效的 BLADE.md 内容");return Z("✨ 正在写入 BLADE.md..."),await J2.writeFile(q,U,"utf-8"),{success:!0,message:"✅ 已成功生成 BLADE.md 文件"}}catch(X){return{success:!1,error:`初始化失败: ${X instanceof Error?X.message:"未知错误"}`}}}},q3=hQ;var xQ={name:"model",description:"管理和切换模型配置",usage:"/model [子命令] [参数]",fullDescription:`
1393
+ **Final output**: Return ONLY the complete BLADE.md content (markdown format), ready to be written to the file.`,U=await W.chat(O,{messages:[],userId:"cli-user",sessionId:J||"init-session",workspaceRoot:X},{onToolStart:(H)=>{if(H.type!=="function")return;try{let _=JSON.parse(H.function.arguments),z=H2(H.function.name,_);Q(z,{toolName:H.function.name,phase:"start",summary:z,params:_})}catch{}},onToolResult:async(H,_)=>{if(H.type!=="function")return;if(_?.metadata?.summary)Q(_.metadata.summary,{toolName:H.function.name,phase:"complete",summary:_.metadata.summary})}});if(!U||U.trim().length===0)throw Error("Agent 未能生成有效的 BLADE.md 内容");return Z("✨ 正在写入 BLADE.md..."),await _2.writeFile(q,U,"utf-8"),{success:!0,message:"✅ 已成功生成 BLADE.md 文件"}}catch(X){return{success:!1,error:`初始化失败: ${X instanceof Error?X.message:"未知错误"}`}}}},v3=ZJ;var QJ={name:"model",description:"管理和切换模型配置",usage:"/model [子命令] [参数]",fullDescription:`
1398
1394
  管理和切换模型配置
1399
1395
 
1400
1396
  子命令:
@@ -1406,11 +1402,11 @@ ${W}
1406
1402
  /model # 显示模型选择器
1407
1403
  /model add # 添加新模型
1408
1404
  /model remove 千问 # 删除名称包含"千问"的模型
1409
- `,async handler($,Y){let X=$[0];if(!X){if(c$().length===0)return{success:!1,message:`❌ 没有可用的模型配置
1405
+ `,async handler($,Y){let X=$[0];if(!X){if(e$().length===0)return{success:!1,message:`❌ 没有可用的模型配置
1410
1406
 
1411
1407
  使用 /model add 添加模型`};return{success:!0,message:"show_model_selector",data:{action:"show_model_selector"}}}switch(X){case"add":return{success:!0,message:"show_model_add_wizard",data:{action:"show_model_add_wizard",mode:"add"}};case"remove":{let Z=$.slice(1).join(" ");if(!Z)return{success:!1,message:`❌ 请指定要删除的模型名称
1412
- 用法: /model remove <名称>`};let J=c$().find((q)=>q.name.toLowerCase().includes(Z.toLowerCase()));if(!J)return{success:!1,message:`❌ 未找到匹配的模型配置: ${Z}`};try{return await e().removeModel(J.id),{success:!0,message:`✅ 已删除模型配置: ${J.name}`}}catch(q){return{success:!1,message:`❌ ${q.message}`}}}default:return{success:!1,message:`❌ 未知的子命令: ${X}
1413
- 使用 /model 查看可用操作`}}}},G3=xQ;async function pQ($,Y){return{success:!0,message:"show_theme_selector",data:{action:"show_theme_selector"}}}var gQ={name:"theme",description:"打开交互式主题选择器",aliases:["themes","style"],usage:"/theme",examples:["/theme"],category:"ui",handler:pQ},K3=gQ;var Z6={...c5,init:q3,theme:K3,permissions:e2,model:G3,git:t5,ide:Z3};function W3($){return $.trim().startsWith("/")}function uQ($){let Y=$.trim();if(!Y.startsWith("/"))throw Error("不是有效的 slash command");let X=Y.slice(1).split(/\s+/),Z=X[0]||"",Q=X.slice(1);return{command:Z,args:Q}}function dQ($){if(Z6[$])return Z6[$];for(let Y of Object.values(Z6))if(Y.aliases?.includes($))return Y;return}async function U3($,Y){try{let{command:X,args:Z}=uQ($),Q=dQ(X);if(!Q)return{success:!1,error:`未知命令: /${X}\\n使用 /help 查看可用命令`};return await Q.handler(Z,Y)}catch(X){return{success:!1,error:`命令执行失败: ${X instanceof Error?X.message:"未知错误"}`}}}function O3($){let Y=($.startsWith("/")?$.slice(1):$).trim(),X=Object.values(Z6).map((q)=>({name:q.name,description:q.description,aliases:q.aliases||[],command:q}));if(!Y)return X.map((q)=>({command:`/${q.name}`,description:q.description,matchScore:50}));return new mQ(X,{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)}import{useMemoizedFn as H3}from"ahooks";import{useRef as cQ}from"react";function _3($){let Y=cQ(void 0),X=H3(async()=>{let Q=await v0.create({systemPrompt:$.systemPrompt,appendSystemPrompt:$.appendSystemPrompt,maxTurns:$.maxTurns});return Y.current=Q,Q}),Z=H3(()=>{if(Y.current)Y.current=void 0});return{agentRef:Y,createAgent:X,cleanupAgent:Z}}var rQ=Y0("UI");function aQ($,Y,X){switch($){case"show_theme_selector":return X.setActiveModal("themeSelector"),!0;case"show_model_selector":return X.setActiveModal("modelSelector"),!0;case"show_model_add_wizard":return X.setActiveModal("modelAddWizard"),!0;case"show_permissions_manager":return X.setActiveModal("permissionsManager"),!0;case"show_agents_manager":return X.setActiveModal("agentsManager"),!0;case"show_agent_creation_wizard":return X.setActiveModal("agentCreationWizard"),!0;case"show_session_selector":{let Z=Y?.sessions;return X.showSessionSelector(Z),!0}case"exit_application":return process.exit(0),!0;default:return!1}}var F3=($,Y,X,Z)=>{let Q=T5(),J=o2(),q=A5(),G=I$(),K=V$(),W=D$(),O=C5(),U=iQ(!1),{createAgent:H,cleanupAgent:_}=_3({systemPrompt:$,appendSystemPrompt:Y,maxTurns:Z});lQ(()=>{return()=>{_()}},[_]);let z=W8(()=>{if(!Q)return;if(!U.current)K.addAssistantMessage("✋ 任务已停止"),U.current=!0;O.abort(),W.setTodos([])}),F=W8(async(w)=>{try{if(K.addUserMessage(w),W3(w)){await b2();let B={cwd:process.cwd()},D=await U3(w,B);if(D.message){if(aQ(D.message,D.data,W))return{success:!0}}if(!D.success&&D.error)return K.addAssistantMessage(`❌ ${D.error}`),{success:D.success,output:D.message,error:D.error,metadata:D.data};let C=D.message;if(D.success&&typeof C==="string"&&C.trim()!=="")K.addAssistantMessage(C);return{success:D.success,output:D.message,error:D.error,metadata:D.data}}let N=await H(),A=O.createAbortController(),b={messages:J.map((B)=>({role:B.role,content:B.content})),userId:"cli-user",sessionId:q,workspaceRoot:process.cwd(),signal:A.signal,confirmationHandler:X,permissionMode:G},y={onContent:(B)=>{if(B.trim())K.addAssistantMessage(B)},onToolStart:(B)=>{if(B.type!=="function")return;if(B.function.name==="TodoWrite")return;try{let D=JSON.parse(B.function.arguments),C=Q2(B.function.name,D);K.addToolMessage(C,{toolName:B.function.name,phase:"start",summary:C,params:D})}catch(D){rQ.error("[useCommandHandler] onToolStart error:",D)}},onToolResult:async(B,D)=>{if(B.type!=="function")return;if(!D?.metadata?.summary)return;let C=Q3(B.function.name,D)?D.displayContent:void 0;K.addToolMessage(D.metadata.summary,{toolName:B.function.name,phase:"complete",summary:D.metadata.summary,detail:C})},onTokenUsage:(B)=>{K.updateTokenUsage(B)},onCompacting:(B)=>{K.setCompacting(B)}},R=await N.chat(w,b,y);if(!R||R.trim()==="")return{success:!0,output:"任务已停止"};return{success:!0,output:R}}catch(N){let A=N instanceof Error?N.message:"未知错误",b={success:!1,error:A};return K.addAssistantMessage(`❌ ${A}`),b}}),L=W8(async(w)=>{if(!w.trim())return;let N=w.trim();if(Q){O.enqueueCommand(N);return}W.setTodos([]),U.current=!1,O.setProcessing(!0),K.setThinking(!0);try{let A=await F(N);if(!A.success&&A.error)K.setError(A.error)}catch(A){if(A instanceof Error&&(A.name==="AbortError"||A.message.includes("aborted")));else{let b=A instanceof Error?A.message:"未知错误";K.setError(`执行失败: ${b}`)}}finally{O.setProcessing(!1),K.setThinking(!1),O.clearAbortController();let A=O.dequeueCommand();if(A)setTimeout(()=>L(A),100)}});return{executeCommand:L,handleAbort:z,isProcessing:Q}};import{useMemoizedFn as Q6}from"ahooks";import{useState as z3}from"react";var N3=()=>{let[$,Y]=z3([]),[X,Z]=z3(-1),Q=Q6((K)=>{Y((W)=>[...W,K]),Z(-1)}),J=Q6(()=>{if($.length===0)return"";let K=X===-1?$.length-1:Math.max(0,X-1);return Z(K),$[K]||""}),q=Q6(()=>{if(X===-1)return"";let K=X+1;if(K>=$.length)return Z(-1),"";else return Z(K),$[K]||""}),G=Q6(()=>{Z(-1)});return{commandHistory:$,historyIndex:X,addToHistory:Q,getPreviousCommand:J,getNextCommand:q,resetHistoryIndex:G}};import{useMemoizedFn as B3}from"ahooks";import{useMemo as nQ,useState as oQ}from"react";var L3=()=>{let[$,Y]=oQ({isVisible:!1,details:null,resolver:null}),X=B3((J)=>{return new Promise((q)=>{Y({isVisible:!0,details:J,resolver:q})})}),Z=B3((J)=>{if($.resolver)$.resolver(J);Y({isVisible:!1,details:null,resolver:null})}),Q=nQ(()=>({requestConfirmation:X}),[X]);return{confirmationState:$,confirmationHandler:Q,handleResponse:Z}};import{useMemoizedFn as U8}from"ahooks";import{useState as sQ}from"react";function w3($="",Y=0){let[X,Z]=sQ({value:$,cursorPosition:Y}),Q=U8((G)=>{Z((K)=>({value:G,cursorPosition:K.cursorPosition}))}),J=U8((G)=>{Z((K)=>({...K,cursorPosition:Math.max(0,Math.min(G,K.value.length))}))}),q=U8(()=>{Z({value:"",cursorPosition:0})});return{value:X.value,cursorPosition:X.cursorPosition,setValue:Q,setCursorPosition:J,clear:q}}import{useMemoizedFn as I3}from"ahooks";import{useInput as QJ}from"ink";import{useEffect as k3,useRef as v3,useState as F8}from"react";import{useMemoizedFn as eB}from"ahooks";import tQ from"fast-glob";import eQ from"fuse.js";import{useEffect as A3,useMemo as O8,useState as H8}from"react";var v$=null,$J=5000;function YJ($,Y){let X=[...$.matchAll(/(?:^|\s)(@(?:"[^"]*"|(?:[^\\ ]|\\ )*))/g)];for(let Z of X){let Q=Z[1],J=Z.index+(Z[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 XJ=[...z1.map(($)=>`${$}/**`),...z1,...q4.map(($)=>`**/${$}`)];function R3($,Y,X={}){let{cwd:Z=process.cwd(),maxSuggestions:Q=15,ignorePatterns:J=XJ,debounceDelay:q=300,fuzzyMatch:G=!0}=X,[K,W]=H8([]),[O,U]=H8(!1),[H,_]=H8(0),z=O8(()=>JSON.stringify(J),[J]),F=O8(()=>{if(Y===void 0)return{hasQuery:!1,query:"",startIndex:-1,endIndex:-1,quoted:!1};return YJ($,Y)},[$,Y]);A3(()=>{if(!$.includes("@")){W([]),U(!1);return}let w=Date.now();if(v$&&v$.cwd===Z&&v$.ignoreKey===z&&w-v$.timestamp<$J){W(v$.files),U(!1);return}let N=!1,b=setTimeout(async()=>{U(!0);try{let R=(await tQ("**/*",{cwd:Z,dot:!1,followSymbolicLinks:!1,onlyFiles:!1,markDirectories:!0,unique:!0,ignore:J})).map((B)=>B.replace(/\\/g,"/"));if(!N)W(R),v$={cwd:Z,ignoreKey:z,files:R,timestamp:w}}catch(y){if(console.error("Failed to load files for @ completion:",y),!N)W([])}finally{if(!N)U(!1)}},q);return()=>{N=!0,clearTimeout(b)}},[$,Z,q,z]);let L=O8(()=>{if(!F.hasQuery||K.length===0)return[];let w=F.query.toLowerCase();if(w==="")return K.slice(0,Q);if(G)return new eQ(K,{threshold:0.4,ignoreLocation:!0,minMatchCharLength:1}).search(w).slice(0,Q).map((b)=>b.item);return K.filter((N)=>N.toLowerCase().includes(w)).slice(0,Q)},[F,K,Q,G]);return A3(()=>{_(0)},[L]),{...F,suggestions:L,selectedIndex:H,loading:O}}function ZJ($,Y=!1){if($.includes(" ")||Y)return`@"${$}"`;return`@${$}`}function _8($,Y,X){if(!Y.hasQuery)return{newInput:$,newCursorPos:$.length};let Z=ZJ(X,Y.quoted),Q=$.slice(0,Y.startIndex),J=$.slice(Y.endIndex),q=Q+Z+" "+J,G=Y.startIndex+Z.length+1;return{newInput:q,newCursorPos:G}}import{useMemoizedFn as b3}from"ahooks";import{useEffect as V3,useRef as D3}from"react";var b0=($,Y)=>{let X=D3(!1),Z=D3(null),Q=b3(()=>{if(Z.current)clearTimeout(Z.current);Z.current=setTimeout(()=>{X1().setAwaitingSecondCtrlC(!1),X.current=!1,Z.current=null},3000)}),J=()=>{a2().shutdown("SIGINT",0)},q=b3(()=>{if(!X.current){if(X.current=!0,$&&Y)Y();X1().setAwaitingSecondCtrlC(!0),Q()}else{if(Z.current)clearTimeout(Z.current),Z.current=null;X1().setAwaitingSecondCtrlC(!1),J()}});return V3(()=>{if($){if(X1().setAwaitingSecondCtrlC(!1),X.current=!1,Z.current)clearTimeout(Z.current),Z.current=null}},[$]),V3(()=>{return()=>{if(Z.current)clearTimeout(Z.current)}},[]),q};var J6=Y0("UI"),M3=($,Y,X,Z,Q,J,q,G,K,W)=>{let U=i0()==="main-input",H=$.value,_=$.setValue,z=$.cursorPosition,F=V$(),[L,w]=F8(!1),[N,A]=F8([]),[b,y]=F8(0),R=R3(H,z,{cwd:process.cwd(),maxSuggestions:10}),B=b0(q||!1,J),D=v3(0),C=500,p=v3(!1);k3(()=>{if(q)p.current=!1},[q]),k3(()=>{if(H.startsWith("/"))if(H.includes(" "))w(!1),A([]);else{let S=O3(H);A(S),w(S.length>0),y(0)}else if(R.hasQuery&&R.suggestions.length>0){let i=R.suggestions.map((S)=>({command:S,description:S.endsWith("/")?`Directory: ${S}`:`File: ${S}`,matchScore:1}));A(i),w(!0),y(0)}else w(!1),A([])},[H,R.hasQuery,R.suggestions]);let E=I3(()=>{F.clearMessages(),F.setError(null)}),M=I3(()=>{J6.debug("[DIAG] handleSubmit called:",{input:H,showSuggestions:L});let i=H.trim();if(i)J6.debug("[DIAG] Submitting command:",i),w(!1),A([]),Q(i),$.clear(),Y(i),J6.debug("[DIAG] Command submitted to onSubmit callback");else J6.debug("[DIAG] Empty command, not submitting")});return QJ((i,S)=>{if(i==="?"&&!H){K?.(),setTimeout(()=>$.clear(),0);return}if(S.backspace||S.delete||S.leftArrow||S.rightArrow||S.pageUp||S.pageDown||!S.ctrl&&!S.meta&&!S.escape&&!S.tab&&!S.upArrow&&!S.downArrow&&!S.return&&!(i==="?"&&!H))return;if(S.ctrl&&i==="c"||S.meta&&i==="c"||S.ctrl&&i==="d"||S.meta&&i==="d"){B();return}if(S.ctrl&&i==="l"||S.meta&&i==="l"){E();return}if(S.escape){if(W)K?.();else if(q&&J){if(p.current)return;p.current=!0,J()}else if(L)w(!1),A([]);else if(H){let Q0=Date.now();if(Q0-D.current<500)$.clear(),D.current=0;else D.current=Q0}return}if(S.tab&&S.shift){G?.();return}if(S.tab&&L&&N.length>0){let Q0=N[b].command;if(R.hasQuery&&R.suggestions.includes(Q0)){let{newInput:_0,newCursorPos:y1}=_8(H,R,Q0);_(_0),$.setCursorPosition(y1)}else{let _0=Q0+" ";_(_0),$.setCursorPosition(_0.length)}w(!1),A([]);return}if(S.return){if(L&&N.length>0){let Q0=N[b].command;if(R.hasQuery&&R.suggestions.includes(Q0)){let{newInput:_0,newCursorPos:y1}=_8(H,R,Q0);_(_0),$.setCursorPosition(y1)}else{let _0=Q0+" ";_(_0),$.setCursorPosition(_0.length)}w(!1),A([])}else M();return}if(S.upArrow){if(L&&N.length>0){let Q0=N.length-1;y((_0)=>_0>0?_0-1:Q0)}else{let Q0=X();if(Q0!=="")_(Q0),$.setCursorPosition(Q0.length)}return}if(S.downArrow){if(L&&N.length>0){let Q0=N.length-1;y((_0)=>_0<Q0?_0+1:0)}else{let Q0=Z();if(Q0!=="")_(Q0),$.setCursorPosition(Q0.length)}return}},{isActive:U}),{handleSubmit:M,showSuggestions:L,suggestions:N,selectedSuggestionIndex:b}};import{MultiSelect as JJ}from"@inkjs/ui";import{useMemoizedFn as q6}from"ahooks";import{Box as g,Text as f,useFocus as qJ,useFocusManager as GJ,useInput as j3}from"ink";import G6 from"ink-select-input";import KJ from"ink-spinner";import q2 from"ink-text-input";import y3 from"node:fs";import WJ from"node:os";import z8 from"node:path";import{useEffect as E3,useState as y$}from"react";import{jsxDEV as V}from"react/jsx-dev-runtime";var UJ=[{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"}],OJ=[{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 HJ($){if(!$||$.trim()==="")return"名称不能为空";if(!/^[a-z0-9-]+$/.test($))return"名称只能包含小写字母、数字和连字符";if($.startsWith("-")||$.endsWith("-"))return"名称不能以连字符开头或结尾";return null}function G2({onComplete:$,onCancel:Y,initialConfig:X}){let[Z,Q]=y$(X?"name":"mode"),[J,q]=y$({name:X?.name||"",description:X?.description||"",tools:X?.tools||[],color:X?.color,location:X?.location||"project",systemPrompt:X?.systemPrompt||""}),[G,K]=y$(""),[W,O]=y$(!1),[U,H]=y$(""),[_,z]=y$(X?"edit":"manual"),{focus:F}=GJ(),w={manual:["mode","name","description","tools","color","location","systemPrompt","confirm"],ai:["mode","aiPrompt","aiGenerating","confirm"],edit:["name","description","tools","color","location","systemPrompt","confirm"]}[_];E3(()=>{if(Z==="name"||Z==="description"||Z==="systemPrompt"||Z==="aiPrompt")return;F(`step-${Z}`)},[Z,F]);let N=q6(()=>{let B=w.indexOf(Z);if(B<w.length-1)Q(w[B+1])}),A=q6(()=>{if(U)H("");if(Z==="confirm"&&_==="ai"){Q("aiPrompt");return}let B=w.indexOf(Z);if(B>0)Q(w[B-1]);else Y()}),b=q6(async()=>{O(!0),H("");try{let B=await v0.create(),D=`你是一个 Subagent 配置生成专家。用户会描述他们想要创建的 agent,你需要根据描述生成一个完整的 agent 配置。
1408
+ 用法: /model remove <名称>`};let J=e$().find((q)=>q.name.toLowerCase().includes(Z.toLowerCase()));if(!J)return{success:!1,message:`❌ 未找到匹配的模型配置: ${Z}`};try{return await W0().removeModel(J.id),{success:!0,message:`✅ 已删除模型配置: ${J.name}`}}catch(q){return{success:!1,message:`❌ ${q.message}`}}}default:return{success:!1,message:`❌ 未知的子命令: ${X}
1409
+ 使用 /model 查看可用操作`}}}},M3=QJ;async function JJ($,Y){return{success:!0,message:"show_theme_selector",data:{action:"show_theme_selector"}}}var qJ={name:"theme",description:"打开交互式主题选择器",aliases:["themes","style"],usage:"/theme",examples:["/theme"],category:"ui",handler:JJ},k3=qJ;var U6={...U3,init:v3,theme:k3,permissions:q6,model:M3,git:L3,ide:V3};function y3($){return $.trim().startsWith("/")}function KJ($){let Y=$.trim();if(!Y.startsWith("/"))throw Error("不是有效的 slash command");let X=Y.slice(1).split(/\s+/),Z=X[0]||"",Q=X.slice(1);return{command:Z,args:Q}}function WJ($){if(U6[$])return U6[$];for(let Y of Object.values(U6))if(Y.aliases?.includes($))return Y;return}async function E3($,Y){try{let{command:X,args:Z}=KJ($),Q=WJ(X);if(!Q)return{success:!1,error:`未知命令: /${X}\\n使用 /help 查看可用命令`};return await Q.handler(Z,Y)}catch(X){return{success:!1,error:`命令执行失败: ${X instanceof Error?X.message:"未知错误"}`}}}function j3($){let Y=($.startsWith("/")?$.slice(1):$).trim(),X=Object.values(U6).map((q)=>({name:q.name,description:q.description,aliases:q.aliases||[],command:q}));if(!Y)return X.map((q)=>({command:`/${q.name}`,description:q.description,matchScore:50}));return new GJ(X,{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)}import{useMemoizedFn as P3}from"ahooks";import{useRef as UJ}from"react";function S3($){let Y=UJ(void 0),X=P3(async()=>{let Q=await k0.create({systemPrompt:$.systemPrompt,appendSystemPrompt:$.appendSystemPrompt,maxTurns:$.maxTurns});return Y.current=Q,Q}),Z=P3(()=>{if(Y.current)Y.current=void 0});return{agentRef:Y,createAgent:X,cleanupAgent:Z}}var _J=$0("UI");function FJ($,Y,X){switch($){case"show_theme_selector":return X.setActiveModal("themeSelector"),!0;case"show_model_selector":return X.setActiveModal("modelSelector"),!0;case"show_model_add_wizard":return X.setActiveModal("modelAddWizard"),!0;case"show_permissions_manager":return X.setActiveModal("permissionsManager"),!0;case"show_agents_manager":return X.setActiveModal("agentsManager"),!0;case"show_agent_creation_wizard":return X.setActiveModal("agentCreationWizard"),!0;case"show_session_selector":{let Z=Y?.sessions;return X.showSessionSelector(Z),!0}case"exit_application":return process.exit(0),!0;default:return!1}}var T3=($,Y,X,Z)=>{let Q=s5(),J=X6(),q=x5(),G=j$(),K=E$(),W=u1(),O=t5(),U=HJ(!1),{createAgent:H,cleanupAgent:_}=S3({systemPrompt:$,appendSystemPrompt:Y,maxTurns:Z});OJ(()=>{return()=>{_()}},[_]);let z=L8(()=>{if(!Q)return;if(!U.current)K.addAssistantMessage("✋ 任务已停止"),U.current=!0;O.abort(),W.setTodos([])}),F=L8(async(L)=>{try{if(K.addUserMessage(L),y3(L)){await y2();let w={cwd:process.cwd()},b=await E3(L,w);if(b.message){if(FJ(b.message,b.data,W))return{success:!0}}if(!b.success&&b.error)return K.addAssistantMessage(`❌ ${b.error}`),{success:b.success,output:b.message,error:b.error,metadata:b.data};let E=b.message;if(b.success&&typeof E==="string"&&E.trim()!=="")K.addAssistantMessage(E);return{success:b.success,output:b.message,error:b.error,metadata:b.data}}let N=await H(),A=O.createAbortController(),R={messages:J.map((w)=>({role:w.role,content:w.content})),userId:"cli-user",sessionId:q,workspaceRoot:process.cwd(),signal:A.signal,confirmationHandler:X,permissionMode:G},k={onThinking:(w)=>{K.setCurrentThinkingContent(w)},onContent:(w)=>{if(w.trim())K.addAssistantMessage(w),K.setCurrentThinkingContent(null)},onToolStart:(w)=>{if(w.type!=="function")return;if(w.function.name==="TodoWrite")return;try{let b=JSON.parse(w.function.arguments),E=H2(w.function.name,b);K.addToolMessage(E,{toolName:w.function.name,phase:"start",summary:E,params:b})}catch(b){_J.error("[useCommandHandler] onToolStart error:",b)}},onToolResult:async(w,b)=>{if(w.type!=="function")return;if(!b?.metadata?.summary)return;let E=I3(w.function.name,b)?b.displayContent:void 0;K.addToolMessage(b.metadata.summary,{toolName:w.function.name,phase:"complete",summary:b.metadata.summary,detail:E})},onTokenUsage:(w)=>{K.updateTokenUsage(w)},onCompacting:(w)=>{K.setCompacting(w)},onTurnLimitReached:X?async(w)=>{let b=await X.requestConfirmation({type:"maxTurnsExceeded",title:"对话轮次上限",message:`已进行 ${w.turnsCount} 轮对话。是否继续?`,risks:["继续执行可能导致更长的等待时间","可能产生更多的 API 费用"]});return{continue:b.approved,reason:b.reason}}:void 0},I=await N.chat(L,R,k);if(!I||I.trim()==="")return K.addAssistantMessage("⏹ 已取消"),{success:!0,output:"已取消"};return{success:!0,output:I}}catch(N){let A=N instanceof Error?N.message:"未知错误",R={success:!1,error:A};return K.addAssistantMessage(`❌ ${A}`),R}}),B=L8(async(L)=>{if(!L.trim())return;let N=L.trim();if(Q){O.enqueueCommand(N);return}W.setTodos([]),U.current=!1,O.setProcessing(!0),K.setThinking(!0);try{let A=await F(N);if(!A.success&&A.error)K.setError(A.error)}catch(A){if(A instanceof Error&&(A.name==="AbortError"||A.message.includes("aborted")));else{let R=A instanceof Error?A.message:"未知错误";K.setError(`执行失败: ${R}`)}}finally{O.setProcessing(!1),K.setThinking(!1),O.clearAbortController(),K.setCurrentThinkingContent(null);let A=O.dequeueCommand();if(A)setTimeout(()=>B(A),100)}});return{executeCommand:B,handleAbort:z,isProcessing:Q}};import{useMemoizedFn as O6}from"ahooks";import{useState as C3}from"react";var f3=()=>{let[$,Y]=C3([]),[X,Z]=C3(-1),Q=O6((K)=>{Y((W)=>[...W,K]),Z(-1)}),J=O6(()=>{if($.length===0)return"";let K=X===-1?$.length-1:Math.max(0,X-1);return Z(K),$[K]||""}),q=O6(()=>{if(X===-1)return"";let K=X+1;if(K>=$.length)return Z(-1),"";else return Z(K),$[K]||""}),G=O6(()=>{Z(-1)});return{commandHistory:$,historyIndex:X,addToHistory:Q,getPreviousCommand:J,getNextCommand:q,resetHistoryIndex:G}};import{useMemoizedFn as h3}from"ahooks";import{useMemo as zJ,useState as NJ}from"react";var x3=()=>{let[$,Y]=NJ({isVisible:!1,details:null,resolver:null}),X=h3((J)=>{return new Promise((q)=>{Y({isVisible:!0,details:J,resolver:q})})}),Z=h3((J)=>{if($.resolver)$.resolver(J);Y({isVisible:!1,details:null,resolver:null})}),Q=zJ(()=>({requestConfirmation:X}),[X]);return{confirmationState:$,confirmationHandler:Q,handleResponse:Z}};import{useMemoizedFn as w8}from"ahooks";import{useState as BJ}from"react";function p3($="",Y=0){let[X,Z]=BJ({value:$,cursorPosition:Y}),Q=w8((G)=>{Z((K)=>({value:G,cursorPosition:K.cursorPosition}))}),J=w8((G)=>{Z((K)=>({...K,cursorPosition:Math.max(0,Math.min(G,K.value.length))}))}),q=w8(()=>{Z({value:"",cursorPosition:0})});return{value:X.value,cursorPosition:X.cursorPosition,setValue:Q,setCursorPosition:J,clear:q}}import{useMemoizedFn as l3}from"ahooks";import{useInput as MJ}from"ink";import{useEffect as i3,useRef as r3,useState as V8}from"react";var LJ=[/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];function wJ($){return LJ.some((Y)=>Y.test($))}function AJ($){if($.supportsThinking!==void 0)return{supportsThinking:$.supportsThinking,thinkingBudget:$.thinkingBudget};return{supportsThinking:wJ($.model),thinkingBudget:void 0}}function H6($){return AJ($).supportsThinking}import{useMemoizedFn as jL}from"ahooks";import RJ from"fast-glob";import bJ from"fuse.js";import{useEffect as g3,useMemo as A8,useState as R8}from"react";var S$=null,VJ=5000;function IJ($,Y){let X=[...$.matchAll(/(?:^|\s)(@(?:"[^"]*"|(?:[^\\ ]|\\ )*))/g)];for(let Z of X){let Q=Z[1],J=Z.index+(Z[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 DJ=[...w1.map(($)=>`${$}/**`),...w1,...F4.map(($)=>`**/${$}`)];function m3($,Y,X={}){let{cwd:Z=process.cwd(),maxSuggestions:Q=15,ignorePatterns:J=DJ,debounceDelay:q=300,fuzzyMatch:G=!0}=X,[K,W]=R8([]),[O,U]=R8(!1),[H,_]=R8(0),z=A8(()=>JSON.stringify(J),[J]),F=A8(()=>{if(Y===void 0)return{hasQuery:!1,query:"",startIndex:-1,endIndex:-1,quoted:!1};return IJ($,Y)},[$,Y]);g3(()=>{if(!$.includes("@")){W([]),U(!1);return}let L=Date.now();if(S$&&S$.cwd===Z&&S$.ignoreKey===z&&L-S$.timestamp<VJ){W(S$.files),U(!1);return}let N=!1,R=setTimeout(async()=>{U(!0);try{let I=(await RJ("**/*",{cwd:Z,dot:!1,followSymbolicLinks:!1,onlyFiles:!1,markDirectories:!0,unique:!0,ignore:J})).map((w)=>w.replace(/\\/g,"/"));if(!N)W(I),S$={cwd:Z,ignoreKey:z,files:I,timestamp:L}}catch(k){if(console.error("Failed to load files for @ completion:",k),!N)W([])}finally{if(!N)U(!1)}},q);return()=>{N=!0,clearTimeout(R)}},[$,Z,q,z]);let B=A8(()=>{if(!F.hasQuery||K.length===0)return[];let L=F.query.toLowerCase();if(L==="")return K.slice(0,Q);if(G)return new bJ(K,{threshold:0.4,ignoreLocation:!0,minMatchCharLength:1}).search(L).slice(0,Q).map((R)=>R.item);return K.filter((N)=>N.toLowerCase().includes(L)).slice(0,Q)},[F,K,Q,G]);return g3(()=>{_(0)},[B]),{...F,suggestions:B,selectedIndex:H,loading:O}}function vJ($,Y=!1){if($.includes(" ")||Y)return`@"${$}"`;return`@${$}`}function b8($,Y,X){if(!Y.hasQuery)return{newInput:$,newCursorPos:$.length};let Z=vJ(X,Y.quoted),Q=$.slice(0,Y.startIndex),J=$.slice(Y.endIndex),q=Q+Z+" "+J,G=Y.startIndex+Z.length+1;return{newInput:q,newCursorPos:G}}import{useMemoizedFn as u3}from"ahooks";import{useEffect as d3,useRef as c3}from"react";var V0=($,Y)=>{let X=c3(!1),Z=c3(null),Q=u3(()=>{if(Z.current)clearTimeout(Z.current);Z.current=setTimeout(()=>{q1().setAwaitingSecondCtrlC(!1),X.current=!1,Z.current=null},3000)}),J=()=>{G$().shutdown("SIGINT",0)},q=u3(()=>{if(!X.current){if(X.current=!0,$&&Y)Y();q1().setAwaitingSecondCtrlC(!0),Q()}else{if(Z.current)clearTimeout(Z.current),Z.current=null;q1().setAwaitingSecondCtrlC(!1),J()}});return d3(()=>{if($){if(q1().setAwaitingSecondCtrlC(!1),X.current=!1,Z.current)clearTimeout(Z.current),Z.current=null}},[$]),d3(()=>{return()=>{if(Z.current)clearTimeout(Z.current)}},[]),q};var _6=$0("UI"),a3=($,Y,X,Z,Q,J,q,G,K,W)=>{let U=a0()==="main-input",H=$.value,_=$.setValue,z=$.cursorPosition,F=E$(),B=u1(),L=J6(),N=L?H6(L):!1,[A,R]=V8(!1),[k,I]=V8([]),[w,b]=V8(0),E=m3(H,z,{cwd:process.cwd(),maxSuggestions:10}),f=V0(q||!1,J),h=r3(0),v=500,m=r3(!1);i3(()=>{if(q)m.current=!1},[q]),i3(()=>{if(H.startsWith("/"))if(H.includes(" "))R(!1),I([]);else{let u=j3(H);I(u),R(u.length>0),b(0)}else if(E.hasQuery&&E.suggestions.length>0){let G0=E.suggestions.map((u)=>({command:u,description:u.endsWith("/")?`Directory: ${u}`:`File: ${u}`,matchScore:1}));I(G0),R(!0),b(0)}else R(!1),I([])},[H,E.hasQuery,E.suggestions]);let z1=l3(()=>{F.clearMessages(),F.setError(null)}),J0=l3(()=>{_6.debug("[DIAG] handleSubmit called:",{input:H,showSuggestions:A});let G0=H.trim();if(G0)_6.debug("[DIAG] Submitting command:",G0),R(!1),I([]),Q(G0),$.clear(),Y(G0),_6.debug("[DIAG] Command submitted to onSubmit callback");else _6.debug("[DIAG] Empty command, not submitting")});return MJ((G0,u)=>{if(G0==="?"&&!H){K?.(),setTimeout(()=>$.clear(),0);return}if(u.backspace||u.delete||u.leftArrow||u.rightArrow||u.pageUp||u.pageDown||!u.ctrl&&!u.meta&&!u.escape&&!u.tab&&!u.upArrow&&!u.downArrow&&!u.return&&!(G0==="?"&&!H))return;if(u.ctrl&&G0==="c"||u.meta&&G0==="c"||u.ctrl&&G0==="d"||u.meta&&G0==="d"){f();return}if(u.ctrl&&G0==="l"||u.meta&&G0==="l"){z1();return}if(u.ctrl&&G0==="t"||u.meta&&G0==="t"){F.toggleThinkingExpanded();return}if(u.escape){if(W)K?.();else if(q&&J){if(m.current)return;m.current=!0,J()}else if(A)R(!1),I([]);else if(H){let Y0=Date.now();if(Y0-h.current<500)$.clear(),h.current=0;else h.current=Y0}return}if(u.tab&&u.shift){G?.();return}if(u.tab){if(A&&k.length>0){let Y0=k[w].command;if(E.hasQuery&&E.suggestions.includes(Y0)){let{newInput:z0,newCursorPos:a1}=b8(H,E,Y0);_(z0),$.setCursorPosition(a1)}else{let z0=Y0+" ";_(z0),$.setCursorPosition(z0.length)}R(!1),I([])}else if(N)B.toggleThinkingMode();return}if(u.return){if(A&&k.length>0){let Y0=k[w].command;if(E.hasQuery&&E.suggestions.includes(Y0)){let{newInput:z0,newCursorPos:a1}=b8(H,E,Y0);_(z0),$.setCursorPosition(a1)}else{let z0=Y0+" ";_(z0),$.setCursorPosition(z0.length)}R(!1),I([])}else J0();return}if(u.upArrow){if(A&&k.length>0){let Y0=k.length-1;b((z0)=>z0>0?z0-1:Y0)}else{let Y0=X();if(Y0!=="")_(Y0),$.setCursorPosition(Y0.length)}return}if(u.downArrow){if(A&&k.length>0){let Y0=k.length-1;b((z0)=>z0<Y0?z0+1:0)}else{let Y0=Z();if(Y0!=="")_(Y0),$.setCursorPosition(Y0.length)}return}},{isActive:U}),{handleSubmit:J0,showSuggestions:A,suggestions:k,selectedSuggestionIndex:w}};import{MultiSelect as kJ}from"@inkjs/ui";import{useMemoizedFn as F6}from"ahooks";import{Box as p,Text as T,useFocus as yJ,useFocusManager as EJ,useInput as s3}from"ink";import z6 from"ink-select-input";import jJ from"ink-spinner";import F2 from"ink-text-input";import n3 from"node:fs";import PJ from"node:os";import I8 from"node:path";import{useEffect as o3,useState as C$}from"react";import{jsxDEV as V}from"react/jsx-dev-runtime";var SJ=[{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"}],TJ=[{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 CJ($){if(!$||$.trim()==="")return"名称不能为空";if(!/^[a-z0-9-]+$/.test($))return"名称只能包含小写字母、数字和连字符";if($.startsWith("-")||$.endsWith("-"))return"名称不能以连字符开头或结尾";return null}function z2({onComplete:$,onCancel:Y,initialConfig:X}){let[Z,Q]=C$(X?"name":"mode"),[J,q]=C$({name:X?.name||"",description:X?.description||"",tools:X?.tools||[],color:X?.color,location:X?.location||"project",systemPrompt:X?.systemPrompt||""}),[G,K]=C$(""),[W,O]=C$(!1),[U,H]=C$(""),[_,z]=C$(X?"edit":"manual"),{focus:F}=EJ(),L={manual:["mode","name","description","tools","color","location","systemPrompt","confirm"],ai:["mode","aiPrompt","aiGenerating","confirm"],edit:["name","description","tools","color","location","systemPrompt","confirm"]}[_];o3(()=>{if(Z==="name"||Z==="description"||Z==="systemPrompt"||Z==="aiPrompt")return;F(`step-${Z}`)},[Z,F]);let N=F6(()=>{let w=L.indexOf(Z);if(w<L.length-1)Q(L[w+1])}),A=F6(()=>{if(U)H("");if(Z==="confirm"&&_==="ai"){Q("aiPrompt");return}let w=L.indexOf(Z);if(w>0)Q(L[w-1]);else Y()}),R=F6(async()=>{O(!0),H("");try{let w=await k0.create(),b=`你是一个 Subagent 配置生成专家。用户会描述他们想要创建的 agent,你需要根据描述生成一个完整的 agent 配置。
1414
1410
 
1415
1411
  ## 可用工具列表
1416
1412
 
@@ -1447,7 +1443,7 @@ ${W}
1447
1443
  4. **color**: 选择一个合适的颜色用于 UI 区分
1448
1444
  5. **systemPrompt**: 详细说明 agent 的职责、使用的工具、输出格式等,使用 Markdown 格式
1449
1445
 
1450
- **重要**:请直接返回 JSON,不要添加任何额外的解释或文字。`,p=(await B.chatWithSystem(`你是一个 Subagent 配置生成专家。用户会描述他们想要创建的 agent,你需要根据描述生成一个完整的 agent 配置。
1446
+ **重要**:请直接返回 JSON,不要添加任何额外的解释或文字。`,f=(await w.chatWithSystem(`你是一个 Subagent 配置生成专家。用户会描述他们想要创建的 agent,你需要根据描述生成一个完整的 agent 配置。
1451
1447
 
1452
1448
  ## 可用工具列表
1453
1449
 
@@ -1484,26 +1480,28 @@ ${W}
1484
1480
  4. **color**: 选择一个合适的颜色用于 UI 区分
1485
1481
  5. **systemPrompt**: 详细说明 agent 的职责、使用的工具、输出格式等,使用 Markdown 格式
1486
1482
 
1487
- **重要**:请直接返回 JSON,不要添加任何额外的解释或文字。`,G)).trim(),E=p.match(/```(?:json)?\s*\n([\s\S]*?)\n```/);if(E)p=E[1];let M=JSON.parse(p);if(!M.name||!M.description||!M.systemPrompt)throw Error("Missing required fields: name, description, or systemPrompt");if(!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(M.name))throw Error("Invalid name format. Must be kebab-case (lowercase, numbers, hyphens only)");q({name:M.name,description:M.description,tools:Array.isArray(M.tools)?M.tools:[],color:M.color||"blue",location:"project",systemPrompt:M.systemPrompt}),Q("confirm")}catch(B){H(B instanceof Error?B.message:String(B))}finally{O(!1)}});E3(()=>{if(Z==="aiGenerating"&&!W&&!U)b()},[Z,W,U,b]);let y=q6(async()=>{try{let B=J.location==="project"?z8.join(process.cwd(),".blade","agents"):z8.join(WJ.homedir(),".blade","agents");await y3.promises.mkdir(B,{recursive:!0});let D=["---",`name: ${J.name}`,`description: ${J.description}`];if(J.tools.length>0&&!J.tools.includes("all")){D.push("tools:");for(let E of J.tools)D.push(` - ${E}`)}if(J.color)D.push(`color: ${J.color}`);D.push("---");let C=[D.join(`
1483
+ **重要**:请直接返回 JSON,不要添加任何额外的解释或文字。`,G)).trim(),h=f.match(/```(?:json)?\s*\n([\s\S]*?)\n```/);if(h)f=h[1];let v=JSON.parse(f);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(w){H(w instanceof Error?w.message:String(w))}finally{O(!1)}});o3(()=>{if(Z==="aiGenerating"&&!W&&!U)R()},[Z,W,U,R]);let k=F6(async()=>{try{let w=J.location==="project"?I8.join(process.cwd(),".blade","agents"):I8.join(PJ.homedir(),".blade","agents");await n3.promises.mkdir(w,{recursive:!0});let b=["---",`name: ${J.name}`,`description: ${J.description}`];if(J.tools.length>0&&!J.tools.includes("all")){b.push("tools:");for(let h of J.tools)b.push(` - ${h}`)}if(J.color)b.push(`color: ${J.color}`);b.push("---");let E=[b.join(`
1488
1484
  `),"",`# ${J.name} Subagent`,"",J.systemPrompt||"你是一个专门的代理,负责执行特定任务。",""].join(`
1489
- `),p=z8.join(B,`${J.name}.md`);await y3.promises.writeFile(p,C,"utf-8"),$()}catch(B){console.error("保存配置失败:",B)}}),R=b0(!1,Y);if(j3((B,D)=>{if(D.escape)A();else if(D.ctrl&&B==="c"||D.meta&&B==="c")R()},{isActive:Z!=="tools"}),Z==="mode")return V(g,{flexDirection:"column",paddingY:1,children:[V(g,{marginBottom:1,children:V(f,{bold:!0,color:"cyan",children:"\uD83C\uDFAF 选择创建方式"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(g,{marginBottom:1,children:V(f,{dimColor:!0,children:"你可以手动配置每个细节,或让 AI 根据你的描述自动生成配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(G6,{items:[{label:"\uD83E\uDD16 AI 智能生成 - 根据描述自动生成完整配置",value:"ai"},{label:"✍️ 手动配置 - 逐步配置每个选项",value:"manual"}],onSelect:(B)=>{if(B.value==="ai")z("ai"),Q("aiPrompt");else z("manual"),Q("name")}},void 0,!1,void 0,this),V(g,{marginTop:1,children:V(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(Z==="aiPrompt")return V(g,{flexDirection:"column",paddingY:1,children:[V(g,{marginBottom:1,children:V(f,{bold:!0,color:"cyan",children:"\uD83E\uDD16 AI 智能生成"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(g,{marginBottom:1,children:V(f,{dimColor:!0,children:'描述你想要创建的 Agent(例如:"一个专门用于代码审查的 agent,能够分析代码质量和潜在bug")'},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(g,{marginBottom:1,children:[V(f,{color:"green",children:"描述: "},void 0,!1,void 0,this),V(q2,{value:G,onChange:K,onSubmit:(B)=>{if(!B.trim())return;Q("aiGenerating")}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),V(g,{children:V(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(Z==="aiGenerating"){if(U)return V(g,{flexDirection:"column",paddingY:1,children:[V(g,{marginBottom:1,children:V(f,{bold:!0,color:"red",children:"❌ AI 生成失败"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(g,{marginBottom:1,children:V(f,{color:"red",children:U},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(g,{marginBottom:1,children:V(f,{dimColor:!0,children:"按 ESC 返回修改描述"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return V(g,{flexDirection:"column",paddingY:1,children:[V(g,{marginBottom:1,children:V(f,{bold:!0,color:"yellow",children:[V(KJ,{type:"dots"},void 0,!1,void 0,this)," AI 正在生成配置..."]},void 0,!0,void 0,this)},void 0,!1,void 0,this),V(g,{marginBottom:1,children:V(f,{dimColor:!0,children:['根据你的描述:"',G,'"']},void 0,!0,void 0,this)},void 0,!1,void 0,this),V(g,{marginBottom:1,children:V(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(Z==="name"){let B=_==="edit";return V(g,{flexDirection:"column",paddingY:1,children:[V(g,{marginBottom:1,children:V(f,{bold:!0,color:"cyan",children:["\uD83D\uDCDD Step 1/7: ",B?"Agent 名称(不可修改)":"输入 Agent 名称"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),V(g,{marginBottom:1,children:V(f,{dimColor:!0,children:B?"编辑模式下名称不可修改(修改名称相当于创建新 Agent)":"名称只能包含小写字母、数字和连字符(例如:code-reviewer)"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(g,{marginBottom:1,children:[V(f,{color:"green",children:"名称: "},void 0,!1,void 0,this),B?V(f,{children:J.name},void 0,!1,void 0,this):V(q2,{value:J.name,onChange:(D)=>q({...J,name:D}),onSubmit:(D)=>{if(HJ(D))return;N()}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),V(g,{children:V(f,{dimColor:!0,children:B?"按 Enter 继续 | ESC 返回":"按 Enter 继续 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this),B&&V(q2,{value:"",onChange:()=>{},onSubmit:N,showCursor:!1},"edit-mode-dummy-input",!1,void 0,this)]},void 0,!0,void 0,this)}if(Z==="description")return V(g,{flexDirection:"column",paddingY:1,children:[V(g,{marginBottom:1,children:V(f,{bold:!0,color:"cyan",children:"\uD83D\uDCDD Step 2/7: 输入描述信息"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(g,{marginBottom:1,children:V(f,{dimColor:!0,children:"简短描述这个 Agent 的用途和使用场景(这将帮助主 Agent 决定何时使用它)"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(g,{marginBottom:1,children:[V(f,{color:"green",children:"描述: "},void 0,!1,void 0,this),V(q2,{value:J.description,onChange:(B)=>q({...J,description:B}),onSubmit:(B)=>{if(!B.trim())return;N()}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),V(g,{children:V(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(Z==="tools")return V(_J,{config:J,setConfig:q,onNext:N,onPrev:A},void 0,!1,void 0,this);if(Z==="color")return V(g,{flexDirection:"column",paddingY:1,children:[V(g,{marginBottom:1,children:V(f,{bold:!0,color:"cyan",children:"\uD83C\uDFA8 Step 4/7: 选择背景颜色"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(g,{marginBottom:1,children:V(f,{dimColor:!0,children:"为 Agent 选择一个颜色标识(用于在 UI 中区分不同的 Agents)"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(G6,{items:OJ,onSelect:(B)=>{let D=B.value==="none"?void 0:B.value;q({...J,color:D}),N()}},void 0,!1,void 0,this),V(g,{marginTop:1,children:V(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(Z==="location")return V(g,{flexDirection:"column",paddingY:1,children:[V(g,{marginBottom:1,children:V(f,{bold:!0,color:"cyan",children:"\uD83D\uDCC2 Step 5/7: 选择保存位置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(g,{marginBottom:1,children:V(f,{dimColor:!0,children:"项目级配置仅在当前项目生效,用户级配置全局可用"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(G6,{items:[{label:"\uD83D\uDCC1 项目级 (.blade/agents/) - 仅当前项目",value:"project"},{label:"\uD83C\uDFE0 用户级 (~/.blade/agents/) - 全局可用",value:"user"}],onSelect:(B)=>{q({...J,location:B.value}),N()}},void 0,!1,void 0,this),V(g,{marginTop:1,children:V(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(Z==="systemPrompt")return V(g,{flexDirection:"column",paddingY:1,children:[V(g,{marginBottom:1,children:V(f,{bold:!0,color:"cyan",children:"\uD83D\uDCAC Step 6/7: 输入系统提示词"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(g,{marginBottom:1,children:V(f,{dimColor:!0,children:"定义 Agent 的行为和职责(可选,留空将使用默认提示)"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(g,{marginBottom:1,children:[V(f,{color:"green",children:"提示词: "},void 0,!1,void 0,this),V(q2,{value:J.systemPrompt,onChange:(B)=>q({...J,systemPrompt:B}),onSubmit:()=>N()},void 0,!1,void 0,this)]},void 0,!0,void 0,this),V(g,{children:V(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(Z==="confirm")return V(g,{flexDirection:"column",paddingY:1,children:[V(g,{marginBottom:1,children:V(f,{bold:!0,color:"cyan",children:"✅ Step 7/7: 确认配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(g,{flexDirection:"column",paddingLeft:2,marginBottom:1,children:[V(f,{children:[V(f,{bold:!0,color:"green",children:["名称:"," "]},void 0,!0,void 0,this),V(f,{children:J.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),V(f,{children:[V(f,{bold:!0,color:"green",children:["描述:"," "]},void 0,!0,void 0,this),V(f,{children:J.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this),V(f,{children:[V(f,{bold:!0,color:"green",children:["工具:"," "]},void 0,!0,void 0,this),V(f,{children:J.tools.includes("all")?"所有工具":J.tools.join(", ")||"所有工具"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),V(f,{children:[V(f,{bold:!0,color:"green",children:["颜色:"," "]},void 0,!0,void 0,this),V(f,{children:J.color||"默认"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),V(f,{children:[V(f,{bold:!0,color:"green",children:["位置:"," "]},void 0,!0,void 0,this),V(f,{children:J.location==="project"?"项目级":"用户级"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),V(f,{children:[V(f,{bold:!0,color:"green",children:["提示词:"," "]},void 0,!0,void 0,this),V(f,{children:J.systemPrompt||"(使用默认)"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),V(G6,{items:[{label:"✅ 确认并保存",value:"save"},{label:"⬅️ 返回上一步",value:"back"},{label:"❌ 取消",value:"cancel"}],onSelect:(B)=>{if(B.value==="save")y();else if(B.value==="back")A();else Y()}},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return null}function _J({config:$,setConfig:Y,onNext:X,onPrev:Z}){let{isFocused:Q}=qJ({id:"step-tools"});j3((q,G)=>{if(G.escape)Z()},{isActive:Q});let J=(q)=>{if(q.includes("all"))Y({...$,tools:["all"]});else Y({...$,tools:q});X()};return V(g,{flexDirection:"column",paddingY:1,children:[V(g,{marginBottom:1,children:V(f,{bold:!0,color:"cyan",children:"\uD83D\uDD27 Step 3/7: 选择可用工具"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(g,{marginBottom:1,children:V(f,{dimColor:!0,children:"方向键导航,空格切换勾选,Enter 确认进入下一步 | ESC 返回上一步"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(JJ,{options:UJ,defaultValue:$.tools,onSubmit:J},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{useMemoizedFn as K2}from"ahooks";import{Box as J0,Text as O0,useInput as FJ}from"ink";import N8 from"ink-select-input";import zJ from"node:fs";import{useMemo as NJ,useState as B8}from"react";import{jsxDEV as T}from"react/jsx-dev-runtime";function P3({initialMode:$="menu",onComplete:Y,onCancel:X}){let[Z,Q]=B8($),[J,q]=B8(null),[G,K]=B8(0),W=K2(()=>{N0.clear(),N0.loadFromStandardLocations(),K((N)=>N+1)}),O=NJ(()=>{return N0.getAllSubagents()},[G]),U=[{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"}],H=K2((N)=>{if(N.value==="cancel"){X?.();return}Q(N.value)}),_=K2((N)=>{if(q(N.value),Z==="edit")Q("editWizard");else if(Z==="delete")Q("deleteConfirm")}),z=K2(async()=>{if(!J?.configPath)return;try{await zJ.promises.unlink(J.configPath),W(),F()}catch(N){console.error("删除失败:",N)}}),F=K2(()=>{Q("menu"),q(null)}),L=b0(!1,X);if(FJ((N,A)=>{if(A.escape){if(Z==="menu")X?.();else if(Z==="list"||Z==="edit"||Z==="delete")F();else if(Z==="deleteConfirm")F()}else if(A.ctrl&&N==="c"||A.meta&&N==="c")L()},{isActive:Z!=="create"&&Z!=="editWizard"}),Z==="menu")return T(J0,{flexDirection:"column",paddingY:1,children:[T(J0,{marginBottom:1,children:T(O0,{bold:!0,color:"cyan",children:"\uD83D\uDCCB Agents 管理"},void 0,!1,void 0,this)},void 0,!1,void 0,this),T(N8,{items:U,onSelect:H},void 0,!1,void 0,this),T(J0,{marginTop:1,children:T(O0,{dimColor:!0,children:"使用方向键选择 | Enter 确认 | ESC 退出"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(Z==="list"){if(O.length===0)return T(J0,{flexDirection:"column",paddingY:1,children:[T(J0,{marginBottom:1,children:T(O0,{bold:!0,color:"cyan",children:"\uD83D\uDCCB 所有 Agents"},void 0,!1,void 0,this)},void 0,!1,void 0,this),T(J0,{paddingLeft:2,children:T(O0,{color:"gray",children:"❌ 没有找到任何 agent 配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),T(J0,{marginTop:1,paddingLeft:2,children:T(O0,{color:"gray",children:"\uD83D\uDCA1 配置文件位置: .blade/agents/ 或 ~/.blade/agents/"},void 0,!1,void 0,this)},void 0,!1,void 0,this),T(J0,{marginTop:1,paddingLeft:2,children:T(O0,{dimColor:!0,children:"按 ESC 返回菜单"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return T(J0,{flexDirection:"column",paddingY:1,children:[T(J0,{marginBottom:1,children:[T(O0,{bold:!0,color:"cyan",children:"\uD83D\uDCCB 所有 Agents"},void 0,!1,void 0,this),T(O0,{color:"gray",children:[" (找到 ",O.length," 个)"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),O.map((N)=>T(J0,{flexDirection:"column",paddingLeft:2,children:[T(J0,{children:T(O0,{children:[T(O0,{bold:!0,color:N.color||"white",children:["• ",N.name]},void 0,!0,void 0,this),T(O0,{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&&T(J0,{paddingLeft:2,children:T(O0,{color:"gray",children:["工具: ",N.tools.join(", ")]},void 0,!0,void 0,this)},void 0,!1,void 0,this),N.configPath&&T(J0,{paddingLeft:2,children:T(O0,{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)),T(J0,{marginTop:1,paddingLeft:2,children:T(O0,{dimColor:!0,children:"按 ESC 返回菜单"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}let w=(N)=>{if(O.length===0)return T(J0,{flexDirection:"column",paddingY:1,children:[T(J0,{marginBottom:1,children:T(O0,{bold:!0,color:"cyan",children:N},void 0,!1,void 0,this)},void 0,!1,void 0,this),T(J0,{paddingLeft:2,children:T(O0,{color:"gray",children:"❌ 没有找到任何 agent 配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),T(J0,{marginTop:1,paddingLeft:2,children:T(O0,{dimColor:!0,children:"按 ESC 返回菜单"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);let A=O.map((b)=>({key:b.name,label:`${b.name} - ${b.description}`,value:b}));return T(J0,{flexDirection:"column",paddingY:1,children:[T(J0,{marginBottom:1,children:T(O0,{bold:!0,color:"cyan",children:N},void 0,!1,void 0,this)},void 0,!1,void 0,this),T(N8,{items:A,onSelect:_},void 0,!1,void 0,this),T(J0,{marginTop:1,children:T(O0,{dimColor:!0,children:"使用方向键选择 | Enter 确认 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};if(Z==="create")return T(G2,{onComplete:()=>{W(),F()},onCancel:F},void 0,!1,void 0,this);if(Z==="edit")return w("✏️ 编辑 Agent");if(Z==="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 T(G2,{initialConfig:N,onComplete:()=>{W(),F()},onCancel:F},void 0,!1,void 0,this)}if(Z==="delete")return w("\uD83D\uDDD1️ 删除 Agent");if(Z==="deleteConfirm"&&J)return T(J0,{flexDirection:"column",paddingY:1,children:[T(J0,{marginBottom:1,children:T(O0,{bold:!0,color:"red",children:"⚠️ 确认删除"},void 0,!1,void 0,this)},void 0,!1,void 0,this),T(J0,{marginBottom:1,paddingLeft:2,children:T(O0,{children:["你确定要删除 Agent"," ",T(O0,{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),T(J0,{marginBottom:1,paddingLeft:2,children:T(O0,{dimColor:!0,children:["文件路径: ",J.configPath]},void 0,!0,void 0,this)},void 0,!1,void 0,this),T(J0,{marginBottom:1,paddingLeft:2,children:T(O0,{color:"red",children:"此操作无法撤销!"},void 0,!1,void 0,this)},void 0,!1,void 0,this),T(N8,{items:[{label:"\uD83D\uDDD1️ 确认删除",value:"confirm"},{label:"❌ 取消",value:"cancel"}],onSelect:(N)=>{if(N.value==="confirm")z();else F()}},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return null}import{Box as E$,Text as H0}from"ink";import LJ from"react";import{useEffect as BJ,useState as S3}from"react";function T3($=process.cwd(),Y=5000){let[X,Z]=S3(null),[Q,J]=S3(!0);return BJ(()=>{let q=!0,G=async()=>{try{let W=await X2($);if(!q)return;if(!W){Z(null),J(!1);return}let O=await i5($);if(!q)return;Z(O)}catch{if(q)Z(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:X,loading:Q}}import{jsxDEV as t,Fragment as K6}from"react/jsx-dev-runtime";var C3=LJ.memo(()=>{let $=t2(),Y=h1(),X=I$(),Q=s2()==="shortcuts",J=M5(),{branch:q}=T3(),G=j5(),K=b5(),W=R5(),U=(()=>{if(X==="default")return null;if(X==="autoEdit")return t(H0,{color:"magenta",children:["▶▶ auto edit on ",t(H0,{color:"gray",children:"(shift+tab to cycle)"},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(X==="plan")return t(H0,{color:"cyan",children:["‖ plan mode on ",t(H0,{color:"gray",children:"(shift+tab to cycle)"},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(X==="yolo")return t(H0,{color:"red",children:["⚡ yolo mode on ",t(H0,{color:"gray",children:"(all tools auto-approved)"},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return null})(),H=U!==null,_=[["Enter:发送","Shift+Enter:换行","Esc:中止"],["Shift+Tab:切换模式","↑/↓:历史","Tab:补全"],["Ctrl+A:行首","Ctrl+E:行尾","Ctrl+K:删到尾"],["Ctrl+U:删到首","Ctrl+W:删单词","Ctrl+C:退出"]];return t(E$,{flexDirection:"row",justifyContent:"space-between",paddingX:2,paddingY:0,children:[Q?t(E$,{flexDirection:"column",gap:0,children:_.map((z,F)=>t(E$,{flexDirection:"row",children:[z.map((L,w)=>{let[N,A]=L.split(":");return t(E$,{flexDirection:"row",width:20,children:[t(H0,{color:"yellow",children:N},void 0,!1,void 0,this),t(H0,{color:"gray",children:":"},void 0,!1,void 0,this),t(H0,{color:"white",children:A},void 0,!1,void 0,this)]},w,!0,void 0,this)}),F===_.length-1&&t(H0,{color:"cyan",children:" ? 关闭"},void 0,!1,void 0,this)]},F,!0,void 0,this))},void 0,!1,void 0,this):t(E$,{flexDirection:"row",gap:1,children:[q&&t(K6,{children:[t(H0,{color:"gray",children:[" ",q]},void 0,!0,void 0,this),t(H0,{color:"gray",children:"·"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),U,H&&t(H0,{color:"gray",children:"·"},void 0,!1,void 0,this),t(H0,{color:"gray",children:"? for shortcuts"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),t(E$,{flexDirection:"row",gap:1,children:!$?t(H0,{color:"red",children:"⚠ API 密钥未配置"},void 0,!1,void 0,this):t(K6,{children:[G&&t(H0,{color:"gray",children:G.model},void 0,!1,void 0,this),t(H0,{color:"gray",children:"·"},void 0,!1,void 0,this),W?t(H0,{color:"yellow",children:"压缩中..."},void 0,!1,void 0,this):t(H0,{color:K<20?"red":K<50?"yellow":"gray",children:[K,"%"]},void 0,!0,void 0,this),Y&&t(K6,{children:[t(H0,{color:"gray",children:"·"},void 0,!1,void 0,this),t(H0,{color:"yellow",children:"Processing..."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),J&&t(K6,{children:[t(H0,{color:"gray",children:"·"},void 0,!1,void 0,this),t(H0,{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 L8,Text as w8}from"ink";import wJ from"react";import{jsxDEV as j$}from"react/jsx-dev-runtime";var f3=wJ.memo(({suggestions:$,selectedIndex:Y,visible:X,maxDisplay:Z=8})=>{if(!X||$.length===0)return null;let Q=0,J=Math.min(Z,$.length),q=Y>=$.length;if(Y>=Z&&!q)Q=Y-Z+1,J=Y+1;let G=$.slice(Q,J),K=$.length>Z;return j$(L8,{flexDirection:"column",paddingX:2,paddingY:0,children:[G.map((W,O)=>{let H=Q+O===Y;return j$(L8,{justifyContent:"space-between",paddingX:1,children:[j$(w8,{color:H?"cyan":"white",bold:H,children:W.command},void 0,!1,void 0,this),j$(w8,{color:H?"cyan":"gray",dimColor:!H,children:W.description},void 0,!1,void 0,this)]},W.command,!0,void 0,this)}),K&&j$(L8,{paddingX:1,children:j$(w8,{color:q?"cyan":"gray",bold:q,dimColor:!q,children:["... and ",$.length-Z," more"]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)});import{Box as s0,Text as K1,useInput as Xq}from"ink";import Zq from"ink-select-input";import{useMemo as Qq}from"react";import{useEffect as AJ,useState as RJ}from"react";import{useStdout as bJ}from"ink";import{debounce as VJ}from"lodash-es";function P$($=200){let{stdout:Y}=bJ(),[X,Z]=RJ(Y.columns||80);return AJ(()=>{let Q=VJ(()=>{Z(Y.columns||80)},$);return Q(),Y.on("resize",Q),()=>{Y.off("resize",Q),Q.cancel()}},[Y,$]),X}import{Box as M0,Text as h0}from"ink";import H6 from"react";var DJ={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)"}},IJ={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)"}},kJ={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)"}},vJ={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)"}},MJ={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)"}},yJ={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)"}},EJ={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)"}},jJ={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)"}},PJ={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)"}},SJ={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)"}},TJ={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)"}},CJ={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)"}},fJ={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)"}},L1=[{id:"ayu-dark",label:"Ayu Dark",theme:DJ,tags:["dark","popular"]},{id:"dracula",label:"Dracula",theme:IJ,tags:["dark","popular"]},{id:"monokai",label:"Monokai",theme:kJ,tags:["dark","classic"]},{id:"nord",label:"Nord",theme:vJ,tags:["dark","minimal"]},{id:"solarized-light",label:"Solarized Light",theme:MJ,tags:["light"]},{id:"solarized-dark",label:"Solarized Dark",theme:yJ,tags:["dark"]},{id:"tokyo-night",label:"Tokyo Night",theme:EJ,tags:["dark","popular"]},{id:"github",label:"GitHub",theme:jJ,tags:["light","minimal"]},{id:"gruvbox",label:"Gruvbox",theme:PJ,tags:["dark","warm"]},{id:"one-dark",label:"One Dark",theme:SJ,tags:["dark","popular"]},{id:"catppuccin",label:"Catppuccin",theme:TJ,tags:["dark","pastel"]},{id:"rose-pine",label:"Rose Pine",theme:CJ,tags:["dark","elegant"]},{id:"kanagawa",label:"Kanagawa",theme:fJ,tags:["dark","japanese"]}];function W6($){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 X=["primary","secondary","muted","light"],Z=["primary","secondary","dark"],Q=["light","dark"];for(let J of X)if(!$.colors.text[J]||typeof $.colors.text[J]!=="string")return!1;for(let J of Z)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 h3={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"}},U6={name:"default",colors:h3,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)"}},x3={...U6,name:"dark",colors:{...h3,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 A8{currentTheme=U6;themes=new Map;constructor(){this.themes.set("default",U6),this.themes.set("dark",x3);for(let $ of L1)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(!W6(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"||L1.some((X)=>X.id===$))throw Error(`Cannot remove built-in theme '${$}'`);this.themes.delete($)}hasTheme($){return this.themes.has($)}validateTheme($){return W6($)}}var $0=new A8;import{Box as S$,Text as x1}from"ink";import{common as hJ,createLowlight as xJ}from"lowlight";import pJ from"react";import{jsxDEV as P0}from"react/jsx-dev-runtime";var R8=xJ(hJ);function O6($,Y,X=0){if($.type==="text")return P0(x1,{children:$.value},X,!1,void 0,this);if($.type==="element"){let Z=$.properties?.className?.[0]||"",Q=Y.default;if(Z.includes("comment"))Q=Y.comment;else if(Z.includes("string"))Q=Y.string;else if(Z.includes("number"))Q=Y.number;else if(Z.includes("keyword"))Q=Y.keyword;else if(Z.includes("function"))Q=Y.function;else if(Z.includes("variable"))Q=Y.variable;else if(Z.includes("operator"))Q=Y.operator;else if(Z.includes("type"))Q=Y.type;else if(Z.includes("tag"))Q=Y.tag;else if(Z.includes("attr"))Q=Y.attr;let J=$.children?.map((q,G)=>O6(q,Y,G));return P0(x1,{color:Q,children:J},X,!1,void 0,this)}if($.type==="root"&&$.children)return P0(pJ.Fragment,{children:$.children.map((Z,Q)=>O6(Z,Y,Q))},X,!1,void 0,this);return P0(x1,{},X,!1,void 0,this)}function gJ($,Y,X,Z){let Q=X||$0.getTheme().colors.syntax,J=$;if(Z&&$.length>Z)J=$.slice(0,Z-3)+"...";try{if(!Y||!R8.registered(Y)){let G=R8.highlightAuto(J);return O6(G,Q)}let q=R8.highlight(Y,J);return O6(q,Q)}catch(q){return P0(x1,{color:Q.default,children:J},void 0,!1,void 0,this)}}var b8=({content:$,language:Y,showLineNumbers:X=!0,terminalWidth:Z,availableHeight:Q})=>{let J=$0.getTheme(),q=$.split(`
1490
- `),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,O=Math.max(20,Z-W-6);return P0(S$,{borderStyle:"round",borderColor:J.colors.border.light,paddingX:1,paddingY:0,marginY:1,flexDirection:"column",children:[Y&&P0(S$,{marginBottom:0,children:P0(x1,{color:J.colors.text.secondary,children:Y},void 0,!1,void 0,this)},void 0,!1,void 0,this),G>0&&P0(S$,{marginBottom:0,children:P0(x1,{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 _=H+G+1;return P0(S$,{flexDirection:"row",children:[X&&P0(S$,{width:W,children:P0(x1,{color:J.colors.text.muted,dimColor:!0,children:String(_).padStart(W-1," ")},void 0,!1,void 0,this)},void 0,!1,void 0,this),P0(S$,{flexShrink:1,children:U.trim()===""?P0(x1,{children:" "},void 0,!1,void 0,this):gJ(U,Y,J.colors.syntax,O)},void 0,!1,void 0,this)]},H,!0,void 0,this)})]},void 0,!0,void 0,this)};import{Box as p3,Text as w1}from"ink";import{jsxDEV as r0}from"react/jsx-dev-runtime";function mJ($){let Y=$.split(`
1491
- `),X=[],Z=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)Z=parseInt(q[1],10),Q=parseInt(q[3],10);X.push({type:"header",content:J});continue}if(J.startsWith("-")){X.push({type:"remove",content:J.substring(1),lineNumber:Z}),Z++;continue}if(J.startsWith("+")){X.push({type:"add",content:J.substring(1),lineNumber:Q}),Q++;continue}if(J.startsWith(" ")||J===""){X.push({type:"context",content:J.substring(1),lineNumber:Q}),Z++,Q++;continue}}return X}var V8=({patch:$,startLine:Y,matchLine:X,terminalWidth:Z,maxLines:Q=20})=>{let J=$0.getTheme(),q=mJ($),K=Math.max(...q.map((_)=>_.lineNumber||0)).toString().length+1,W=q.length,O=W>Q,U=O?q.slice(0,Q):q,H=W-Q;return r0(p3,{flexDirection:"column",marginTop:1,marginBottom:1,children:[r0(w1,{color:J.colors.muted,children:"─".repeat(Math.max(0,Math.min(60,Z)))},void 0,!1,void 0,this),O&&r0(w1,{color:J.colors.info,children:["\uD83D\uDCCA 显示前 ",Q," 行,共 ",W," 行 diff"]},void 0,!0,void 0,this),O&&r0(w1,{color:J.colors.muted,children:"─".repeat(Math.max(0,Math.min(60,Z)))},void 0,!1,void 0,this),U.map((_,z)=>{if(_.type==="header")return r0(w1,{color:J.colors.muted,dimColor:!0,children:_.content},z,!1,void 0,this);let F=_.lineNumber?_.lineNumber.toString().padStart(K," "):" ".repeat(K),L=" ",w,N;if(_.type==="add")L="+",N=J.colors.success,w=void 0;else if(_.type==="remove")L="-",N=J.colors.error,w=void 0;else N=J.colors.text.primary;let A=Math.max(0,Z-K-2),b=_.content;if(b.length>A)b=b.substring(0,A-3)+"...";return r0(w1,{color:N,backgroundColor:w,children:[r0(w1,{dimColor:!0,children:F},void 0,!1,void 0,this),r0(w1,{children:L},void 0,!1,void 0,this),r0(w1,{children:[" ",b]},void 0,!0,void 0,this)]},z,!0,void 0,this)}),O&&r0(p3,{marginTop:1,children:r0(w1,{color:J.colors.warning,dimColor:!0,children:["⚠️ 已隐藏剩余 ",H," 行 diff(总共 ",W," 行)"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),r0(w1,{color:J.colors.muted,children:"─".repeat(Math.max(0,Math.min(60,Z)))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{Text as q1}from"ink";import dJ from"react";import uJ from"string-width";var X$=($)=>{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 uJ(Y)},g3=($,Y,X="...")=>{if(X$($)<=Y)return $;if(Y<=X.length)return X.substring(0,Y);let Q=0,J=$.length,q="";while(Q<=J){let G=Math.floor((Q+J)/2),K=$.substring(0,G);if(X$(K)<=Y-X.length)q=K,Q=G+1;else J=G-1}return q+X},m3=($)=>{return/[*_~`<[\]https?:]/.test($)};import{jsxDEV as a0,Fragment as lJ}from"react/jsx-dev-runtime";var D8=2,I8=1,k8=2;var cJ=({text:$})=>{let Y=$0.getTheme();if(!m3($))return a0(q1,{children:$},void 0,!1,void 0,this);let X=[],Z=0,Q=/(\*\*.*?\*\*|\*(?!\s).*?(?<!\s)\*|_(?!\s).*?(?<!\s)_|~~.*?~~|`+[^`]+`+|\[.*?\]\(.*?\)|https?:\/\/\S+)/g,J;while((J=Q.exec($))!==null){if(J.index>Z)X.push(a0(q1,{children:$.slice(Z,J.index)},`t-${Z}`,!1,void 0,this));let q=J[0],G=null,K=`m-${J.index}`;try{if(q.startsWith("**")&&q.endsWith("**")&&q.length>D8*2)G=a0(q1,{bold:!0,children:q.slice(D8,-D8)},K,!1,void 0,this);else if(q.length>I8*2&&(q.startsWith("*")&&q.endsWith("*")||q.startsWith("_")&&q.endsWith("_"))){let W=$.substring(J.index-1,J.index),O=$.substring(Q.lastIndex,Q.lastIndex+1);if(!(/\w/.test(W)||/\w/.test(O)||/[./\\]/.test(W+O)))G=a0(q1,{italic:!0,children:q.slice(I8,-I8)},K,!1,void 0,this)}else if(q.startsWith("~~")&&q.endsWith("~~")&&q.length>k8*2)G=a0(q1,{strikethrough:!0,children:q.slice(k8,-k8)},K,!1,void 0,this);else if(q.startsWith("`")&&q.endsWith("`")){let W=q.match(/^(`+)([^`]+)\1$/);if(W&&W[2])G=a0(q1,{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 O=W[1],U=W[2];G=a0(q1,{children:[O,a0(q1,{color:Y.colors.info,children:[" (",U,")"]},void 0,!0,void 0,this)]},K,!0,void 0,this)}}else if(q.match(/^https?:\/\//))G=a0(q1,{color:Y.colors.info,children:q},K,!1,void 0,this)}catch(W){console.error("InlineRenderer 解析错误:",q,W),G=null}X.push(G??a0(q1,{children:q},K,!1,void 0,this)),Z=Q.lastIndex}if(Z<$.length)X.push(a0(q1,{children:$.slice(Z)},`t-${Z}`,!1,void 0,this));return a0(lJ,{children:X.filter((q)=>q!==null)},void 0,!1,void 0,this)},n0=dJ.memo(cJ);import{Box as v8,Text as u3}from"ink";import iJ from"react";import{jsxDEV as T$}from"react/jsx-dev-runtime";var rJ=({itemText:$,type:Y,marker:X,leadingWhitespace:Z=""})=>{let Q=Y==="ol"?`${X}. `:`${X} `,J=Q.length,q=Z.length;return T$(v8,{paddingLeft:q+1,flexDirection:"row",children:[T$(v8,{width:J,children:T$(u3,{children:Q},void 0,!1,void 0,this)},void 0,!1,void 0,this),T$(v8,{flexGrow:1,children:T$(u3,{wrap:"wrap",children:T$(n0,{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)},d3=iJ.memo(rJ);import{Box as aJ,Text as Z$}from"ink";import c3 from"react";import{jsxDEV as o0}from"react/jsx-dev-runtime";var l3=({headers:$,rows:Y,terminalWidth:X})=>{let Z=$0.getTheme();if($.length===0||Y.length===0)return null;let Q=$.map((H,_)=>{let z=X$(H),F=Math.max(...Y.map((L)=>X$(L[_]||"")));return Math.max(z,F)+2}),J=$.length+1,q=Q.reduce((H,_)=>H+_,0)+J,G=q>X?X/q:1,K=Q.map((H)=>Math.floor(H*G)),W=(H,_,z=!1)=>{let F=Math.max(0,_-2),L=X$(H),w=H;if(L>F)w=g3(H,F);let N=X$(w),A=Math.max(0,F-N);return o0(Z$,{children:[z?o0(Z$,{bold:!0,color:Z.colors.primary,children:o0(n0,{text:w},void 0,!1,void 0,this)},void 0,!1,void 0,this):o0(n0,{text:w},void 0,!1,void 0,this)," ".repeat(A)]},void 0,!0,void 0,this)},O=(H)=>{let z={top:{left:"┌",middle:"┬",right:"┐",horizontal:"─"},middle:{left:"├",middle:"┼",right:"┤",horizontal:"─"},bottom:{left:"└",middle:"┴",right:"┘",horizontal:"─"}}[H],F=K.map((w)=>z.horizontal.repeat(w)),L=z.left+F.join(z.middle)+z.right;return o0(Z$,{color:Z.colors.text.muted,dimColor:!0,children:L},void 0,!1,void 0,this)},U=(H,_=!1)=>{let z=H.map((F,L)=>{let w=K[L]||0;return W(F||"",w,_)});return o0(Z$,{children:[o0(Z$,{color:Z.colors.text.muted,children:"│ "},void 0,!1,void 0,this),z.map((F,L)=>o0(c3.Fragment,{children:[F,L<z.length-1&&o0(Z$,{color:Z.colors.text.muted,children:" │ "},void 0,!1,void 0,this)]},L,!0,void 0,this)),o0(Z$,{color:Z.colors.text.muted,children:" │"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};return o0(aJ,{flexDirection:"column",marginY:1,children:[O("top"),U($,!0),O("middle"),Y.map((H,_)=>o0(c3.Fragment,{children:U(H)},_,!1,void 0,this)),O("bottom")]},void 0,!0,void 0,this)};import{jsxDEV as x}from"react/jsx-dev-runtime";var nJ=($,Y)=>{let Z=$0.getTheme().colors;switch($){case"user":return{color:Z.info,prefix:"> "};case"assistant":return{color:Z.success,prefix:"• "};case"system":return{color:Z.warning,prefix:"⚙ "};case"tool":{let Q=Y&&"phase"in Y?Y.phase:void 0;return{color:Z.text.secondary,prefix:Q==="start"?"• ":Q==="complete"?" └ ":" "}}default:return{color:Z.text.primary,prefix:" "}}},G1={codeBlock:/^```(\w+)?\s*$/,heading:/^ *(#{1,4}) +(.+)/,ulItem:/^([ \t]*)([-*+]) +(.+)/,olItem:/^([ \t]*)(\d+)\. +(.+)/,hr:/^ *([-*_] *){3,} *$/,table:/^\|(.+)\|$/,tableSeparator:/^\|[\s]*:?-+:?[\s]*(\|[\s]*:?-+:?[\s]*)+\|?$/,diffStart:/^<<<DIFF>>>$/,diffEnd:/^<<<\/DIFF>>>$/};function oJ($){let Y=[],X=$.split(/\r?\n/),Z=!1,Q=[],J=null,q=!1,G=[],K=[],W=!1,O=[],U=!0;for(let H=0;H<X.length;H++){let _=X[H];if(W){if(_.match(G1.diffEnd)){try{let y=JSON.parse(O.join(`
1492
- `));Y.push({type:"diff",content:"",diffData:{patch:y.patch,startLine:y.startLine,matchLine:y.matchLine}})}catch(y){Y.push({type:"text",content:O.join(`
1493
- `)})}W=!1,O=[],U=!1;continue}O.push(_);continue}if(_.match(G1.diffStart)){W=!0,O=[],U=!1;continue}if(Z){if(_.match(G1.codeBlock))Y.push({type:"code",content:Q.join(`
1494
- `),language:J||void 0}),Z=!1,Q=[],J=null,U=!1;else Q.push(_);continue}let z=_.match(G1.codeBlock);if(z){Z=!0,J=z[1]||null,U=!1;continue}let F=_.match(G1.table),L=_.match(G1.tableSeparator);if(F&&!q){if(H+1<X.length){if(X[H+1].match(G1.tableSeparator)){q=!0,G=F[1].split("|").map((R)=>R.trim()).filter((R)=>R.length>0),K=[],U=!1;continue}}}if(q&&L)continue;if(q&&F){let y=F[1].split("|").map((R)=>R.trim()).filter((R)=>R.length>0);while(y.length<G.length)y.push("");if(y.length>G.length)y.length=G.length;K.push(y);continue}if(q&&!F){if(G.length>0&&K.length>0)Y.push({type:"table",content:"",tableData:{headers:G,rows:K}});q=!1,G=[],K=[]}let w=_.match(G1.heading);if(w){Y.push({type:"heading",content:w[2],level:w[1].length}),U=!1;continue}let N=_.match(G1.ulItem);if(N){Y.push({type:"list",content:N[3],listType:"ul",marker:N[2],indentation:N[1].length}),U=!1;continue}let A=_.match(G1.olItem);if(A){Y.push({type:"list",content:A[3],listType:"ol",marker:A[2],indentation:A[1].length}),U=!1;continue}if(_.match(G1.hr)){Y.push({type:"hr",content:""}),U=!1;continue}if(_.trim().length===0){if(!U)Y.push({type:"empty",content:""}),U=!0;continue}Y.push({type:"text",content:_}),U=!1}if(Z)Y.push({type:"code",content:Q.join(`
1495
- `),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 sJ=({content:$,language:Y,terminalWidth:X})=>{return x(b8,{content:$,language:Y,showLineNumbers:!0,terminalWidth:X},void 0,!1,void 0,this)},tJ=({content:$,level:Y})=>{let X=$0.getTheme();switch(Y){case 1:return x(h0,{bold:!0,color:X.colors.primary,children:x(n0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this);case 2:return x(h0,{bold:!0,color:X.colors.primary,children:x(n0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this);case 3:return x(h0,{bold:!0,color:X.colors.text.primary,children:x(n0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this);case 4:return x(h0,{italic:!0,color:X.colors.text.muted,children:x(n0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this);default:return x(h0,{children:x(n0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this)}},eJ=({terminalWidth:$})=>{let Y=$0.getTheme(),X=Math.max(0,Math.min($-4,80));return x(h0,{dimColor:!0,color:Y.colors.text.muted,children:"─".repeat(X)},void 0,!1,void 0,this)},$q=({content:$})=>{return x(h0,{wrap:"wrap",children:x(n0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this)},Yq=H6.memo(({detail:$,terminalWidth:Y})=>{let X=$0.getTheme(),Z=50,Q=$.split(`
1485
+ `),f=I8.join(w,`${J.name}.md`);await n3.promises.writeFile(f,E,"utf-8"),$()}catch(w){console.error("保存配置失败:",w)}}),I=V0(!1,Y);if(s3((w,b)=>{if(b.escape)A();else if(b.ctrl&&w==="c"||b.meta&&w==="c")I()},{isActive:Z!=="tools"}),Z==="mode")return V(p,{flexDirection:"column",paddingY:1,children:[V(p,{marginBottom:1,children:V(T,{bold:!0,color:"cyan",children:"\uD83C\uDFAF 选择创建方式"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(p,{marginBottom:1,children:V(T,{dimColor:!0,children:"你可以手动配置每个细节,或让 AI 根据你的描述自动生成配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(z6,{items:[{label:"\uD83E\uDD16 AI 智能生成 - 根据描述自动生成完整配置",value:"ai"},{label:"✍️ 手动配置 - 逐步配置每个选项",value:"manual"}],onSelect:(w)=>{if(w.value==="ai")z("ai"),Q("aiPrompt");else z("manual"),Q("name")}},void 0,!1,void 0,this),V(p,{marginTop:1,children:V(T,{dimColor:!0,children:"使用方向键选择 | Enter 确认 | ESC 取消"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(Z==="aiPrompt")return V(p,{flexDirection:"column",paddingY:1,children:[V(p,{marginBottom:1,children:V(T,{bold:!0,color:"cyan",children:"\uD83E\uDD16 AI 智能生成"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(p,{marginBottom:1,children:V(T,{dimColor:!0,children:'描述你想要创建的 Agent(例如:"一个专门用于代码审查的 agent,能够分析代码质量和潜在bug")'},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(p,{marginBottom:1,children:[V(T,{color:"green",children:"描述: "},void 0,!1,void 0,this),V(F2,{value:G,onChange:K,onSubmit:(w)=>{if(!w.trim())return;Q("aiGenerating")}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),V(p,{children:V(T,{dimColor:!0,children:"按 Enter 开始生成 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(Z==="aiGenerating"){if(U)return V(p,{flexDirection:"column",paddingY:1,children:[V(p,{marginBottom:1,children:V(T,{bold:!0,color:"red",children:"❌ AI 生成失败"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(p,{marginBottom:1,children:V(T,{color:"red",children:U},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(p,{marginBottom:1,children:V(T,{dimColor:!0,children:"按 ESC 返回修改描述"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return V(p,{flexDirection:"column",paddingY:1,children:[V(p,{marginBottom:1,children:V(T,{bold:!0,color:"yellow",children:[V(jJ,{type:"dots"},void 0,!1,void 0,this)," AI 正在生成配置..."]},void 0,!0,void 0,this)},void 0,!1,void 0,this),V(p,{marginBottom:1,children:V(T,{dimColor:!0,children:['根据你的描述:"',G,'"']},void 0,!0,void 0,this)},void 0,!1,void 0,this),V(p,{marginBottom:1,children:V(T,{color:"gray",children:"正在调用 LLM 生成 agent 配置,请稍候..."},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}if(Z==="name"){let w=_==="edit";return V(p,{flexDirection:"column",paddingY:1,children:[V(p,{marginBottom:1,children:V(T,{bold:!0,color:"cyan",children:["\uD83D\uDCDD Step 1/7: ",w?"Agent 名称(不可修改)":"输入 Agent 名称"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),V(p,{marginBottom:1,children:V(T,{dimColor:!0,children:w?"编辑模式下名称不可修改(修改名称相当于创建新 Agent)":"名称只能包含小写字母、数字和连字符(例如:code-reviewer)"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(p,{marginBottom:1,children:[V(T,{color:"green",children:"名称: "},void 0,!1,void 0,this),w?V(T,{children:J.name},void 0,!1,void 0,this):V(F2,{value:J.name,onChange:(b)=>q({...J,name:b}),onSubmit:(b)=>{if(CJ(b))return;N()}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),V(p,{children:V(T,{dimColor:!0,children:w?"按 Enter 继续 | ESC 返回":"按 Enter 继续 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this),w&&V(F2,{value:"",onChange:()=>{},onSubmit:N,showCursor:!1},"edit-mode-dummy-input",!1,void 0,this)]},void 0,!0,void 0,this)}if(Z==="description")return V(p,{flexDirection:"column",paddingY:1,children:[V(p,{marginBottom:1,children:V(T,{bold:!0,color:"cyan",children:"\uD83D\uDCDD Step 2/7: 输入描述信息"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(p,{marginBottom:1,children:V(T,{dimColor:!0,children:"简短描述这个 Agent 的用途和使用场景(这将帮助主 Agent 决定何时使用它)"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(p,{marginBottom:1,children:[V(T,{color:"green",children:"描述: "},void 0,!1,void 0,this),V(F2,{value:J.description,onChange:(w)=>q({...J,description:w}),onSubmit:(w)=>{if(!w.trim())return;N()}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),V(p,{children:V(T,{dimColor:!0,children:"按 Enter 继续 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(Z==="tools")return V(fJ,{config:J,setConfig:q,onNext:N,onPrev:A},void 0,!1,void 0,this);if(Z==="color")return V(p,{flexDirection:"column",paddingY:1,children:[V(p,{marginBottom:1,children:V(T,{bold:!0,color:"cyan",children:"\uD83C\uDFA8 Step 4/7: 选择背景颜色"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(p,{marginBottom:1,children:V(T,{dimColor:!0,children:"为 Agent 选择一个颜色标识(用于在 UI 中区分不同的 Agents)"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(z6,{items:TJ,onSelect:(w)=>{let b=w.value==="none"?void 0:w.value;q({...J,color:b}),N()}},void 0,!1,void 0,this),V(p,{marginTop:1,children:V(T,{dimColor:!0,children:"使用方向键选择 | Enter 确认 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(Z==="location")return V(p,{flexDirection:"column",paddingY:1,children:[V(p,{marginBottom:1,children:V(T,{bold:!0,color:"cyan",children:"\uD83D\uDCC2 Step 5/7: 选择保存位置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(p,{marginBottom:1,children:V(T,{dimColor:!0,children:"项目级配置仅在当前项目生效,用户级配置全局可用"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(z6,{items:[{label:"\uD83D\uDCC1 项目级 (.blade/agents/) - 仅当前项目",value:"project"},{label:"\uD83C\uDFE0 用户级 (~/.blade/agents/) - 全局可用",value:"user"}],onSelect:(w)=>{q({...J,location:w.value}),N()}},void 0,!1,void 0,this),V(p,{marginTop:1,children:V(T,{dimColor:!0,children:"使用方向键选择 | Enter 确认 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(Z==="systemPrompt")return V(p,{flexDirection:"column",paddingY:1,children:[V(p,{marginBottom:1,children:V(T,{bold:!0,color:"cyan",children:"\uD83D\uDCAC Step 6/7: 输入系统提示词"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(p,{marginBottom:1,children:V(T,{dimColor:!0,children:"定义 Agent 的行为和职责(可选,留空将使用默认提示)"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(p,{marginBottom:1,children:[V(T,{color:"green",children:"提示词: "},void 0,!1,void 0,this),V(F2,{value:J.systemPrompt,onChange:(w)=>q({...J,systemPrompt:w}),onSubmit:()=>N()},void 0,!1,void 0,this)]},void 0,!0,void 0,this),V(p,{children:V(T,{dimColor:!0,children:"按 Enter 继续 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(Z==="confirm")return V(p,{flexDirection:"column",paddingY:1,children:[V(p,{marginBottom:1,children:V(T,{bold:!0,color:"cyan",children:"✅ Step 7/7: 确认配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(p,{flexDirection:"column",paddingLeft:2,marginBottom:1,children:[V(T,{children:[V(T,{bold:!0,color:"green",children:["名称:"," "]},void 0,!0,void 0,this),V(T,{children:J.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),V(T,{children:[V(T,{bold:!0,color:"green",children:["描述:"," "]},void 0,!0,void 0,this),V(T,{children:J.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this),V(T,{children:[V(T,{bold:!0,color:"green",children:["工具:"," "]},void 0,!0,void 0,this),V(T,{children:J.tools.includes("all")?"所有工具":J.tools.join(", ")||"所有工具"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),V(T,{children:[V(T,{bold:!0,color:"green",children:["颜色:"," "]},void 0,!0,void 0,this),V(T,{children:J.color||"默认"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),V(T,{children:[V(T,{bold:!0,color:"green",children:["位置:"," "]},void 0,!0,void 0,this),V(T,{children:J.location==="project"?"项目级":"用户级"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),V(T,{children:[V(T,{bold:!0,color:"green",children:["提示词:"," "]},void 0,!0,void 0,this),V(T,{children:J.systemPrompt||"(使用默认)"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),V(z6,{items:[{label:"✅ 确认并保存",value:"save"},{label:"⬅️ 返回上一步",value:"back"},{label:"❌ 取消",value:"cancel"}],onSelect:(w)=>{if(w.value==="save")k();else if(w.value==="back")A();else Y()}},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return null}function fJ({config:$,setConfig:Y,onNext:X,onPrev:Z}){let{isFocused:Q}=yJ({id:"step-tools"});s3((q,G)=>{if(G.escape)Z()},{isActive:Q});let J=(q)=>{if(q.includes("all"))Y({...$,tools:["all"]});else Y({...$,tools:q});X()};return V(p,{flexDirection:"column",paddingY:1,children:[V(p,{marginBottom:1,children:V(T,{bold:!0,color:"cyan",children:"\uD83D\uDD27 Step 3/7: 选择可用工具"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(p,{marginBottom:1,children:V(T,{dimColor:!0,children:"方向键导航,空格切换勾选,Enter 确认进入下一步 | ESC 返回上一步"},void 0,!1,void 0,this)},void 0,!1,void 0,this),V(kJ,{options:SJ,defaultValue:$.tools,onSubmit:J},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{useMemoizedFn as N2}from"ahooks";import{Box as q0,Text as F0,useInput as hJ}from"ink";import D8 from"ink-select-input";import xJ from"node:fs";import{useMemo as pJ,useState as v8}from"react";import{jsxDEV as S}from"react/jsx-dev-runtime";function t3({initialMode:$="menu",onComplete:Y,onCancel:X}){let[Z,Q]=v8($),[J,q]=v8(null),[G,K]=v8(0),W=N2(()=>{B0.clear(),B0.loadFromStandardLocations(),K((N)=>N+1)}),O=pJ(()=>{return B0.getAllSubagents()},[G]),U=[{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"}],H=N2((N)=>{if(N.value==="cancel"){X?.();return}Q(N.value)}),_=N2((N)=>{if(q(N.value),Z==="edit")Q("editWizard");else if(Z==="delete")Q("deleteConfirm")}),z=N2(async()=>{if(!J?.configPath)return;try{await xJ.promises.unlink(J.configPath),W(),F()}catch(N){console.error("删除失败:",N)}}),F=N2(()=>{Q("menu"),q(null)}),B=V0(!1,X);if(hJ((N,A)=>{if(A.escape){if(Z==="menu")X?.();else if(Z==="list"||Z==="edit"||Z==="delete")F();else if(Z==="deleteConfirm")F()}else if(A.ctrl&&N==="c"||A.meta&&N==="c")B()},{isActive:Z!=="create"&&Z!=="editWizard"}),Z==="menu")return S(q0,{flexDirection:"column",paddingY:1,children:[S(q0,{marginBottom:1,children:S(F0,{bold:!0,color:"cyan",children:"\uD83D\uDCCB Agents 管理"},void 0,!1,void 0,this)},void 0,!1,void 0,this),S(D8,{items:U,onSelect:H},void 0,!1,void 0,this),S(q0,{marginTop:1,children:S(F0,{dimColor:!0,children:"使用方向键选择 | Enter 确认 | ESC 退出"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(Z==="list"){if(O.length===0)return S(q0,{flexDirection:"column",paddingY:1,children:[S(q0,{marginBottom:1,children:S(F0,{bold:!0,color:"cyan",children:"\uD83D\uDCCB 所有 Agents"},void 0,!1,void 0,this)},void 0,!1,void 0,this),S(q0,{paddingLeft:2,children:S(F0,{color:"gray",children:"❌ 没有找到任何 agent 配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),S(q0,{marginTop:1,paddingLeft:2,children:S(F0,{color:"gray",children:"\uD83D\uDCA1 配置文件位置: .blade/agents/ 或 ~/.blade/agents/"},void 0,!1,void 0,this)},void 0,!1,void 0,this),S(q0,{marginTop:1,paddingLeft:2,children:S(F0,{dimColor:!0,children:"按 ESC 返回菜单"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return S(q0,{flexDirection:"column",paddingY:1,children:[S(q0,{marginBottom:1,children:[S(F0,{bold:!0,color:"cyan",children:"\uD83D\uDCCB 所有 Agents"},void 0,!1,void 0,this),S(F0,{color:"gray",children:[" (找到 ",O.length," 个)"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),O.map((N)=>S(q0,{flexDirection:"column",paddingLeft:2,children:[S(q0,{children:S(F0,{children:[S(F0,{bold:!0,color:N.color||"white",children:["• ",N.name]},void 0,!0,void 0,this),S(F0,{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&&S(q0,{paddingLeft:2,children:S(F0,{color:"gray",children:["工具: ",N.tools.join(", ")]},void 0,!0,void 0,this)},void 0,!1,void 0,this),N.configPath&&S(q0,{paddingLeft:2,children:S(F0,{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)),S(q0,{marginTop:1,paddingLeft:2,children:S(F0,{dimColor:!0,children:"按 ESC 返回菜单"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}let L=(N)=>{if(O.length===0)return S(q0,{flexDirection:"column",paddingY:1,children:[S(q0,{marginBottom:1,children:S(F0,{bold:!0,color:"cyan",children:N},void 0,!1,void 0,this)},void 0,!1,void 0,this),S(q0,{paddingLeft:2,children:S(F0,{color:"gray",children:"❌ 没有找到任何 agent 配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),S(q0,{marginTop:1,paddingLeft:2,children:S(F0,{dimColor:!0,children:"按 ESC 返回菜单"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this);let A=O.map((R)=>({key:R.name,label:`${R.name} - ${R.description}`,value:R}));return S(q0,{flexDirection:"column",paddingY:1,children:[S(q0,{marginBottom:1,children:S(F0,{bold:!0,color:"cyan",children:N},void 0,!1,void 0,this)},void 0,!1,void 0,this),S(D8,{items:A,onSelect:_},void 0,!1,void 0,this),S(q0,{marginTop:1,children:S(F0,{dimColor:!0,children:"使用方向键选择 | Enter 确认 | ESC 返回"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};if(Z==="create")return S(z2,{onComplete:()=>{W(),F()},onCancel:F},void 0,!1,void 0,this);if(Z==="edit")return L("✏️ 编辑 Agent");if(Z==="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 S(z2,{initialConfig:N,onComplete:()=>{W(),F()},onCancel:F},void 0,!1,void 0,this)}if(Z==="delete")return L("\uD83D\uDDD1️ 删除 Agent");if(Z==="deleteConfirm"&&J)return S(q0,{flexDirection:"column",paddingY:1,children:[S(q0,{marginBottom:1,children:S(F0,{bold:!0,color:"red",children:"⚠️ 确认删除"},void 0,!1,void 0,this)},void 0,!1,void 0,this),S(q0,{marginBottom:1,paddingLeft:2,children:S(F0,{children:["你确定要删除 Agent"," ",S(F0,{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),S(q0,{marginBottom:1,paddingLeft:2,children:S(F0,{dimColor:!0,children:["文件路径: ",J.configPath]},void 0,!0,void 0,this)},void 0,!1,void 0,this),S(q0,{marginBottom:1,paddingLeft:2,children:S(F0,{color:"red",children:"此操作无法撤销!"},void 0,!1,void 0,this)},void 0,!1,void 0,this),S(D8,{items:[{label:"\uD83D\uDDD1️ 确认删除",value:"confirm"},{label:"❌ 取消",value:"cancel"}],onSelect:(N)=>{if(N.value==="confirm")z();else F()}},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return null}import{Box as f$,Text as O0}from"ink";import mJ from"react";import{useEffect as gJ,useState as e3}from"react";function $7($=process.cwd(),Y=5000){let[X,Z]=e3(null),[Q,J]=e3(!0);return gJ(()=>{let q=!0,G=async()=>{try{let W=await U2($);if(!q)return;if(!W){Z(null),J(!1);return}let O=await H3($);if(!q)return;Z(O)}catch{if(q)Z(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:X,loading:Q}}import{jsxDEV as a,Fragment as B2}from"react/jsx-dev-runtime";var Y7=mJ.memo(()=>{let $=Q6(),Y=m1(),X=j$(),Q=Z6()==="shortcuts",J=i5(),{branch:q}=$7(),G=J6(),K=g5(),W=p5(),O=$3(),U=G?H6(G):!1,_=(()=>{if(X==="default")return null;if(X==="autoEdit")return a(O0,{color:"magenta",children:["▶▶ auto edit on ",a(O0,{color:"gray",children:"(shift+tab to cycle)"},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(X==="plan")return a(O0,{color:"cyan",children:["‖ plan mode on ",a(O0,{color:"gray",children:"(shift+tab to cycle)"},void 0,!1,void 0,this)]},void 0,!0,void 0,this);if(X==="yolo")return a(O0,{color:"red",children:["⚡ yolo mode on ",a(O0,{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 a(f$,{flexDirection:"row",justifyContent:"space-between",paddingX:2,paddingY:0,children:[Q?a(f$,{flexDirection:"column",gap:0,children:F.map((B,L)=>a(f$,{flexDirection:"row",children:[B.map((N,A)=>{let[R,k]=N.split(":");return a(f$,{flexDirection:"row",width:20,children:[a(O0,{color:"yellow",children:R},void 0,!1,void 0,this),a(O0,{color:"gray",children:":"},void 0,!1,void 0,this),a(O0,{color:"white",children:k},void 0,!1,void 0,this)]},A,!0,void 0,this)}),L===F.length-1&&a(O0,{color:"cyan",children:" ? 关闭"},void 0,!1,void 0,this)]},L,!0,void 0,this))},void 0,!1,void 0,this):a(f$,{flexDirection:"row",gap:1,children:[q&&a(B2,{children:[a(O0,{color:"gray",children:[" ",q]},void 0,!0,void 0,this),a(O0,{color:"gray",children:"·"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),_,z&&a(O0,{color:"gray",children:"·"},void 0,!1,void 0,this),a(O0,{color:"gray",children:"? for shortcuts"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),a(f$,{flexDirection:"row",gap:1,children:!$?a(O0,{color:"red",children:"⚠ API 密钥未配置"},void 0,!1,void 0,this):a(B2,{children:[U&&a(B2,{children:[O?a(O0,{color:"cyan",children:"Thinking on"},void 0,!1,void 0,this):a(O0,{color:"gray",children:"Tab:Thinking"},void 0,!1,void 0,this),a(O0,{color:"gray",children:"·"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),G&&a(O0,{color:"gray",children:G.model},void 0,!1,void 0,this),a(O0,{color:"gray",children:"·"},void 0,!1,void 0,this),W?a(O0,{color:"yellow",children:"压缩中..."},void 0,!1,void 0,this):a(O0,{color:K<20?"red":K<50?"yellow":"gray",children:[K,"%"]},void 0,!0,void 0,this),Y&&a(B2,{children:[a(O0,{color:"gray",children:"·"},void 0,!1,void 0,this),a(O0,{color:"yellow",children:"Processing..."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),J&&a(B2,{children:[a(O0,{color:"gray",children:"·"},void 0,!1,void 0,this),a(O0,{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 M8,Text as k8}from"ink";import uJ from"react";import{jsxDEV as h$}from"react/jsx-dev-runtime";var X7=uJ.memo(({suggestions:$,selectedIndex:Y,visible:X,maxDisplay:Z=8})=>{if(!X||$.length===0)return null;let Q=0,J=Math.min(Z,$.length),q=Y>=$.length;if(Y>=Z&&!q)Q=Y-Z+1,J=Y+1;let G=$.slice(Q,J),K=$.length>Z;return h$(M8,{flexDirection:"column",paddingX:2,paddingY:0,children:[G.map((W,O)=>{let H=Q+O===Y;return h$(M8,{justifyContent:"space-between",paddingX:1,children:[h$(k8,{color:H?"cyan":"white",bold:H,children:W.command},void 0,!1,void 0,this),h$(k8,{color:H?"cyan":"gray",dimColor:!H,children:W.description},void 0,!1,void 0,this)]},W.command,!0,void 0,this)}),K&&h$(M8,{paddingX:1,children:h$(k8,{color:q?"cyan":"gray",bold:q,dimColor:!q,children:["... and ",$.length-Z," more"]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)});import{Box as e0,Text as H1,useInput as Dq}from"ink";import vq from"ink-select-input";import{useMemo as Mq}from"react";import{useEffect as dJ,useState as cJ}from"react";import{useStdout as lJ}from"ink";import{debounce as iJ}from"lodash-es";function x$($=200){let{stdout:Y}=lJ(),[X,Z]=cJ(Y.columns||80);return dJ(()=>{let Q=iJ(()=>{Z(Y.columns||80)},$);return Q(),Y.on("resize",Q),()=>{Y.off("resize",Q),Q.cancel()}},[Y,$]),X}import{Box as y0,Text as p0}from"ink";import w6 from"react";var rJ={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)"}},aJ={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)"}},nJ={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)"}},oJ={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)"}},sJ={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)"}},tJ={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)"}},eJ={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)"}},$q={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)"}},Yq={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)"}},Xq={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)"}},Zq={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)"}},Qq={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)"}},Jq={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)"}},b1=[{id:"ayu-dark",label:"Ayu Dark",theme:rJ,tags:["dark","popular"]},{id:"dracula",label:"Dracula",theme:aJ,tags:["dark","popular"]},{id:"monokai",label:"Monokai",theme:nJ,tags:["dark","classic"]},{id:"nord",label:"Nord",theme:oJ,tags:["dark","minimal"]},{id:"solarized-light",label:"Solarized Light",theme:sJ,tags:["light"]},{id:"solarized-dark",label:"Solarized Dark",theme:tJ,tags:["dark"]},{id:"tokyo-night",label:"Tokyo Night",theme:eJ,tags:["dark","popular"]},{id:"github",label:"GitHub",theme:$q,tags:["light","minimal"]},{id:"gruvbox",label:"Gruvbox",theme:Yq,tags:["dark","warm"]},{id:"one-dark",label:"One Dark",theme:Xq,tags:["dark","popular"]},{id:"catppuccin",label:"Catppuccin",theme:Zq,tags:["dark","pastel"]},{id:"rose-pine",label:"Rose Pine",theme:Qq,tags:["dark","elegant"]},{id:"kanagawa",label:"Kanagawa",theme:Jq,tags:["dark","japanese"]}];function N6($){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 X=["primary","secondary","muted","light"],Z=["primary","secondary","dark"],Q=["light","dark"];for(let J of X)if(!$.colors.text[J]||typeof $.colors.text[J]!=="string")return!1;for(let J of Z)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 Z7={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"}},B6={name:"default",colors:Z7,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)"}},Q7={...B6,name:"dark",colors:{...Z7,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 y8{currentTheme=B6;themes=new Map;constructor(){this.themes.set("default",B6),this.themes.set("dark",Q7);for(let $ of b1)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(!N6(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"||b1.some((X)=>X.id===$))throw Error(`Cannot remove built-in theme '${$}'`);this.themes.delete($)}hasTheme($){return this.themes.has($)}validateTheme($){return N6($)}}var e=new y8;import{Box as p$,Text as d1}from"ink";import{common as qq,createLowlight as Gq}from"lowlight";import Kq from"react";import{jsxDEV as f0}from"react/jsx-dev-runtime";var E8=Gq(qq);function L6($,Y,X=0){if($.type==="text")return f0(d1,{children:$.value},X,!1,void 0,this);if($.type==="element"){let Z=$.properties?.className?.[0]||"",Q=Y.default;if(Z.includes("comment"))Q=Y.comment;else if(Z.includes("string"))Q=Y.string;else if(Z.includes("number"))Q=Y.number;else if(Z.includes("keyword"))Q=Y.keyword;else if(Z.includes("function"))Q=Y.function;else if(Z.includes("variable"))Q=Y.variable;else if(Z.includes("operator"))Q=Y.operator;else if(Z.includes("type"))Q=Y.type;else if(Z.includes("tag"))Q=Y.tag;else if(Z.includes("attr"))Q=Y.attr;let J=$.children?.map((q,G)=>L6(q,Y,G));return f0(d1,{color:Q,children:J},X,!1,void 0,this)}if($.type==="root"&&$.children)return f0(Kq.Fragment,{children:$.children.map((Z,Q)=>L6(Z,Y,Q))},X,!1,void 0,this);return f0(d1,{},X,!1,void 0,this)}function Wq($,Y,X,Z){let Q=X||e.getTheme().colors.syntax,J=$;if(Z&&$.length>Z)J=$.slice(0,Z-3)+"...";try{if(!Y||!E8.registered(Y)){let G=E8.highlightAuto(J);return L6(G,Q)}let q=E8.highlight(Y,J);return L6(q,Q)}catch(q){return f0(d1,{color:Q.default,children:J},void 0,!1,void 0,this)}}var j8=({content:$,language:Y,showLineNumbers:X=!0,terminalWidth:Z,availableHeight:Q})=>{let J=e.getTheme(),q=$.split(`
1486
+ `),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,O=Math.max(20,Z-W-6);return f0(p$,{borderStyle:"round",borderColor:J.colors.border.light,paddingX:1,paddingY:0,marginY:1,flexDirection:"column",children:[Y&&f0(p$,{marginBottom:0,children:f0(d1,{color:J.colors.text.secondary,children:Y},void 0,!1,void 0,this)},void 0,!1,void 0,this),G>0&&f0(p$,{marginBottom:0,children:f0(d1,{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 _=H+G+1;return f0(p$,{flexDirection:"row",children:[X&&f0(p$,{width:W,children:f0(d1,{color:J.colors.text.muted,dimColor:!0,children:String(_).padStart(W-1," ")},void 0,!1,void 0,this)},void 0,!1,void 0,this),f0(p$,{flexShrink:1,children:U.trim()===""?f0(d1,{children:" "},void 0,!1,void 0,this):Wq(U,Y,J.colors.syntax,O)},void 0,!1,void 0,this)]},H,!0,void 0,this)})]},void 0,!0,void 0,this)};import{Box as J7,Text as V1}from"ink";import{jsxDEV as n0}from"react/jsx-dev-runtime";function Uq($){let Y=$.split(`
1487
+ `),X=[],Z=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)Z=parseInt(q[1],10),Q=parseInt(q[3],10);X.push({type:"header",content:J});continue}if(J.startsWith("-")){X.push({type:"remove",content:J.substring(1),lineNumber:Z}),Z++;continue}if(J.startsWith("+")){X.push({type:"add",content:J.substring(1),lineNumber:Q}),Q++;continue}if(J.startsWith(" ")||J===""){X.push({type:"context",content:J.substring(1),lineNumber:Q}),Z++,Q++;continue}}return X}var P8=({patch:$,startLine:Y,matchLine:X,terminalWidth:Z,maxLines:Q=20})=>{let J=e.getTheme(),q=Uq($),K=Math.max(...q.map((_)=>_.lineNumber||0)).toString().length+1,W=q.length,O=W>Q,U=O?q.slice(0,Q):q,H=W-Q;return n0(J7,{flexDirection:"column",marginTop:1,marginBottom:1,children:[n0(V1,{color:J.colors.muted,children:"─".repeat(Math.max(0,Math.min(60,Z)))},void 0,!1,void 0,this),O&&n0(V1,{color:J.colors.info,children:["\uD83D\uDCCA 显示前 ",Q," 行,共 ",W," 行 diff"]},void 0,!0,void 0,this),O&&n0(V1,{color:J.colors.muted,children:"─".repeat(Math.max(0,Math.min(60,Z)))},void 0,!1,void 0,this),U.map((_,z)=>{if(_.type==="header")return n0(V1,{color:J.colors.muted,dimColor:!0,children:_.content},z,!1,void 0,this);let F=_.lineNumber?_.lineNumber.toString().padStart(K," "):" ".repeat(K),B=" ",L,N;if(_.type==="add")B="+",N=J.colors.success,L=void 0;else if(_.type==="remove")B="-",N=J.colors.error,L=void 0;else N=J.colors.text.primary;let A=Math.max(0,Z-K-2),R=_.content;if(R.length>A)R=R.substring(0,A-3)+"...";return n0(V1,{color:N,backgroundColor:L,children:[n0(V1,{dimColor:!0,children:F},void 0,!1,void 0,this),n0(V1,{children:B},void 0,!1,void 0,this),n0(V1,{children:[" ",R]},void 0,!0,void 0,this)]},z,!0,void 0,this)}),O&&n0(J7,{marginTop:1,children:n0(V1,{color:J.colors.warning,dimColor:!0,children:["⚠️ 已隐藏剩余 ",H," 行 diff(总共 ",W," 行)"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),n0(V1,{color:J.colors.muted,children:"─".repeat(Math.max(0,Math.min(60,Z)))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{Text as U1}from"ink";import Hq from"react";import Oq from"string-width";var W$=($)=>{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 Oq(Y)},q7=($,Y,X="...")=>{if(W$($)<=Y)return $;if(Y<=X.length)return X.substring(0,Y);let Q=0,J=$.length,q="";while(Q<=J){let G=Math.floor((Q+J)/2),K=$.substring(0,G);if(W$(K)<=Y-X.length)q=K,Q=G+1;else J=G-1}return q+X},G7=($)=>{return/[*_~`<[\]https?:]/.test($)};import{jsxDEV as o0,Fragment as Fq}from"react/jsx-dev-runtime";var S8=2,T8=1,C8=2;var _q=({text:$})=>{let Y=e.getTheme();if(!G7($))return o0(U1,{children:$},void 0,!1,void 0,this);let X=[],Z=0,Q=/(\*\*.*?\*\*|\*(?!\s).*?(?<!\s)\*|_(?!\s).*?(?<!\s)_|~~.*?~~|`+[^`]+`+|\[.*?\]\(.*?\)|https?:\/\/\S+)/g,J;while((J=Q.exec($))!==null){if(J.index>Z)X.push(o0(U1,{children:$.slice(Z,J.index)},`t-${Z}`,!1,void 0,this));let q=J[0],G=null,K=`m-${J.index}`;try{if(q.startsWith("**")&&q.endsWith("**")&&q.length>S8*2)G=o0(U1,{bold:!0,children:q.slice(S8,-S8)},K,!1,void 0,this);else if(q.length>T8*2&&(q.startsWith("*")&&q.endsWith("*")||q.startsWith("_")&&q.endsWith("_"))){let W=$.substring(J.index-1,J.index),O=$.substring(Q.lastIndex,Q.lastIndex+1);if(!(/\w/.test(W)||/\w/.test(O)||/[./\\]/.test(W+O)))G=o0(U1,{italic:!0,children:q.slice(T8,-T8)},K,!1,void 0,this)}else if(q.startsWith("~~")&&q.endsWith("~~")&&q.length>C8*2)G=o0(U1,{strikethrough:!0,children:q.slice(C8,-C8)},K,!1,void 0,this);else if(q.startsWith("`")&&q.endsWith("`")){let W=q.match(/^(`+)([^`]+)\1$/);if(W&&W[2])G=o0(U1,{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 O=W[1],U=W[2];G=o0(U1,{children:[O,o0(U1,{color:Y.colors.info,children:[" (",U,")"]},void 0,!0,void 0,this)]},K,!0,void 0,this)}}else if(q.match(/^https?:\/\//))G=o0(U1,{color:Y.colors.info,children:q},K,!1,void 0,this)}catch(W){console.error("InlineRenderer 解析错误:",q,W),G=null}X.push(G??o0(U1,{children:q},K,!1,void 0,this)),Z=Q.lastIndex}if(Z<$.length)X.push(o0(U1,{children:$.slice(Z)},`t-${Z}`,!1,void 0,this));return o0(Fq,{children:X.filter((q)=>q!==null)},void 0,!1,void 0,this)},s0=Hq.memo(_q);import{Box as f8,Text as K7}from"ink";import zq from"react";import{jsxDEV as g$}from"react/jsx-dev-runtime";var Nq=({itemText:$,type:Y,marker:X,leadingWhitespace:Z=""})=>{let Q=Y==="ol"?`${X}. `:`${X} `,J=Q.length,q=Z.length;return g$(f8,{paddingLeft:q+1,flexDirection:"row",children:[g$(f8,{width:J,children:g$(K7,{children:Q},void 0,!1,void 0,this)},void 0,!1,void 0,this),g$(f8,{flexGrow:1,children:g$(K7,{wrap:"wrap",children:g$(s0,{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)},W7=zq.memo(Nq);import{Box as Bq,Text as U$}from"ink";import U7 from"react";import{jsxDEV as t0}from"react/jsx-dev-runtime";var O7=({headers:$,rows:Y,terminalWidth:X})=>{let Z=e.getTheme();if($.length===0||Y.length===0)return null;let Q=$.map((H,_)=>{let z=W$(H),F=Math.max(...Y.map((B)=>W$(B[_]||"")));return Math.max(z,F)+2}),J=$.length+1,q=Q.reduce((H,_)=>H+_,0)+J,G=q>X?X/q:1,K=Q.map((H)=>Math.floor(H*G)),W=(H,_,z=!1)=>{let F=Math.max(0,_-2),B=W$(H),L=H;if(B>F)L=q7(H,F);let N=W$(L),A=Math.max(0,F-N);return t0(U$,{children:[z?t0(U$,{bold:!0,color:Z.colors.primary,children:t0(s0,{text:L},void 0,!1,void 0,this)},void 0,!1,void 0,this):t0(s0,{text:L},void 0,!1,void 0,this)," ".repeat(A)]},void 0,!0,void 0,this)},O=(H)=>{let z={top:{left:"┌",middle:"┬",right:"┐",horizontal:"─"},middle:{left:"├",middle:"┼",right:"┤",horizontal:"─"},bottom:{left:"└",middle:"┴",right:"┘",horizontal:"─"}}[H],F=K.map((L)=>z.horizontal.repeat(L)),B=z.left+F.join(z.middle)+z.right;return t0(U$,{color:Z.colors.text.muted,dimColor:!0,children:B},void 0,!1,void 0,this)},U=(H,_=!1)=>{let z=H.map((F,B)=>{let L=K[B]||0;return W(F||"",L,_)});return t0(U$,{children:[t0(U$,{color:Z.colors.text.muted,children:"│ "},void 0,!1,void 0,this),z.map((F,B)=>t0(U7.Fragment,{children:[F,B<z.length-1&&t0(U$,{color:Z.colors.text.muted,children:" │ "},void 0,!1,void 0,this)]},B,!0,void 0,this)),t0(U$,{color:Z.colors.text.muted,children:" │"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};return t0(Bq,{flexDirection:"column",marginY:1,children:[O("top"),U($,!0),O("middle"),Y.map((H,_)=>t0(U7.Fragment,{children:U(H)},_,!1,void 0,this)),O("bottom")]},void 0,!0,void 0,this)};import{jsxDEV as x}from"react/jsx-dev-runtime";var Lq=($,Y)=>{let Z=e.getTheme().colors;switch($){case"user":return{color:Z.info,prefix:"> "};case"assistant":return{color:Z.success,prefix:"• "};case"system":return{color:Z.warning,prefix:"⚙ "};case"tool":{let Q=Y&&"phase"in Y?Y.phase:void 0;return{color:Z.text.secondary,prefix:Q==="start"?"• ":Q==="complete"?" └ ":" "}}default:return{color:Z.text.primary,prefix:" "}}},O1={codeBlock:/^```(\w+)?\s*$/,heading:/^ *(#{1,4}) +(.+)/,ulItem:/^([ \t]*)([-*+]) +(.+)/,olItem:/^([ \t]*)(\d+)\. +(.+)/,hr:/^ *([-*_] *){3,} *$/,table:/^\|(.+)\|$/,tableSeparator:/^\|[\s]*:?-+:?[\s]*(\|[\s]*:?-+:?[\s]*)+\|?$/,diffStart:/^<<<DIFF>>>$/,diffEnd:/^<<<\/DIFF>>>$/};function wq($){let Y=[],X=$.split(/\r?\n/),Z=!1,Q=[],J=null,q=!1,G=[],K=[],W=!1,O=[],U=!0;for(let H=0;H<X.length;H++){let _=X[H];if(W){if(_.match(O1.diffEnd)){try{let k=JSON.parse(O.join(`
1488
+ `));Y.push({type:"diff",content:"",diffData:{patch:k.patch,startLine:k.startLine,matchLine:k.matchLine}})}catch(k){Y.push({type:"text",content:O.join(`
1489
+ `)})}W=!1,O=[],U=!1;continue}O.push(_);continue}if(_.match(O1.diffStart)){W=!0,O=[],U=!1;continue}if(Z){if(_.match(O1.codeBlock))Y.push({type:"code",content:Q.join(`
1490
+ `),language:J||void 0}),Z=!1,Q=[],J=null,U=!1;else Q.push(_);continue}let z=_.match(O1.codeBlock);if(z){Z=!0,J=z[1]||null,U=!1;continue}let F=_.match(O1.table),B=_.match(O1.tableSeparator);if(F&&!q){if(H+1<X.length){if(X[H+1].match(O1.tableSeparator)){q=!0,G=F[1].split("|").map((I)=>I.trim()).filter((I)=>I.length>0),K=[],U=!1;continue}}}if(q&&B)continue;if(q&&F){let k=F[1].split("|").map((I)=>I.trim()).filter((I)=>I.length>0);while(k.length<G.length)k.push("");if(k.length>G.length)k.length=G.length;K.push(k);continue}if(q&&!F){if(G.length>0&&K.length>0)Y.push({type:"table",content:"",tableData:{headers:G,rows:K}});q=!1,G=[],K=[]}let L=_.match(O1.heading);if(L){Y.push({type:"heading",content:L[2],level:L[1].length}),U=!1;continue}let N=_.match(O1.ulItem);if(N){Y.push({type:"list",content:N[3],listType:"ul",marker:N[2],indentation:N[1].length}),U=!1;continue}let A=_.match(O1.olItem);if(A){Y.push({type:"list",content:A[3],listType:"ol",marker:A[2],indentation:A[1].length}),U=!1;continue}if(_.match(O1.hr)){Y.push({type:"hr",content:""}),U=!1;continue}if(_.trim().length===0){if(!U)Y.push({type:"empty",content:""}),U=!0;continue}Y.push({type:"text",content:_}),U=!1}if(Z)Y.push({type:"code",content:Q.join(`
1491
+ `),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 Aq=({content:$,language:Y,terminalWidth:X})=>{return x(j8,{content:$,language:Y,showLineNumbers:!0,terminalWidth:X},void 0,!1,void 0,this)},Rq=({content:$,level:Y})=>{let X=e.getTheme();switch(Y){case 1:return x(p0,{bold:!0,color:X.colors.primary,children:x(s0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this);case 2:return x(p0,{bold:!0,color:X.colors.primary,children:x(s0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this);case 3:return x(p0,{bold:!0,color:X.colors.text.primary,children:x(s0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this);case 4:return x(p0,{italic:!0,color:X.colors.text.muted,children:x(s0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this);default:return x(p0,{children:x(s0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this)}},bq=({terminalWidth:$})=>{let Y=e.getTheme(),X=Math.max(0,Math.min($-4,80));return x(p0,{dimColor:!0,color:Y.colors.text.muted,children:"─".repeat(X)},void 0,!1,void 0,this)},Vq=({content:$})=>{return x(p0,{wrap:"wrap",children:x(s0,{text:$},void 0,!1,void 0,this)},void 0,!1,void 0,this)},Iq=w6.memo(({detail:$,terminalWidth:Y})=>{let X=e.getTheme(),Z=50,Q=$.split(`
1496
1492
  `),J=Q.length>50,q=J?Q.slice(0,50):Q,G=q.join(`
1497
- `),K=G.includes("<<<DIFF>>>"),W=G.includes("```");if(K){let O=G.match(/<<<DIFF>>>\s*({[\s\S]*?})\s*<<<\/DIFF>>>/);if(O)try{let U=JSON.parse(O[1]);return x(M0,{flexDirection:"column",children:[x(V8,{patch:U.patch,startLine:U.startLine,matchLine:U.matchLine,terminalWidth:Y},void 0,!1,void 0,this),J&&x(M0,{marginTop:1,children:x(h0,{dimColor:!0,color:X.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 O=G.match(/```(\w+)?\s*\n([\s\S]*?)\n```/);if(O){let U=O[1]||"text",H=O[2];return x(M0,{flexDirection:"column",children:[x(b8,{content:H,language:U,showLineNumbers:!1,terminalWidth:Y},void 0,!1,void 0,this),J&&x(M0,{marginTop:1,children:x(h0,{dimColor:!0,color:X.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 x(M0,{flexDirection:"column",children:[q.map((O,U)=>x(h0,{color:X.colors.text.primary,children:O},U,!1,void 0,this)),J&&x(M0,{marginTop:1,children:x(h0,{dimColor:!0,color:X.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)}),W2=H6.memo(({content:$,role:Y,terminalWidth:X,metadata:Z,isPending:Q=!1})=>{let J=H6.useMemo(()=>nJ(Y,Z),[Y,Z]),{color:q,prefix:G}=J;if(Y==="tool"&&Z&&"detail"in Z){let W=Z;if(W.detail)return x(M0,{flexDirection:"column",marginBottom:1,children:[x(M0,{flexDirection:"row",children:[x(M0,{marginRight:1,children:x(h0,{color:q,bold:!0,children:G},void 0,!1,void 0,this)},void 0,!1,void 0,this),x(h0,{color:q,children:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this),x(M0,{marginLeft:G.length+1,marginTop:1,children:x(Yq,{detail:W.detail,terminalWidth:X-(G.length+1)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}let K=H6.useMemo(()=>oJ($),[$]);return x(M0,{flexDirection:"column",marginBottom:1,children:K.map((W,O)=>{if(W.type==="empty")return x(M0,{height:1},O,!1,void 0,this);return x(M0,{flexDirection:"row",children:[O===0&&x(M0,{marginRight:1,children:x(h0,{color:q,bold:!0,children:G},void 0,!1,void 0,this)},void 0,!1,void 0,this),O>0&&x(M0,{width:G.length+1},void 0,!1,void 0,this),x(M0,{flexGrow:1,children:W.type==="code"?x(sJ,{content:W.content,language:W.language,terminalWidth:X-(G.length+1)},void 0,!1,void 0,this):W.type==="table"&&W.tableData?x(l3,{headers:W.tableData.headers,rows:W.tableData.rows,terminalWidth:X-(G.length+1)},void 0,!1,void 0,this):W.type==="heading"?x(tJ,{content:W.content,level:W.level||1},void 0,!1,void 0,this):W.type==="list"?x(d3,{type:W.listType||"ul",marker:W.marker||"-",itemText:W.content,leadingWhitespace:" ".repeat(W.indentation||0)},void 0,!1,void 0,this):W.type==="hr"?x(eJ,{terminalWidth:X-(G.length+1)},void 0,!1,void 0,this):W.type==="diff"&&W.diffData?x(V8,{patch:W.diffData.patch,startLine:W.diffData.startLine,matchLine:W.diffData.matchLine,terminalWidth:X-(G.length+1)},void 0,!1,void 0,this):x($q,{content:W.content},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},O,!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 W0}from"react/jsx-dev-runtime";var Jq=({label:$,isSelected:Y})=>W0(K1,{color:Y?"yellow":void 0,children:$},void 0,!1,void 0,this),i3=({details:$,onResponse:Y})=>{let X=P$(),Q=i0()==="confirmation-prompt",J=b0(!1);Xq((U,H)=>{if(H.ctrl&&U==="c"||H.meta&&U==="c"){J();return}if(H.escape){Y({approved:!1,reason:"用户取消"});return}let _=U.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(_==="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 q=$.type==="exitPlanMode",G=$.type==="enterPlanMode",K=Qq(()=>{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 模式"}}];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]),O=(()=>{if(q)return{color:"cyan",title:"\uD83D\uDD35 Plan Mode - Review Implementation Plan"};if(G)return{color:"magenta",title:"\uD83D\uDFE3 Enter Plan Mode?"};return{color:"yellow",title:"\uD83D\uDD14 Confirmation Required"}})();return W0(s0,{flexDirection:"column",borderStyle:"round",borderColor:Q?O.color:"gray",padding:1,children:[W0(s0,{marginBottom:1,children:W0(K1,{bold:!0,color:O.color,children:O.title},void 0,!1,void 0,this)},void 0,!1,void 0,this),$.title&&W0(s0,{marginBottom:1,children:W0(K1,{bold:!0,children:$.title},void 0,!1,void 0,this)},void 0,!1,void 0,this),W0(s0,{marginBottom:1,children:W0(K1,{children:$.message},void 0,!1,void 0,this)},void 0,!1,void 0,this),($.planContent||$.details)&&W0(s0,{flexDirection:"column",marginBottom:1,borderStyle:"single",borderColor:O.color,padding:1,children:[W0(K1,{bold:!0,color:O.color,children:q?"\uD83D\uDCCB Implementation Plan:":G?"\uD83D\uDCDD Details:":"\uD83D\uDCC4 Operation Details:"},void 0,!1,void 0,this),W0(s0,{marginTop:1,children:W0(W2,{content:$.planContent||$.details||"",role:"assistant",terminalWidth:X-4},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$.risks&&$.risks.length>0&&W0(s0,{flexDirection:"column",marginBottom:1,children:[W0(K1,{color:"red",bold:!0,children:"⚠️ 风险提示:"},void 0,!1,void 0,this),$.risks.map((U,H)=>W0(s0,{marginLeft:2,children:W0(K1,{color:"red",children:["• ",U]},void 0,!0,void 0,this)},H,!1,void 0,this))]},void 0,!0,void 0,this),$.affectedFiles&&$.affectedFiles.length>0&&W0(s0,{flexDirection:"column",marginBottom:1,children:[W0(K1,{color:"yellow",children:"\uD83D\uDCC1 影响的文件:"},void 0,!1,void 0,this),$.affectedFiles.slice(0,3).map((U,H)=>W0(s0,{marginLeft:2,children:W0(K1,{children:["• ",U]},void 0,!0,void 0,this)},H,!1,void 0,this)),$.affectedFiles.length>3&&W0(s0,{marginLeft:2,children:W0(K1,{color:"gray",children:["...还有 ",$.affectedFiles.length-3," 个文件"]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),W0(s0,{flexDirection:"column",children:[W0(K1,{color:"gray",children:"使用 ↑ ↓ 选择,回车确认(支持 Y/S/N 快捷键,ESC 取消)"},void 0,!1,void 0,this),W0(Zq,{items:K,isFocused:Q,itemComponent:Jq,onSelect:(U)=>{Y(U.value)}},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{useMemoizedFn as YY}from"ahooks";import{Box as Iq,Text as kq}from"ink";import vq from"react";import{writeFileSync as qq}from"node:fs";import{join as Gq}from"node:path";import{tmpdir as Kq}from"node:os";import{nanoid as Wq}from"nanoid";function r3($,Y,X){let Z=Uq(Y),Q=Date.now(),J=Wq(8),q=X||`blade_image_${Q}_${J}.${Z}`,G=Kq(),K=Gq(G,q),W=Buffer.from($,"base64");qq(K,W);let O=`[Image: ${q}]`;return console.log(`[ImageHandler] Saved image to: ${K}`),console.log(`[ImageHandler] Size: ${(W.length/1024).toFixed(2)} KB`),{filePath:K,filename:q,tag:O}}function Uq($){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 Lq}from"ahooks";import Q$ from"chalk";import{Text as wq,useInput as Aq}from"ink";import{useEffect as e3,useRef as Rq}from"react";var p1={TIMEOUT_MS:100,RAPID_INPUT_THRESHOLD_MS:150,LARGE_INPUT_THRESHOLD:300,MEDIUM_SIZE_MULTI_CHUNK_THRESHOLD:200};import{execSync as Oq}from"node:child_process";import{existsSync as wA,readFileSync as a3}from"node:fs";import{basename as n3,isAbsolute as Hq}from"node:path";function _q(){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 RA=_q();function Fq($){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 zq(){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"},X={darwin:{checkImage:"osascript -e 'the clipboard as «class PNGf»'",saveImage:(Z)=>`osascript -e 'set png_data to (the clipboard as «class PNGf»)' -e 'set fp to open for access POSIX file "${Z}" 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:(Z)=>`rm -f "${Z}"`},linux:{checkImage:'xclip -selection clipboard -t TARGETS -o | grep -E "image/(png|jpeg|jpg|gif|webp)"',saveImage:(Z)=>`xclip -selection clipboard -t image/png -o > "${Z}" || wl-paste --type image/png > "${Z}"`,getPath:"xclip -selection clipboard -t text/plain -o",deleteFile:(Z)=>`rm -f "${Z}"`},win32:{checkImage:'powershell -Command "(Get-Clipboard -Format Image) -ne $null"',saveImage:(Z)=>`powershell -Command "$img = Get-Clipboard -Format Image; if ($img) { $img.Save('${Z.replace(/\\/g,"\\\\")}', [System.Drawing.Imaging.ImageFormat]::Png) }"`,getPath:'powershell -Command "Get-Clipboard"',deleteFile:(Z)=>`del /f "${Z}"`}};return{commands:X[$]||X.linux,screenshotPath:Y[$]||Y.linux}}function Nq(){let{commands:$}=zq();try{return Oq($.getPath,{encoding:"utf-8"}).trim()}catch(Y){return console.error("Failed to get clipboard path:",Y),null}}function o3($){if($.startsWith('"')&&$.endsWith('"')||$.startsWith("'")&&$.endsWith("'"))return $.slice(1,-1);return $}function s3($){if(process.platform==="win32")return $;let Y="__DOUBLE_BACKSLASH__";return $.replace(/\\\\/g,Y).replace(/\\(.)/g,"$1").replace(new RegExp(Y,"g"),"\\")}function M8($){let Y=o3($.trim()),X=s3(Y);return/\.(png|jpe?g|gif|webp)$/i.test(X)}function Bq($){let Y=o3($.trim()),X=s3(Y);if(M8(X))return X;return null}async function t3($){let Y=Bq($);if(!Y)return null;let X;try{if(Hq(Y))X=a3(Y);else{let q=Nq();if(q&&Y===n3(q))X=a3(q);else return null}}catch(q){return console.error("Failed to read image file:",q),null}let Z=X.toString("base64"),Q=Fq(Z),J=n3(Y);return{path:Y,base64:Z,mediaType:Q,filename:J}}import{jsxDEV as Dq}from"react/jsx-dev-runtime";var bq=/\r\n/g,Vq=/\r/g;function _6($){if(!$.includes("\r"))return $;return $.replace(bq,`
1498
- `).replace(Vq,`
1499
- `)}function F6($,Y,X){let Z=Math.max(0,Math.min(X,Y.length)),Q=Y.slice(0,Z),J=Y.slice(Z);return{newValue:Q+$+J,newCursorPosition:Z+$.length}}function $Y({value:$,placeholder:Y="",focus:X=!0,onChange:Z,cursorPosition:Q,onChangeCursorPosition:J,onPaste:q,onImagePaste:G,disabledKeys:K=[]}){let W=Rq({chunks:[],timeoutId:null,firstInputTime:null,lastInputTime:null,totalLength:0});e3(()=>{return()=>{if(W.current.timeoutId)clearTimeout(W.current.timeoutId)}},[]),e3(()=>{if(Q>$.length)J($.length)},[$,Q,J]);let O=Lq(()=>{let z=W.current;if(z.timeoutId)clearTimeout(z.timeoutId);let F=setTimeout(async()=>{let L=W.current.chunks,w=W.current.totalLength;if(L.length===0)return;let N=_6(L.join(""));if(W.current={chunks:[],timeoutId:null,firstInputTime:null,lastInputTime:null,totalLength:0},G&&M8(N))try{let D=await t3(N);if(D){let C=await G(D.base64,D.mediaType,D.filename);if(C?.prompt){let p=_6(C.prompt),{newValue:E,newCursorPosition:M}=F6(p,$,Q);Z(E),J(M)}return}}catch(D){console.error("Failed to process image path:",D)}let A=N.includes(`
1500
- `),b=w>p1.MEDIUM_SIZE_MULTI_CHUNK_THRESHOLD&&L.length>3;if((w>p1.LARGE_INPUT_THRESHOLD||A||b)&&q){let D=await q(N);if(D?.prompt){let C=_6(D.prompt),{newValue:p,newCursorPosition:E}=F6(C,$,Q);Z(p),J(E);return}}let{newValue:R,newCursorPosition:B}=F6(N,$,Q);Z(R),J(B)},p1.TIMEOUT_MS);W.current.timeoutId=F});Aq((z,F)=>{let L=_6(z);if(K.some((R)=>F[R])||F.ctrl&&z==="c"||F.shift&&F.tab||L==="?"&&$==="")return;let N=Date.now(),A=W.current,b=Q,y=$;if(F.leftArrow)b--;else if(F.rightArrow)b++;else if(F.backspace||F.delete){if(z===""){if(Q>0)y=$.slice(0,Q-1)+$.slice(Q,$.length),b--}else if(Q<$.length)y=$.slice(0,Q)+$.slice(Q+1,$.length)}else if(F.ctrl&&L==="a")b=0;else if(F.ctrl&&L==="e")b=$.length;else if(F.ctrl&&L==="k")y=$.slice(0,Q);else if(F.ctrl&&L==="u")y=$.slice(Q),b=0;else if(F.ctrl&&L==="w"){let B=$.slice(0,Q).match(/\s*\S+\s*$/);if(B){let D=B[0].length;y=$.slice(0,Q-D)+$.slice(Q),b-=D}}else if(F.pageUp)b=0;else if(F.pageDown)b=$.length;else if(L===`
1501
- `&&(F.shift||F.meta)){let{newValue:R,newCursorPosition:B}=F6(L,$,Q);Z(R),J(B);return}else if(!F.ctrl&&!F.meta){if(!A.firstInputTime)A.firstInputTime=N;A.lastInputTime=N;let R=N-(A.firstInputTime||N),B=L.length>p1.LARGE_INPUT_THRESHOLD,D=L.includes(`
1502
- `)&&L.length>1,C=R<p1.RAPID_INPUT_THRESHOLD_MS&&A.chunks.length>0,p=R<p1.RAPID_INPUT_THRESHOLD_MS&&L.length>10,E=A.timeoutId!==null;if(q&&(B||D||C||p||E)){A.chunks.push(L),A.totalLength+=L.length,O();return}if(L.length===1&&!A.timeoutId)A.chunks=[],A.firstInputTime=null,A.lastInputTime=null,A.totalLength=0;y=$.slice(0,Q)+L+$.slice(Q,$.length),b+=L.length}if(b<0)b=0;if(b>y.length)b=y.length;if(y!==$)Z(y);if(b!==Q)J(b)},{isActive:X});let U=X,H=$,_=Y?Q$.grey(Y):void 0;if(U)if(_=Y.length>0?Q$.inverse(Y[0])+Q$.grey(Y.slice(1)):Q$.inverse(" "),$.length===0)H=Q$.inverse(" ");else{H="";for(let z=0;z<$.length;z++)if(z===Q&&Q<$.length)H+=Q$.inverse($[z]);else H+=$[z];if(Q>=$.length)H+=Q$.inverse(" ")}return Dq(wq,{children:Y?$.length>0?H:_:H},void 0,!1,void 0,this)}import{jsxDEV as y8}from"react/jsx-dev-runtime";var XY=vq.memo(({input:$,cursorPosition:Y,onChange:X,onChangeCursorPosition:Z})=>{let J=i0()==="main-input",q=YY((K)=>{let W=K.split(`
1503
- `).length,O=K.length,U=500,H=10;if(O>500||W>10){let _=K.slice(0,30).replace(/\n/g," ");return{prompt:`[Pasted: ${O} chars, ${W} lines] ${_}...`}}return{}}),G=YY(async(K,W,O)=>{try{return{prompt:`[Image saved to ${r3(K,W,O).filePath}. Note: Image attachments not yet supported by @ mentions] `}}catch(U){return console.error("[Image Paste] Failed to process image:",U),{prompt:`[Image paste failed: ${U instanceof Error?U.message:"Unknown error"}] `}}});return y8(Iq,{flexDirection:"row",paddingX:2,paddingY:0,borderStyle:"round",borderColor:"gray",children:[y8(kq,{color:"blue",bold:!0,children:"> "},void 0,!1,void 0,this),y8($Y,{value:$,cursorPosition:Y,onChange:X,onChangeCursorPosition:Z,onPaste:q,onImagePaste:G,placeholder:" 输入命令...",focus:J,disabledKeys:["upArrow","downArrow","tab","return","escape"]},void 0,!1,void 0,this)]},void 0,!0,void 0,this)});import{Box as z6,Text as W1}from"ink";import Pq,{useEffect as Sq,useState as Tq}from"react";import{useEffect as jq,useState as qY}from"react";import{useEffect as Mq,useState as yq}from"react";var Eq=15000,ZY=["炼化代码灵气...","参悟 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 广纳贤才..."],QY=["Esc - 立即停止当前任务","Shift+Tab - 切换权限模式 (default/auto_edit/plan)","Tab - 智能补全斜杠命令","↑↓ - 浏览输入历史记录","双击 Esc - 快速清空输入框","Ctrl+C - 强制终止程序","Ctrl+D - 优雅退出 Blade","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 JY($,Y){let[X,Z]=yq("");return Mq(()=>{if(Y){Z("等待用户确认...");return}if(!$){Z("");return}let Q=()=>{if(Math.random()<0.16666666666666666){let K=Math.floor(Math.random()*QY.length);return QY[K]}let G=Math.floor(Math.random()*ZY.length);return ZY[G]};Z(Q());let J=setInterval(()=>{Z(Q())},Eq);return()=>{clearInterval(J)}},[$,Y]),X}function GY($,Y=!1){let[X,Z]=qY(0),[Q,J]=qY(null),q=JY($,Y);return jq(()=>{if(!$){Z(0),J(null);return}if(Q===null)J(Date.now());let G=setInterval(()=>{if(Q!==null){let K=Math.floor((Date.now()-Q)/1000);Z(K)}},1000);return()=>{clearInterval(G)}},[$,Q]),{currentPhrase:q,elapsedTime:X}}import{jsxDEV as y0,Fragment as fq}from"react/jsx-dev-runtime";var E8=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"],Cq=80;function KY($){if($<60)return`${$}s`;let Y=Math.floor($/60),X=$%60;return`${Y}m ${X}s`}var WY=Pq.memo(({message:$})=>{let Y=h1(),X=t2(),Z=Y||!X,[Q,J]=Tq(0),q=$0.getTheme(),K=P$()>=Cq,{currentPhrase:W,elapsedTime:O}=GY(Z,!1);if(Sq(()=>{if(!Z){J(0);return}let H=setInterval(()=>{J((_)=>(_+1)%E8.length)},80);return()=>clearInterval(H)},[Z]),!Z)return null;let U=W||$||"正在思考中...";if(K)return y0(z6,{paddingX:2,paddingBottom:1,flexDirection:"row",gap:1,children:[y0(W1,{color:q.colors.warning,bold:!0,children:E8[Q]},void 0,!1,void 0,this),y0(W1,{color:q.colors.text.primary,children:U},void 0,!1,void 0,this),O>0&&y0(fq,{children:[y0(W1,{color:q.colors.muted,children:"|"},void 0,!1,void 0,this),y0(W1,{color:q.colors.info,children:["已用时: ",KY(O)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),y0(W1,{color:q.colors.muted,children:"|"},void 0,!1,void 0,this),y0(W1,{color:q.colors.secondary,children:"Esc 取消"},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return y0(z6,{paddingX:2,paddingBottom:1,flexDirection:"column",children:[y0(z6,{flexDirection:"row",gap:1,children:[y0(W1,{color:q.colors.warning,bold:!0,children:E8[Q]},void 0,!1,void 0,this),y0(W1,{color:q.colors.text.primary,children:U},void 0,!1,void 0,this)]},void 0,!0,void 0,this),O>0&&y0(z6,{marginLeft:2,flexDirection:"row",gap:1,children:[y0(W1,{color:q.colors.info,children:["已用时: ",KY(O)]},void 0,!0,void 0,this),y0(W1,{color:q.colors.muted,children:"|"},void 0,!1,void 0,this),y0(W1,{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 H2,Static as uq}from"ink";import dq,{useMemo as P8}from"react";import{Box as U2,Text as O2}from"ink";import hq from"ink-big-text";import xq from"ink-gradient";import pq from"react";import{jsxDEV as t0}from"react/jsx-dev-runtime";var UY=pq.memo(()=>{return t0(U2,{flexDirection:"column",paddingX:2,paddingTop:1,paddingBottom:1,children:[t0(U2,{flexDirection:"column",children:t0(xq,{name:"pastel",children:t0(hq,{text:"BLADE",font:"block"},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),t0(U2,{marginBottom:1,children:t0(O2,{color:"white",dimColor:!0,children:m8()},void 0,!1,void 0,this)},void 0,!1,void 0,this),t0(U2,{flexDirection:"column",marginBottom:1,children:[t0(U2,{marginBottom:1,children:t0(O2,{color:"white",bold:!0,children:"使用指南:"},void 0,!1,void 0,this)},void 0,!1,void 0,this),t0(O2,{color:"white",children:"1. 输入问题、编辑文件或运行命令"},void 0,!1,void 0,this),t0(O2,{color:"white",children:"2. 使用 /init 创建项目配置文件"},void 0,!1,void 0,this),t0(O2,{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 N6,Text as j8}from"ink";import{useState as OY}from"react";function gq(){let[$,Y]=OY($0.getTheme()),[X,Z]=OY($0.getCurrentThemeName()),Q=(K)=>{try{$0.setTheme(K),Y($0.getTheme()),Z(K)}catch(W){console.error("Failed to change theme:",W)}},J=$0.getAvailableThemes();return{theme:$,themeName:X,changeTheme:Q,availableThemes:J,hasTheme:(K)=>$0.hasTheme(K),getThemeByName:(K)=>$0.getThemeByName(K),colors:$.colors,spacing:$.spacing,typography:$.typography}}function HY(){let{colors:$}=gq();return $}import{jsxDEV as g1}from"react/jsx-dev-runtime";var _Y=({todos:$,visible:Y=!0,compact:X=!1})=>{let Z=HY();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 g1(N6,{flexDirection:"column",borderStyle:"single",borderColor:Z.border.light,paddingX:1,paddingY:X?0:1,marginBottom:1,children:[g1(N6,{marginBottom:X?0:1,children:[g1(j8,{dimColor:!0,children:"Tasks "},void 0,!1,void 0,this),g1(j8,{color:Z.text.muted,children:[Q.completed,"/",Q.total]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),g1(N6,{flexDirection:"column",children:$.map((J,q)=>g1(mq,{todo:J,compact:X},J.id||q,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},mq=({todo:$,compact:Y})=>{let X,Z=!1,Q;switch($.status){case"completed":X="✓",Z=!0,Q=$.content;break;case"in_progress":X="▶",Z=!1,Q=$.activeForm;break;case"pending":default:X="○",Z=!0,Q=$.content;break}return g1(N6,{paddingY:Y?0:0,children:g1(j8,{dimColor:Z,children:[X," ",Q]},void 0,!0,void 0,this)},void 0,!1,void 0,this)};import{jsxDEV as A1}from"react/jsx-dev-runtime";var FY=dq.memo(()=>{let $=o2(),Y=h1(),X=I5(),Z=y5(),Q=f5(),J=P$(),{completedMessages:q,streamingMessage:G}=P8(()=>{if(Y&&$.length>0)return{completedMessages:$.slice(0,-1),streamingMessage:$[$.length-1]};return{completedMessages:$,streamingMessage:null}},[$,Y]),K=P8(()=>{return X.some((U)=>U.status==="pending"||U.status==="in_progress")},[X]),W=(U,H,_=!1)=>A1(H2,{flexDirection:"column",children:A1(W2,{content:U.content,role:U.role,terminalWidth:J,metadata:U.metadata,isPending:_},void 0,!1,void 0,this)},U.id,!1,void 0,this),O=P8(()=>{let U=[];return U.push(A1(UY,{},"header",!1,void 0,this)),q.forEach((H,_)=>{U.push(W(H,_))}),U},[q,J]);return A1(H2,{flexDirection:"column",flexGrow:1,paddingX:2,children:A1(H2,{flexDirection:"column",flexGrow:1,children:[A1(uq,{items:O,children:(U)=>U},void 0,!1,void 0,this),G&&W(G,q.length,!0),Z&&K&&A1(H2,{marginTop:1,children:A1(_Y,{todos:X,visible:!0,compact:!1},void 0,!1,void 0,this)},void 0,!1,void 0,this),Q.map((U,H)=>A1(H2,{flexDirection:"column",children:A1(W2,{content:U,role:"user",terminalWidth:J},void 0,!1,void 0,this)},`pending-${H}`,!1,void 0,this))]},void 0,!0,void 0,this)},void 0,!1,void 0,this)});import{Box as l,Text as h,useFocus as zY,useFocusManager as cq,useInput as w6}from"ink";import lq from"ink-select-input";import iq from"ink-text-input";import{useEffect as rq,useState as _2}from"react";import{jsxDEV as I,Fragment as L6}from"react/jsx-dev-runtime";var aq=({isSelected:$})=>I(l,{marginRight:1,children:I(h,{color:$?"yellow":"gray",children:$?"▶":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),nq=({isSelected:$,label:Y})=>I(h,{bold:$,color:$?"yellow":void 0,children:Y},void 0,!1,void 0,this),oq=({onSelect:$,onCancel:Y,initialProvider:X})=>{let{isFocused:Z}=zY({id:"provider-step"});w6((q,G)=>{if(G.escape)Y()},{isActive:Z});let Q=[{label:"⚡ OpenAI Compatible - 兼容 OpenAI API 的服务 (千问/豆包/DeepSeek等)",value:"openai-compatible"},{label:"\uD83E\uDD16 Anthropic Claude API - Claude 官方 API",value:"anthropic"}],J=X?Math.max(0,Q.findIndex((q)=>q.value===X)):0;return I(l,{flexDirection:"column",marginBottom:1,children:[I(l,{marginBottom:1,children:I(h,{bold:!0,color:"blue",children:"\uD83D\uDCE1 Step 2: 选择 API 提供商"},void 0,!1,void 0,this)},void 0,!1,void 0,this),I(l,{marginBottom:1,children:I(h,{children:"根据您使用的 LLM 服务选择对应的 API 类型"},void 0,!1,void 0,this)},void 0,!1,void 0,this),I(l,{marginBottom:1,children:I(lq,{items:Q,onSelect:(q)=>$(q.value),indicatorComponent:aq,itemComponent:nq,initialIndex:J},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},B6=({stepNumber:$,icon:Y,title:X,description:Z,hint:Q,examples:J,value:q,placeholder:G,mask:K,previousValue:W,onChange:O,onSubmit:U,onCancel:H})=>{return w6((_,z)=>{if(z.escape)H()},{isActive:!0}),I(l,{flexDirection:"column",marginBottom:1,children:[I(l,{marginBottom:1,children:I(h,{bold:!0,color:"blue",children:[Y," Step ",$,": ",X]},void 0,!0,void 0,this)},void 0,!1,void 0,this),I(l,{marginBottom:1,children:I(h,{children:Z},void 0,!1,void 0,this)},void 0,!1,void 0,this),W&&I(l,{marginBottom:1,children:I(h,{color:"green",children:["✓ ",W]},void 0,!0,void 0,this)},void 0,!1,void 0,this),Q&&I(l,{marginBottom:1,children:I(h,{dimColor:!0,children:Q},void 0,!1,void 0,this)},void 0,!1,void 0,this),J&&J.length>0&&I(L6,{children:[I(l,{marginBottom:1,children:I(h,{dimColor:!0,children:"常见示例:"},void 0,!1,void 0,this)},void 0,!1,void 0,this),I(l,{marginBottom:1,paddingLeft:2,children:I(h,{dimColor:!0,children:J.join(`
1504
- `)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),I(l,{children:[I(h,{bold:!0,color:"cyan",children:["▶"," "]},void 0,!0,void 0,this),I(iq,{value:q,onChange:O,onSubmit:U,placeholder:G,mask:K},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},sq=({mode:$,config:Y,isSaving:X,onConfirm:Z,onBack:Q,onCancel:J})=>{let{isFocused:q}=zY({id:"confirm-step"});return w6((G,K)=>{if(X)return;if(G==="y"||G==="Y")Z();else if(G==="n"||G==="N")Q();else if(K.escape)J()},{isActive:q&&!X}),I(l,{flexDirection:"column",marginBottom:1,children:[I(l,{marginBottom:1,children:I(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),I(l,{marginBottom:1,children:I(h,{children:$==="edit"?"请确认修改内容,保存后将立即生效。":"请确认以下配置信息:"},void 0,!1,void 0,this)},void 0,!1,void 0,this),I(l,{flexDirection:"column",marginBottom:1,paddingLeft:2,children:[I(l,{marginBottom:1,children:[I(h,{dimColor:!0,children:"名称: "},void 0,!1,void 0,this),I(h,{bold:!0,color:"cyan",children:Y.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),I(l,{marginBottom:1,children:[I(h,{dimColor:!0,children:"Provider: "},void 0,!1,void 0,this),I(h,{bold:!0,color:"cyan",children:Y.provider==="openai-compatible"?"⚡ OpenAI Compatible":"\uD83E\uDD16 Anthropic"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),I(l,{marginBottom:1,children:[I(h,{dimColor:!0,children:"Base URL: "},void 0,!1,void 0,this),I(h,{bold:!0,color:"blue",children:Y.baseUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this),I(l,{marginBottom:1,children:[I(h,{dimColor:!0,children:"API Key: "},void 0,!1,void 0,this),I(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),I(l,{children:[I(h,{dimColor:!0,children:"Model: "},void 0,!1,void 0,this),I(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),!X&&I(l,{marginTop:1,children:I(h,{children:[$==="edit"?"保存修改? ":"确认保存配置? ","[",I(h,{bold:!0,color:"green",children:"Y"},void 0,!1,void 0,this),"/",I(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),X&&I(l,{children:I(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)},S8=({mode:$,initialConfig:Y,modelId:X,onComplete:Z,onCancel:Q})=>{let J=$==="edit",[q,G]=_2("name"),[K,W]=_2(()=>J&&Y?{...Y}:{}),[O,U]=_2(J&&Y?Y.name:""),[H,_]=_2(!1),[z,F]=_2(null),L=b0(!1);w6((M,i)=>{if(i.ctrl&&M==="c"||i.meta&&M==="c")if($==="setup")L();else Q()},{isActive:!0});let{focus:w}=cq();rq(()=>{if(q==="provider")w("provider-step");else if(q==="confirm")w("confirm-step")},[q,w]);let N=()=>{if(!O.trim()){F("配置名称不能为空");return}W({...K,name:O}),U(""),F(null),G("provider")},A=(M)=>{W({...K,provider:M});let i=J?K.baseUrl??Y?.baseUrl??"":"";U(i),G("baseUrl")},b=()=>{if(!O.trim()){F("Base URL 不能为空");return}try{new URL(O)}catch{F("请输入有效的 URL (例如: https://api.openai.com/v1)");return}W({...K,baseUrl:O});let M=J?K.apiKey??Y?.apiKey??"":"";U(M),F(null),G("apiKey")},y=()=>{if(!O.trim()){F("API Key 不能为空");return}W({...K,apiKey:O});let M=J?K.model??Y?.model??"":"";U(M),F(null),G("model")},R=()=>{if(!O.trim()){F("Model 不能为空");return}W({...K,model:O}),U(""),F(null),G("confirm")},B=async()=>{_(!0),F(null);try{let M={name:K.name,provider:K.provider,baseUrl:K.baseUrl,apiKey:K.apiKey,model:K.model};if($==="setup")Z(M);else if($==="add")await e().addModel(M),Z(M);else{if(!X)throw Error("未提供模型 ID,无法编辑");await e().updateModel(X,M),Z(M)}}catch(M){F(M instanceof Error?M.message:"配置失败"),_(!1)}},D=()=>{switch(F(null),U(""),q){case"provider":U(K.name||""),G("name");break;case"baseUrl":G("provider");break;case"apiKey":U(K.baseUrl||""),G("baseUrl");break;case"model":G("apiKey");break;case"confirm":U(K.model||""),G("model");break}},C=q==="name"?1:q==="provider"?2:q==="baseUrl"?3:q==="apiKey"?4:q==="model"?5:6,p=Math.floor((C-1)/5*40);return I(l,{...$==="setup"?{flexDirection:"column",padding:1}:$==="add"?{flexDirection:"column",borderStyle:"round",borderColor:"blue",padding:1}:{flexDirection:"column",borderStyle:"round",borderColor:"yellow",padding:1},children:[$==="setup"?I(L6,{children:[I(l,{marginBottom:1,children:I(h,{bold:!0,color:"blue",children:"\uD83D\uDE80 欢迎使用 Blade Code"},void 0,!1,void 0,this)},void 0,!1,void 0,this),I(l,{marginBottom:1,children:I(h,{children:"AI 驱动的代码助手 - 让我们开始配置您的助手"},void 0,!1,void 0,this)},void 0,!1,void 0,this),I(l,{marginBottom:1,children:[I(h,{bold:!0,color:"blue",children:"█".repeat(p)},void 0,!1,void 0,this),I(h,{dimColor:!0,children:"░".repeat(40-p)},void 0,!1,void 0,this),I(h,{children:" "},void 0,!1,void 0,this),I(h,{bold:!0,color:"cyan",children:[C,"/6"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),I(l,{marginBottom:1,children:I(h,{dimColor:!0,children:"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this):$==="add"?I(L6,{children:[I(l,{justifyContent:"center",marginBottom:1,children:I(h,{bold:!0,color:"blue",children:"添加新模型配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),I(l,{marginBottom:1,children:I(h,{children:["步骤: ",C,"/6"]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this):I(L6,{children:[I(l,{justifyContent:"center",marginBottom:1,children:I(h,{bold:!0,color:"yellow",children:"编辑模型配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),I(l,{marginBottom:1,children:I(h,{children:["步骤: ",C,"/6"]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q==="name"&&I(B6,{stepNumber:1,icon:"\uD83D\uDCDD",title:"配置名称",description:"给这个模型配置起一个易于识别的名称",value:O,placeholder:"例如: 千问工作账号",onChange:U,onSubmit:N,onCancel:Q},void 0,!1,void 0,this),q==="provider"&&I(oq,{onSelect:A,onCancel:Q,initialProvider:K.provider},void 0,!1,void 0,this),q==="baseUrl"&&I(B6,{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:O,placeholder:"https://api.example.com/v1",onChange:U,onSubmit:b,onCancel:Q},void 0,!1,void 0,this),q==="apiKey"&&I(B6,{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:O,placeholder:"sk-...",mask:"*",onChange:U,onSubmit:y,onCancel:Q},void 0,!1,void 0,this),q==="model"&&I(B6,{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:O,placeholder:"例如: gpt-5",onChange:U,onSubmit:R,onCancel:Q},void 0,!1,void 0,this),q==="confirm"&&I(sq,{mode:$,config:K,isSaving:H,onConfirm:B,onBack:D,onCancel:Q},void 0,!1,void 0,this),z&&I(l,{marginTop:1,borderStyle:"round",borderColor:"red",paddingX:1,children:I(h,{color:"red",children:["❌ ",z]},void 0,!0,void 0,this)},void 0,!1,void 0,this),I(l,{marginTop:1,children:I(h,{dimColor:!0,children:"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"},void 0,!1,void 0,this)},void 0,!1,void 0,this),!H&&q==="provider"&&I(l,{marginTop:1,children:I(h,{dimColor:!0,children:["\uD83D\uDCA1 使用 ",I(h,{bold:!0,children:"↑/↓"},void 0,!1,void 0,this)," 键选择,",I(h,{bold:!0,children:"Enter"},void 0,!1,void 0,this)," 确认,",I(h,{bold:!0,children:"Esc"},void 0,!1,void 0,this)," 取消"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),!H&&q!=="confirm"&&q!=="provider"&&I(l,{marginTop:1,children:I(h,{dimColor:!0,children:["\uD83D\uDCA1 输入完成后按 ",I(h,{bold:!0,children:"Enter"},void 0,!1,void 0,this),",",I(h,{bold:!0,children:"Ctrl+C"},void 0,!1,void 0,this)," 退出"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),!H&&q==="confirm"&&I(l,{marginTop:1,children:I(h,{dimColor:!0,children:["\uD83D\uDCA1 按"," ",I(h,{bold:!0,color:"green",children:"Y"},void 0,!1,void 0,this)," ","保存,",I(h,{bold:!0,color:"red",children:"N"},void 0,!1,void 0,this)," ","返回修改,",I(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 A6,useMount as tq}from"ahooks";import{Box as e0,Text as Z0,useFocus as eq,useFocusManager as $G,useInput as YG}from"ink";import XG from"ink-select-input";import{memo as ZG,useMemo as QG,useState as R6}from"react";import{jsxDEV as u}from"react/jsx-dev-runtime";var JG=({isSelected:$})=>u(e0,{marginRight:1,children:u(Z0,{color:$?"yellow":"gray",children:$?"▶":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),qG=({isSelected:$,label:Y})=>u(Z0,{bold:$,color:$?"yellow":void 0,children:Y},void 0,!1,void 0,this),NY=ZG(({onClose:$,onEdit:Y})=>{let X=E5(),Z=P5()??"",{isFocused:Q}=eq({id:"model-selector"}),J=$G(),[q,G]=R6(""),[K,W]=R6(!1),[O,U]=R6(null),H=b0(!1),[_]=R6(()=>{let R=process.stdout?.columns||80;return Math.max(20,R-8)});tq(()=>{if(J?.focus("model-selector"),X.length>0)G(X[0].id)}),YG((R,B)=>{if(K)return;if(B.ctrl&&R==="c"||B.meta&&R==="c"){H();return}if(B.escape){$();return}if(!Q)return;if(R==="d"||R==="D"){F();return}if((R==="e"||R==="E")&&Y)L()},{isActive:!0});let z=A6(async(R)=>{if(K)return;let B=R.value;if(B===Z){$();return}W(!0),U(null);try{await e().setCurrentModel(B),$()}catch(D){U(D.message),W(!1)}}),F=A6(async()=>{if(K||q===Z)return;W(!0),U(null);try{if(await e().removeModel(q),X.length<=1)$()}catch(R){U(R.message)}finally{W(!1)}}),L=A6(()=>{if(K||!Y)return;let R=X.find((B)=>B.id===q);if(!R)return;Y(R)}),w=A6((R)=>{G(R.value)}),N=QG(()=>{return X.find((R)=>R.id===q)},[X,q]),A=X.map((R)=>({label:R.name+(R.id===Z?" (当前)":""),value:R.id})),b=q===Z;return u(e0,{flexDirection:"column",borderStyle:"round",borderColor:"gray",padding:1,width:"100%",children:[u(e0,{flexDirection:"row",justifyContent:"space-between",marginBottom:1,children:[u(Z0,{bold:!0,color:"cyan",children:"模型管理"},void 0,!1,void 0,this),u(Z0,{dimColor:!0,children:[K?"⏳ 处理中...":b?"Enter=关闭 • E=编辑 • Esc=取消":"Enter=切换 • D=删除 • E=编辑 • Esc=取消"," • Ctrl+C=退出"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),u(e0,{flexDirection:"row",children:[u(e0,{flexDirection:"column",flexGrow:2,marginRight:2,borderStyle:"single",borderColor:"gray",padding:1,children:[u(Z0,{dimColor:!0,children:["已配置模型 (",X.length,")"]},void 0,!0,void 0,this),u(e0,{marginTop:1,children:u(XG,{items:A,onSelect:z,onHighlight:w,indicatorComponent:JG,itemComponent:qG},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),u(e0,{flexDirection:"column",flexGrow:3,borderStyle:"single",borderColor:"gray",padding:1,children:[u(Z0,{dimColor:!0,children:"模型详情"},void 0,!1,void 0,this),u(e0,{marginY:1,children:u(Z0,{color:b?"green":"yellow",children:b?"● 当前使用":"● 可切换"},void 0,!1,void 0,this)},void 0,!1,void 0,this),N?u(e0,{flexDirection:"column",children:[u(Z0,{children:[u(Z0,{dimColor:!0,children:"名称: "},void 0,!1,void 0,this),u(Z0,{bold:!0,color:"cyan",children:N.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),u(Z0,{children:[u(Z0,{dimColor:!0,children:"Provider: "},void 0,!1,void 0,this),u(Z0,{bold:!0,children:N.provider},void 0,!1,void 0,this)]},void 0,!0,void 0,this),u(Z0,{children:[u(Z0,{dimColor:!0,children:"Model: "},void 0,!1,void 0,this),u(Z0,{bold:!0,children:N.model},void 0,!1,void 0,this)]},void 0,!0,void 0,this),u(Z0,{children:[u(Z0,{dimColor:!0,children:"Base URL: "},void 0,!1,void 0,this),u(Z0,{color:"blueBright",children:N.baseUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this),N.temperature!==void 0&&u(Z0,{children:[u(Z0,{dimColor:!0,children:"Temperature: "},void 0,!1,void 0,this),u(Z0,{children:N.temperature},void 0,!1,void 0,this)]},void 0,!0,void 0,this),N.maxContextTokens!==void 0&&u(Z0,{children:[u(Z0,{dimColor:!0,children:"Context Window: "},void 0,!1,void 0,this),u(Z0,{children:N.maxContextTokens},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this):u(Z0,{dimColor:!0,children:"请选择一个模型查看详情"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),O&&u(e0,{marginTop:1,children:u(Z0,{color:"red",children:["❌ ",O]},void 0,!0,void 0,this)},void 0,!1,void 0,this),u(e0,{justifyContent:"center",marginTop:1,children:u(Z0,{dimColor:!0,children:"─".repeat(_)},void 0,!1,void 0,this)},void 0,!1,void 0,this),u(e0,{justifyContent:"center",children:u(Z0,{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 F2}from"ahooks";import{promises as AY}from"fs";import{Box as p0,Text as U0,useInput as GG}from"ink";import BY from"ink-select-input";import KG from"ink-text-input";import WG from"os";import b6 from"path";import{useEffect as UG,useMemo as V6,useRef as OG,useState as m1}from"react";import{jsxDEV as d}from"react/jsx-dev-runtime";var z2=[{key:"allow",label:"Allow"},{key:"ask",label:"Ask"},{key:"deny",label:"Deny"},{key:"info",label:"Info"}],HG={allow:"Add a new rule...",ask:"Add a new rule...",deny:"Add a new rule..."},_G={allow:"Allow permission rules",ask:"Ask permission rules",deny:"Deny permission rules"},LY={project:"[项目共享配置]",global:"[用户全局配置]",local:"[本地配置]"},FG=["project","global","local"],zG={allow:[],ask:[],deny:[]},NG={localExists:!1,projectExists:!1,globalExists:!1},wY={allow:[],ask:[],deny:[]};function BG($){let Y=(Z)=>Array.isArray(Z)?Z.filter((Q)=>typeof Q==="string"):[],X=$?.permissions??{};return{allow:Y(X?.allow),ask:Y(X?.ask),deny:Y(X?.deny)}}async function LG($){try{let Y=await AY.readFile($,"utf-8"),X=JSON.parse(Y);return{exists:!0,raw:X,permissions:BG(X)}}catch(Y){if(Y.code==="ENOENT")return{exists:!1,raw:{},permissions:{...wY}};return console.warn(`[PermissionsManager] Failed to read ${$}:`,Y),{exists:!0,raw:{},permissions:{...wY}}}}function wG($,Y){let X=$.padEnd(32," "),Z=Y==="local"?`${LY[Y]} ← 可删除`:LY[Y];return`${X} ${Z}`}var RY=({onClose:$})=>{let X=i0()==="permissions-manager",Z=b0(!1),[Q,J]=m1(0),q=z2[Q].key,[G,K]=m1(zG),[W,O]=m1(NG),[U,H]=m1(!0),[_,z]=m1("list"),[F,L]=m1(""),[w,N]=m1(null),[A,b]=m1(null),y=OG(!1),R=V6(()=>b6.join(process.cwd(),".blade","settings.local.json"),[]),B=V6(()=>b6.join(process.cwd(),".blade","settings.json"),[]),D=V6(()=>b6.join(WG.homedir(),".blade","settings.json"),[]),C=F2(async()=>{H(!0);let c=[{source:"local",path:R},{source:"project",path:B},{source:"global",path:D}],X0=await Promise.all(c.map(async({source:w0,path:b1})=>{let u0=await LG(b1);return{source:w0,path:b1,...u0}})),a={localExists:X0.find((w0)=>w0.source==="local")?.exists??!1,projectExists:X0.find((w0)=>w0.source==="project")?.exists??!1,globalExists:X0.find((w0)=>w0.source==="global")?.exists??!1};O(a);let x0={allow:[],ask:[],deny:[]},d1=Object.fromEntries(X0.map((w0)=>[w0.source,w0]));["allow","ask","deny"].forEach((w0)=>{FG.forEach((b1)=>{(d1[b1]?.permissions[w0]??[]).forEach(($1,c1)=>{let M6={key:`${b1}:${c1}:${$1}`,rule:$1,source:b1};x0[w0].push(M6)})})}),K(x0),H(!1)});UG(()=>{C()},[C]);let p=F2(async(c,X0)=>{try{let a=b6.join(process.cwd(),".blade","settings.local.json"),x0={allow:[],ask:[],deny:[]};try{let w0=await AY.readFile(a,"utf-8"),u0=JSON.parse(w0).permissions||{};x0={allow:Array.isArray(u0.allow)?u0.allow:[],ask:Array.isArray(u0.ask)?u0.ask:[],deny:Array.isArray(u0.deny)?u0.deny:[]}}catch(w0){}let d1=X0(x0);await e().updateConfig({permissions:d1},{scope:"local",immediate:!0}),await C()}catch(a){throw console.error("[PermissionsManager] 修改权限规则失败:",a),a}});GG((c,X0)=>{if(X0.ctrl&&c==="c"||X0.meta&&c==="c"){Z();return}if(_==="locked"){if(y.current){y.current=!1;return}z("list"),N(null),b(null);return}if(X0.escape){if(_==="list"||q==="info")$();else z("list"),L(""),N(null),b(null);return}if(_==="list"){if(X0.tab&&X0.shift)J((a)=>(a-1+z2.length)%z2.length);else if(X0.tab)J((a)=>(a+1)%z2.length);else if(c?.toLowerCase()==="q")$()}},{isActive:X});let E=F2((c)=>{let X0=c.value;if(q==="info")return;if(X0.type==="add"){z("add"),L(""),b(null);return}if(X0.entry.source!=="local"){z("locked"),y.current=!0,N({tab:q,entry:X0.entry}),b({type:"error",text:X0.entry.source==="project"?"此规则定义在项目共享配置中,无法在此删除。":"此规则来自用户全局配置,无法在此删除。"});return}z("confirm-delete"),N({tab:q,entry:X0.entry}),b(null)}),M=F2(async()=>{if(q==="info")return;let c=F.trim();if(!c){b({type:"error",text:"Permission rule 不能为空"});return}if(G[q].map((a)=>a.rule).includes(c)){b({type:"error",text:"该规则已存在"});return}try{await p(q,(a)=>{let x0={allow:[...a.allow],ask:[...a.ask],deny:[...a.deny]};return x0[q]=[...new Set([...a[q],c])],x0}),z("list"),L(""),b({type:"success",text:"已添加本地权限规则"})}catch(a){b({type:"error",text:`保存失败: ${a instanceof Error?a.message:"未知错误"}`})}}),i=F2(async()=>{if(!w)return;let{tab:c,entry:X0}=w;try{await p(c,(a)=>{let x0={allow:[...a.allow],ask:[...a.ask],deny:[...a.deny]};return x0[c]=a[c].filter((d1)=>d1!==X0.rule),x0}),z("list"),N(null),b({type:"success",text:"已删除本地权限规则"})}catch(a){b({type:"error",text:`删除失败: ${a instanceof Error?a.message:"未知错误"}`})}}),S=V6(()=>{if(q==="info")return[];let c=q;return[{label:`› ${HG[c]}`,value:{type:"add"}},...G[c].map((a)=>({label:wG(a.rule,a.source),value:{type:"rule",entry:a}}))]},[q,G]),O1=()=>d(p0,{marginBottom:1,children:z2.map((c,X0)=>d(p0,{marginRight:2,children:d(U0,{color:X0===Q?"yellow":"gray",children:["[",c.label,"]"]},void 0,!0,void 0,this)},c.key,!1,void 0,this))},void 0,!1,void 0,this),Q0=()=>d(p0,{flexDirection:"column",gap:1,children:[d(U0,{children:"配置文件优先级(从高到低):"},void 0,!1,void 0,this),d(p0,{flexDirection:"column",marginLeft:2,children:[d(U0,{children:["1. .blade/settings.local.json (本地配置,不提交 Git)"," ",W.localExists?"✓ 存在":"✗ 不存在"]},void 0,!0,void 0,this),d(U0,{children:["2. .blade/settings.json (项目配置,提交 Git)"," ",W.projectExists?"✓ 存在":"✗ 不存在"]},void 0,!0,void 0,this),d(U0,{children:["3. ~/.blade/settings.json (用户全局配置)"," ",W.globalExists?"✓ 存在":"✗ 不存在"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),d(U0,{children:"说明:"},void 0,!1,void 0,this),d(p0,{flexDirection:"column",marginLeft:2,children:[d(U0,{children:"- /permissions 命令只管理本地配置 (.blade/settings.local.json)"},void 0,!1,void 0,this),d(U0,{children:"- 修改全局或项目配置请直接编辑对应文件"},void 0,!1,void 0,this),d(U0,{children:"- 本地配置不会提交到 Git"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),_0=(c)=>d(p0,{flexDirection:"column",gap:1,children:[d(U0,{bold:!0,children:_G[c]},void 0,!1,void 0,this),d(U0,{children:"Permission rules are a tool name, optionally followed by a specifier in parentheses."},void 0,!1,void 0,this),d(U0,{color:"gray",children:"例如: WebFetch 或 Bash(ls:*)"},void 0,!1,void 0,this),d(p0,{marginTop:1,children:d(KG,{value:F,onChange:L,onSubmit:M},void 0,!1,void 0,this)},void 0,!1,void 0,this),d(U0,{color:"gray",children:"Enter 提交 · Esc 取消"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y1=(c,X0)=>d(p0,{flexDirection:"column",gap:1,children:[d(U0,{bold:!0,children:["Delete ",c," permission rule?"]},void 0,!0,void 0,this),d(U0,{children:X0.rule},void 0,!1,void 0,this),d(U0,{color:"gray",children:"From project local settings"},void 0,!1,void 0,this),d(U0,{children:"Are you sure you want to delete this permission rule?"},void 0,!1,void 0,this),d(BY,{items:[{label:"Yes",value:"yes"},{label:"No",value:"no"}],onSelect:(a)=>{if(a.value==="yes")i();else z("list"),N(null)}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q$=(c)=>d(p0,{flexDirection:"column",gap:1,children:[d(U0,{bold:!0,children:"Cannot delete this rule"},void 0,!1,void 0,this),d(U0,{children:c.rule},void 0,!1,void 0,this),d(U0,{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),d(U0,{color:"gray",children:"按任意键继续"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),f$=(c)=>d(BY,{items:S,isFocused:_==="list",onSelect:E},void 0,!1,void 0,this),v6=()=>{if(U)return d(U0,{children:"加载中..."},void 0,!1,void 0,this);if(q==="info")return Q0();if(_==="add")return _0(q);if(_==="confirm-delete"&&w)return y1(w.tab,w.entry);if(_==="locked"&&w)return q$(w.entry);return f$(q)};return d(p0,{flexDirection:"column",borderStyle:"round",borderColor:X?"cyan":"gray",padding:1,width:80,children:[d(U0,{color:"cyan",bold:!0,children:"⚙️ 权限管理器"},void 0,!1,void 0,this),O1(),d(p0,{flexDirection:"column",gap:1,children:v6()},void 0,!1,void 0,this),A&&d(p0,{marginTop:1,children:d(U0,{color:A.type==="success"?"green":"red",children:A.text},void 0,!1,void 0,this)},void 0,!1,void 0,this),d(p0,{marginTop:1,children:d(U0,{color:"gray",children:"Tab 切换视图 · Esc 关闭 · Q 退出"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{Box as C$,Text as U1,useInput as AG}from"ink";import RG from"ink-select-input";import{useEffect as bY,useMemo as D6,useState as T8}from"react";import{jsxDEV as V0}from"react/jsx-dev-runtime";function bG($){let Y=new Date($),Z=new Date().getTime()-Y.getTime(),Q=Math.floor(Z/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 VG($){let Y=$.split("/");return Y[Y.length-1]||$}var DG=({isSelected:$})=>V0(C$,{marginRight:1,children:V0(U1,{color:$?"cyan":"gray",children:$?"❯":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),IG=({isSelected:$,label:Y})=>V0(U1,{color:$?"cyan":"white",bold:$,children:Y},void 0,!1,void 0,this),N2=20,VY=({sessions:$,onSelect:Y,onCancel:X})=>{let[Z,Q]=T8([]),[J,q]=T8(!1),[G,K]=T8(0),O=i0()==="session-selector",U=b0(!1);AG((N,A)=>{if(A.ctrl&&N==="c"||A.meta&&N==="c"){U();return}if(A.escape&&X){X();return}if(A.leftArrow||N==="h"||N==="H"){if(G>0)K((b)=>b-1);return}if(A.rightArrow||N==="l"||N==="L"){if(G<z-1)K((b)=>b+1);return}},{isActive:O}),bY(()=>{if($){Q($);return}(async()=>{q(!0);try{let A=await N1.listSessions();Q(A)}catch(A){console.error("[SessionSelector] Failed to load sessions:",A),Q([])}finally{q(!1)}})()},[$]);let H=$||Z,_=D6(()=>{return H.map((N)=>{let A=VG(N.projectPath),b=bG(N.lastMessageTime),y=N.gitBranch?` (${N.gitBranch})`:"",R=N.hasErrors?" ⚠️":"";return{label:`\uD83D\uDCC5 ${b} | ${A}${y} | ${N.messageCount} 条消息${R}`,value:N.sessionId}})},[H]),z=D6(()=>Math.max(1,Math.ceil(_.length/N2)),[_.length]),F=D6(()=>{let N=G*N2;return _.slice(N,N+N2)},[_,G]),L=D6(()=>({start:G*N2+1,end:Math.min((G+1)*N2,_.length)}),[G,_.length]);bY(()=>{K(0)},[H.length]);let w=(N)=>{Y(N.value)};if(J)return V0(C$,{flexDirection:"column",paddingX:2,paddingY:1,children:V0(U1,{children:"⏳ 正在加载会话列表..."},void 0,!1,void 0,this)},void 0,!1,void 0,this);if(H.length===0)return V0(C$,{flexDirection:"column",paddingX:2,paddingY:1,children:[V0(U1,{color:"yellow",children:"⚠️ 没有找到历史会话"},void 0,!1,void 0,this),V0(U1,{dimColor:!0,children:[`
1505
- `,"提示: 开始一次对话后,会话历史将保存到 ~/.blade/projects/"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this);return V0(C$,{flexDirection:"column",paddingX:2,paddingY:1,children:[V0(U1,{bold:!0,color:"cyan",children:"\uD83D\uDCC2 选择要恢复的会话:"},void 0,!1,void 0,this),V0(U1,{dimColor:!0,children:[`
1493
+ `),K=G.includes("<<<DIFF>>>"),W=G.includes("```");if(K){let O=G.match(/<<<DIFF>>>\s*({[\s\S]*?})\s*<<<\/DIFF>>>/);if(O)try{let U=JSON.parse(O[1]);return x(y0,{flexDirection:"column",children:[x(P8,{patch:U.patch,startLine:U.startLine,matchLine:U.matchLine,terminalWidth:Y},void 0,!1,void 0,this),J&&x(y0,{marginTop:1,children:x(p0,{dimColor:!0,color:X.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 O=G.match(/```(\w+)?\s*\n([\s\S]*?)\n```/);if(O){let U=O[1]||"text",H=O[2];return x(y0,{flexDirection:"column",children:[x(j8,{content:H,language:U,showLineNumbers:!1,terminalWidth:Y},void 0,!1,void 0,this),J&&x(y0,{marginTop:1,children:x(p0,{dimColor:!0,color:X.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 x(y0,{flexDirection:"column",children:[q.map((O,U)=>x(p0,{color:X.colors.text.primary,children:O},U,!1,void 0,this)),J&&x(y0,{marginTop:1,children:x(p0,{dimColor:!0,color:X.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)}),L2=w6.memo(({content:$,role:Y,terminalWidth:X,metadata:Z,isPending:Q=!1})=>{let J=w6.useMemo(()=>Lq(Y,Z),[Y,Z]),{color:q,prefix:G}=J;if(Y==="tool"&&Z&&"detail"in Z){let W=Z;if(W.detail)return x(y0,{flexDirection:"column",marginBottom:1,children:[x(y0,{flexDirection:"row",children:[x(y0,{marginRight:1,children:x(p0,{color:q,bold:!0,children:G},void 0,!1,void 0,this)},void 0,!1,void 0,this),x(p0,{color:q,children:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this),x(y0,{marginLeft:G.length+1,marginTop:1,children:x(Iq,{detail:W.detail,terminalWidth:X-(G.length+1)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}let K=w6.useMemo(()=>wq($),[$]);return x(y0,{flexDirection:"column",marginBottom:1,children:K.map((W,O)=>{if(W.type==="empty")return x(y0,{height:1},O,!1,void 0,this);return x(y0,{flexDirection:"row",children:[O===0&&x(y0,{marginRight:1,children:x(p0,{color:q,bold:!0,children:G},void 0,!1,void 0,this)},void 0,!1,void 0,this),O>0&&x(y0,{width:G.length+1},void 0,!1,void 0,this),x(y0,{flexGrow:1,children:W.type==="code"?x(Aq,{content:W.content,language:W.language,terminalWidth:X-(G.length+1)},void 0,!1,void 0,this):W.type==="table"&&W.tableData?x(O7,{headers:W.tableData.headers,rows:W.tableData.rows,terminalWidth:X-(G.length+1)},void 0,!1,void 0,this):W.type==="heading"?x(Rq,{content:W.content,level:W.level||1},void 0,!1,void 0,this):W.type==="list"?x(W7,{type:W.listType||"ul",marker:W.marker||"-",itemText:W.content,leadingWhitespace:" ".repeat(W.indentation||0)},void 0,!1,void 0,this):W.type==="hr"?x(bq,{terminalWidth:X-(G.length+1)},void 0,!1,void 0,this):W.type==="diff"&&W.diffData?x(P8,{patch:W.diffData.patch,startLine:W.diffData.startLine,matchLine:W.diffData.matchLine,terminalWidth:X-(G.length+1)},void 0,!1,void 0,this):x(Vq,{content:W.content},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},O,!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 H0}from"react/jsx-dev-runtime";var kq=({label:$,isSelected:Y})=>H0(H1,{color:Y?"yellow":void 0,children:$},void 0,!1,void 0,this),H7=({details:$,onResponse:Y})=>{let X=x$(),Q=a0()==="confirmation-prompt",J=V0(!1),q=$.type==="exitPlanMode",G=$.type==="enterPlanMode",K=$.type==="maxTurnsExceeded";Dq((H,_)=>{if(_.ctrl&&H==="c"||_.meta&&H==="c"){J();return}if(_.escape){Y({approved:!1,reason:"用户取消"});return}let z=H.toLowerCase();if(q){if(z==="y"){Y({approved:!0,targetMode:"autoEdit"});return}if(z==="s"){Y({approved:!0,targetMode:"default"});return}if(z==="n"){Y({approved:!1,reason:"方案需要改进"});return}}else if(G){if(z==="y"){Y({approved:!0});return}if(z==="n"){Y({approved:!1,reason:"用户拒绝进入 Plan 模式"});return}}else if(K){if(z==="y"){Y({approved:!0});return}if(z==="n"){Y({approved:!1,reason:"用户选择停止"});return}}else{if(z==="y"){Y({approved:!0,scope:"once"});return}if(z==="s"){Y({approved:!0,scope:"session"});return}if(z==="n"){Y({approved:!1,reason:"用户拒绝"});return}}},{isActive:Q});let W=Mq(()=>{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]),U=(()=>{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 H0(e0,{flexDirection:"column",borderStyle:"round",borderColor:Q?U.color:"gray",padding:1,children:[H0(e0,{marginBottom:1,children:H0(H1,{bold:!0,color:U.color,children:U.title},void 0,!1,void 0,this)},void 0,!1,void 0,this),$.title&&H0(e0,{marginBottom:1,children:H0(H1,{bold:!0,children:$.title},void 0,!1,void 0,this)},void 0,!1,void 0,this),H0(e0,{marginBottom:1,children:H0(H1,{children:$.message},void 0,!1,void 0,this)},void 0,!1,void 0,this),($.planContent||$.details)&&H0(e0,{flexDirection:"column",marginBottom:1,borderStyle:"single",borderColor:U.color,padding:1,children:[H0(H1,{bold:!0,color:U.color,children:q?"\uD83D\uDCCB Implementation Plan:":G?"\uD83D\uDCDD Details:":"\uD83D\uDCC4 Operation Details:"},void 0,!1,void 0,this),H0(e0,{marginTop:1,children:H0(L2,{content:$.planContent||$.details||"",role:"assistant",terminalWidth:X-4},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$.risks&&$.risks.length>0&&H0(e0,{flexDirection:"column",marginBottom:1,children:[H0(H1,{color:"red",bold:!0,children:"⚠️ 风险提示:"},void 0,!1,void 0,this),$.risks.map((H,_)=>H0(e0,{marginLeft:2,children:H0(H1,{color:"red",children:["• ",H]},void 0,!0,void 0,this)},_,!1,void 0,this))]},void 0,!0,void 0,this),$.affectedFiles&&$.affectedFiles.length>0&&H0(e0,{flexDirection:"column",marginBottom:1,children:[H0(H1,{color:"yellow",children:"\uD83D\uDCC1 影响的文件:"},void 0,!1,void 0,this),$.affectedFiles.slice(0,3).map((H,_)=>H0(e0,{marginLeft:2,children:H0(H1,{children:["• ",H]},void 0,!0,void 0,this)},_,!1,void 0,this)),$.affectedFiles.length>3&&H0(e0,{marginLeft:2,children:H0(H1,{color:"gray",children:["...还有 ",$.affectedFiles.length-3," 个文件"]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),H0(e0,{flexDirection:"column",children:[H0(H1,{color:"gray",children:"使用 ↑ ↓ 选择,回车确认(支持 Y/S/N 快捷键,ESC 取消)"},void 0,!1,void 0,this),H0(vq,{items:W,isFocused:Q,itemComponent:kq,onSelect:(H)=>{Y(H.value)}},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)};import{useMemoizedFn as R7}from"ahooks";import{Box as aq,Text as nq}from"ink";import oq from"react";import{writeFileSync as yq}from"node:fs";import{join as Eq}from"node:path";import{tmpdir as jq}from"node:os";import{nanoid as Pq}from"nanoid";function _7($,Y,X){let Z=Sq(Y),Q=Date.now(),J=Pq(8),q=X||`blade_image_${Q}_${J}.${Z}`,G=jq(),K=Eq(G,q),W=Buffer.from($,"base64");yq(K,W);let O=`[Image: ${q}]`;return console.log(`[ImageHandler] Saved image to: ${K}`),console.log(`[ImageHandler] Size: ${(W.length/1024).toFixed(2)} KB`),{filePath:K,filename:q,tag:O}}function Sq($){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 mq}from"ahooks";import O$ from"chalk";import{Text as uq,useInput as dq}from"ink";import{useEffect as w7,useRef as cq}from"react";var c1={TIMEOUT_MS:100,RAPID_INPUT_THRESHOLD_MS:150,LARGE_INPUT_THRESHOLD:300,MEDIUM_SIZE_MULTI_CHUNK_THRESHOLD:200};import{execSync as Tq}from"node:child_process";import{existsSync as eA,readFileSync as F7}from"node:fs";import{basename as z7,isAbsolute as Cq}from"node:path";function fq(){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 YR=fq();function hq($){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 xq(){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"},X={darwin:{checkImage:"osascript -e 'the clipboard as «class PNGf»'",saveImage:(Z)=>`osascript -e 'set png_data to (the clipboard as «class PNGf»)' -e 'set fp to open for access POSIX file "${Z}" 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:(Z)=>`rm -f "${Z}"`},linux:{checkImage:'xclip -selection clipboard -t TARGETS -o | grep -E "image/(png|jpeg|jpg|gif|webp)"',saveImage:(Z)=>`xclip -selection clipboard -t image/png -o > "${Z}" || wl-paste --type image/png > "${Z}"`,getPath:"xclip -selection clipboard -t text/plain -o",deleteFile:(Z)=>`rm -f "${Z}"`},win32:{checkImage:'powershell -Command "(Get-Clipboard -Format Image) -ne $null"',saveImage:(Z)=>`powershell -Command "$img = Get-Clipboard -Format Image; if ($img) { $img.Save('${Z.replace(/\\/g,"\\\\")}', [System.Drawing.Imaging.ImageFormat]::Png) }"`,getPath:'powershell -Command "Get-Clipboard"',deleteFile:(Z)=>`del /f "${Z}"`}};return{commands:X[$]||X.linux,screenshotPath:Y[$]||Y.linux}}function pq(){let{commands:$}=xq();try{return Tq($.getPath,{encoding:"utf-8"}).trim()}catch(Y){return console.error("Failed to get clipboard path:",Y),null}}function N7($){if($.startsWith('"')&&$.endsWith('"')||$.startsWith("'")&&$.endsWith("'"))return $.slice(1,-1);return $}function B7($){if(process.platform==="win32")return $;let Y="__DOUBLE_BACKSLASH__";return $.replace(/\\\\/g,Y).replace(/\\(.)/g,"$1").replace(new RegExp(Y,"g"),"\\")}function h8($){let Y=N7($.trim()),X=B7(Y);return/\.(png|jpe?g|gif|webp)$/i.test(X)}function gq($){let Y=N7($.trim()),X=B7(Y);if(h8(X))return X;return null}async function L7($){let Y=gq($);if(!Y)return null;let X;try{if(Cq(Y))X=F7(Y);else{let q=pq();if(q&&Y===z7(q))X=F7(q);else return null}}catch(q){return console.error("Failed to read image file:",q),null}let Z=X.toString("base64"),Q=hq(Z),J=z7(Y);return{path:Y,base64:Z,mediaType:Q,filename:J}}import{jsxDEV as rq}from"react/jsx-dev-runtime";var lq=/\r\n/g,iq=/\r/g;function A6($){if(!$.includes("\r"))return $;return $.replace(lq,`
1494
+ `).replace(iq,`
1495
+ `)}function R6($,Y,X){let Z=Math.max(0,Math.min(X,Y.length)),Q=Y.slice(0,Z),J=Y.slice(Z);return{newValue:Q+$+J,newCursorPosition:Z+$.length}}function A7({value:$,placeholder:Y="",focus:X=!0,onChange:Z,cursorPosition:Q,onChangeCursorPosition:J,onPaste:q,onImagePaste:G,disabledKeys:K=[]}){let W=cq({chunks:[],timeoutId:null,firstInputTime:null,lastInputTime:null,totalLength:0});w7(()=>{return()=>{if(W.current.timeoutId)clearTimeout(W.current.timeoutId)}},[]),w7(()=>{if(Q>$.length)J($.length)},[$,Q,J]);let O=mq(()=>{let z=W.current;if(z.timeoutId)clearTimeout(z.timeoutId);let F=setTimeout(async()=>{let B=W.current.chunks,L=W.current.totalLength;if(B.length===0)return;let N=A6(B.join(""));if(W.current={chunks:[],timeoutId:null,firstInputTime:null,lastInputTime:null,totalLength:0},G&&h8(N))try{let b=await L7(N);if(b){let E=await G(b.base64,b.mediaType,b.filename);if(E?.prompt){let f=A6(E.prompt),{newValue:h,newCursorPosition:v}=R6(f,$,Q);Z(h),J(v)}return}}catch(b){console.error("Failed to process image path:",b)}let A=N.includes(`
1496
+ `),R=L>c1.MEDIUM_SIZE_MULTI_CHUNK_THRESHOLD&&B.length>3;if((L>c1.LARGE_INPUT_THRESHOLD||A||R)&&q){let b=await q(N);if(b?.prompt){let E=A6(b.prompt),{newValue:f,newCursorPosition:h}=R6(E,$,Q);Z(f),J(h);return}}let{newValue:I,newCursorPosition:w}=R6(N,$,Q);Z(I),J(w)},c1.TIMEOUT_MS);W.current.timeoutId=F});dq((z,F)=>{let B=A6(z);if(K.some((I)=>F[I])||F.ctrl&&z==="c"||F.shift&&F.tab||B==="?"&&$==="")return;let N=Date.now(),A=W.current,R=Q,k=$;if(F.leftArrow)R--;else if(F.rightArrow)R++;else if(F.backspace||F.delete){if(z===""){if(Q>0)k=$.slice(0,Q-1)+$.slice(Q,$.length),R--}else if(Q<$.length)k=$.slice(0,Q)+$.slice(Q+1,$.length)}else if(F.ctrl&&B==="a")R=0;else if(F.ctrl&&B==="e")R=$.length;else if(F.ctrl&&B==="k")k=$.slice(0,Q);else if(F.ctrl&&B==="u")k=$.slice(Q),R=0;else if(F.ctrl&&B==="w"){let w=$.slice(0,Q).match(/\s*\S+\s*$/);if(w){let b=w[0].length;k=$.slice(0,Q-b)+$.slice(Q),R-=b}}else if(F.pageUp)R=0;else if(F.pageDown)R=$.length;else if(B===`
1497
+ `&&(F.shift||F.meta)){let{newValue:I,newCursorPosition:w}=R6(B,$,Q);Z(I),J(w);return}else if(!F.ctrl&&!F.meta){if(!A.firstInputTime)A.firstInputTime=N;A.lastInputTime=N;let I=N-(A.firstInputTime||N),w=B.length>c1.LARGE_INPUT_THRESHOLD,b=B.includes(`
1498
+ `)&&B.length>1,E=I<c1.RAPID_INPUT_THRESHOLD_MS&&A.chunks.length>0,f=I<c1.RAPID_INPUT_THRESHOLD_MS&&B.length>10,h=A.timeoutId!==null;if(q&&(w||b||E||f||h)){A.chunks.push(B),A.totalLength+=B.length,O();return}if(B.length===1&&!A.timeoutId)A.chunks=[],A.firstInputTime=null,A.lastInputTime=null,A.totalLength=0;k=$.slice(0,Q)+B+$.slice(Q,$.length),R+=B.length}if(R<0)R=0;if(R>k.length)R=k.length;if(k!==$)Z(k);if(R!==Q)J(R)},{isActive:X});let U=X,H=$,_=Y?O$.grey(Y):void 0;if(U)if(_=Y.length>0?O$.inverse(Y[0])+O$.grey(Y.slice(1)):O$.inverse(" "),$.length===0)H=O$.inverse(" ");else{H="";for(let z=0;z<$.length;z++)if(z===Q&&Q<$.length)H+=O$.inverse($[z]);else H+=$[z];if(Q>=$.length)H+=O$.inverse(" ")}return rq(uq,{children:Y?$.length>0?H:_:H},void 0,!1,void 0,this)}import{jsxDEV as x8}from"react/jsx-dev-runtime";var b7=oq.memo(({input:$,cursorPosition:Y,onChange:X,onChangeCursorPosition:Z})=>{let J=a0()==="main-input",q=R7((K)=>{let W=K.split(`
1499
+ `).length,O=K.length,U=500,H=10;if(O>500||W>10){let _=K.slice(0,30).replace(/\n/g," ");return{prompt:`[Pasted: ${O} chars, ${W} lines] ${_}...`}}return{}}),G=R7(async(K,W,O)=>{try{return{prompt:`[Image saved to ${_7(K,W,O).filePath}. Note: Image attachments not yet supported by @ mentions] `}}catch(U){return console.error("[Image Paste] Failed to process image:",U),{prompt:`[Image paste failed: ${U instanceof Error?U.message:"Unknown error"}] `}}});return x8(aq,{flexDirection:"row",paddingX:2,paddingY:0,borderStyle:"round",borderColor:"gray",children:[x8(nq,{color:"blue",bold:!0,children:"> "},void 0,!1,void 0,this),x8(A7,{value:$,cursorPosition:Y,onChange:X,onChangeCursorPosition:Z,onPaste:q,onImagePaste:G,placeholder:" 输入命令...",focus:J,disabledKeys:["upArrow","downArrow","tab","return","escape"]},void 0,!1,void 0,this)]},void 0,!0,void 0,this)});import{Box as b6,Text as _1}from"ink";import YG,{useEffect as XG,useState as ZG}from"react";import{useEffect as $G,useState as v7}from"react";import{useEffect as sq,useState as tq}from"react";var eq=15000,V7=["炼化代码灵气...","参悟 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 广纳贤才..."],I7=["Esc - 立即停止当前任务","Shift+Tab - 切换权限模式 (default/auto_edit/plan)","Tab - 智能补全斜杠命令","↑↓ - 浏览输入历史记录","双击 Esc - 快速清空输入框","Ctrl+C - 强制终止程序","Ctrl+D - 优雅退出 Blade","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 D7($,Y){let[X,Z]=tq("");return sq(()=>{if(Y){Z("等待用户确认...");return}if(!$){Z("");return}let Q=()=>{if(Math.random()<0.16666666666666666){let K=Math.floor(Math.random()*I7.length);return I7[K]}let G=Math.floor(Math.random()*V7.length);return V7[G]};Z(Q());let J=setInterval(()=>{Z(Q())},eq);return()=>{clearInterval(J)}},[$,Y]),X}function M7($,Y=!1){let[X,Z]=v7(0),[Q,J]=v7(null),q=D7($,Y);return $G(()=>{if(!$){Z(0),J(null);return}if(Q===null)J(Date.now());let G=setInterval(()=>{if(Q!==null){let K=Math.floor((Date.now()-Q)/1000);Z(K)}},1000);return()=>{clearInterval(G)}},[$,Q]),{currentPhrase:q,elapsedTime:X}}import{jsxDEV as E0,Fragment as JG}from"react/jsx-dev-runtime";var p8=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"],QG=80;function k7($){if($<60)return`${$}s`;let Y=Math.floor($/60),X=$%60;return`${Y}m ${X}s`}var y7=YG.memo(({message:$})=>{let Y=m1(),X=Q6(),Z=Y||!X,[Q,J]=ZG(0),q=e.getTheme(),K=x$()>=QG,{currentPhrase:W,elapsedTime:O}=M7(Z,!1);if(XG(()=>{if(!Z){J(0);return}let H=setInterval(()=>{J((_)=>(_+1)%p8.length)},80);return()=>clearInterval(H)},[Z]),!Z)return null;let U=W||$||"正在思考中...";if(K)return E0(b6,{paddingX:2,paddingBottom:1,flexDirection:"row",gap:1,children:[E0(_1,{color:q.colors.warning,bold:!0,children:p8[Q]},void 0,!1,void 0,this),E0(_1,{color:q.colors.text.primary,children:U},void 0,!1,void 0,this),O>0&&E0(JG,{children:[E0(_1,{color:q.colors.muted,children:"|"},void 0,!1,void 0,this),E0(_1,{color:q.colors.info,children:["已用时: ",k7(O)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),E0(_1,{color:q.colors.muted,children:"|"},void 0,!1,void 0,this),E0(_1,{color:q.colors.secondary,children:"Esc 取消"},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return E0(b6,{paddingX:2,paddingBottom:1,flexDirection:"column",children:[E0(b6,{flexDirection:"row",gap:1,children:[E0(_1,{color:q.colors.warning,bold:!0,children:p8[Q]},void 0,!1,void 0,this),E0(_1,{color:q.colors.text.primary,children:U},void 0,!1,void 0,this)]},void 0,!0,void 0,this),O>0&&E0(b6,{marginLeft:2,flexDirection:"row",gap:1,children:[E0(_1,{color:q.colors.info,children:["已用时: ",k7(O)]},void 0,!0,void 0,this),E0(_1,{color:q.colors.muted,children:"|"},void 0,!1,void 0,this),E0(_1,{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 u$,Static as FG}from"ink";import zG,{useMemo as d8}from"react";import{Box as w2,Text as A2}from"ink";import qG from"ink-big-text";import GG from"ink-gradient";import KG from"react";import{jsxDEV as $1}from"react/jsx-dev-runtime";var E7=KG.memo(()=>{return $1(w2,{flexDirection:"column",paddingX:2,paddingTop:1,paddingBottom:1,children:[$1(w2,{flexDirection:"column",children:$1(GG,{name:"pastel",children:$1(qG,{text:"BLADE",font:"block"},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),$1(w2,{marginBottom:1,children:$1(A2,{color:"white",dimColor:!0,children:$9()},void 0,!1,void 0,this)},void 0,!1,void 0,this),$1(w2,{flexDirection:"column",marginBottom:1,children:[$1(w2,{marginBottom:1,children:$1(A2,{color:"white",bold:!0,children:"使用指南:"},void 0,!1,void 0,this)},void 0,!1,void 0,this),$1(A2,{color:"white",children:"1. 输入问题、编辑文件或运行命令"},void 0,!1,void 0,this),$1(A2,{color:"white",children:"2. 使用 /init 创建项目配置文件"},void 0,!1,void 0,this),$1(A2,{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 g8,Text as m$}from"ink";import WG,{useMemo as j7}from"react";import{jsxDEV as j1}from"react/jsx-dev-runtime";function UG($,Y=60){if(!$)return"";let X=$.split(`
1500
+ `)[0]||"";if(X.length<=Y)return X;return`${X.slice(0,Y)}...`}function OG($){if(!$)return 0;return $.split(`
1501
+ `).length}var m8=WG.memo(({content:$,isStreaming:Y=!1,isExpanded:X})=>{let Z=e.getTheme(),Q=j7(()=>OG($),[$]),J=j7(()=>UG($),[$]),q=Z.colors.info,G=Z.colors.muted;return j1(g8,{flexDirection:"column",marginBottom:1,children:[j1(g8,{flexDirection:"row",children:[j1(m$,{color:q,children:X?"▼":"▶"},void 0,!1,void 0,this),j1(m$,{children:" "},void 0,!1,void 0,this),j1(m$,{color:G,children:["Thinking",Y?"...":` (${Q} lines)`]},void 0,!0,void 0,this),!X&&!Y&&J&&j1(m$,{color:G,children:[" - ",J]},void 0,!0,void 0,this),j1(m$,{color:G,dimColor:!0,children:[" ","[Ctrl+T]"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),X&&$&&j1(g8,{marginLeft:2,marginTop:1,borderStyle:"round",borderColor:"gray",paddingX:1,paddingY:0,children:j1(m$,{color:G,children:$},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)});m8.displayName="ThinkingBlock";import{Box as V6,Text as u8}from"ink";import{useState as P7}from"react";function HG(){let[$,Y]=P7(e.getTheme()),[X,Z]=P7(e.getCurrentThemeName()),Q=(K)=>{try{e.setTheme(K),Y(e.getTheme()),Z(K)}catch(W){console.error("Failed to change theme:",W)}},J=e.getAvailableThemes();return{theme:$,themeName:X,changeTheme:Q,availableThemes:J,hasTheme:(K)=>e.hasTheme(K),getThemeByName:(K)=>e.getThemeByName(K),colors:$.colors,spacing:$.spacing,typography:$.typography}}function S7(){let{colors:$}=HG();return $}import{jsxDEV as l1}from"react/jsx-dev-runtime";var T7=({todos:$,visible:Y=!0,compact:X=!1})=>{let Z=S7();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 l1(V6,{flexDirection:"column",borderStyle:"single",borderColor:Z.border.light,paddingX:1,paddingY:X?0:1,marginBottom:1,children:[l1(V6,{marginBottom:X?0:1,children:[l1(u8,{dimColor:!0,children:"Tasks "},void 0,!1,void 0,this),l1(u8,{color:Z.text.muted,children:[Q.completed,"/",Q.total]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),l1(V6,{flexDirection:"column",children:$.map((J,q)=>l1(_G,{todo:J,compact:X},J.id||q,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},_G=({todo:$,compact:Y})=>{let X,Z=!1,Q;switch($.status){case"completed":X="✓",Z=!0,Q=$.content;break;case"in_progress":X="▶",Z=!1,Q=$.activeForm;break;case"pending":default:X="○",Z=!0,Q=$.content;break}return l1(V6,{paddingY:Y?0:0,children:l1(u8,{dimColor:Z,children:[X," ",Q]},void 0,!0,void 0,this)},void 0,!1,void 0,this)};import{jsxDEV as Y1}from"react/jsx-dev-runtime";var C7=zG.memo(()=>{let $=X6(),Y=m1(),X=d5(),Z=r5(),Q=e5(),J=Y3(),q=X3(),G=x$(),{completedMessages:K,streamingMessage:W}=d8(()=>{if(Y&&$.length>0)return{completedMessages:$.slice(0,-1),streamingMessage:$[$.length-1]};return{completedMessages:$,streamingMessage:null}},[$,Y]),O=d8(()=>{return X.some((_)=>_.status==="pending"||_.status==="in_progress")},[X]),U=(_,z,F=!1)=>Y1(u$,{flexDirection:"column",children:Y1(L2,{content:_.content,role:_.role,terminalWidth:G,metadata:_.metadata,isPending:F},void 0,!1,void 0,this)},_.id,!1,void 0,this),H=d8(()=>{let _=[];return _.push(Y1(E7,{},"header",!1,void 0,this)),K.forEach((z,F)=>{_.push(U(z,F))}),_},[K,G]);return Y1(u$,{flexDirection:"column",flexGrow:1,paddingX:2,children:Y1(u$,{flexDirection:"column",flexGrow:1,children:[Y1(FG,{items:H,children:(_)=>_},void 0,!1,void 0,this),J&&Y1(u$,{marginBottom:1,children:Y1(m8,{content:J,isStreaming:Y,isExpanded:q},void 0,!1,void 0,this)},void 0,!1,void 0,this),W&&U(W,K.length,!0),Z&&O&&Y1(u$,{marginTop:1,children:Y1(T7,{todos:X,visible:!0,compact:!1},void 0,!1,void 0,this)},void 0,!1,void 0,this),Q.map((_,z)=>Y1(u$,{flexDirection:"column",children:Y1(L2,{content:_,role:"user",terminalWidth:G},void 0,!1,void 0,this)},`pending-${z}`,!1,void 0,this))]},void 0,!0,void 0,this)},void 0,!1,void 0,this)});import{Box as r,Text as C,useFocus as f7,useFocusManager as NG,useInput as v6}from"ink";import BG from"ink-select-input";import LG from"ink-text-input";import{useEffect as wG,useState as R2}from"react";import{jsxDEV as D,Fragment as D6}from"react/jsx-dev-runtime";var AG=({isSelected:$})=>D(r,{marginRight:1,children:D(C,{color:$?"yellow":"gray",children:$?"▶":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),RG=({isSelected:$,label:Y})=>D(C,{bold:$,color:$?"yellow":void 0,children:Y},void 0,!1,void 0,this),bG=({onSelect:$,onCancel:Y,initialProvider:X})=>{let{isFocused:Z}=f7({id:"provider-step"});v6((q,G)=>{if(G.escape)Y()},{isActive:Z});let Q=[{label:"⚡ OpenAI Compatible - 兼容 OpenAI API 的服务 (千问/豆包/DeepSeek等)",value:"openai-compatible"},{label:"\uD83E\uDD16 Anthropic Claude API - Claude 官方 API",value:"anthropic"}],J=X?Math.max(0,Q.findIndex((q)=>q.value===X)):0;return D(r,{flexDirection:"column",marginBottom:1,children:[D(r,{marginBottom:1,children:D(C,{bold:!0,color:"blue",children:"\uD83D\uDCE1 Step 2: 选择 API 提供商"},void 0,!1,void 0,this)},void 0,!1,void 0,this),D(r,{marginBottom:1,children:D(C,{children:"根据您使用的 LLM 服务选择对应的 API 类型"},void 0,!1,void 0,this)},void 0,!1,void 0,this),D(r,{marginBottom:1,children:D(BG,{items:Q,onSelect:(q)=>$(q.value),indicatorComponent:AG,itemComponent:RG,initialIndex:J},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},I6=({stepNumber:$,icon:Y,title:X,description:Z,hint:Q,examples:J,value:q,placeholder:G,mask:K,previousValue:W,onChange:O,onSubmit:U,onCancel:H})=>{return v6((_,z)=>{if(z.escape)H()},{isActive:!0}),D(r,{flexDirection:"column",marginBottom:1,children:[D(r,{marginBottom:1,children:D(C,{bold:!0,color:"blue",children:[Y," Step ",$,": ",X]},void 0,!0,void 0,this)},void 0,!1,void 0,this),D(r,{marginBottom:1,children:D(C,{children:Z},void 0,!1,void 0,this)},void 0,!1,void 0,this),W&&D(r,{marginBottom:1,children:D(C,{color:"green",children:["✓ ",W]},void 0,!0,void 0,this)},void 0,!1,void 0,this),Q&&D(r,{marginBottom:1,children:D(C,{dimColor:!0,children:Q},void 0,!1,void 0,this)},void 0,!1,void 0,this),J&&J.length>0&&D(D6,{children:[D(r,{marginBottom:1,children:D(C,{dimColor:!0,children:"常见示例:"},void 0,!1,void 0,this)},void 0,!1,void 0,this),D(r,{marginBottom:1,paddingLeft:2,children:D(C,{dimColor:!0,children:J.join(`
1502
+ `)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D(r,{children:[D(C,{bold:!0,color:"cyan",children:["▶"," "]},void 0,!0,void 0,this),D(LG,{value:q,onChange:O,onSubmit:U,placeholder:G,mask:K},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},VG=({mode:$,config:Y,isSaving:X,onConfirm:Z,onBack:Q,onCancel:J})=>{let{isFocused:q}=f7({id:"confirm-step"});return v6((G,K)=>{if(X)return;if(G==="y"||G==="Y")Z();else if(G==="n"||G==="N")Q();else if(K.escape)J()},{isActive:q&&!X}),D(r,{flexDirection:"column",marginBottom:1,children:[D(r,{marginBottom:1,children:D(C,{bold:!0,color:$==="edit"?"yellow":"blue",children:$==="edit"?"\uD83D\uDCBE 确认修改":"✅ Step 6: 确认配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),D(r,{marginBottom:1,children:D(C,{children:$==="edit"?"请确认修改内容,保存后将立即生效。":"请确认以下配置信息:"},void 0,!1,void 0,this)},void 0,!1,void 0,this),D(r,{flexDirection:"column",marginBottom:1,paddingLeft:2,children:[D(r,{marginBottom:1,children:[D(C,{dimColor:!0,children:"名称: "},void 0,!1,void 0,this),D(C,{bold:!0,color:"cyan",children:Y.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D(r,{marginBottom:1,children:[D(C,{dimColor:!0,children:"Provider: "},void 0,!1,void 0,this),D(C,{bold:!0,color:"cyan",children:Y.provider==="openai-compatible"?"⚡ OpenAI Compatible":"\uD83E\uDD16 Anthropic"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D(r,{marginBottom:1,children:[D(C,{dimColor:!0,children:"Base URL: "},void 0,!1,void 0,this),D(C,{bold:!0,color:"blue",children:Y.baseUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this),D(r,{marginBottom:1,children:[D(C,{dimColor:!0,children:"API Key: "},void 0,!1,void 0,this),D(C,{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),D(r,{children:[D(C,{dimColor:!0,children:"Model: "},void 0,!1,void 0,this),D(C,{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),!X&&D(r,{marginTop:1,children:D(C,{children:[$==="edit"?"保存修改? ":"确认保存配置? ","[",D(C,{bold:!0,color:"green",children:"Y"},void 0,!1,void 0,this),"/",D(C,{bold:!0,color:"red",children:"n"},void 0,!1,void 0,this),"]"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),X&&D(r,{children:D(C,{color:"yellow",children:"⏳ 正在保存配置到 ~/.blade/config.json..."},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},c8=({mode:$,initialConfig:Y,modelId:X,onComplete:Z,onCancel:Q})=>{let J=$==="edit",[q,G]=R2("name"),[K,W]=R2(()=>J&&Y?{...Y}:{}),[O,U]=R2(J&&Y?Y.name:""),[H,_]=R2(!1),[z,F]=R2(null),B=V0(!1);v6((v,m)=>{if(m.ctrl&&v==="c"||m.meta&&v==="c")if($==="setup")B();else Q()},{isActive:!0});let{focus:L}=NG();wG(()=>{if(q==="provider")L("provider-step");else if(q==="confirm")L("confirm-step")},[q,L]);let N=()=>{if(!O.trim()){F("配置名称不能为空");return}W({...K,name:O}),U(""),F(null),G("provider")},A=(v)=>{W({...K,provider:v});let m=J?K.baseUrl??Y?.baseUrl??"":"";U(m),G("baseUrl")},R=()=>{if(!O.trim()){F("Base URL 不能为空");return}try{new URL(O)}catch{F("请输入有效的 URL (例如: https://api.openai.com/v1)");return}W({...K,baseUrl:O});let v=J?K.apiKey??Y?.apiKey??"":"";U(v),F(null),G("apiKey")},k=()=>{if(!O.trim()){F("API Key 不能为空");return}W({...K,apiKey:O});let v=J?K.model??Y?.model??"":"";U(v),F(null),G("model")},I=()=>{if(!O.trim()){F("Model 不能为空");return}W({...K,model:O}),U(""),F(null),G("confirm")},w=async()=>{_(!0),F(null);try{let v={name:K.name,provider:K.provider,baseUrl:K.baseUrl,apiKey:K.apiKey,model:K.model};if($==="setup")Z(v);else if($==="add"){let m=await W0().addModel(v);await W0().setCurrentModel(m.id),Z(v)}else{if(!X)throw Error("未提供模型 ID,无法编辑");await W0().updateModel(X,v),Z(v)}}catch(v){F(v instanceof Error?v.message:"配置失败"),_(!1)}},b=()=>{switch(F(null),U(""),q){case"provider":U(K.name||""),G("name");break;case"baseUrl":G("provider");break;case"apiKey":U(K.baseUrl||""),G("baseUrl");break;case"model":G("apiKey");break;case"confirm":U(K.model||""),G("model");break}},E=q==="name"?1:q==="provider"?2:q==="baseUrl"?3:q==="apiKey"?4:q==="model"?5:6,f=Math.floor((E-1)/5*40);return D(r,{...$==="setup"?{flexDirection:"column",padding:1}:$==="add"?{flexDirection:"column",borderStyle:"round",borderColor:"blue",padding:1}:{flexDirection:"column",borderStyle:"round",borderColor:"yellow",padding:1},children:[$==="setup"?D(D6,{children:[D(r,{marginBottom:1,children:D(C,{bold:!0,color:"blue",children:"\uD83D\uDE80 欢迎使用 Blade Code"},void 0,!1,void 0,this)},void 0,!1,void 0,this),D(r,{marginBottom:1,children:D(C,{children:"AI 驱动的代码助手 - 让我们开始配置您的助手"},void 0,!1,void 0,this)},void 0,!1,void 0,this),D(r,{marginBottom:1,children:[D(C,{bold:!0,color:"blue",children:"█".repeat(f)},void 0,!1,void 0,this),D(C,{dimColor:!0,children:"░".repeat(40-f)},void 0,!1,void 0,this),D(C,{children:" "},void 0,!1,void 0,this),D(C,{bold:!0,color:"cyan",children:[E,"/6"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),D(r,{marginBottom:1,children:D(C,{dimColor:!0,children:"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this):$==="add"?D(D6,{children:[D(r,{justifyContent:"center",marginBottom:1,children:D(C,{bold:!0,color:"blue",children:"添加新模型配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),D(r,{marginBottom:1,children:D(C,{children:["步骤: ",E,"/6"]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this):D(D6,{children:[D(r,{justifyContent:"center",marginBottom:1,children:D(C,{bold:!0,color:"yellow",children:"编辑模型配置"},void 0,!1,void 0,this)},void 0,!1,void 0,this),D(r,{marginBottom:1,children:D(C,{children:["步骤: ",E,"/6"]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q==="name"&&D(I6,{stepNumber:1,icon:"\uD83D\uDCDD",title:"配置名称",description:"给这个模型配置起一个易于识别的名称",value:O,placeholder:"例如: 千问工作账号",onChange:U,onSubmit:N,onCancel:Q},void 0,!1,void 0,this),q==="provider"&&D(bG,{onSelect:A,onCancel:Q,initialProvider:K.provider},void 0,!1,void 0,this),q==="baseUrl"&&D(I6,{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:O,placeholder:"https://api.example.com/v1",onChange:U,onSubmit:R,onCancel:Q},void 0,!1,void 0,this),q==="apiKey"&&D(I6,{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:O,placeholder:"sk-...",mask:"*",onChange:U,onSubmit:k,onCancel:Q},void 0,!1,void 0,this),q==="model"&&D(I6,{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:O,placeholder:"例如: gpt-5",onChange:U,onSubmit:I,onCancel:Q},void 0,!1,void 0,this),q==="confirm"&&D(VG,{mode:$,config:K,isSaving:H,onConfirm:w,onBack:b,onCancel:Q},void 0,!1,void 0,this),z&&D(r,{marginTop:1,borderStyle:"round",borderColor:"red",paddingX:1,children:D(C,{color:"red",children:["❌ ",z]},void 0,!0,void 0,this)},void 0,!1,void 0,this),D(r,{marginTop:1,children:D(C,{dimColor:!0,children:"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"},void 0,!1,void 0,this)},void 0,!1,void 0,this),!H&&q==="provider"&&D(r,{marginTop:1,children:D(C,{dimColor:!0,children:["\uD83D\uDCA1 使用 ",D(C,{bold:!0,children:"↑/↓"},void 0,!1,void 0,this)," 键选择,",D(C,{bold:!0,children:"Enter"},void 0,!1,void 0,this)," 确认,",D(C,{bold:!0,children:"Esc"},void 0,!1,void 0,this)," 取消"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),!H&&q!=="confirm"&&q!=="provider"&&D(r,{marginTop:1,children:D(C,{dimColor:!0,children:["\uD83D\uDCA1 输入完成后按 ",D(C,{bold:!0,children:"Enter"},void 0,!1,void 0,this),",",D(C,{bold:!0,children:"Ctrl+C"},void 0,!1,void 0,this)," 退出"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),!H&&q==="confirm"&&D(r,{marginTop:1,children:D(C,{dimColor:!0,children:["\uD83D\uDCA1 按"," ",D(C,{bold:!0,color:"green",children:"Y"},void 0,!1,void 0,this)," ","保存,",D(C,{bold:!0,color:"red",children:"N"},void 0,!1,void 0,this)," ","返回修改,",D(C,{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 M6,useMount as IG}from"ahooks";import{Box as X1,Text as Q0,useFocus as DG,useFocusManager as vG,useInput as MG}from"ink";import kG from"ink-select-input";import{memo as yG,useMemo as EG,useState as k6}from"react";import{jsxDEV as d}from"react/jsx-dev-runtime";var jG=({isSelected:$})=>d(X1,{marginRight:1,children:d(Q0,{color:$?"yellow":"gray",children:$?"▶":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),PG=({isSelected:$,label:Y})=>d(Q0,{bold:$,color:$?"yellow":void 0,children:Y},void 0,!1,void 0,this),h7=yG(({onClose:$,onEdit:Y})=>{let X=a5(),Z=n5()??"",{isFocused:Q}=DG({id:"model-selector"}),J=vG(),[q,G]=k6(""),[K,W]=k6(!1),[O,U]=k6(null),H=V0(!1),[_]=k6(()=>{let I=process.stdout?.columns||80;return Math.max(20,I-8)});IG(()=>{if(J?.focus("model-selector"),X.length>0)G(X[0].id)}),MG((I,w)=>{if(K)return;if(w.ctrl&&I==="c"||w.meta&&I==="c"){H();return}if(w.escape){$();return}if(!Q)return;if(I==="d"||I==="D"){F();return}if((I==="e"||I==="E")&&Y)B()},{isActive:!0});let z=M6(async(I)=>{if(K)return;let w=I.value;if(w===Z){$();return}W(!0),U(null);try{await W0().setCurrentModel(w),$()}catch(b){U(b.message),W(!1)}}),F=M6(async()=>{if(K||q===Z)return;W(!0),U(null);try{if(await W0().removeModel(q),X.length<=1)$()}catch(I){U(I.message)}finally{W(!1)}}),B=M6(()=>{if(K||!Y)return;let I=X.find((w)=>w.id===q);if(!I)return;Y(I)}),L=M6((I)=>{G(I.value)}),N=EG(()=>{return X.find((I)=>I.id===q)},[X,q]),A=X.map((I)=>({label:I.name+(I.id===Z?" (当前)":""),value:I.id})),R=q===Z;return d(X1,{flexDirection:"column",borderStyle:"round",borderColor:"gray",padding:1,width:"100%",children:[d(X1,{flexDirection:"row",justifyContent:"space-between",marginBottom:1,children:[d(Q0,{bold:!0,color:"cyan",children:"模型管理"},void 0,!1,void 0,this),d(Q0,{dimColor:!0,children:[K?"⏳ 处理中...":R?"Enter=关闭 • E=编辑 • Esc=取消":"Enter=切换 • D=删除 • E=编辑 • Esc=取消"," • Ctrl+C=退出"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),d(X1,{flexDirection:"row",children:[d(X1,{flexDirection:"column",flexGrow:2,marginRight:2,borderStyle:"single",borderColor:"gray",padding:1,children:[d(Q0,{dimColor:!0,children:["已配置模型 (",X.length,")"]},void 0,!0,void 0,this),d(X1,{marginTop:1,children:d(kG,{items:A,onSelect:z,onHighlight:L,indicatorComponent:jG,itemComponent:PG},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),d(X1,{flexDirection:"column",flexGrow:3,borderStyle:"single",borderColor:"gray",padding:1,children:[d(Q0,{dimColor:!0,children:"模型详情"},void 0,!1,void 0,this),d(X1,{marginY:1,children:d(Q0,{color:R?"green":"yellow",children:R?"● 当前使用":"● 可切换"},void 0,!1,void 0,this)},void 0,!1,void 0,this),N?d(X1,{flexDirection:"column",children:[d(Q0,{children:[d(Q0,{dimColor:!0,children:"名称: "},void 0,!1,void 0,this),d(Q0,{bold:!0,color:"cyan",children:N.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),d(Q0,{children:[d(Q0,{dimColor:!0,children:"Provider: "},void 0,!1,void 0,this),d(Q0,{bold:!0,children:N.provider},void 0,!1,void 0,this)]},void 0,!0,void 0,this),d(Q0,{children:[d(Q0,{dimColor:!0,children:"Model: "},void 0,!1,void 0,this),d(Q0,{bold:!0,children:N.model},void 0,!1,void 0,this)]},void 0,!0,void 0,this),d(Q0,{children:[d(Q0,{dimColor:!0,children:"Base URL: "},void 0,!1,void 0,this),d(Q0,{color:"blueBright",children:N.baseUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this),N.temperature!==void 0&&d(Q0,{children:[d(Q0,{dimColor:!0,children:"Temperature: "},void 0,!1,void 0,this),d(Q0,{children:N.temperature},void 0,!1,void 0,this)]},void 0,!0,void 0,this),N.maxContextTokens!==void 0&&d(Q0,{children:[d(Q0,{dimColor:!0,children:"Context Window: "},void 0,!1,void 0,this),d(Q0,{children:N.maxContextTokens},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this):d(Q0,{dimColor:!0,children:"请选择一个模型查看详情"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),O&&d(X1,{marginTop:1,children:d(Q0,{color:"red",children:["❌ ",O]},void 0,!0,void 0,this)},void 0,!1,void 0,this),d(X1,{justifyContent:"center",marginTop:1,children:d(Q0,{dimColor:!0,children:"─".repeat(_)},void 0,!1,void 0,this)},void 0,!1,void 0,this),d(X1,{justifyContent:"center",children:d(Q0,{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 b2}from"ahooks";import{promises as m7}from"fs";import{Box as u0,Text as _0,useInput as SG}from"ink";import x7 from"ink-select-input";import TG from"ink-text-input";import CG from"os";import y6 from"path";import{useEffect as fG,useMemo as E6,useRef as hG,useState as i1}from"react";import{jsxDEV as c}from"react/jsx-dev-runtime";var V2=[{key:"allow",label:"Allow"},{key:"ask",label:"Ask"},{key:"deny",label:"Deny"},{key:"info",label:"Info"}],xG={allow:"Add a new rule...",ask:"Add a new rule...",deny:"Add a new rule..."},pG={allow:"Allow permission rules",ask:"Ask permission rules",deny:"Deny permission rules"},p7={project:"[项目共享配置]",global:"[用户全局配置]",local:"[本地配置]"},gG=["project","global","local"],mG={allow:[],ask:[],deny:[]},uG={localExists:!1,projectExists:!1,globalExists:!1},g7={allow:[],ask:[],deny:[]};function dG($){let Y=(Z)=>Array.isArray(Z)?Z.filter((Q)=>typeof Q==="string"):[],X=$?.permissions??{};return{allow:Y(X?.allow),ask:Y(X?.ask),deny:Y(X?.deny)}}async function cG($){try{let Y=await m7.readFile($,"utf-8"),X=JSON.parse(Y);return{exists:!0,raw:X,permissions:dG(X)}}catch(Y){if(Y.code==="ENOENT")return{exists:!1,raw:{},permissions:{...g7}};return console.warn(`[PermissionsManager] Failed to read ${$}:`,Y),{exists:!0,raw:{},permissions:{...g7}}}}function lG($,Y){let X=$.padEnd(32," "),Z=Y==="local"?`${p7[Y]} ← 可删除`:p7[Y];return`${X} ${Z}`}var u7=({onClose:$})=>{let X=a0()==="permissions-manager",Z=V0(!1),[Q,J]=i1(0),q=V2[Q].key,[G,K]=i1(mG),[W,O]=i1(uG),[U,H]=i1(!0),[_,z]=i1("list"),[F,B]=i1(""),[L,N]=i1(null),[A,R]=i1(null),k=hG(!1),I=E6(()=>y6.join(process.cwd(),".blade","settings.local.json"),[]),w=E6(()=>y6.join(process.cwd(),".blade","settings.json"),[]),b=E6(()=>y6.join(CG.homedir(),".blade","settings.json"),[]),E=b2(async()=>{H(!0);let X0=await Promise.all([{source:"local",path:I},{source:"project",path:w},{source:"global",path:b}].map(async({source:A0,path:D1})=>{let Z1=await cG(D1);return{source:A0,path:D1,...Z1}})),n={localExists:X0.find((A0)=>A0.source==="local")?.exists??!1,projectExists:X0.find((A0)=>A0.source==="project")?.exists??!1,globalExists:X0.find((A0)=>A0.source==="global")?.exists??!1};O(n);let m0={allow:[],ask:[],deny:[]},n1=Object.fromEntries(X0.map((A0)=>[A0.source,A0]));["allow","ask","deny"].forEach((A0)=>{gG.forEach((D1)=>{(n1[D1]?.permissions[A0]??[]).forEach((l$,N1)=>{let o1={key:`${D1}:${N1}:${l$}`,rule:l$,source:D1};m0[A0].push(o1)})})}),K(m0),H(!1)});fG(()=>{E()},[E]);let f=b2(async(l,X0)=>{try{let n=y6.join(process.cwd(),".blade","settings.local.json"),m0={allow:[],ask:[],deny:[]};try{let A0=await m7.readFile(n,"utf-8"),Z1=JSON.parse(A0).permissions||{};m0={allow:Array.isArray(Z1.allow)?Z1.allow:[],ask:Array.isArray(Z1.ask)?Z1.ask:[],deny:Array.isArray(Z1.deny)?Z1.deny:[]}}catch(A0){}let n1=X0(m0);await W0().updateConfig({permissions:n1},{scope:"local",immediate:!0}),await E()}catch(n){throw console.error("[PermissionsManager] 修改权限规则失败:",n),n}});SG((l,X0)=>{if(X0.ctrl&&l==="c"||X0.meta&&l==="c"){Z();return}if(_==="locked"){if(k.current){k.current=!1;return}z("list"),N(null),R(null);return}if(X0.escape){if(_==="list"||q==="info")$();else z("list"),B(""),N(null),R(null);return}if(_==="list"){if(X0.tab&&X0.shift)J((n)=>(n-1+V2.length)%V2.length);else if(X0.tab)J((n)=>(n+1)%V2.length);else if(l?.toLowerCase()==="q")$()}},{isActive:X});let h=b2((l)=>{let X0=l.value;if(q==="info")return;if(X0.type==="add"){z("add"),B(""),R(null);return}if(X0.entry.source!=="local"){z("locked"),k.current=!0,N({tab:q,entry:X0.entry}),R({type:"error",text:X0.entry.source==="project"?"此规则定义在项目共享配置中,无法在此删除。":"此规则来自用户全局配置,无法在此删除。"});return}z("confirm-delete"),N({tab:q,entry:X0.entry}),R(null)}),v=b2(async()=>{if(q==="info")return;let l=F.trim();if(!l){R({type:"error",text:"Permission rule 不能为空"});return}if(G[q].map((n)=>n.rule).includes(l)){R({type:"error",text:"该规则已存在"});return}try{await f(q,(n)=>{let m0={allow:[...n.allow],ask:[...n.ask],deny:[...n.deny]};return m0[q]=[...new Set([...n[q],l])],m0}),z("list"),B(""),R({type:"success",text:"已添加本地权限规则"})}catch(n){R({type:"error",text:`保存失败: ${n instanceof Error?n.message:"未知错误"}`})}}),m=b2(async()=>{if(!L)return;let{tab:l,entry:X0}=L;try{await f(l,(n)=>{let m0={allow:[...n.allow],ask:[...n.ask],deny:[...n.deny]};return m0[l]=n[l].filter((n1)=>n1!==X0.rule),m0}),z("list"),N(null),R({type:"success",text:"已删除本地权限规则"})}catch(n){R({type:"error",text:`删除失败: ${n instanceof Error?n.message:"未知错误"}`})}}),z1=E6(()=>{if(q==="info")return[];let l=q;return[{label:`› ${xG[l]}`,value:{type:"add"}},...G[l].map((n)=>({label:lG(n.rule,n.source),value:{type:"rule",entry:n}}))]},[q,G]),J0=()=>c(u0,{marginBottom:1,children:V2.map((l,X0)=>c(u0,{marginRight:2,children:c(_0,{color:X0===Q?"yellow":"gray",children:["[",l.label,"]"]},void 0,!0,void 0,this)},l.key,!1,void 0,this))},void 0,!1,void 0,this),G0=()=>c(u0,{flexDirection:"column",gap:1,children:[c(_0,{children:"配置文件优先级(从高到低):"},void 0,!1,void 0,this),c(u0,{flexDirection:"column",marginLeft:2,children:[c(_0,{children:["1. .blade/settings.local.json (本地配置,不提交 Git)"," ",W.localExists?"✓ 存在":"✗ 不存在"]},void 0,!0,void 0,this),c(_0,{children:["2. .blade/settings.json (项目配置,提交 Git)"," ",W.projectExists?"✓ 存在":"✗ 不存在"]},void 0,!0,void 0,this),c(_0,{children:["3. ~/.blade/settings.json (用户全局配置)"," ",W.globalExists?"✓ 存在":"✗ 不存在"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),c(_0,{children:"说明:"},void 0,!1,void 0,this),c(u0,{flexDirection:"column",marginLeft:2,children:[c(_0,{children:"- /permissions 命令只管理本地配置 (.blade/settings.local.json)"},void 0,!1,void 0,this),c(_0,{children:"- 修改全局或项目配置请直接编辑对应文件"},void 0,!1,void 0,this),c(_0,{children:"- 本地配置不会提交到 Git"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),u=(l)=>c(u0,{flexDirection:"column",gap:1,children:[c(_0,{bold:!0,children:pG[l]},void 0,!1,void 0,this),c(_0,{children:"Permission rules are a tool name, optionally followed by a specifier in parentheses."},void 0,!1,void 0,this),c(_0,{color:"gray",children:"例如: WebFetch 或 Bash(ls:*)"},void 0,!1,void 0,this),c(u0,{marginTop:1,children:c(TG,{value:F,onChange:B,onSubmit:v},void 0,!1,void 0,this)},void 0,!1,void 0,this),c(_0,{color:"gray",children:"Enter 提交 · Esc 取消"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),c$=(l,X0)=>c(u0,{flexDirection:"column",gap:1,children:[c(_0,{bold:!0,children:["Delete ",l," permission rule?"]},void 0,!0,void 0,this),c(_0,{children:X0.rule},void 0,!1,void 0,this),c(_0,{color:"gray",children:"From project local settings"},void 0,!1,void 0,this),c(_0,{children:"Are you sure you want to delete this permission rule?"},void 0,!1,void 0,this),c(x7,{items:[{label:"Yes",value:"yes"},{label:"No",value:"no"}],onSelect:(n)=>{if(n.value==="yes")m();else z("list"),N(null)}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Y0=(l)=>c(u0,{flexDirection:"column",gap:1,children:[c(_0,{bold:!0,children:"Cannot delete this rule"},void 0,!1,void 0,this),c(_0,{children:l.rule},void 0,!1,void 0,this),c(_0,{color:"gray",children:l.source==="project"?"This rule is defined in .blade/settings.json. 请手动编辑该文件以移除规则。":"This rule is defined in ~/.blade/settings.json. 请手动编辑该文件以移除规则。"},void 0,!1,void 0,this),c(_0,{color:"gray",children:"按任意键继续"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),z0=(l)=>c(x7,{items:z1,isFocused:_==="list",onSelect:h},void 0,!1,void 0,this),a1=()=>{if(U)return c(_0,{children:"加载中..."},void 0,!1,void 0,this);if(q==="info")return G0();if(_==="add")return u(q);if(_==="confirm-delete"&&L)return c$(L.tab,L.entry);if(_==="locked"&&L)return Y0(L.entry);return z0(q)};return c(u0,{flexDirection:"column",borderStyle:"round",borderColor:X?"cyan":"gray",padding:1,width:80,children:[c(_0,{color:"cyan",bold:!0,children:"⚙️ 权限管理器"},void 0,!1,void 0,this),J0(),c(u0,{flexDirection:"column",gap:1,children:a1()},void 0,!1,void 0,this),A&&c(u0,{marginTop:1,children:c(_0,{color:A.type==="success"?"green":"red",children:A.text},void 0,!1,void 0,this)},void 0,!1,void 0,this),c(u0,{marginTop:1,children:c(_0,{color:"gray",children:"Tab 切换视图 · Esc 关闭 · Q 退出"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{Box as d$,Text as F1,useInput as iG}from"ink";import rG from"ink-select-input";import{useEffect as d7,useMemo as j6,useState as l8}from"react";import{jsxDEV as I0}from"react/jsx-dev-runtime";function aG($){let Y=new Date($),Z=new Date().getTime()-Y.getTime(),Q=Math.floor(Z/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 nG($){let Y=$.split("/");return Y[Y.length-1]||$}var oG=({isSelected:$})=>I0(d$,{marginRight:1,children:I0(F1,{color:$?"cyan":"gray",children:$?"❯":" "},void 0,!1,void 0,this)},void 0,!1,void 0,this),sG=({isSelected:$,label:Y})=>I0(F1,{color:$?"cyan":"white",bold:$,children:Y},void 0,!1,void 0,this),I2=20,c7=({sessions:$,onSelect:Y,onCancel:X})=>{let[Z,Q]=l8([]),[J,q]=l8(!1),[G,K]=l8(0),O=a0()==="session-selector",U=V0(!1);iG((N,A)=>{if(A.ctrl&&N==="c"||A.meta&&N==="c"){U();return}if(A.escape&&X){X();return}if(A.leftArrow||N==="h"||N==="H"){if(G>0)K((R)=>R-1);return}if(A.rightArrow||N==="l"||N==="L"){if(G<z-1)K((R)=>R+1);return}},{isActive:O}),d7(()=>{if($){Q($);return}(async()=>{q(!0);try{let A=await A1.listSessions();Q(A)}catch(A){console.error("[SessionSelector] Failed to load sessions:",A),Q([])}finally{q(!1)}})()},[$]);let H=$||Z,_=j6(()=>{return H.map((N)=>{let A=nG(N.projectPath),R=aG(N.lastMessageTime),k=N.gitBranch?` (${N.gitBranch})`:"",I=N.hasErrors?" ⚠️":"";return{label:`\uD83D\uDCC5 ${R} | ${A}${k} | ${N.messageCount} 条消息${I}`,value:N.sessionId}})},[H]),z=j6(()=>Math.max(1,Math.ceil(_.length/I2)),[_.length]),F=j6(()=>{let N=G*I2;return _.slice(N,N+I2)},[_,G]),B=j6(()=>({start:G*I2+1,end:Math.min((G+1)*I2,_.length)}),[G,_.length]);d7(()=>{K(0)},[H.length]);let L=(N)=>{Y(N.value)};if(J)return I0(d$,{flexDirection:"column",paddingX:2,paddingY:1,children:I0(F1,{children:"⏳ 正在加载会话列表..."},void 0,!1,void 0,this)},void 0,!1,void 0,this);if(H.length===0)return I0(d$,{flexDirection:"column",paddingX:2,paddingY:1,children:[I0(F1,{color:"yellow",children:"⚠️ 没有找到历史会话"},void 0,!1,void 0,this),I0(F1,{dimColor:!0,children:[`
1503
+ `,"提示: 开始一次对话后,会话历史将保存到 ~/.blade/projects/"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this);return I0(d$,{flexDirection:"column",paddingX:2,paddingY:1,children:[I0(F1,{bold:!0,color:"cyan",children:"\uD83D\uDCC2 选择要恢复的会话:"},void 0,!1,void 0,this),I0(F1,{dimColor:!0,children:[`
1506
1504
  `,"(←→ 翻页 | ↑↓ 选择 | Enter 确认 | Esc 取消)",`
1507
- `]},void 0,!0,void 0,this),V0(RG,{items:F,onSelect:w,indicatorComponent:DG,itemComponent:IG},void 0,!1,void 0,this),V0(C$,{marginTop:1,flexDirection:"column",children:[V0(U1,{dimColor:!0,children:["第 ",G+1,"/",z," 页 · 共 ",H.length," 个会话 · 显示"," ",L.start,"-",L.end]},void 0,!0,void 0,this),z>1&&V0(C$,{marginTop:1,children:[V0(U1,{color:G>0?"cyan":"gray",children:G>0?"◀ ← 上一页":" "},void 0,!1,void 0,this),V0(U1,{children:" "},void 0,!1,void 0,this),V0(U1,{color:G<z-1?"cyan":"gray",children:G<z-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 kG}from"ahooks";import{Box as R1,Text as P,useInput as vG}from"ink";import MG from"ink-select-input";import{useState as DY}from"react";import{jsxDEV as v}from"react/jsx-dev-runtime";var IY=L1.map(($)=>({label:$.label,value:$.id})),yG=({theme:$})=>{let{colors:Y}=$;return v(R1,{flexDirection:"column",paddingLeft:1,paddingTop:1,children:[v(P,{bold:!0,color:Y.text.primary,children:"代码预览"},void 0,!1,void 0,this),v(P,{children:" "},void 0,!1,void 0,this),v(P,{color:Y.syntax.comment,children:"# function"},void 0,!1,void 0,this),v(P,{children:[v(P,{color:Y.syntax.keyword,children:"def"},void 0,!1,void 0,this)," ",v(P,{color:Y.syntax.function,children:"fibonacci"},void 0,!1,void 0,this),v(P,{color:Y.text.primary,children:"("},void 0,!1,void 0,this),v(P,{color:Y.syntax.variable,children:"n"},void 0,!1,void 0,this),v(P,{color:Y.text.primary,children:"):"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),v(P,{children:[" ",v(P,{color:Y.syntax.variable,children:"a"},void 0,!1,void 0,this),v(P,{color:Y.syntax.operator,children:","},void 0,!1,void 0,this)," ",v(P,{color:Y.syntax.variable,children:"b"},void 0,!1,void 0,this)," ",v(P,{color:Y.syntax.operator,children:"="},void 0,!1,void 0,this)," ",v(P,{color:Y.syntax.number,children:"0"},void 0,!1,void 0,this),v(P,{color:Y.syntax.operator,children:","},void 0,!1,void 0,this)," ",v(P,{color:Y.syntax.number,children:"1"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),v(P,{children:[" ",v(P,{color:Y.syntax.keyword,children:"for"},void 0,!1,void 0,this)," ",v(P,{color:Y.syntax.variable,children:"_"},void 0,!1,void 0,this)," ",v(P,{color:Y.syntax.keyword,children:"in"},void 0,!1,void 0,this)," ",v(P,{color:Y.syntax.function,children:"range"},void 0,!1,void 0,this),v(P,{color:Y.text.primary,children:"("},void 0,!1,void 0,this),v(P,{color:Y.syntax.variable,children:"n"},void 0,!1,void 0,this),v(P,{color:Y.text.primary,children:"):"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),v(P,{children:[" ",v(P,{color:Y.syntax.variable,children:"a"},void 0,!1,void 0,this),v(P,{color:Y.syntax.operator,children:","},void 0,!1,void 0,this)," ",v(P,{color:Y.syntax.variable,children:"b"},void 0,!1,void 0,this)," ",v(P,{color:Y.syntax.operator,children:"="},void 0,!1,void 0,this)," ",v(P,{color:Y.syntax.variable,children:"b"},void 0,!1,void 0,this),v(P,{color:Y.syntax.operator,children:","},void 0,!1,void 0,this)," ",v(P,{color:Y.syntax.variable,children:"a"},void 0,!1,void 0,this)," ",v(P,{color:Y.syntax.operator,children:"+"},void 0,!1,void 0,this)," ",v(P,{color:Y.syntax.variable,children:"b"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),v(P,{children:[" ",v(P,{color:Y.syntax.keyword,children:"return"},void 0,!1,void 0,this)," ",v(P,{color:Y.syntax.variable,children:"a"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),v(P,{children:" "},void 0,!1,void 0,this),v(P,{color:Y.error,children:["- print(",v(P,{color:Y.syntax.string,children:'"Hello, "'},void 0,!1,void 0,this)," + name)"]},void 0,!0,void 0,this),v(P,{color:Y.success,children:["+ print(",v(P,{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)},EG=({theme:$})=>{let{colors:Y}=$;return v(R1,{flexDirection:"column",paddingLeft:1,paddingTop:1,children:[v(P,{children:" "},void 0,!1,void 0,this),v(P,{bold:!0,color:Y.text.primary,children:"颜色配置"},void 0,!1,void 0,this),v(P,{children:" "},void 0,!1,void 0,this),v(P,{children:[v(P,{color:Y.text.muted,children:"Primary: "},void 0,!1,void 0,this),v(P,{color:Y.primary,children:Y.primary},void 0,!1,void 0,this)]},void 0,!0,void 0,this),v(P,{children:[v(P,{color:Y.text.muted,children:"Success: "},void 0,!1,void 0,this),v(P,{color:Y.success,children:Y.success},void 0,!1,void 0,this)]},void 0,!0,void 0,this),v(P,{children:[v(P,{color:Y.text.muted,children:"Error: "},void 0,!1,void 0,this),v(P,{color:Y.error,children:Y.error},void 0,!1,void 0,this)]},void 0,!0,void 0,this),v(P,{children:[v(P,{color:Y.text.muted,children:"Warning: "},void 0,!1,void 0,this),v(P,{color:Y.warning,children:Y.warning},void 0,!1,void 0,this)]},void 0,!0,void 0,this),v(P,{children:[v(P,{color:Y.text.muted,children:"Info: "},void 0,!1,void 0,this),v(P,{color:Y.info,children:Y.info},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},kY=()=>{let $=D$(),Y=$0.getCurrentThemeName(),X=L1.findIndex((z)=>z.label===Y),Z=X>=0?L1[X].theme:L1[0].theme,[Q,J]=DY(Z),[q,G]=DY(!1),K=kG(async(z)=>{if(q)return;G(!0);try{$0.setTheme(z.value),await e().setTheme(z.value),$.closeModal()}catch(F){console.error("❌ 主题切换失败:",F instanceof Error?F.message:F)}finally{G(!1)}}),W=(z)=>{let F=L1.find((L)=>L.id===z.value);if(F)J(F.theme)},U=i0()==="theme-selector",H=b0(!1);vG((z,F)=>{if(F.ctrl&&z==="c"||F.meta&&z==="c"){H();return}if(F.escape&&!q)$.closeModal()},{isActive:U});let _=(z)=>{let{isSelected:F,label:L}=z,N=L===Y?"✓":" ";return v(P,{color:F?Q.colors.primary:Q.colors.text.primary,children:[N," ",L]},void 0,!0,void 0,this)};return v(R1,{flexDirection:"column",height:"100%",children:[v(R1,{paddingX:2,paddingY:1,borderStyle:"single",borderColor:Q.colors.border.light,children:v(P,{bold:!0,color:Q.colors.primary,children:"\uD83C\uDFA8 主题选择器"},void 0,!1,void 0,this)},void 0,!1,void 0,this),v(R1,{flexDirection:"row",flexGrow:1,children:[v(R1,{width:"40%",borderStyle:"single",borderColor:Q.colors.border.light,paddingX:1,children:v(R1,{flexDirection:"column",children:[v(R1,{paddingTop:1,paddingBottom:1,children:v(P,{bold:!0,color:Q.colors.text.primary,children:["可用主题 (",IY.length,")"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),v(MG,{items:IY,initialIndex:X>=0?X:0,onSelect:K,onHighlight:W,itemComponent:_},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),v(R1,{width:"60%",flexDirection:"column",borderStyle:"single",borderColor:Q.colors.border.light,children:[v(yG,{theme:Q},void 0,!1,void 0,this),v(EG,{theme:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),v(R1,{paddingX:2,paddingY:1,borderStyle:"single",borderColor:Q.colors.border.light,children:v(P,{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 B0,Fragment as PG}from"react/jsx-dev-runtime";var m0=Y0("UI"),vY=({debug:$,...Y})=>{if($)m0.debug("[Debug] BladeInterface props:",{permissionMode:Y.permissionMode,yolo:Y.yolo});let X=I6(!1),Z=I6(!1),Q=I6(!1),J=I6(null),q=V5(),G=D5(),K=s2(),W=v5(),O=k5(),U=D$(),H=V$(),_=S5(),z=I$(),F=h1(),{exit:L}=jG(),w=q==="ready",N=q==="needsSetup",A=q==="idle",{confirmationState:b,confirmationHandler:y,handleResponse:R}=L3(),{executeCommand:B,handleAbort:D}=F3(Y.systemPrompt,Y.appendSystemPrompt,y,Y.maxTurns),{getPreviousCommand:C,getNextCommand:p,addToHistory:E}=N3(),M=w3("",0),i=g0(async()=>{let r=z,q0;if(r==="default")q0="autoEdit";else if(r==="autoEdit")q0="plan";else q0="default";try{await e().setPermissionMode(q0)}catch(Y1){m0.error("❌ 权限模式切换失败:",Y1 instanceof Error?Y1.message:Y1)}}),S=g0(async(r)=>{try{await e().addModel({name:r.name,provider:r.provider,apiKey:r.apiKey,baseUrl:r.baseUrl,model:r.model}),U.setInitializationStatus("ready")}catch(q0){m0.error("❌ 初始化配置保存失败:",q0 instanceof Error?q0.message:q0),U.setInitializationStatus("ready")}}),O1=g0(()=>{if(K==="shortcuts")U.closeModal();else U.setActiveModal("shortcuts")}),{showSuggestions:Q0,suggestions:_0,selectedSuggestionIndex:y1}=M3(M,B,C,p,E,D,F,i,O1,K==="shortcuts");J$(()=>{if(M.value&&K==="shortcuts")U.closeModal()},[M.value,K,U]);let q$=g0(async()=>{try{if(typeof Y.resume==="string"&&Y.resume!=="true"){let q0=await N1.loadSession(Y.resume),Y1=q0.map((V1,h$)=>({id:`restored-${Date.now()}-${h$}`,role:V1.role,content:typeof V1.content==="string"?V1.content:JSON.stringify(V1.content),timestamp:Date.now()-(q0.length-h$)*1000}));H.restoreSession(Y.resume,Y1);return}let r=await N1.listSessions();if(r.length===0)m0.error("没有找到历史会话"),process.exit(1);U.showSessionSelector(r)}catch(r){m0.error("[BladeInterface] 加载会话失败:",r),process.exit(1)}});J$(()=>{if(X.current)return;if(!Y.resume)return;X.current=!0,q$()},[Y.resume,q$]);let f$=g0(async(r)=>{let q0=b.details?.type;if(q0==="enterPlanMode"&&r.approved)try{await e().setPermissionMode("plan"),m0.debug("[BladeInterface] Entered Plan mode")}catch(Y1){m0.error("[BladeInterface] Failed to enter Plan mode:",Y1)}if(q0==="exitPlanMode"&&r.approved)m0.debug("[BladeInterface] ExitPlanMode approved, Store auto-synced");R(r)}),v6=g0(()=>{H.addAssistantMessage("❌ 设置已取消"),H.addAssistantMessage("Blade 需要 API 配置才能正常工作。"),H.addAssistantMessage("您可以稍后运行 Blade 重新进入设置向导。"),process.exit(0)}),c=g0(()=>{U.closeModal()}),X0=g0(async(r)=>{try{let q0=await N1.loadSession(r),Y1=q0.map((V1,h$)=>({id:`restored-${Date.now()}-${h$}`,role:V1.role,content:typeof V1.content==="string"?V1.content:JSON.stringify(V1.content),timestamp:Date.now()-(q0.length-h$)*1000}));H.restoreSession(r,Y1),U.closeModal()}catch(q0){m0.error("[BladeInterface] Failed to restore session:",q0),U.closeModal()}}),a=g0(()=>{if(Y.resume)L();else U.closeModal()}),x0=g0((r)=>{U.showModelEditWizard(r)}),d1=g0((r)=>{H.addAssistantMessage(`✅ 已更新模型配置: ${r.name}`),c()});J$(()=>{if(N){_.setFocus("model-config-wizard");return}if(b.isVisible)_.setFocus("confirmation-prompt");else if(K==="sessionSelector")_.setFocus("session-selector");else if(K==="themeSelector")_.setFocus("theme-selector");else if(K==="modelSelector")_.setFocus("model-selector");else if(K==="modelAddWizard"||K==="modelEditWizard")_.setFocus("model-config-wizard");else if(K==="permissionsManager")_.setFocus("permissions-manager");else if(K==="agentsManager")_.setFocus("agents-manager");else if(K==="agentCreationWizard")_.setFocus("agent-creation-wizard");else if(K==="shortcuts")_.setFocus("main-input");else _.setFocus("main-input")},[N,b.isVisible,K,_.setFocus]),J$(()=>{if(!w||Q.current)return;Q.current=!0,H.addAssistantMessage("请输入您的问题,我将为您提供帮助。")},[w,H.addAssistantMessage]),J$(()=>{if(!G)return;if(J.current===G)return;if(J.current=G,q==="error")H.addAssistantMessage(`❌ 初始化失败: ${G}`);else H.addAssistantMessage(`❌ ${G}`),H.addAssistantMessage("请重新尝试设置,或检查文件权限")},[G,q,H.addAssistantMessage]);let w0=g0(async(r)=>{try{await B(r)}catch(q0){let Y1=q0 instanceof Error?q0.message:"无法发送初始消息";H.addAssistantMessage(`❌ 初始消息发送失败:${Y1}`)}});J$(()=>{let r=Y.initialMessage?.trim();if(!r||Z.current||!w||N)return;Z.current=!0,E(r),w0(r)},[Y.initialMessage,w,N,B,E]);let b1=g0(async(r)=>{try{await e().setPermissionMode(r)}catch(q0){m0.error("❌ 权限模式初始化失败:",q0 instanceof Error?q0.message:q0)}});if(J$(()=>{let r=Y.permissionMode;if($)m0.debug("[Debug] permissionMode from CLI:",r),m0.debug("[Debug] current permissionMode:",z);if(!r||r===z)return;b1(r)},[Y.permissionMode,z]),A)return null;if(N)return B0(S8,{mode:"setup",onComplete:S,onCancel:v6},void 0,!1,void 0,this);if($)m0.debug("[Debug] 渲染主界面,条件检查:",{confirmationVisible:b.isVisible,activeModal:K});let u0=K==="modelSelector",$1=O,c1=K==="modelAddWizard"?"add":K==="modelEditWizard"&&$1?"edit":null,M6=u0||Boolean(c1),TY=K==="agentsManager",CY=K==="agentCreationWizard",fY=$1?{name:$1.name,provider:$1.provider,baseUrl:$1.baseUrl,apiKey:$1.apiKey,model:$1.model}:void 0,hY=b.isVisible&&b.details?B0(i3,{details:b.details,onResponse:f$},void 0,!1,void 0,this):K==="themeSelector"?B0(kY,{},void 0,!1,void 0,this):K==="permissionsManager"?B0(RY,{onClose:c},void 0,!1,void 0,this):K==="sessionSelector"?B0(VY,{sessions:W,onSelect:X0,onCancel:a},void 0,!1,void 0,this):null;return B0(B2,{flexDirection:"column",width:"100%",height:"100%",children:hY??B0(PG,{children:[B0(FY,{},void 0,!1,void 0,this),B0(WY,{},void 0,!1,void 0,this),B0(XY,{input:M.value,cursorPosition:M.cursorPosition,onChange:M.setValue,onChangeCursorPosition:M.setCursorPosition},void 0,!1,void 0,this),u0&&B0(B2,{marginTop:1,paddingX:2,children:B0(NY,{onClose:c,onEdit:x0},void 0,!1,void 0,this)},void 0,!1,void 0,this),c1&&B0(B2,{marginTop:1,paddingX:2,children:B0(S8,{mode:c1,modelId:$1?.id,initialConfig:c1==="edit"?fY:void 0,onComplete:c1==="edit"?d1:c,onCancel:c},void 0,!1,void 0,this)},void 0,!1,void 0,this),TY&&B0(B2,{marginTop:1,paddingX:2,children:B0(P3,{onComplete:c,onCancel:c},void 0,!1,void 0,this)},void 0,!1,void 0,this),CY&&B0(B2,{marginTop:1,paddingX:2,children:B0(G2,{onComplete:c,onCancel:c},void 0,!1,void 0,this)},void 0,!1,void 0,this),B0(f3,{suggestions:_0,selectedIndex:y1,visible:Q0&&!M6},void 0,!1,void 0,this),B0(C3,{},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)};import{Box as SG,Text as u1}from"ink";import TG from"react";import{jsxDEV as M1}from"react/jsx-dev-runtime";class C8 extends TG.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 M1(SG,{flexDirection:"column",padding:1,borderStyle:"round",borderColor:"red",children:[M1(u1,{color:"red",children:"\uD83D\uDCA5 应用发生错误"},void 0,!1,void 0,this),M1(u1,{children:" "},void 0,!1,void 0,this),M1(u1,{color:"red",children:this.state.error?.message},void 0,!1,void 0,this),M1(u1,{children:" "},void 0,!1,void 0,this),M1(u1,{color:"gray",children:"错误详情:"},void 0,!1,void 0,this),M1(u1,{color:"gray",children:this.state.error?.stack},void 0,!1,void 0,this),M1(u1,{children:" "},void 0,!1,void 0,this),M1(u1,{color:"yellow",children:"请重启应用或联系开发者"},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return this.props.children}}function k6($){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 yY}from"react/jsx-dev-runtime";function MY($){if(s().config.actions.setConfig($),!$.models||$.models.length===0){if($.debug)console.log("[Debug] 未检测到模型配置,进入设置向导");X1().setInitializationStatus("needsSetup");return}if($.debug)console.log("[Debug] 模型配置检查通过,准备就绪");X1().setInitializationStatus("ready")}var EY=($)=>{let[Y,X]=hG(!1),Z=CG(async()=>{try{let J=await D0.getInstance().initialize(),q=A2(J,$);if(MY(q),q.debug)S0.setGlobalDebug(q.debug),console.error("[Debug] 全局 Logger 已启用 debug 模式"),console.error("[Debug] 运行时配置:",q);let G=q.theme;if(G&&$0.hasTheme(G)){if($0.setTheme(G),$.debug)console.log(`✓ 已加载主题: ${G}`)}try{let K=N0.loadFromStandardLocations();if($.debug&&K>0)console.log(`✓ 已加载 ${K} 个 subagents: ${N0.getAllNames().join(", ")}`)}catch(K){if($.debug)console.warn("⚠️ Subagents 加载失败:",k6(K))}try{if(l0.getInstance().loadConfig(q.hooks||{}),$.debug&&q.hooks?.enabled)console.log("✓ Hooks 系统已启用")}catch(K){if($.debug)console.warn("⚠️ Hooks 初始化失败:",k6(K))}F5().then((K)=>{if(K)console.log(""),console.log(K),console.log("")}),N5(async()=>{f0.getInstance().killAll(),await k0.getInstance().disconnectAll(),l0.getInstance().cleanup()}),X(!0)}catch(Q){if($.debug)console.warn("⚠️ 配置初始化失败,使用默认配置:",k6(Q));let J=A2(G$,$);if(MY(J),J.debug)S0.setGlobalDebug(J.debug),console.error("[Debug] 全局 Logger 已启用 debug 模式(fallback)");X(!0)}});if(fG(()=>{Z()},[]),!Y)return null;return yY(C8,{children:yY(vY,{...$},void 0,!1,void 0,this)},void 0,!1,void 0,this)};var SY=PY(process.argv),jY=SY.indexOf("--debug");if(jY!==-1){let $=SY[jY+1],Y=$&&!$.startsWith("-")?$:!0;S0.setGlobalDebug(Y)}async function mG(){if(B5(),await U5())return;let $=gG(PY(process.argv)).scriptName(l1.scriptName).usage(l1.usage).version(l1.version).locale(l1.locale).showHelpOnFail(l1.showHelpOnFail).demandCommand(0,"").recommendCommands().strict(l1.strict).parserConfiguration({"populate--":!0}).options(u8).middleware([e8,$9,Y9]).command(U9).command(X9).command(z5).command(Z9).completion("completion",!1).help("help","Show help").alias("help","h").alias("version","V").fail((Y,X,Z)=>{if(X)console.error("\uD83D\uDCA5 An error occurred:"),console.error(X.message),console.error(`
1508
- Stack trace:`),console.error(X.stack),process.exit(1);if(Y)console.error("❌ Invalid arguments:"),console.error(Y),console.error(`
1509
- \uD83D\uDCA1 Did you mean:`),Z.showHelp(),process.exit(1)}).command("$0",!1,()=>{},async(Y)=>{let X=Y._.slice(1),Z=X.length>0?X.join(" "):void 0,Q={...Y,initialMessage:Z,debug:Y.debug,print:Boolean(Y.print)};delete Q._,delete Q.$0,delete Q.message,xG(pG.createElement(EY,Q),{patchConsole:!0,exitOnCtrlC:!1})});try{await $.parse()}catch(Y){console.error("❌ Parse error:",Y),process.exit(1)}}if(A0.main==A0.module)mG().catch(console.error);export{mG as main};
1505
+ `]},void 0,!0,void 0,this),I0(rG,{items:F,onSelect:L,indicatorComponent:oG,itemComponent:sG},void 0,!1,void 0,this),I0(d$,{marginTop:1,flexDirection:"column",children:[I0(F1,{dimColor:!0,children:["第 ",G+1,"/",z," 页 · 共 ",H.length," 个会话 · 显示"," ",B.start,"-",B.end]},void 0,!0,void 0,this),z>1&&I0(d$,{marginTop:1,children:[I0(F1,{color:G>0?"cyan":"gray",children:G>0?"◀ ← 上一页":" "},void 0,!1,void 0,this),I0(F1,{children:" "},void 0,!1,void 0,this),I0(F1,{color:G<z-1?"cyan":"gray",children:G<z-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 tG}from"ahooks";import{Box as I1,Text as P,useInput as eG}from"ink";import $K from"ink-select-input";import{useState as l7}from"react";import{jsxDEV as y}from"react/jsx-dev-runtime";var i7=b1.map(($)=>({label:$.label,value:$.id})),YK=({theme:$})=>{let{colors:Y}=$;return y(I1,{flexDirection:"column",paddingLeft:1,paddingTop:1,children:[y(P,{bold:!0,color:Y.text.primary,children:"代码预览"},void 0,!1,void 0,this),y(P,{children:" "},void 0,!1,void 0,this),y(P,{color:Y.syntax.comment,children:"# function"},void 0,!1,void 0,this),y(P,{children:[y(P,{color:Y.syntax.keyword,children:"def"},void 0,!1,void 0,this)," ",y(P,{color:Y.syntax.function,children:"fibonacci"},void 0,!1,void 0,this),y(P,{color:Y.text.primary,children:"("},void 0,!1,void 0,this),y(P,{color:Y.syntax.variable,children:"n"},void 0,!1,void 0,this),y(P,{color:Y.text.primary,children:"):"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y(P,{children:[" ",y(P,{color:Y.syntax.variable,children:"a"},void 0,!1,void 0,this),y(P,{color:Y.syntax.operator,children:","},void 0,!1,void 0,this)," ",y(P,{color:Y.syntax.variable,children:"b"},void 0,!1,void 0,this)," ",y(P,{color:Y.syntax.operator,children:"="},void 0,!1,void 0,this)," ",y(P,{color:Y.syntax.number,children:"0"},void 0,!1,void 0,this),y(P,{color:Y.syntax.operator,children:","},void 0,!1,void 0,this)," ",y(P,{color:Y.syntax.number,children:"1"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y(P,{children:[" ",y(P,{color:Y.syntax.keyword,children:"for"},void 0,!1,void 0,this)," ",y(P,{color:Y.syntax.variable,children:"_"},void 0,!1,void 0,this)," ",y(P,{color:Y.syntax.keyword,children:"in"},void 0,!1,void 0,this)," ",y(P,{color:Y.syntax.function,children:"range"},void 0,!1,void 0,this),y(P,{color:Y.text.primary,children:"("},void 0,!1,void 0,this),y(P,{color:Y.syntax.variable,children:"n"},void 0,!1,void 0,this),y(P,{color:Y.text.primary,children:"):"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y(P,{children:[" ",y(P,{color:Y.syntax.variable,children:"a"},void 0,!1,void 0,this),y(P,{color:Y.syntax.operator,children:","},void 0,!1,void 0,this)," ",y(P,{color:Y.syntax.variable,children:"b"},void 0,!1,void 0,this)," ",y(P,{color:Y.syntax.operator,children:"="},void 0,!1,void 0,this)," ",y(P,{color:Y.syntax.variable,children:"b"},void 0,!1,void 0,this),y(P,{color:Y.syntax.operator,children:","},void 0,!1,void 0,this)," ",y(P,{color:Y.syntax.variable,children:"a"},void 0,!1,void 0,this)," ",y(P,{color:Y.syntax.operator,children:"+"},void 0,!1,void 0,this)," ",y(P,{color:Y.syntax.variable,children:"b"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y(P,{children:[" ",y(P,{color:Y.syntax.keyword,children:"return"},void 0,!1,void 0,this)," ",y(P,{color:Y.syntax.variable,children:"a"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y(P,{children:" "},void 0,!1,void 0,this),y(P,{color:Y.error,children:["- print(",y(P,{color:Y.syntax.string,children:'"Hello, "'},void 0,!1,void 0,this)," + name)"]},void 0,!0,void 0,this),y(P,{color:Y.success,children:["+ print(",y(P,{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)},XK=({theme:$})=>{let{colors:Y}=$;return y(I1,{flexDirection:"column",paddingLeft:1,paddingTop:1,children:[y(P,{children:" "},void 0,!1,void 0,this),y(P,{bold:!0,color:Y.text.primary,children:"颜色配置"},void 0,!1,void 0,this),y(P,{children:" "},void 0,!1,void 0,this),y(P,{children:[y(P,{color:Y.text.muted,children:"Primary: "},void 0,!1,void 0,this),y(P,{color:Y.primary,children:Y.primary},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y(P,{children:[y(P,{color:Y.text.muted,children:"Success: "},void 0,!1,void 0,this),y(P,{color:Y.success,children:Y.success},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y(P,{children:[y(P,{color:Y.text.muted,children:"Error: "},void 0,!1,void 0,this),y(P,{color:Y.error,children:Y.error},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y(P,{children:[y(P,{color:Y.text.muted,children:"Warning: "},void 0,!1,void 0,this),y(P,{color:Y.warning,children:Y.warning},void 0,!1,void 0,this)]},void 0,!0,void 0,this),y(P,{children:[y(P,{color:Y.text.muted,children:"Info: "},void 0,!1,void 0,this),y(P,{color:Y.info,children:Y.info},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},r7=()=>{let $=u1(),Y=e.getCurrentThemeName(),X=b1.findIndex((z)=>z.label===Y),Z=X>=0?b1[X].theme:b1[0].theme,[Q,J]=l7(Z),[q,G]=l7(!1),K=tG(async(z)=>{if(q)return;G(!0);try{e.setTheme(z.value),await W0().setTheme(z.value),$.closeModal()}catch(F){console.error("❌ 主题切换失败:",F instanceof Error?F.message:F)}finally{G(!1)}}),W=(z)=>{let F=b1.find((B)=>B.id===z.value);if(F)J(F.theme)},U=a0()==="theme-selector",H=V0(!1);eG((z,F)=>{if(F.ctrl&&z==="c"||F.meta&&z==="c"){H();return}if(F.escape&&!q)$.closeModal()},{isActive:U});let _=(z)=>{let{isSelected:F,label:B}=z,N=B===Y?"✓":" ";return y(P,{color:F?Q.colors.primary:Q.colors.text.primary,children:[N," ",B]},void 0,!0,void 0,this)};return y(I1,{flexDirection:"column",height:"100%",children:[y(I1,{paddingX:2,paddingY:1,borderStyle:"single",borderColor:Q.colors.border.light,children:y(P,{bold:!0,color:Q.colors.primary,children:"\uD83C\uDFA8 主题选择器"},void 0,!1,void 0,this)},void 0,!1,void 0,this),y(I1,{flexDirection:"row",flexGrow:1,children:[y(I1,{width:"40%",borderStyle:"single",borderColor:Q.colors.border.light,paddingX:1,children:y(I1,{flexDirection:"column",children:[y(I1,{paddingTop:1,paddingBottom:1,children:y(P,{bold:!0,color:Q.colors.text.primary,children:["可用主题 (",i7.length,")"]},void 0,!0,void 0,this)},void 0,!1,void 0,this),y($K,{items:i7,initialIndex:X>=0?X:0,onSelect:K,onHighlight:W,itemComponent:_},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),y(I1,{width:"60%",flexDirection:"column",borderStyle:"single",borderColor:Q.colors.border.light,children:[y(YK,{theme:Q},void 0,!1,void 0,this),y(XK,{theme:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),y(I1,{paddingX:2,paddingY:1,borderStyle:"single",borderColor:Q.colors.border.light,children:y(P,{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 L0,Fragment as QK}from"react/jsx-dev-runtime";var d0=$0("UI"),a7=({debug:$,...Y})=>{if($)d0.debug("[Debug] BladeInterface props:",{permissionMode:Y.permissionMode,yolo:Y.yolo,maxTurns:Y.maxTurns});let X=P6(!1),Z=P6(!1),Q=P6(!1),J=P6(null),q=m5(),G=u5(),K=Z6(),W=l5(),O=c5(),U=u1(),H=E$(),_=o5(),z=j$(),F=m1(),{exit:B}=ZK(),L=q==="ready",N=q==="needsSetup",A=q==="idle",{confirmationState:R,confirmationHandler:k,handleResponse:I}=x3(),{executeCommand:w,handleAbort:b}=T3(Y.systemPrompt,Y.appendSystemPrompt,k,Y.maxTurns),{getPreviousCommand:E,getNextCommand:f,addToHistory:h}=f3(),v=p3("",0),m=g0(async()=>{let i=z,K0;if(i==="default")K0="autoEdit";else if(i==="autoEdit")K0="plan";else K0="default";try{await W0().setPermissionMode(K0)}catch(Q1){d0.error("❌ 权限模式切换失败:",Q1 instanceof Error?Q1.message:Q1)}}),z1=g0(async(i)=>{try{await W0().addModel({name:i.name,provider:i.provider,apiKey:i.apiKey,baseUrl:i.baseUrl,model:i.model}),U.setInitializationStatus("ready")}catch(K0){d0.error("❌ 初始化配置保存失败:",K0 instanceof Error?K0.message:K0),U.setInitializationStatus("ready")}}),J0=g0(()=>{if(K==="shortcuts")U.closeModal();else U.setActiveModal("shortcuts")}),{showSuggestions:G0,suggestions:u,selectedSuggestionIndex:c$}=a3(v,w,E,f,h,b,F,m,J0,K==="shortcuts");H$(()=>{if(v.value&&K==="shortcuts")U.closeModal()},[v.value,K,U]);let Y0=g0(async()=>{try{if(typeof Y.resume==="string"&&Y.resume!=="true"){let K0=await A1.loadSession(Y.resume),Q1=K0.map((v1,i$)=>({id:`restored-${Date.now()}-${i$}`,role:v1.role,content:typeof v1.content==="string"?v1.content:JSON.stringify(v1.content),timestamp:Date.now()-(K0.length-i$)*1000}));H.restoreSession(Y.resume,Q1);return}let i=await A1.listSessions();if(i.length===0)d0.error("没有找到历史会话"),process.exit(1);U.showSessionSelector(i)}catch(i){d0.error("[BladeInterface] 加载会话失败:",i),process.exit(1)}});H$(()=>{if(X.current)return;if(!Y.resume)return;X.current=!0,Y0()},[Y.resume,Y0]);let z0=g0(async(i)=>{let K0=R.details?.type;if(K0==="enterPlanMode"&&i.approved)try{await W0().setPermissionMode("plan"),d0.debug("[BladeInterface] Entered Plan mode")}catch(Q1){d0.error("[BladeInterface] Failed to enter Plan mode:",Q1)}if(K0==="exitPlanMode"&&i.approved)d0.debug("[BladeInterface] ExitPlanMode approved, Store auto-synced");I(i)}),a1=g0(()=>{H.addAssistantMessage("❌ 设置已取消"),H.addAssistantMessage("Blade 需要 API 配置才能正常工作。"),H.addAssistantMessage("您可以稍后运行 Blade 重新进入设置向导。"),process.exit(0)}),l=g0(()=>{U.closeModal()}),X0=g0(async(i)=>{try{let K0=await A1.loadSession(i),Q1=K0.map((v1,i$)=>({id:`restored-${Date.now()}-${i$}`,role:v1.role,content:typeof v1.content==="string"?v1.content:JSON.stringify(v1.content),timestamp:Date.now()-(K0.length-i$)*1000}));H.restoreSession(i,Q1),U.closeModal()}catch(K0){d0.error("[BladeInterface] Failed to restore session:",K0),U.closeModal()}}),n=g0(()=>{if(Y.resume)B();else U.closeModal()}),m0=g0((i)=>{U.showModelEditWizard(i)}),n1=g0((i)=>{H.addAssistantMessage(`✅ 已添加模型配置: ${i.name},并已切换到该模型`),l()}),A0=g0((i)=>{H.addAssistantMessage(`✅ 已更新模型配置: ${i.name}`),l()});H$(()=>{if(N){_.setFocus("model-config-wizard");return}if(R.isVisible)_.setFocus("confirmation-prompt");else if(K==="sessionSelector")_.setFocus("session-selector");else if(K==="themeSelector")_.setFocus("theme-selector");else if(K==="modelSelector")_.setFocus("model-selector");else if(K==="modelAddWizard"||K==="modelEditWizard")_.setFocus("model-config-wizard");else if(K==="permissionsManager")_.setFocus("permissions-manager");else if(K==="agentsManager")_.setFocus("agents-manager");else if(K==="agentCreationWizard")_.setFocus("agent-creation-wizard");else if(K==="shortcuts")_.setFocus("main-input");else _.setFocus("main-input")},[N,R.isVisible,K,_.setFocus]),H$(()=>{if(!L||Q.current)return;Q.current=!0,H.addAssistantMessage("请输入您的问题,我将为您提供帮助。")},[L,H.addAssistantMessage]),H$(()=>{if(!G)return;if(J.current===G)return;if(J.current=G,q==="error")H.addAssistantMessage(`❌ 初始化失败: ${G}`);else H.addAssistantMessage(`❌ ${G}`),H.addAssistantMessage("请重新尝试设置,或检查文件权限")},[G,q,H.addAssistantMessage]);let D1=g0(async(i)=>{try{await w(i)}catch(K0){let Q1=K0 instanceof Error?K0.message:"无法发送初始消息";H.addAssistantMessage(`❌ 初始消息发送失败:${Q1}`)}});H$(()=>{let i=Y.initialMessage?.trim();if(!i||Z.current||!L||N)return;Z.current=!0,h(i),D1(i)},[Y.initialMessage,L,N,w,h]);let Z1=g0(async(i)=>{try{await W0().setPermissionMode(i)}catch(K0){d0.error("❌ 权限模式初始化失败:",K0 instanceof Error?K0.message:K0)}});if(H$(()=>{let i=Y.permissionMode;if($)d0.debug("[Debug] permissionMode from CLI:",i),d0.debug("[Debug] current permissionMode:",z);if(!i||i===z)return;Z1(i)},[Y.permissionMode,z]),A)return null;if(N)return L0(c8,{mode:"setup",onComplete:z1,onCancel:a1},void 0,!1,void 0,this);if($)d0.debug("[Debug] 渲染主界面,条件检查:",{confirmationVisible:R.isVisible,activeModal:K});let l$=K==="modelSelector",N1=O,o1=K==="modelAddWizard"?"add":K==="modelEditWizard"&&N1?"edit":null,YY=l$||Boolean(o1),XY=K==="agentsManager",ZY=K==="agentCreationWizard",QY=N1?{name:N1.name,provider:N1.provider,baseUrl:N1.baseUrl,apiKey:N1.apiKey,model:N1.model}:void 0,JY=R.isVisible&&R.details?L0(H7,{details:R.details,onResponse:z0},void 0,!1,void 0,this):K==="themeSelector"?L0(r7,{},void 0,!1,void 0,this):K==="permissionsManager"?L0(u7,{onClose:l},void 0,!1,void 0,this):K==="sessionSelector"?L0(c7,{sessions:W,onSelect:X0,onCancel:n},void 0,!1,void 0,this):null;return L0(D2,{flexDirection:"column",width:"100%",height:"100%",children:JY??L0(QK,{children:[L0(C7,{},void 0,!1,void 0,this),L0(y7,{},void 0,!1,void 0,this),L0(b7,{input:v.value,cursorPosition:v.cursorPosition,onChange:v.setValue,onChangeCursorPosition:v.setCursorPosition},void 0,!1,void 0,this),l$&&L0(D2,{marginTop:1,paddingX:2,children:L0(h7,{onClose:l,onEdit:m0},void 0,!1,void 0,this)},void 0,!1,void 0,this),o1&&L0(D2,{marginTop:1,paddingX:2,children:L0(c8,{mode:o1,modelId:N1?.id,initialConfig:o1==="edit"?QY:void 0,onComplete:o1==="edit"?A0:n1,onCancel:l},void 0,!1,void 0,this)},void 0,!1,void 0,this),XY&&L0(D2,{marginTop:1,paddingX:2,children:L0(t3,{onComplete:l,onCancel:l},void 0,!1,void 0,this)},void 0,!1,void 0,this),ZY&&L0(D2,{marginTop:1,paddingX:2,children:L0(z2,{onComplete:l,onCancel:l},void 0,!1,void 0,this)},void 0,!1,void 0,this),L0(X7,{suggestions:u,selectedIndex:c$,visible:G0&&!YY},void 0,!1,void 0,this),L0(Y7,{},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)};import{Box as JK,Text as r1}from"ink";import qK from"react";import{jsxDEV as P1}from"react/jsx-dev-runtime";class S6 extends qK.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 P1(JK,{flexDirection:"column",padding:1,borderStyle:"round",borderColor:"red",children:[P1(r1,{color:"red",children:"\uD83D\uDCA5 应用发生错误"},void 0,!1,void 0,this),P1(r1,{children:" "},void 0,!1,void 0,this),P1(r1,{color:"red",children:this.state.error?.message},void 0,!1,void 0,this),P1(r1,{children:" "},void 0,!1,void 0,this),P1(r1,{color:"gray",children:"错误详情:"},void 0,!1,void 0,this),P1(r1,{color:"gray",children:this.state.error?.stack},void 0,!1,void 0,this),P1(r1,{children:" "},void 0,!1,void 0,this),P1(r1,{color:"yellow",children:"请重启应用或联系开发者"},void 0,!1,void 0,this)]},void 0,!0,void 0,this);return this.props.children}}import{Box as _$,Text as S1,useInput as GK}from"ink";import{useState as i8}from"react";import{jsxDEV as j0}from"react/jsx-dev-runtime";var T6=[{key:"update",label:"Update now",description:`runs \`${H8()}\``},{key:"skip",label:"Skip",description:""},{key:"skip_until_next",label:"Skip until next version",description:""}],n7=({versionInfo:$,onComplete:Y})=>{let[X,Z]=i8(0),[Q,J]=i8(!1),[q,G]=i8(null);GK((W,O)=>{if(O.ctrl&&W==="c"){G$().shutdown("SIGINT",0);return}if(Q||q)return;if(O.upArrow||W==="k")Z((U)=>U>0?U-1:T6.length-1);else if(O.downArrow||W==="j")Z((U)=>U<T6.length-1?U+1:0);else if(O.return)K(T6[X].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 O=await j5();G(O.message),setTimeout(()=>{G$().shutdown("SIGINT",0)},1500);break}case"skip":Y();break;case"skip_until_next":if($.latestVersion)await E5($.latestVersion);Y();break}};if(q)return j0(_$,{flexDirection:"column",marginY:1,children:j0(S1,{children:q},void 0,!1,void 0,this)},void 0,!1,void 0,this);if(Q)return j0(_$,{flexDirection:"column",marginY:1,children:j0(S1,{color:"cyan",children:"Updating..."},void 0,!1,void 0,this)},void 0,!1,void 0,this);return j0(_$,{flexDirection:"column",marginY:1,children:[j0(S1,{color:"yellow",bold:!0,children:["✨ Update available! ",j0(S1,{color:"gray",children:[$.currentVersion," ","→"," ",$.latestVersion]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),j0(_$,{marginTop:1,children:j0(S1,{color:"gray",children:["Release notes:"," ",j0(S1,{color:"cyan",underline:!0,children:$.releaseNotesUrl},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),j0(_$,{flexDirection:"column",marginTop:1,children:T6.map((W,O)=>{let U=O===X,H=U?"› ":" ",_=`${O+1}. `;return j0(_$,{children:j0(S1,{color:U?"cyan":void 0,children:[H,_,W.label,W.description&&j0(S1,{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),j0(_$,{marginTop:1,children:j0(S1,{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 r8($){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 C6}from"react/jsx-dev-runtime";function WK($){if(o().config.actions.setConfig($),!$.models||$.models.length===0){if($.debug)console.log("[Debug] 未检测到模型配置,进入设置向导");q1().setInitializationStatus("needsSetup");return}if($.debug)console.log("[Debug] 模型配置检查通过,准备就绪");q1().setInitializationStatus("ready")}var s7=($)=>{let[Y,X]=a8(!1),[Z,Q]=a8(null),[J,q]=a8(!1),G=o7(()=>{let W=o().config.config??F$,O=f6(W,$);if(WK(O),O.debug)console.error("[Debug] 运行时配置:",O);let U=O.theme;if(U&&e.hasTheme(U)){if(e.setTheme(U),$.debug)console.log(`✓ 已加载主题: ${U}`)}try{let H=B0.loadFromStandardLocations();if($.debug&&H>0)console.log(`✓ 已加载 ${H} 个 subagents: ${B0.getAllNames().join(", ")}`)}catch(H){if($.debug)console.warn("⚠️ Subagents 加载失败:",r8(H))}try{if(r0.getInstance().loadConfig(O.hooks||{}),$.debug&&O.hooks?.enabled)console.log("✓ Hooks 系统已启用")}catch(H){if($.debug)console.warn("⚠️ Hooks 初始化失败:",r8(H))}T5(async()=>{x0.getInstance().killAll(),await v0.getInstance().disconnectAll(),r0.getInstance().cleanup()}),X(!0)}),K=o7(async()=>{if($.versionCheckPromise){let W=await $.versionCheckPromise;if(W){Q(W),q(!0);return}}G()});if(KK(()=>{K()},[]),J&&Z)return C6(S6,{children:C6(n7,{versionInfo:Z,onComplete:()=>{q(!1),G()}},void 0,!1,void 0,this)},void 0,!1,void 0,this);if(!Y)return null;return C6(S6,{children:C6(a7,{...$},void 0,!1,void 0,this)},void 0,!1,void 0,this)};var $Y=e7(process.argv),t7=$Y.indexOf("--debug");if(t7!==-1){let $=$Y[t7+1],Y=$&&!$.startsWith("-")?$:!0;J1.setGlobalDebug(Y)}async function _K(){C5();let $=P5();if(await I5())return;let Y=HK(e7(process.argv)).scriptName(s1.scriptName).usage(s1.usage).version(s1.version).locale(s1.locale).showHelpOnFail(s1.showHelpOnFail).demandCommand(0,"").recommendCommands().strict(s1.strict).parserConfiguration({"populate--":!0}).options(Y9).middleware([H9,_9,F9]).command(I9).command(z9).command(S5).command(N9).completion("completion",!1).help("help","Show help").alias("help","h").alias("version","V").fail((X,Z,Q)=>{if(Z)console.error("\uD83D\uDCA5 An error occurred:"),console.error(Z.message),console.error(`
1506
+ Stack trace:`),console.error(Z.stack),process.exit(1);if(X)console.error("❌ Invalid arguments:"),console.error(X),console.error(`
1507
+ \uD83D\uDCA1 Did you mean:`),Q.showHelp(),process.exit(1)}).command("$0",!1,()=>{},async(X)=>{let Z=X._.slice(1),Q=Z.length>0?Z.join(" "):void 0,J={...X,initialMessage:Q,debug:X.debug,print:Boolean(X.print),versionCheckPromise:$};delete J._,delete J.$0,delete J.message,UK(OK.createElement(s7,J),{patchConsole:!0,exitOnCtrlC:!1})});try{await Y.parse()}catch(X){console.error("❌ Parse error:",X),process.exit(1)}}if(R0.main==R0.module)_K().catch(console.error);export{_K as main};