blade-code 0.8.3 → 0.10.0

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 (133) hide show
  1. package/README.md +20 -5
  2. package/dist/blade.js +4 -4
  3. package/dist/chunk-0aj7gp37.js +2 -0
  4. package/dist/{chunk-7bqkkjxf.js → chunk-0h81hxkw.js} +1 -1
  5. package/dist/chunk-2beq0syt.js +2 -0
  6. package/dist/chunk-2fdjn926.js +1 -0
  7. package/dist/chunk-3c5gvxr6.js +1 -0
  8. package/dist/chunk-44wkjs2j.js +114 -0
  9. package/dist/chunk-4vaywb2r.js +2 -0
  10. package/dist/{chunk-crbh6x86.js → chunk-61087jc8.js} +2 -2
  11. package/dist/chunk-6g21dh3n.js +1 -0
  12. package/dist/chunk-6hj2dk75.js +3 -0
  13. package/dist/chunk-6n5xdf2r.js +2 -0
  14. package/dist/chunk-6qe5k7dw.js +4 -0
  15. package/dist/chunk-7dcm1aqd.js +1 -0
  16. package/dist/chunk-7eptyk20.js +1 -0
  17. package/dist/chunk-88vy9hh0.js +4 -0
  18. package/dist/chunk-8nm1hqr1.js +2 -0
  19. package/dist/chunk-8rg05w47.js +174 -0
  20. package/dist/chunk-93ptxa5p.js +4 -0
  21. package/dist/chunk-949btxxx.js +1485 -0
  22. package/dist/chunk-9jy87d0y.js +3 -0
  23. package/dist/chunk-9kd14cwq.js +1 -0
  24. package/dist/chunk-a7nbn5kf.js +3 -0
  25. package/dist/chunk-af49jmns.js +5 -0
  26. package/dist/chunk-asbp4cv4.js +1 -0
  27. package/dist/chunk-beqaxytd.js +2 -0
  28. package/dist/chunk-bqdc3m0p.js +6 -0
  29. package/dist/chunk-bx50res5.js +99 -0
  30. package/dist/chunk-cznge1n7.js +1 -0
  31. package/dist/{chunk-5yt80bn2.js → chunk-d3236505.js} +1 -1
  32. package/dist/chunk-d9ddpapp.js +18 -0
  33. package/dist/chunk-e3tk2jna.js +636 -0
  34. package/dist/chunk-f8db8ftd.js +10 -0
  35. package/dist/chunk-fjp5tvh8.js +1 -0
  36. package/dist/chunk-fjw32ex5.js +2 -0
  37. package/dist/chunk-gafbzeyk.js +1 -0
  38. package/dist/chunk-hh3xw391.js +6 -0
  39. package/dist/chunk-hzvp3bc1.js +44 -0
  40. package/dist/chunk-jv4nkkb5.js +1 -0
  41. package/dist/{chunk-eyypmc9m.js → chunk-jxv6r0c7.js} +2 -2
  42. package/dist/{chunk-mqqajem9.js → chunk-kq5my0yy.js} +2 -2
  43. package/dist/chunk-m3tx1k0s.js +1 -0
  44. package/dist/chunk-m78ceafk.js +1 -0
  45. package/dist/{chunk-be7qz4cv.js → chunk-mjp61rqd.js} +1 -1
  46. package/dist/chunk-mvwp3c11.js +45 -0
  47. package/dist/chunk-mwrn7mcr.js +1 -0
  48. package/dist/chunk-mxhg6jt9.js +25 -0
  49. package/dist/chunk-nah0cbnp.js +2 -0
  50. package/dist/chunk-px5ck9pf.js +2 -0
  51. package/dist/chunk-qev36qrb.js +2 -0
  52. package/dist/{chunk-ar5564sf.js → chunk-sndbq5xt.js} +1 -1
  53. package/dist/chunk-t8q9ks7e.js +3 -0
  54. package/dist/{chunk-wcf80p9y.js → chunk-th7sxjtk.js} +2 -2
  55. package/dist/{chunk-97qxd4yb.js → chunk-ty2kc6kg.js} +2 -2
  56. package/dist/chunk-v4mr98vm.js +1 -0
  57. package/dist/chunk-vb0t2hhd.js +25 -0
  58. package/dist/chunk-vjpd3nee.js +2 -0
  59. package/dist/chunk-vvy506b3.js +3 -0
  60. package/dist/chunk-vyq9r31h.js +22 -0
  61. package/dist/chunk-w4qsayn6.js +9 -0
  62. package/dist/chunk-wsqz3x2e.js +161 -0
  63. package/dist/{chunk-vxpdjtqc.js → chunk-wvj9h7mb.js} +1 -1
  64. package/dist/chunk-yvah5h4x.js +13 -0
  65. package/dist/chunk-z5ae4qvf.js +2 -0
  66. package/dist/chunk-zcw7kyf4.js +2 -0
  67. package/dist/{chunk-qvtahmff.js → chunk-zkbf8n6y.js} +1 -1
  68. package/dist/web/assets/ChatView-CnwNosSG.js +7 -0
  69. package/dist/web/assets/CodeBlockHighlighter-CBo_AxjZ.js +8 -0
  70. package/dist/web/assets/FilePreview-hNo6RCNY.js +8 -0
  71. package/dist/web/assets/MarkdownRenderer-BON4fqSr.js +30 -0
  72. package/dist/web/assets/McpModal-Go_8v1Vu.js +5 -0
  73. package/dist/web/assets/SettingsModal-CRu1zGQf.js +1 -0
  74. package/dist/web/assets/TaskSwitcher-Ds8CBVtp.js +1 -0
  75. package/dist/web/assets/TerminalPanel-Dm4bu6ib.js +1 -0
  76. package/dist/web/assets/index-BNsnHxlt.js +32 -0
  77. package/dist/web/assets/index-DI8ZWdWH.js +11 -0
  78. package/dist/web/assets/index-DVTiq-7u.css +1 -0
  79. package/dist/web/assets/vendor-icons-CsBKlDXT.js +381 -0
  80. package/dist/web/assets/vendor-radix-DXRuAJHH.js +45 -0
  81. package/dist/web/assets/vendor-react-DG5dkZ_t.js +49 -0
  82. package/dist/web/index.html +5 -2
  83. package/package.json +37 -34
  84. package/dist/chunk-1m63zddw.js +0 -2
  85. package/dist/chunk-23h9grdr.js +0 -1
  86. package/dist/chunk-2c69g6t9.js +0 -34
  87. package/dist/chunk-5sccs44n.js +0 -1
  88. package/dist/chunk-6msfa7jh.js +0 -9
  89. package/dist/chunk-6spmzx13.js +0 -6
  90. package/dist/chunk-724djh7r.js +0 -1
  91. package/dist/chunk-804j7say.js +0 -1
  92. package/dist/chunk-8yk5w2ks.js +0 -1
  93. package/dist/chunk-9cr3jexy.js +0 -2
  94. package/dist/chunk-b922cq7k.js +0 -41
  95. package/dist/chunk-bqhghfmt.js +0 -6
  96. package/dist/chunk-d7nrqg5b.js +0 -5
  97. package/dist/chunk-fma9cbq5.js +0 -10
  98. package/dist/chunk-ghf5tgjr.js +0 -1
  99. package/dist/chunk-hqtskyc1.js +0 -2
  100. package/dist/chunk-jc7k8pfn.js +0 -22
  101. package/dist/chunk-kf43f8sy.js +0 -1577
  102. package/dist/chunk-kjc2aqww.js +0 -2
  103. package/dist/chunk-kjddt9xy.js +0 -1
  104. package/dist/chunk-m0ded6ky.js +0 -615
  105. package/dist/chunk-msr67f6q.js +0 -3
  106. package/dist/chunk-mvww9cmc.js +0 -151
  107. package/dist/chunk-nbpjzzrg.js +0 -13
  108. package/dist/chunk-ncvr73ev.js +0 -1
  109. package/dist/chunk-qwn46cd6.js +0 -2
  110. package/dist/chunk-sva5bdgz.js +0 -2
  111. package/dist/chunk-t9cqscfq.js +0 -2
  112. package/dist/chunk-tzr992v4.js +0 -1
  113. package/dist/chunk-x8xfx9nv.js +0 -1
  114. package/dist/chunk-yewg510f.js +0 -24
  115. package/dist/chunk-zj3q4btp.js +0 -4
  116. package/dist/chunk-zjks0ncc.js +0 -6
  117. package/dist/chunk-zsyff0ky.js +0 -3
  118. package/dist/web/assets/CodeBlockHighlighter-D8_cOYpG.js +0 -1
  119. package/dist/web/assets/FilePreview-B5g8yi8d.js +0 -7
  120. package/dist/web/assets/MarkdownRenderer-qBCxzEb_.js +0 -1
  121. package/dist/web/assets/McpModal-C7y2Fsqc.js +0 -5
  122. package/dist/web/assets/SettingsModal-Dmc7Dw_E.js +0 -1
  123. package/dist/web/assets/SettingsStore-BfoB9tNV.js +0 -1
  124. package/dist/web/assets/SkillsModal-CqFAIfj5.js +0 -1
  125. package/dist/web/assets/TerminalPanel-EHh8-9b9.js +0 -1
  126. package/dist/web/assets/index-B-BRpW1c.js +0 -16
  127. package/dist/web/assets/index-Ch0eqSLM.css +0 -1
  128. package/dist/web/assets/useRequest-B4kP-cmG.js +0 -1
  129. package/dist/web/assets/vendor-icons-DBM55KTG.js +0 -251
  130. package/dist/web/assets/vendor-markdown-b9iCqZWK.js +0 -36
  131. package/dist/web/assets/vendor-monaco-w6PwaWGP.js +0 -11
  132. package/dist/web/assets/vendor-radix-DyP_DOwV.js +0 -45
  133. package/dist/web/assets/vendor-react-FPIC4Czm.js +0 -49
@@ -1,22 +0,0 @@
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};