blade-code 0.8.2 → 0.8.3

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 (74) hide show
  1. package/dist/blade.js +2 -2
  2. package/dist/{chunk-0z5qe4m2.js → chunk-1m63zddw.js} +1 -1
  3. package/dist/chunk-23h9grdr.js +1 -0
  4. package/dist/{chunk-6jq8h5s9.js → chunk-2c69g6t9.js} +2 -2
  5. package/dist/{chunk-p4yrmzyr.js → chunk-5sccs44n.js} +1 -1
  6. package/dist/{chunk-5ad4qmfj.js → chunk-5yt80bn2.js} +1 -1
  7. package/dist/chunk-6msfa7jh.js +9 -0
  8. package/dist/{chunk-yfcfx0zk.js → chunk-6spmzx13.js} +1 -1
  9. package/dist/chunk-724djh7r.js +1 -0
  10. package/dist/{chunk-81p4kz0b.js → chunk-7bqkkjxf.js} +1 -1
  11. package/dist/chunk-804j7say.js +1 -0
  12. package/dist/chunk-8yk5w2ks.js +1 -0
  13. package/dist/chunk-97qxd4yb.js +2 -0
  14. package/dist/{chunk-qwfqp465.js → chunk-9cr3jexy.js} +1 -1
  15. package/dist/{chunk-kne7h7p5.js → chunk-ar5564sf.js} +1 -1
  16. package/dist/{chunk-f3pvwxp8.js → chunk-b922cq7k.js} +3 -3
  17. package/dist/{chunk-w4xcmzjm.js → chunk-be7qz4cv.js} +1 -1
  18. package/dist/chunk-bqhghfmt.js +6 -0
  19. package/dist/{chunk-s1y8w68s.js → chunk-crbh6x86.js} +1 -1
  20. package/dist/{chunk-5fw9k1ff.js → chunk-d7nrqg5b.js} +2 -2
  21. package/dist/{chunk-9xvnrq7m.js → chunk-eyypmc9m.js} +2 -2
  22. package/dist/{chunk-j77gyhpf.js → chunk-fma9cbq5.js} +1 -1
  23. package/dist/chunk-ghf5tgjr.js +1 -0
  24. package/dist/{chunk-11s7t9dp.js → chunk-hqtskyc1.js} +2 -2
  25. package/dist/chunk-jc7k8pfn.js +22 -0
  26. package/dist/{chunk-eycs00af.js → chunk-kf43f8sy.js} +218 -218
  27. package/dist/{chunk-rxjt7ma7.js → chunk-kjc2aqww.js} +1 -1
  28. package/dist/chunk-kjddt9xy.js +1 -0
  29. package/dist/{chunk-6avkjdjc.js → chunk-m0ded6ky.js} +27 -27
  30. package/dist/{chunk-fpdqvnmq.js → chunk-mqqajem9.js} +2 -2
  31. package/dist/{chunk-a90mfxv9.js → chunk-msr67f6q.js} +1 -1
  32. package/dist/{chunk-y08szyf9.js → chunk-mvww9cmc.js} +20 -20
  33. package/dist/{chunk-fkaebj8c.js → chunk-nbpjzzrg.js} +1 -1
  34. package/dist/chunk-ncvr73ev.js +1 -0
  35. package/dist/{chunk-9b297mzh.js → chunk-qvtahmff.js} +1 -1
  36. package/dist/chunk-qwn46cd6.js +2 -0
  37. package/dist/{chunk-887qxhn5.js → chunk-sva5bdgz.js} +2 -2
  38. package/dist/{chunk-4fye39a8.js → chunk-t9cqscfq.js} +1 -1
  39. package/dist/chunk-tzr992v4.js +1 -0
  40. package/dist/{chunk-1x3846v7.js → chunk-vxpdjtqc.js} +1 -1
  41. package/dist/{chunk-6x6zqjcs.js → chunk-wcf80p9y.js} +1 -1
  42. package/dist/chunk-x8xfx9nv.js +1 -0
  43. package/dist/{chunk-8fp3q919.js → chunk-yewg510f.js} +2 -2
  44. package/dist/{chunk-w11ht6f9.js → chunk-zj3q4btp.js} +1 -1
  45. package/dist/chunk-zjks0ncc.js +6 -0
  46. package/dist/{chunk-0g9cb41d.js → chunk-zsyff0ky.js} +2 -2
  47. package/dist/web/assets/{FilePreview-60E51igH.js → FilePreview-B5g8yi8d.js} +1 -1
  48. package/dist/web/assets/{MarkdownRenderer-DU7jPn9K.js → MarkdownRenderer-qBCxzEb_.js} +1 -1
  49. package/dist/web/assets/{McpModal-CAMU6yrS.js → McpModal-C7y2Fsqc.js} +1 -1
  50. package/dist/web/assets/{SettingsModal-Cjj8NUQy.js → SettingsModal-Dmc7Dw_E.js} +1 -1
  51. package/dist/web/assets/{SettingsStore-CjvkbtuZ.js → SettingsStore-BfoB9tNV.js} +1 -1
  52. package/dist/web/assets/{SkillsModal-Cyc2JAFj.js → SkillsModal-CqFAIfj5.js} +1 -1
  53. package/dist/web/assets/{TerminalPanel-DI-Ls-U8.js → TerminalPanel-EHh8-9b9.js} +1 -1
  54. package/dist/web/assets/index-B-BRpW1c.js +16 -0
  55. package/dist/web/assets/index-Ch0eqSLM.css +1 -0
  56. package/dist/web/index.html +2 -2
  57. package/package.json +1 -1
  58. package/dist/chunk-1evg2hdd.js +0 -2
  59. package/dist/chunk-3wghk9bp.js +0 -1
  60. package/dist/chunk-510rwhx6.js +0 -1
  61. package/dist/chunk-83dkggbx.js +0 -1
  62. package/dist/chunk-8epvwyg8.js +0 -6
  63. package/dist/chunk-9jkbykwq.js +0 -1
  64. package/dist/chunk-a83s9mww.js +0 -1
  65. package/dist/chunk-btst30by.js +0 -6
  66. package/dist/chunk-e9t5ga1b.js +0 -1
  67. package/dist/chunk-gvf4gff0.js +0 -9
  68. package/dist/chunk-j14rn2dx.js +0 -22
  69. package/dist/chunk-kcjgbbec.js +0 -1
  70. package/dist/chunk-q223bq79.js +0 -1
  71. package/dist/chunk-x83a97eh.js +0 -1
  72. package/dist/chunk-zns65xsy.js +0 -2
  73. package/dist/web/assets/index-BC0ssrep.js +0 -16
  74. package/dist/web/assets/index-Ci6gCUjf.css +0 -1
@@ -1,2 +1,2 @@
1
- import{fc as r}from"./chunk-0g9cb41d.js";function s(e,a,i){let t=r().resolveConfig(e),o=e.overrides;return{config:e,model:t,displayName:e.displayName??t.name,chat:{provider:e.provider,model:e.model,apiKey:process.env.BLADE_API_KEY,baseUrl:process.env.BLADE_BASE_URL??o?.baseUrl,temperature:o?.temperature??a.temperature,maxContextTokens:t.contextWindow,maxOutputTokens:o?.maxOutputTokens,timeout:o?.timeout??a.timeout,reasoningEnabled:t.reasoning&&i,fallbackModels:e.fallbackModels,enablePromptCaching:o?.enablePromptCaching,customHeaders:o?.customHeaders,apiVersion:o?.apiVersion,maxRetries:o?.maxRetries}}}function n(e){try{return e.displayName??r().getModel(e.provider,e.model).name}catch{return e.displayName??e.model}}
2
- export{s as Ja,n as Ka};
1
+ import{nc as r}from"./chunk-zsyff0ky.js";function s(e,a,i){let t=r().resolveConfig(e),o=e.overrides;return{config:e,model:t,displayName:e.displayName??t.name,chat:{provider:e.provider,model:e.model,apiKey:process.env.BLADE_API_KEY,baseUrl:process.env.BLADE_BASE_URL??o?.baseUrl,temperature:o?.temperature??a.temperature,maxContextTokens:t.contextWindow,maxOutputTokens:o?.maxOutputTokens,timeout:o?.timeout??a.timeout,reasoningEnabled:t.reasoning&&i,fallbackModels:e.fallbackModels,enablePromptCaching:o?.enablePromptCaching,customHeaders:o?.customHeaders,apiVersion:o?.apiVersion,maxRetries:o?.maxRetries}}}function n(e){try{return e.displayName??r().getModel(e.provider,e.model).name}catch{return e.displayName??e.model}}
2
+ export{s as Ra,n as Sa};
@@ -0,0 +1,22 @@
1
+ import{Sb as V,Ub as j,Vb as y}from"./chunk-kjc2aqww.js";import{bc as O}from"./chunk-eyypmc9m.js";import{nc as x}from"./chunk-zsyff0ky.js";var N={currentModelId:"",models:[],temperature:0,maxOutputTokens:void 0,stream:!0,topP:0.9,topK:50,timeout:180000,theme:"dracula",uiTheme:"system",language:"zh-CN",fontSize:14,autoSaveSessions:!0,notifyBuild:!0,notifyErrors:!1,notifySounds:!1,privacyTelemetry:!1,privacyCrash:!0,debug:!1,mcpEnabled:!1,mcpServers:{},permissions:{allow:["Bash(pwd)","Bash(which *)","Bash(whoami)","Bash(hostname)","Bash(uname *)","Bash(date)","Bash(echo *)","Bash(ls *)","Bash(tree *)","Bash(git status)","Bash(git status -*)","Bash(git log *)","Bash(git diff *)","Bash(git show *)","Bash(git branch -* *)","Bash(git branch)","Bash(git tag -l *)","Bash(git tag --list *)","Bash(git stash list *)","Bash(git stash show *)","Bash(git rev-parse *)","Bash(git describe *)","Bash(git blame *)","Bash(git ls-files *)","Bash(git config --get *)","Bash(git config --list *)","Bash(git shortlog *)","Bash(git merge-base *)","Bash(git cat-file *)","Bash(git for-each-ref *)","Bash(git grep *)","Bash(git worktree list *)","Bash(git reflog show *)","Bash(git reflog)","Bash(git rev-list *)","Bash(git ls-remote *)","Bash(git remote -v)","Bash(git remote --verbose)","Bash(git remote)","Bash(gh pr view *)","Bash(gh pr list *)","Bash(gh pr diff *)","Bash(gh pr checks *)","Bash(gh pr status *)","Bash(gh issue view *)","Bash(gh issue list *)","Bash(gh issue status *)","Bash(gh run list *)","Bash(gh run view *)","Bash(gh repo view *)","Bash(gh auth status)","Bash(npm list *)","Bash(bun pm ls *)","Bash(npm view *)","Bash(npm outdated *)","Bash(pnpm list *)","Bash(yarn list *)","Bash(pip list *)","Bash(pip show *)"],ask:["Bash(curl *)","Bash(wget *)","Bash(aria2c *)","Bash(axel *)","Bash(rm -rf *)","Bash(rm -r *)","Bash(rm --recursive *)","Bash(nc *)","Bash(netcat *)","Bash(telnet *)","Bash(ncat *)"],deny:["Read(./.env)","Read(./.env.*)","Bash(rm -rf /)","Bash(rm -rf /*)","Bash(sudo *)","Bash(chmod 777 *)","Bash(bash *)","Bash(sh *)","Bash(zsh *)","Bash(fish *)","Bash(dash *)","Bash(eval *)","Bash(source *)","Bash(mkfs *)","Bash(fdisk *)","Bash(dd *)","Bash(format *)","Bash(parted *)","Bash(open http*)","Bash(open https*)","Bash(xdg-open http*)","Bash(xdg-open https*)"]},permissionMode:"default",hooks:{enabled:!1,defaultTimeout:60,timeoutBehavior:"ignore",failureBehavior:"ignore",maxConcurrentHooks:5,PreToolUse:[],PostToolUse:[],PostToolUseFailure:[],PermissionRequest:[],UserPromptSubmit:[],SessionStart:[],SessionEnd:[],Stop:[],SubagentStop:[],Notification:[],Compaction:[]},env:{},disableAllHooks:!1,maxTurns:-1,maxConcurrentTasks:3,maxQueuedTasks:100};import{promises as S}from"fs";import{merge as b}from"lodash-es";import D from"os";import $ from"path";var h={sonnet:"claude-sonnet-4-20250514",opus:"claude-opus-4-20250514",haiku:"claude-3-5-haiku-20241022",claude:"claude-sonnet-4-20250514",gpt4o:"gpt-4o",gpt4:"gpt-4o",o1:"o1",o3:"o3","o4-mini":"o4-mini",deepseek:"deepseek-chat","deepseek-v3":"deepseek-chat","deepseek-r1":"deepseek-reasoner","deepseek-v4":"deepseek-v4-0324",gemini:"gemini-2.5-pro",flash:"gemini-2.5-flash",qwen:"qwen3-235b-a22b","qwen-max":"qwen-max","qwen-plus":"qwen-plus"};function T(X){let K=X.toLowerCase().trim();return h[K]??X}var A=1,F=64,E=1,M=1e4;function L(X){return Number.isInteger(X)&&X>=1&&X<=64}function w(X){return Number.isInteger(X)&&X>=1&&X<=1e4}class U{static instance=null;runtimePermissionOverrides;constructor(){}static getInstance(){if(!U.instance)U.instance=new U;return U.instance}static resetInstance(){U.instance=null}async initialize(X){try{this.runtimePermissionOverrides=X?.permissions;let K=await this.loadConfigFiles(),Q=await this.loadSettingsFiles(),q={...K,...Q};if(X)q=this.mergeSettings(q,X);let H=this.normalizeConfig(q),J={...N,...H};if(this.resolveEnvInterpolation(J),process.env.BLADE_MODEL&&J.models?.length>0){let W=T(process.env.BLADE_MODEL),Y=J.models.find((Z)=>Z.id===W||Z.model===W||Z.id===process.env.BLADE_MODEL||Z.model===process.env.BLADE_MODEL);if(Y)J.currentModelId=Y.id}if(process.env.BLADE_DEBUG)J.debug=process.env.BLADE_DEBUG==="1"||process.env.BLADE_DEBUG==="true"||process.env.BLADE_DEBUG;if(J.models.length>0)this.validateConfig(J);if(J.debug)console.log("[ConfigManager] Configuration loaded successfully");return J}catch(K){return console.error("[ConfigManager] Failed to initialize:",K),N}}async loadConfigFiles(){let X=$.join(D.homedir(),".blade","config.json"),K=$.join(V(),".blade","config.json"),Q={},q=await this.loadJsonFile(X);if(q)Q={...Q,...q};let H=await this.loadJsonFile(K);if(H){let J={...Q.mcpServers||{},...H.mcpServers||{}};if(Q={...Q,...H},Object.keys(J).length>0)Q.mcpServers=J}return Q}async loadSettingsFiles(){let X=$.join(D.homedir(),".blade","settings.json"),K=$.join(V(),".blade","settings.json"),Q=$.join(V(),".blade","settings.local.json"),q={},H=await this.loadJsonFile(X);if(H)q=this.mergeSettings(q,H);let J=await this.loadJsonFile(K);if(J)q=this.mergeSettings(q,J);let W=await this.loadJsonFile(Q);if(W)q=this.mergeSettings(q,W);return q}async loadWorkspacePermissions(X,K){let Q={allow:[...K.allow],ask:[...K.ask],deny:[...K.deny]};if($.resolve(X)!==$.resolve(V())){let H=await this.loadWorkspacePermissionOverrides(V()),J=await this.loadJsonFile($.join(D.homedir(),".blade","settings.json")),W={allow:Array.from(new Set([...N.permissions.allow,...J?.permissions?.allow||[],...this.runtimePermissionOverrides?.allow||[]])),ask:Array.from(new Set([...N.permissions.ask,...J?.permissions?.ask||[],...this.runtimePermissionOverrides?.ask||[]])),deny:Array.from(new Set([...N.permissions.deny,...J?.permissions?.deny||[],...this.runtimePermissionOverrides?.deny||[]]))};for(let Y of["allow","ask","deny"]){let Z=new Set(H[Y].filter((R)=>!W[Y].includes(R)));Q[Y]=Q[Y].filter((R)=>!Z.has(R))}}let q=await this.loadWorkspacePermissionOverrides(X);for(let H of["allow","ask","deny"])Q[H]=Array.from(new Set([...Q[H],...q[H]]));return Q}async loadWorkspacePermissionOverrides(X){let K={allow:[],ask:[],deny:[]},Q=[$.join(X,".blade","settings.json"),$.join(X,".blade","settings.local.json")];for(let q of Q){let H=await this.loadJsonFile(q);if(!H?.permissions)continue;for(let J of["allow","ask","deny"])K[J]=Array.from(new Set([...K[J],...H.permissions[J]||[]]))}return K}mergeSettings(X,K){let Q={...JSON.parse(JSON.stringify(X)),...JSON.parse(JSON.stringify(K))};if(K.permissions)Q.permissions={allow:Array.from(new Set([...X.permissions?.allow||[],...K.permissions.allow||[]])),ask:Array.from(new Set([...X.permissions?.ask||[],...K.permissions.ask||[]])),deny:Array.from(new Set([...X.permissions?.deny||[],...K.permissions.deny||[]]))};if(K.hooks)Q.hooks=b({},Q.hooks,K.hooks);if(K.env)Q.env=b({},Q.env,K.env);if(K.mcpServers)Q.mcpServers={...Q.mcpServers||{},...K.mcpServers};if(K.disableAllHooks!==void 0)Q.disableAllHooks=K.disableAllHooks;if(K.permissionMode!==void 0)Q.permissionMode=K.permissionMode;if(K.maxTurns!==void 0)Q.maxTurns=K.maxTurns;return Q}resolveEnvInterpolation(X){let K=/\$\{?([A-Z_][A-Z0-9_]*)(:-([^}]+))?\}?/g,Q=(H)=>{if(typeof H==="string")return H.replace(K,(J,W,Y,Z)=>{return process.env[W]||Z||J});if(Array.isArray(H))return H.map(Q);if(typeof H==="object"&&H!==null){let J=H;for(let[W,Y]of Object.entries(J))J[W]=Q(Y);return J}return H},q=X;for(let[H,J]of Object.entries(q))q[H]=Q(J)}async loadJsonFile(X){try{if(await this.fileExists(X)){let K=await S.readFile(X,"utf-8");return JSON.parse(K)}}catch(K){console.warn(`[ConfigManager] Failed to load ${X}:`,K)}return null}async fileExists(X){try{return await S.access(X),!0}catch{return!1}}normalizeConfig(X){let K=JSON.parse(JSON.stringify(X)),Q=(H)=>H.trim().replace(/^`|`$/g,""),q=(H)=>{for(let[J,W]of Object.entries(H))if(typeof W==="string")H[J]=Q(W);else if(Array.isArray(W))W.forEach((Y,Z)=>{if(typeof Y==="string")W[Z]=Q(Y);else if(typeof Y==="object"&&Y!==null)q(Y)});else if(typeof W==="object"&&W!==null)q(W)};return q(K),K}validateConfig(X){let K=[];if(!X.models||X.models.length===0)K.push("没有可用的模型配置");if(!j(X.maxTurns))K.push(`maxTurns 必须是 ${y()}`);if(!L(X.maxConcurrentTasks))K.push(`maxConcurrentTasks 必须是 ${A}-${F} 之间的整数`);if(!w(X.maxQueuedTasks))K.push(`maxQueuedTasks 必须是 ${E}-${M} 之间的整数`);if(X.models&&X.models.length>0){if(!X.currentModelId)K.push("未设置当前模型 ID");else if(!X.models.find((q)=>q.id===X.currentModelId))K.push(`当前模型 ID "${X.currentModelId}" 在 models 列表中不存在`);for(let Q of X.models){let q=`模型 "${Q.displayName||Q.id}"`,H=["name","apiKey","baseUrl","maxContextTokens","maxOutputTokens","supportsThinking","thinkingBudget","thinkingMode"].filter((J)=>(J in Q));if(H.length>0)K.push(`${q}: 不再支持旧字段 ${H.join(", ")};请重新配置模型`);if(!Q.model)K.push(`${q}: model 字段必填`);if(!Q.provider)K.push(`${q}: provider 字段必填`);if(Q.overrides?.baseUrl&&!Q.overrides.baseUrl.startsWith("http"))K.push(`${q}: overrides.baseUrl "${Q.overrides.baseUrl}" 不是有效的 HTTP URL`);try{x().getModel(Q.provider,Q.model)}catch{K.push(`${q}: 内置 catalog 中不存在 ${Q.provider}/${Q.model}`)}}}if(K.length>0)throw Error(`配置验证失败:
2
+ ${K.map((Q)=>` - ${Q}`).join(`
3
+ `)}
4
+
5
+ `+`请通过以下方式之一提供配置:
6
+ `+` 1. 首次启动: 运行 blade,系统会自动引导配置
7
+ `+` 2. 添加模型: blade 后输入 /model add
8
+ `+` 3. 初始化向导: 输入 /init
9
+
10
+ `+`配置文件示例 (~/.blade/config.json):
11
+ `+`{
12
+ "currentModelId": "model-id-123",
13
+ "models": [
14
+ {
15
+ "id": "model-id-123",
16
+ `+` "displayName": "默认模型",
17
+ `+` "provider": "deepseek",
18
+ "model": "deepseek-v4-pro"
19
+ }
20
+ ]
21
+ }
22
+ `)}}function m(X,K={}){let Q={...X};if(K.debug!==void 0)Q.debug=K.debug===""?!0:K.debug;if(K.model){if(!X.models.some((H)=>H.id===K.model))throw Error(`模型配置未找到: ${K.model}`);Q.currentModelId=K.model}if(K.yolo===!0)Q.permissionMode="yolo";else if(K.permissionMode!==void 0)Q.permissionMode=K.permissionMode;if(K.maxTurns!==void 0)Q.maxTurns=K.maxTurns;if(K.maxConcurrentTasks!==void 0)Q.maxConcurrentTasks=K.maxConcurrentTasks;if(K.maxQueuedTasks!==void 0)Q.maxQueuedTasks=K.maxQueuedTasks;return Q.systemPrompt=K.systemPrompt,Q.appendSystemPrompt=K.appendSystemPrompt,Q.model=K.model,Q.resumeSessionId=K.sessionId,Q.forkSession=K.forkSession,Q.allowedTools=K.allowedTools,Q.disallowedTools=K.disallowedTools,Q.mcpConfigPaths=K.mcpConfig,Q.strictMcpConfig=K.strictMcpConfig,Q.addDirs=K.addDir,Q.outputFormat=K.outputFormat,Q.inputFormat=K.inputFormat,Q.print=K.print,Q.includePartialMessages=K.includePartialMessages,Q.replayUserMessages=K.replayUserMessages,Q.agentsConfig=K.agents,Q.settingSources=K.settingSources,Q}import{promises as G}from"node:fs";import k from"node:os";import B from"node:path";import{Mutex as C}from"async-mutex";import{merge as v}from"lodash-es";import u from"write-file-atomic";var P=O("Service"),_={models:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},currentModelId:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},temperature:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},maxOutputTokens:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},timeout:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},theme:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},uiTheme:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},language:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},debug:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},fontSize:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},autoSaveSessions:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},notifyBuild:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},notifyErrors:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},notifySounds:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},privacyTelemetry:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},privacyCrash:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},permissionMode:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},permissions:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!0},hooks:{target:"settings",defaultScope:"local",mergeStrategy:"deep-merge",persistable:!0},env:{target:"settings",defaultScope:"local",mergeStrategy:"deep-merge",persistable:!0},disableAllHooks:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!0},maxTurns:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!0},maxConcurrentTasks:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!0},maxQueuedTasks:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!0},mcpServers:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!0},stream:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!1},topP:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!1},topK:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!1},mcpEnabled:{target:"config",defaultScope:"global",mergeStrategy:"replace",persistable:!1},systemPrompt:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},appendSystemPrompt:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},initialMessage:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},resumeSessionId:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},forkSession:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},allowedTools:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},disallowedTools:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},mcpConfigPaths:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},strictMcpConfig:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},addDirs:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},outputFormat:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},inputFormat:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},print:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},includePartialMessages:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},replayUserMessages:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},agentsConfig:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1},settingSources:{target:"settings",defaultScope:"local",mergeStrategy:"replace",persistable:!1}},_K=new Set(Object.entries(_).filter(([X,K])=>K.persistable).map(([X])=>X)),GK=new Set(Object.entries(_).filter(([X,K])=>!K.persistable).map(([X])=>X));class z{static instance=null;pendingUpdates=new Map;timers=new Map;fileLocks=new Map;lastSaveError=null;debounceDelay=300;constructor(){}static getInstance(){if(!z.instance)z.instance=new z;return z.instance}static resetInstance(){if(z.instance)for(let X of z.instance.timers.values())clearTimeout(X);z.instance=null}async save(X,K={}){this.validatePersistableFields(X);let Q=this.groupUpdatesByTarget(X,K.scope,K.projectDir);if(K.immediate)await Promise.all(Array.from(Q.entries()).map(([q,H])=>this.flushTarget(q,H)));else for(let[q,H]of Q)this.scheduleSave(q,H)}async flush(){for(let K of this.timers.values())clearTimeout(K);this.timers.clear();let X=Array.from(this.pendingUpdates.entries()).map(([K,Q])=>this.flushTarget(K,Q));this.pendingUpdates.clear(),await Promise.all(X)}getLastSaveError(){return this.lastSaveError}clearLastSaveError(){this.lastSaveError=null}async appendPermissionRule(X,K={}){await this.appendPermissionRuleForDecision(X,"allow",K)}async appendPermissionDenyRule(X,K={}){await this.appendPermissionRuleForDecision(X,"deny",K)}async appendPermissionRuleForDecision(X,K,Q){let q=Q.scope??"local",H=this.resolveFilePath("settings",q,Q.projectDir);await this.flushTargetWithModifier(H,(J)=>{let W=J.permissions??{allow:[],ask:[],deny:[]},Y={allow:K==="allow"?this.dedupeArray([...W.allow||[],X]):W.allow||[],ask:W.ask||[],deny:K==="deny"?this.dedupeArray([...W.deny||[],X]):W.deny||[]};return{...J,permissions:Y}})}async appendLocalPermissionRule(X,K={}){await this.appendPermissionRule(X,{...K,scope:"local"})}async appendLocalPermissionDenyRule(X,K={}){await this.appendPermissionDenyRule(X,{...K,scope:"local"})}validatePersistableFields(X){for(let K of Object.keys(X)){let Q=_[K];if(!Q)throw Error(`Unknown config field: ${K}`);if(!Q.persistable)throw Error(`Field "${K}" is non-persistable and cannot be saved to config files. Non-persistable fields are runtime-only and only valid for the current session.`)}}groupUpdatesByTarget(X,K,Q){let q=new Map;for(let[H,J]of Object.entries(X)){let W=_[H];if(!W)continue;let Y=K??W.defaultScope,Z=this.resolveFilePath(W.target,Y,Q);if(!q.has(Z))q.set(Z,{});q.get(Z)[H]=J}return q}resolveFilePath(X,K,Q){let q=Q??V();if(X==="config")return K==="global"?B.join(k.homedir(),".blade","config.json"):B.join(q,".blade","config.json");switch(K){case"local":return B.join(q,".blade","settings.local.json");case"project":return B.join(q,".blade","settings.json");case"global":return B.join(k.homedir(),".blade","settings.json");default:return B.join(q,".blade","settings.local.json")}}scheduleSave(X,K){let Q=this.pendingUpdates.get(X)??{},q=this.mergePendingUpdates(Q,K);this.pendingUpdates.set(X,q);let H=this.timers.get(X);if(H)clearTimeout(H);let J=setTimeout(async()=>{let W=this.pendingUpdates.get(X);if(W){this.pendingUpdates.delete(X),this.timers.delete(X);try{await this.flushTarget(X,W),this.lastSaveError=null}catch(Y){let Z=Y instanceof Error?Y:Error(String(Y));this.lastSaveError=Z,P.error(`Failed to save config to ${X}:`,Z.message),P.error("Stack trace:",Z.stack)}}},this.debounceDelay);this.timers.set(X,J)}mergePendingUpdates(X,K){let Q={...X};for(let[q,H]of Object.entries(K)){let J=_[q];if(!J){Q[q]=H;continue}switch(J.mergeStrategy){case"replace":Q[q]=H;break;case"append-dedupe":this.applyAppendDedupe(Q,q,H);break;case"deep-merge":this.applyDeepMerge(Q,q,H);break}}return Q}async flushTarget(X,K){let Q=this.fileLocks.get(X);if(!Q)Q=new C,this.fileLocks.set(X,Q);await Q.runExclusive(async()=>{await this.performWrite(X,K)})}async flushTargetWithModifier(X,K){let Q=this.fileLocks.get(X);if(!Q)Q=new C,this.fileLocks.set(X,Q);await Q.runExclusive(async()=>{await G.mkdir(B.dirname(X),{recursive:!0,mode:493});let q={};try{let J=await G.readFile(X,"utf-8");q=JSON.parse(J)}catch{q={}}let H=K(q);await this.atomicWrite(X,H)})}async performWrite(X,K){await G.mkdir(B.dirname(X),{recursive:!0,mode:493});let Q={};try{let H=await G.readFile(X,"utf-8");Q=JSON.parse(H)}catch{Q={}}let q={...Q};for(let[H,J]of Object.entries(K)){let W=_[H];if(!W){q[H]=J;continue}switch(W.mergeStrategy){case"replace":q[H]=J;break;case"append-dedupe":this.applyAppendDedupe(q,H,J);break;case"deep-merge":this.applyDeepMerge(q,H,J);break}}await this.atomicWrite(X,q)}applyAppendDedupe(X,K,Q){if(K==="permissions"&&typeof Q==="object"&&Q!==null){let q=X[K]??{allow:[],ask:[],deny:[]},H=Q;X[K]={allow:this.dedupeArray([...q.allow||[],...H.allow||[]]),ask:this.dedupeArray([...q.ask||[],...H.ask||[]]),deny:this.dedupeArray([...q.deny||[],...H.deny||[]])}}else if(Array.isArray(Q)){let q=Array.isArray(X[K])?X[K]:[];X[K]=this.dedupeArray([...q,...Q])}else X[K]=Q}applyDeepMerge(X,K,Q){if(typeof Q==="object"&&Q!==null&&!Array.isArray(Q)){let q=typeof X[K]==="object"&&X[K]!==null?X[K]:{};X[K]=v({},q,Q)}else X[K]=Q}dedupeArray(X){return Array.from(new Set(X))}async atomicWrite(X,K){await u(X,JSON.stringify(K,null,2),{mode:384,encoding:"utf-8"})}}function d(){return z.getInstance()}export{N as Ha,A as Ia,F as Ja,E as Ka,M as La,L as Ma,w as Na,U as Oa,m as Pa,d as Qa};