blade-code 0.8.2 → 0.9.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 (90) hide show
  1. package/dist/blade.js +2 -2
  2. package/dist/chunk-0abtfzm6.js +1 -0
  3. package/dist/chunk-0zkhjsbv.js +1 -0
  4. package/dist/chunk-119fhp5q.js +9 -0
  5. package/dist/{chunk-j77gyhpf.js → chunk-1rpgvk3r.js} +1 -1
  6. package/dist/{chunk-81p4kz0b.js → chunk-1v2n922p.js} +1 -1
  7. package/dist/{chunk-9xvnrq7m.js → chunk-2fbwmdvg.js} +2 -2
  8. package/dist/chunk-3qgj2y5r.js +1 -0
  9. package/dist/{chunk-887qxhn5.js → chunk-45bme7n9.js} +2 -2
  10. package/dist/{chunk-w11ht6f9.js → chunk-5jq01mg6.js} +2 -2
  11. package/dist/{chunk-p4yrmzyr.js → chunk-5nye3k5w.js} +1 -1
  12. package/dist/chunk-7pevqbfd.js +2 -0
  13. package/dist/chunk-8dqvnx7n.js +2 -0
  14. package/dist/chunk-8edsvxf3.js +1 -0
  15. package/dist/{chunk-11s7t9dp.js → chunk-8vemqfe4.js} +2 -2
  16. package/dist/{chunk-5fw9k1ff.js → chunk-8vtznxpq.js} +2 -2
  17. package/dist/chunk-936ft6kq.js +2 -0
  18. package/dist/chunk-9ax02vtg.js +22 -0
  19. package/dist/chunk-9qknesxs.js +6 -0
  20. package/dist/chunk-acegy4td.js +3 -0
  21. package/dist/chunk-aewrn5xp.js +1 -0
  22. package/dist/{chunk-fpdqvnmq.js → chunk-aq7wf2zt.js} +2 -2
  23. package/dist/{chunk-5ad4qmfj.js → chunk-ax7bx0j8.js} +1 -1
  24. package/dist/chunk-b10vr4xj.js +2 -0
  25. package/dist/{chunk-1x3846v7.js → chunk-bc6wbcrs.js} +1 -1
  26. package/dist/chunk-bfgm5k3e.js +1566 -0
  27. package/dist/chunk-cf3fhs7j.js +1 -0
  28. package/dist/chunk-d7y2mf7c.js +4 -0
  29. package/dist/chunk-e1586s4t.js +1 -0
  30. package/dist/chunk-enk621t7.js +98 -0
  31. package/dist/chunk-fpr6d8zc.js +2 -0
  32. package/dist/{chunk-fkaebj8c.js → chunk-gagt42k2.js} +1 -1
  33. package/dist/chunk-gdm1xzvp.js +2 -0
  34. package/dist/chunk-gm62cfjw.js +1 -0
  35. package/dist/chunk-h3bjmkvz.js +1 -0
  36. package/dist/{chunk-9b297mzh.js → chunk-j8en7x02.js} +1 -1
  37. package/dist/{chunk-6jq8h5s9.js → chunk-jyr9417h.js} +2 -2
  38. package/dist/chunk-mcnfbhpr.js +6 -0
  39. package/dist/{chunk-6x6zqjcs.js → chunk-mns8e65q.js} +1 -1
  40. package/dist/chunk-mpkr3s6b.js +3 -0
  41. package/dist/chunk-n9tgxfvw.js +615 -0
  42. package/dist/{chunk-w4xcmzjm.js → chunk-ppyg431d.js} +1 -1
  43. package/dist/chunk-qxhrzws6.js +1 -0
  44. package/dist/{chunk-y08szyf9.js → chunk-r6h7eja3.js} +20 -20
  45. package/dist/chunk-r8pjwjt6.js +1 -0
  46. package/dist/chunk-rmfk5f9m.js +2 -0
  47. package/dist/chunk-rrg9bw8r.js +25 -0
  48. package/dist/chunk-w3me85va.js +2 -0
  49. package/dist/{chunk-f3pvwxp8.js → chunk-wtxwny0p.js} +3 -3
  50. package/dist/{chunk-s1y8w68s.js → chunk-x40fkg4z.js} +2 -2
  51. package/dist/{chunk-0z5qe4m2.js → chunk-x548f12z.js} +1 -1
  52. package/dist/chunk-xtfzjb72.js +6 -0
  53. package/dist/{chunk-kne7h7p5.js → chunk-z0qxaky4.js} +1 -1
  54. package/dist/web/assets/{FilePreview-60E51igH.js → FilePreview-DpovIbME.js} +1 -1
  55. package/dist/web/assets/{MarkdownRenderer-DU7jPn9K.js → MarkdownRenderer-73wC_SGk.js} +1 -1
  56. package/dist/web/assets/{McpModal-CAMU6yrS.js → McpModal-CIpxuyTG.js} +1 -1
  57. package/dist/web/assets/{SettingsModal-Cjj8NUQy.js → SettingsModal-BBa1libe.js} +1 -1
  58. package/dist/web/assets/{SettingsStore-CjvkbtuZ.js → SettingsStore-C8YBWQPS.js} +1 -1
  59. package/dist/web/assets/{SkillsModal-Cyc2JAFj.js → SkillsModal-DArZ-nCX.js} +1 -1
  60. package/dist/web/assets/{TerminalPanel-DI-Ls-U8.js → TerminalPanel-BX7C7qiD.js} +1 -1
  61. package/dist/web/assets/index-Ch0eqSLM.css +1 -0
  62. package/dist/web/assets/index-DIWzaS2_.js +16 -0
  63. package/dist/web/index.html +2 -2
  64. package/package.json +2 -1
  65. package/dist/chunk-0g9cb41d.js +0 -3
  66. package/dist/chunk-1evg2hdd.js +0 -2
  67. package/dist/chunk-3wghk9bp.js +0 -1
  68. package/dist/chunk-4fye39a8.js +0 -2
  69. package/dist/chunk-510rwhx6.js +0 -1
  70. package/dist/chunk-6avkjdjc.js +0 -615
  71. package/dist/chunk-83dkggbx.js +0 -1
  72. package/dist/chunk-8epvwyg8.js +0 -6
  73. package/dist/chunk-8fp3q919.js +0 -24
  74. package/dist/chunk-9jkbykwq.js +0 -1
  75. package/dist/chunk-a83s9mww.js +0 -1
  76. package/dist/chunk-a90mfxv9.js +0 -3
  77. package/dist/chunk-btst30by.js +0 -6
  78. package/dist/chunk-e9t5ga1b.js +0 -1
  79. package/dist/chunk-eycs00af.js +0 -1577
  80. package/dist/chunk-gvf4gff0.js +0 -9
  81. package/dist/chunk-j14rn2dx.js +0 -22
  82. package/dist/chunk-kcjgbbec.js +0 -1
  83. package/dist/chunk-q223bq79.js +0 -1
  84. package/dist/chunk-qwfqp465.js +0 -2
  85. package/dist/chunk-rxjt7ma7.js +0 -2
  86. package/dist/chunk-x83a97eh.js +0 -1
  87. package/dist/chunk-yfcfx0zk.js +0 -6
  88. package/dist/chunk-zns65xsy.js +0 -2
  89. package/dist/web/assets/index-BC0ssrep.js +0 -16
  90. package/dist/web/assets/index-Ci6gCUjf.css +0 -1
package/dist/blade.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{n as B}from"./chunk-s1y8w68s.js";import{ga as D,ha as F}from"./chunk-fpdqvnmq.js";import"./chunk-8fp3q919.js";import"./chunk-j14rn2dx.js";import"./chunk-f3pvwxp8.js";import"./chunk-0z5qe4m2.js";import"./chunk-81p4kz0b.js";import{Ib as E,Kb as q}from"./chunk-rxjt7ma7.js";import{Ub as H}from"./chunk-9xvnrq7m.js";import"./chunk-0g9cb41d.js";import{gc as J}from"./chunk-w4xcmzjm.js";var X=process.argv.slice(2),$=v(X),w=$!==null;if($!==null)H.setGlobalDebug($);function v(Q){for(let W=0;W<Q.length;W+=1){let T=Q[W];if(T==="--debug"||T==="-d"){let N=Q[W+1];return N&&!N.startsWith("-")?N:!0}if(T.startsWith("--debug="))return T.slice(8)||!0}return null}function C(Q){return Q.length===1&&(Q[0]==="--version"||Q[0]==="-V")}function z(Q,...W){return Q.some((T)=>W.some((N)=>T===N||T.startsWith(`${N}=`)))}async function f(){if(C(X)){let{getVersion:K}=await import("./chunk-x83a97eh.js");console.log(K());return}let Q=D(process.cwd());if(F(Q),E(q()),process.getuid&&process.getuid()===0){let K=!!process.env.SUDO_USER,U=!!process.env.BLADE_ALLOW_ROOT;if(K&&!U)console.error(""),console.error("Error: 请不要使用 sudo 运行 blade"),console.error(""),console.error("原因:"),console.error(" 使用 sudo 会创建属于 root 的配置文件,"),console.error(" 导致普通用户无法访问。"),console.error(""),console.error("正确用法:"),console.error(" blade # 直接运行,不要加 sudo"),console.error(""),console.error("如果遇到权限错误,请运行:"),console.error(" sudo chown -R $USER:$USER ~/.blade/"),console.error(""),console.error("如果你确实需要以 root 运行(容器/CI),设置环境变量:"),console.error(" BLADE_ALLOW_ROOT=1 blade"),console.error(""),process.exit(1)}if(z(X,"--headless")){let{handleHeadlessMode:K}=await import("./chunk-btst30by.js");if(await K())return}if(B(),z(X,"--print","-p")){let{handlePrintMode:K}=await import("./chunk-yfcfx0zk.js");if(await K())return}if(X.includes("--acp")){let{runAcpIntegration:K}=await import("./chunk-gvf4gff0.js");await K();return}let[{default:W},{hideBin:T},{cliConfig:N,globalOptions:G},{loadConfiguration:I,validateOutput:L,validatePermissions:M},{doctorCommands:_},{installCommands:y},{mcpCommands:R},{serveCommand:S},{updateCommands:k},{webCommand:O}]=await Promise.all([import("yargs"),import("yargs/helpers"),import("./chunk-9jkbykwq.js"),import("./chunk-e9t5ga1b.js"),import("./chunk-a90mfxv9.js"),import("./chunk-5ad4qmfj.js"),import("./chunk-fkaebj8c.js"),import("./chunk-a83s9mww.js"),import("./chunk-9b297mzh.js"),import("./chunk-j77gyhpf.js")]),x=W(T(process.argv)).scriptName(N.scriptName).usage(N.usage).version(N.version).locale(N.locale).showHelpOnFail(N.showHelpOnFail).demandCommand(0,"").recommendCommands().strict(N.strict).parserConfiguration({"populate--":!0}).options(G).middleware([I,M,L]).command(R).command(_).command(k).command(y).command(O).command(S).completion("completion",!1).help("help","Show help").alias("help","h").alias("version","V").fail((K,U,Z)=>{if(U){if(console.error("An error occurred:"),console.error(U.message),w&&U.stack)console.error(`
2
+ import{ea as B}from"./chunk-x40fkg4z.js";import{ha as D,ia as F}from"./chunk-aq7wf2zt.js";import"./chunk-rrg9bw8r.js";import"./chunk-9ax02vtg.js";import"./chunk-wtxwny0p.js";import"./chunk-x548f12z.js";import"./chunk-1v2n922p.js";import"./chunk-fpr6d8zc.js";import"./chunk-acegy4td.js";import{qc as E,rc as q}from"./chunk-w3me85va.js";import{uc as H}from"./chunk-2fbwmdvg.js";import"./chunk-gdm1xzvp.js";import{Hc as J}from"./chunk-ppyg431d.js";var X=process.argv.slice(2),$=v(X),w=$!==null;if($!==null)H.setGlobalDebug($);function v(Q){for(let W=0;W<Q.length;W+=1){let T=Q[W];if(T==="--debug"||T==="-d"){let N=Q[W+1];return N&&!N.startsWith("-")?N:!0}if(T.startsWith("--debug="))return T.slice(8)||!0}return null}function C(Q){return Q.length===1&&(Q[0]==="--version"||Q[0]==="-V")}function z(Q,...W){return Q.some((T)=>W.some((N)=>T===N||T.startsWith(`${N}=`)))}async function f(){if(C(X)){let{getVersion:K}=await import("./chunk-e1586s4t.js");console.log(K());return}let Q=D(process.cwd());if(F(Q),E(q()),process.getuid&&process.getuid()===0){let K=!!process.env.SUDO_USER,U=!!process.env.BLADE_ALLOW_ROOT;if(K&&!U)console.error(""),console.error("Error: 请不要使用 sudo 运行 blade"),console.error(""),console.error("原因:"),console.error(" 使用 sudo 会创建属于 root 的配置文件,"),console.error(" 导致普通用户无法访问。"),console.error(""),console.error("正确用法:"),console.error(" blade # 直接运行,不要加 sudo"),console.error(""),console.error("如果遇到权限错误,请运行:"),console.error(" sudo chown -R $USER:$USER ~/.blade/"),console.error(""),console.error("如果你确实需要以 root 运行(容器/CI),设置环境变量:"),console.error(" BLADE_ALLOW_ROOT=1 blade"),console.error(""),process.exit(1)}if(z(X,"--headless")){let{handleHeadlessMode:K}=await import("./chunk-xtfzjb72.js");if(await K())return}if(B(),z(X,"--print","-p")){let{handlePrintMode:K}=await import("./chunk-9qknesxs.js");if(await K())return}if(X.includes("--acp")){let{runAcpIntegration:K}=await import("./chunk-119fhp5q.js");await K();return}let[{default:W},{hideBin:T},{cliConfig:N,globalOptions:G},{loadConfiguration:I,validateOutput:L,validatePermissions:M},{doctorCommands:_},{installCommands:y},{mcpCommands:R},{serveCommand:S},{updateCommands:k},{webCommand:O}]=await Promise.all([import("yargs"),import("yargs/helpers"),import("./chunk-qxhrzws6.js"),import("./chunk-r8pjwjt6.js"),import("./chunk-d7y2mf7c.js"),import("./chunk-ax7bx0j8.js"),import("./chunk-gagt42k2.js"),import("./chunk-3qgj2y5r.js"),import("./chunk-j8en7x02.js"),import("./chunk-1rpgvk3r.js")]),x=W(T(process.argv)).scriptName(N.scriptName).usage(N.usage).version(N.version).locale(N.locale).showHelpOnFail(N.showHelpOnFail).demandCommand(0,"").recommendCommands().strict(N.strict).parserConfiguration({"populate--":!0}).options(G).middleware([I,M,L]).command(R).command(_).command(k).command(y).command(O).command(S).completion("completion",!1).help("help","Show help").alias("help","h").alias("version","V").fail((K,U,Z)=>{if(U){if(console.error("An error occurred:"),console.error(U.message),w&&U.stack)console.error(`
3
3
  Stack trace:`),console.error(U.stack);else console.error(`
4
4
  Run with --debug to show the stack trace.`);process.exit(1)}if(K)console.error("Error: Invalid arguments:"),console.error(K),console.error(`
5
- Hint: Did you mean:`),Z.showHelp(),process.exit(1)}).command("$0",!1,()=>{},async(K)=>{let U=K._.slice(1),Z=U.length>0?U.join(" "):void 0,V=import("./chunk-83dkggbx.js").then(({checkVersionOnStartup:A})=>A()),[{render:b},{createElement:P},{AppWrapper:h}]=await Promise.all([import("ink"),import("react"),import("./chunk-y08szyf9.js")]),Y={...K,initialMessage:Z,debug:K.debug,print:Boolean(K.print),versionCheckPromise:V};delete Y._,delete Y.$0,delete Y.message,b(P(h,Y),{patchConsole:!0,exitOnCtrlC:!1,alternateBuffer:!1})});try{await x.parse()}catch(K){console.error("Error: Parse error:",K),process.exit(1)}}if(J.main==J.module)f().catch(console.error);export{f as main};
5
+ Hint: Did you mean:`),Z.showHelp(),process.exit(1)}).command("$0",!1,()=>{},async(K)=>{let U=K._.slice(1),Z=U.length>0?U.join(" "):void 0,V=import("./chunk-cf3fhs7j.js").then(({checkVersionOnStartup:A})=>A()),[{render:b},{createElement:P},{AppWrapper:h}]=await Promise.all([import("ink"),import("react"),import("./chunk-r6h7eja3.js")]),Y={...K,initialMessage:Z,debug:K.debug,print:Boolean(K.print),versionCheckPromise:V};delete Y._,delete Y.$0,delete Y.message,b(P(h,Y),{patchConsole:!0,exitOnCtrlC:!1,alternateBuffer:!1})});try{await x.parse()}catch(K){console.error("Error: Parse error:",K),process.exit(1)}}if(J.main==J.module)f().catch(console.error);export{f as main};
@@ -0,0 +1 @@
1
+ import{$a as d,Xa as a,Ya as b,_a as c,ab as e,bb as f,cb as g,db as h,eb as i,fb as j,gb as k,hb as l,ib as m,jb as n,kb as o,nb as p,ob as q,pb as r}from"./chunk-n9tgxfvw.js";import"./chunk-5nye3k5w.js";import"./chunk-wtxwny0p.js";import"./chunk-x548f12z.js";import"./chunk-1v2n922p.js";import"./chunk-fpr6d8zc.js";import"./chunk-8vtznxpq.js";import"./chunk-acegy4td.js";import"./chunk-936ft6kq.js";import"./chunk-w3me85va.js";import"./chunk-2fbwmdvg.js";import"./chunk-gdm1xzvp.js";import"./chunk-ppyg431d.js";export{g as saveUserMessage,i as saveToolUse,j as saveToolResult,k as saveCompaction,h as saveAssistantMessage,d as isRootSystemPrompt,l as handleTaskListUpdate,m as handleSkillActivation,n as extractModelSwitch,r as executeLoopGenerator,f as drainLoop,c as checkStopHook,a as checkOutputRecovery,b as checkIncompleteIntent,q as checkAndCompactInLoop,o as applyToolDomainEffects,p as StreamingToolExecutor,e as ConversationState};
@@ -0,0 +1 @@
1
+ import{Qa as a,Ra as b}from"./chunk-8vemqfe4.js";import"./chunk-acegy4td.js";import"./chunk-gdm1xzvp.js";import"./chunk-ppyg431d.js";export{a as resolveModelConfig,b as getModelDisplayName};
@@ -0,0 +1,9 @@
1
+ import{p as v}from"./chunk-b10vr4xj.js";import{A as K,G as h,I as A,J as T,L as b,Q as x,S as q,T as M,s as B}from"./chunk-bfgm5k3e.js";import"./chunk-z0qxaky4.js";import{ba as c}from"./chunk-jyr9417h.js";import"./chunk-aq7wf2zt.js";import{ya as k}from"./chunk-rrg9bw8r.js";import"./chunk-9ax02vtg.js";import{Ra as u}from"./chunk-8vemqfe4.js";import{bb as y}from"./chunk-n9tgxfvw.js";import{tb as N}from"./chunk-5nye3k5w.js";import"./chunk-wtxwny0p.js";import"./chunk-x548f12z.js";import{Db as C}from"./chunk-1v2n922p.js";import"./chunk-fpr6d8zc.js";import"./chunk-8vtznxpq.js";import"./chunk-acegy4td.js";import{Tb as j}from"./chunk-mpkr3s6b.js";import"./chunk-45bme7n9.js";import"./chunk-enk621t7.js";import"./chunk-936ft6kq.js";import{rc as I}from"./chunk-w3me85va.js";import{vc as w}from"./chunk-2fbwmdvg.js";import"./chunk-gdm1xzvp.js";import"./chunk-ppyg431d.js";import{Readable as l,Writable as i}from"node:stream";import*as E from"@agentclientprotocol/sdk";import S from"node:path";import{PROTOCOL_VERSION as m}from"@agentclientprotocol/sdk";import{nanoid as R}from"nanoid";var W=w("Agent");function f(z){return Object.fromEntries(z.map((J)=>[J.name,J.value]))}function p(z){if("command"in z)return{type:"stdio",command:z.command,args:z.args,env:f(z.env)};return{type:z.type,url:z.url,headers:f(z.headers)}}function d(z){return Object.fromEntries(z.map((J)=>[J.name,p(J)]))}function O(z){if(typeof z==="string")return z?[{type:"text",text:z}]:[];return z.flatMap((J)=>{if(J.type==="text")return J.text?[{type:"text",text:J.text}]:[];let H=J.image_url.url,Q=/^data:([^;,]+);base64,(.+)$/s.exec(H);if(!Q)return[{type:"text",text:"[Image]"}];return[{type:"image",mimeType:Q[1]??"image/png",data:Q[2]??""}]})}class L{id;cwd;connection;clientCapabilities;options;agent=null;runtime=null;pendingPrompt=null;pendingResumeRequested=!1;availableCommandsTimer=null;taskStatusUnsubscribe;destroyed=!1;messages;mode="default";constructor(z,J,H,Q,X={}){this.id=z;this.cwd=J;this.connection=H;this.clientCapabilities=Q;this.options=X;this.messages=[...X.initialMessages??[]]}createAgent(){if(!this.runtime)throw Error("Session runtime is unavailable");return b.createWithRuntime(this.runtime,{sessionId:this.id,...this.options.taskWorktree?{toolBlacklist:["EnterWorktree","ExitWorktree"]}:{}})}async initialize(){W.debug(`[AcpSession ${this.id}] Initializing...`),B.initializeSession(this.connection,this.id,this.clientCapabilities,this.cwd),W.debug(`[AcpSession ${this.id}] ACP service context initialized`);let z=this.options.mcpServers?d(this.options.mcpServers):void 0;this.runtime=await h.create({sessionId:this.id,workspaceRoot:this.cwd,...z?{mcpServers:z}:{},...this.options.taskWorktree?{taskWorktree:this.options.taskWorktree}:{},...this.options.taskIsolation?{taskIsolation:this.options.taskIsolation}:{}}),this.agent=await this.createAgent(),W.debug(`[AcpSession ${this.id}] Agent created successfully`),this.taskStatusUnsubscribe?.(),this.taskStatusUnsubscribe=K.subscribe((H)=>{if(H.type!=="task.status"||H.sessionId!==this.id||H.projectPath!==this.cwd)return;this.sendUpdate({sessionUpdate:"session_info_update",updatedAt:typeof H.properties.updatedAt==="string"?H.properties.updatedAt:new Date().toISOString(),_meta:{"blade/taskStatus":H.properties.taskStatus,...typeof H.properties.taskStatusReason==="string"?{"blade/taskStatusReason":H.properties.taskStatusReason}:{},...typeof H.properties.taskStartedAt==="string"?{"blade/taskStartedAt":H.properties.taskStartedAt}:{},...typeof H.properties.taskCompletedAt==="string"?{"blade/taskCompletedAt":H.properties.taskCompletedAt}:{},...H.properties.taskDiffStat&&typeof H.properties.taskDiffStat==="object"?{"blade/taskDiffStat":H.properties.taskDiffStat}:{},...typeof H.properties.taskQueuePosition==="number"?{"blade/taskQueuePosition":H.properties.taskQueuePosition}:{},...typeof H.properties.taskQueueDepth==="number"?{"blade/taskQueueDepth":H.properties.taskQueueDepth}:{},...typeof H.properties.taskConcurrencyLimit==="number"?{"blade/taskConcurrencyLimit":H.properties.taskConcurrencyLimit}:{},...typeof H.properties.taskInFlight==="number"?{"blade/taskInFlight":H.properties.taskInFlight}:{}}})});let J=await this.runtime.getGoal();if(this.runtime.getPendingSteeringCount()>0||J?.status==="active")if(this.options.initialMessages===void 0)this.schedulePendingResume();else this.pendingResumeRequested=!0}async replayHistory(){for(let z of this.messages){if(!this.canSendUpdates())return;let J=z.role==="user"?"user_message_chunk":z.role==="assistant"?"agent_message_chunk":void 0;if(!J)continue;for(let H of O(z.content)){if(!this.canSendUpdates())return;if(!await this.sendUpdateAndWait({sessionUpdate:J,content:H}))return}}if(this.pendingResumeRequested)this.schedulePendingResume()}sendAvailableCommandsDelayed(){if(this.destroyed||this.connection.signal.aborted)return;if(this.availableCommandsTimer!==null)clearTimeout(this.availableCommandsTimer);W.debug(`[AcpSession ${this.id}] Scheduling available commands update (500ms delay)`),this.availableCommandsTimer=setTimeout(()=>{if(this.availableCommandsTimer=null,this.destroyed||this.connection.signal.aborted)return;this.sendAvailableCommands()},500)}async handleSlashCommand(z,J){try{W.debug(`[AcpSession ${this.id}] Executing slash command: ${z}`);let H={cwd:this.cwd,workspaceRoot:this.cwd,sessionId:this.id,messages:[...this.messages],rewind:{listCheckpoints:async()=>{if(!this.runtime)throw Error("Session runtime is unavailable");return this.runtime.listRewindCheckpoints()},execute:async(Z)=>{if(!this.runtime)throw Error("Session runtime is unavailable");let $=await this.runtime.rewindSession(Z);return this.messages=[...$.messages],await this.agent?.destroy(),this.agent=await this.createAgent(),$}},subagents:{list:async()=>{if(!this.runtime)throw Error("Session runtime is unavailable");return this.runtime.listSubagents()},resume:async(Z,$)=>{if(!this.runtime)throw Error("Session runtime is unavailable");let G=!1,V,U=(_)=>{this.sendUpdate({sessionUpdate:"tool_call_update",toolCallId:_.id,status:_.status==="completed"?"completed":"failed",content:[{type:"content",content:{type:"text",text:_.result?.message||_.result?.error||`Subagent ${_.status}`}}]})},D=this.runtime.resumeSubagent({agentId:Z,prompt:$,onCompleted:(_)=>{if(G)U(_);else V=_}});if(this.sendUpdate({sessionUpdate:"tool_call",toolCallId:D.session.id,status:"in_progress",title:`Resuming ${D.session.subagentType} subagent`,content:[{type:"content",content:{type:"text",text:`Resumed from ${D.source.id} at depth ${D.session.resumeDepth}`}}],kind:this.mapToolKind("readonly")}),G=!0,V)U(V);return D}},signal:J,acp:{sendMessage:(Z)=>{this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:Z}})},sendToolStart:(Z,$,G)=>{let V=`tool_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,U=this.mapToolKind(G);this.sendUpdate({sessionUpdate:"tool_call",toolCallId:V,status:"in_progress",title:`${Z}`,content:[{type:"content",content:{type:"text",text:JSON.stringify($,null,2)}}],kind:U})},sendToolResult:(Z,$)=>{if($.summary)this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:$.summary}})}}},Q=await q(z,H),X=Q.data?.action;if(X==="start_goal"||X==="resume_goal")this.schedulePendingResume();if(X==="rewind_session"&&Array.isArray(Q.data?.messages))this.messages=[...Q.data.messages];if((Q.message==="compact_completed"||Q.message==="compact_fallback")&&Q.data?.compactedMessages)this.messages=[...Q.data.compactedMessages];let Y=Q.content||Q.message;if(Y)this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:Y}});if(Q.error)this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:`[FAIL] ${Q.error}`}});return{stopReason:Q.success?"end_turn":"cancelled"}}catch(H){return W.error(`[AcpSession ${this.id}] Slash command error:`,H),this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:`[FAIL] 命令执行失败: ${H instanceof Error?H.message:"未知错误"}`}}),{stopReason:"cancelled"}}}async sendAvailableCommands(){try{let z=M(),J=["model","permissions","theme","config","exit","ide"],Q=z.filter((X)=>!J.includes(X.name)).map((X)=>{let Y;if(X.usage){let Z=X.usage.replace(/^\/\w+\s*/,"").trim();if(Z)Y=Z}if(X.aliases?.length){let Z=`Aliases: ${X.aliases.join(", ")}`;Y=Y?`${Y} | ${Z}`:Z}return{name:X.name,description:X.description,input:Y?{hint:Y}:void 0}});W.info(`[AcpSession ${this.id}] Sending available commands: ${JSON.stringify(Q.map((X)=>X.name))}`),this.sendUpdate({sessionUpdate:"available_commands_update",availableCommands:Q}),W.info(`[AcpSession ${this.id}] Sent ${Q.length} available commands`)}catch(z){W.error(`[AcpSession ${this.id}] Failed to send available commands:`,z)}}async prompt(z,J={}){if(B.setCurrentSession(this.id),!this.agent||!this.runtime)throw Error("Session not initialized");let H=this.resolvePrompt(z.prompt);if(this.pendingPrompt){if(/^\/goal(?:\s|$)/i.test(H.trim()))return this.handleSlashCommand(H,this.pendingPrompt.signal);let X=await this.runtime.enqueueSteering(H,{allowBeforeTurn:!0});if(!X.accepted)throw Error(X.reason==="queue_full"?"Active turn steering queue is full":"Active turn is no longer steerable");if(W.debug(`[AcpSession ${this.id}] Queued steering for active turn (${X.queued})`),X.delivery==="next_turn")this.schedulePendingResume();return{stopReason:"end_turn"}}let Q=new AbortController;this.pendingPrompt=Q;try{if(W.debug(`[AcpSession ${this.id}] Received prompt: ${H.slice(0,100)}...`),x(H))return await this.handleSlashCommand(H,Q.signal);let X={sessionId:this.id,userId:"acp-user",workspaceRoot:this.cwd,messages:[...this.messages],signal:Q.signal,permissionMode:this.mapModeToPermissionMode(),...this.options.taskWorktree?{worktreeActive:!0}:{},confirmationHandler:{requestConfirmation:async(Y)=>{return this.requestPermission(Y)}}};if(await y(this.agent.chatStream(H,X,{pendingInputOnly:J.pendingInputOnly,goalContinuationOnly:J.goalContinuationOnly}),async(Y)=>{switch(Y.kind){case"content_delta":this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:Y.delta}});break;case"thinking_delta":this.sendUpdate({sessionUpdate:"agent_thought_chunk",content:{type:"text",text:Y.delta}});break;case"tool_start":{let Z=Y.toolCall,$="function"in Z?Z.function.name:Z.type,G=this.mapToolKind(Y.toolKind),V=`Executing ${$}`;if($==="Task"&&"function"in Z)try{let U=JSON.parse(Z.function.arguments),D=U.resume_from??U.resume;if(typeof D==="string")V=`Resuming ${String(U.subagent_type||"subagent")} from ${D}`}catch{}this.sendUpdate({sessionUpdate:"tool_call",toolCallId:Z.id,status:"in_progress",title:V,content:[],kind:G});break}case"tool_result":{let{toolCall:Z,result:$}=Y,G=[],V=$.metadata;if(V?.kind==="edit"&&typeof V.file_path==="string"&&typeof V.oldContent==="string"&&(typeof V.newContent==="string"||V.newContent===void 0))G.push({type:"diff",path:V.file_path,oldText:V.oldContent,newText:V.newContent??null});else{let D="function"in Z?Z.function.name:Z.type,_=T(A(D,$));G.push({type:"content",content:{type:"text",text:_}})}let U=$.success?"completed":"failed";this.sendUpdate({sessionUpdate:"tool_call_update",toolCallId:Z.id,status:U,content:G});break}case"task_update":this.sendPlanUpdate(Y.tasks);break;case"steering_applied":break;case"follow_up_started":for(let Z of Y.messages){if(!Z.recovered||Z.persisted)continue;for(let $ of O(Z.content))this.sendUpdate({sessionUpdate:"user_message_chunk",content:$})}if(Y.recovered>0)this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:`[Resuming ${Y.recovered} queued instruction${Y.recovered===1?"":"s"} recovered after restart]
2
+ `}});break;case"goal_updated":if(Y.goal&&Y.goal.status!=="active")this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:`[Goal ${Y.goal.status}: ${Y.goal.objective}]
3
+ `}});break;case"goal_continuation_started":break;default:break}}),this.messages=[...X.messages],Q.signal.aborted)return{stopReason:"cancelled"};return{stopReason:"end_turn"}}catch(X){if(Q.signal.aborted||X instanceof Error&&X.name==="AbortError")return{stopReason:"cancelled"};throw W.error(`[AcpSession ${this.id}] Prompt error:`,X),X}finally{if(this.pendingPrompt===Q){if(this.pendingPrompt=null,!this.destroyed&&this.pendingResumeRequested)this.schedulePendingResume()}}}schedulePendingResume(){if(this.destroyed||this.connection.signal.aborted)return;this.pendingResumeRequested=!0,queueMicrotask(()=>{this.resumePendingIfIdle()})}async resumePendingIfIdle(){if(this.destroyed||this.connection.signal.aborted)return;if(this.pendingPrompt||!this.runtime||!this.agent)return;let z=this.runtime.getPendingSteeringCount()>0,H=(z?null:await this.runtime.getGoal())?.status==="active";if(!z&&!H){this.pendingResumeRequested=!1;return}this.pendingResumeRequested=!1,await this.prompt({sessionId:this.id,prompt:[]},{pendingInputOnly:z,goalContinuationOnly:H}).catch((Q)=>{W.error(`[AcpSession ${this.id}] Failed to resume pending input:`,Q)})}cancel(){if(W.info(`[AcpSession ${this.id}] Cancel requested`),this.pendingResumeRequested=!1,this.pendingPrompt)this.pendingPrompt.abort(),this.pendingPrompt=null,W.info(`[AcpSession ${this.id}] Cancelled successfully`);else W.warn(`[AcpSession ${this.id}] No pending prompt to cancel`)}async setMode(z){let J=["default","auto-edit","yolo","plan"];this.mode=J.includes(z)?z:"default",W.info(`[AcpSession ${this.id}] Mode set to: ${this.mode}`),this.sendUpdate({sessionUpdate:"current_mode_update",currentModeId:this.mode})}mapModeToPermissionMode(){switch(this.mode){case"yolo":return"yolo";case"auto-edit":return"autoEdit";case"plan":return"plan";case"default":default:return"default"}}shouldAutoApprove(z){switch(this.mode){case"yolo":return!0;case"auto-edit":return z==="readonly"||z==="write";case"plan":return z==="readonly";case"default":default:return!1}}async setModel(z){if(W.info(`[AcpSession ${this.id}] Model set to: ${z}`),this.pendingPrompt)throw Error("Cannot switch models while a prompt is active");if(!this.agent)throw Error("Session not initialized");await this.agent.switchModel(z)}async destroy(){if(this.destroyed)return;if(this.destroyed=!0,this.availableCommandsTimer!==null)clearTimeout(this.availableCommandsTimer),this.availableCommandsTimer=null;this.taskStatusUnsubscribe?.(),this.taskStatusUnsubscribe=void 0;let z=this.agent,J=this.runtime;this.agent=null,this.runtime=null;let H,Q=async(X)=>{try{await X()}catch(Y){H??=Y}};if(await Q(()=>this.cancel()),z)await Q(()=>z.destroy());if(J)await Q(()=>J.dispose());if(await Q(()=>B.destroySession(this.id)),W.debug(`[AcpSession ${this.id}] Destroyed`),H!==void 0)throw H}resolvePrompt(z){let J=[];for(let H of z)if(H.type==="text")J.push(H.text);else if(H.type==="image")J.push(`[Image: ${H.mimeType}]`);else if(H.type==="resource"){let Q=H.resource;if("text"in Q)J.push(`<file path="${Q.uri}">
4
+ ${Q.text}
5
+ </file>`)}else if(H.type==="resource_link")J.push(`[Resource: ${H.uri}]`);return J.join(`
6
+ `)}canSendUpdates(){return!this.destroyed&&!this.connection.signal.aborted}async sendUpdateAndWait(z){if(!this.canSendUpdates())return!1;return await this.connection.sessionUpdate({sessionId:this.id,update:z}),this.canSendUpdates()}sendUpdate(z){if(!this.canSendUpdates())return;let J={sessionId:this.id,update:z};this.connection.sessionUpdate(J).catch((H)=>{W.warn(`[AcpSession ${this.id}] Failed to send update:`,H)})}sendPlanUpdate(z){let J=z.map((H)=>({content:H.subject,priority:H.priority,status:H.status}));W.debug(`[AcpSession ${this.id}] Sending plan update with ${J.length} entries`),this.sendUpdate({sessionUpdate:"plan",entries:J})}async requestPermission(z){let J=this.pendingPrompt?.signal;if(z.type==="askUserQuestion")return this.requestUserQuestions(z,J);let H=z.kind?.toLowerCase()||"execute";if(this.shouldAutoApprove(H))return W.debug(`[AcpSession ${this.id}] Auto-approving ${H} in mode: ${this.mode}`),{approved:!0};if(this.mode==="plan"&&(H==="write"||H==="execute"))return W.debug(`[AcpSession ${this.id}] Rejecting ${H} in plan mode`),{approved:!1,reason:"Write and execute operations are not allowed in Plan mode"};try{let Q=R(),X=[];if(z.message)X.push({type:"content",content:{type:"text",text:z.message}});if(z.risks&&z.risks.length>0)X.push({type:"content",content:{type:"text",text:`Risks:
7
+ - ${z.risks.join(`
8
+ - `)}`}});let Y=this.mapToolKind(H),Z={sessionId:this.id,options:[{optionId:"allow_once",name:"Allow once",kind:"allow_once"},{optionId:"allow_always",name:"Always allow",kind:"allow_always"},{optionId:"reject_once",name:"Deny once",kind:"reject_once"},{optionId:"reject_always",name:"Always deny",kind:"reject_always"}],toolCall:{toolCallId:Q,status:"pending",title:z.title||"Permission Required",content:X,kind:Y}},$=await this.waitForClientInteraction(this.connection.requestPermission(Z),J);if(!$)return{approved:!1,reason:N};let G=$.outcome;if(G.outcome==="cancelled")return{approved:!1,reason:"User cancelled the permission request"};let V=G.optionId;if(V==="allow_always")return{approved:!0,scope:"project"};if(V==="reject_always")return{approved:!1,scope:"project",reason:"User permanently denied the permission request"};let U=V==="allow_once";return{approved:U,scope:"once",reason:U?void 0:"User denied the operation"}}catch(Q){return W.warn(`[AcpSession ${this.id}] Permission request failed:`,Q),{approved:!1,reason:"Permission request failed"}}}async requestUserQuestions(z,J){let H=z.questions??[];if(H.length===0)return{approved:!1,reason:"No structured questions were provided"};if(H.some((X)=>X.multiSelect))return{approved:!1,reason:"ACP does not support multi-select question responses"};let Q={};try{for(let[X,Y]of H.entries()){let Z=Y.options.map((U,D)=>`answer:${X}:${D}`),$=`answer:${X}:cancel`,G=await this.waitForClientInteraction(this.connection.requestPermission({sessionId:this.id,options:[...Y.options.map((U,D)=>({optionId:Z[D],name:U.label,kind:"allow_once"})),{optionId:$,name:"Cancel",kind:"reject_once"}],toolCall:{toolCallId:R(),status:"pending",title:Y.header,kind:"think",content:[{type:"content",content:{type:"text",text:[Y.question,...Y.options.map((U)=>`${U.label}: ${U.description}`)].join(`
9
+ `)}}]}}),J);if(!G)return{approved:!1,reason:N};if(G.outcome.outcome!=="selected")return{approved:!1,reason:"User cancelled the question prompt"};let V=Z.indexOf(G.outcome.optionId);if(V<0)return{approved:!1,reason:"User cancelled the question prompt"};Q[Y.header]=Y.options[V].label}return{approved:!0,answers:Q}}catch(X){return W.warn(`[AcpSession ${this.id}] Question request failed:`,X),{approved:!1,reason:"Question request failed"}}}async waitForClientInteraction(z,J){if(!J)return z;if(J.aborted)return;return new Promise((H,Q)=>{let X=!1,Y=($)=>{if(X)return;X=!0,J.removeEventListener("abort",Z),$()},Z=()=>Y(()=>H(void 0));if(J.addEventListener("abort",Z,{once:!0}),J.aborted)Z();z.then(($)=>Y(()=>H($)),($)=>Y(()=>Q($)))})}mapToolKind(z){return{readonly:"read",write:"edit",execute:"execute",read:"read",edit:"edit",delete:"delete",move:"move",search:"search",think:"think",fetch:"fetch"}[z||""]||"other"}}var F=w("Agent");class P{connection;sessions=new Map;sessionLoadQueues=new Map;clientCapabilities;destroyed=!1;constructor(z){this.connection=z}async initialize(z){return F.info("[BladeAgent] Initializing ACP connection"),F.debug(`[BladeAgent] Client capabilities: ${JSON.stringify(z.clientCapabilities)}`),this.clientCapabilities=z.clientCapabilities,{protocolVersion:m,agentCapabilities:{loadSession:!0,sessionCapabilities:{list:{},fork:{}},promptCapabilities:{image:!0,audio:!1,embeddedContext:!0},mcpCapabilities:{http:!0,sse:!0}}}}async authenticate(z){return}async newSession(z){this.assertNotDestroyed();let J=C("acp"),H=z.cwd||I(),Q=z._meta?.["blade/taskIsolation"],X=Q==="local"||Q==="worktree"?Q:void 0,Y=z._meta?.["blade/taskPrompt"],Z=X?await v.createSessionTask({sessionId:J,prompt:typeof Y==="string"&&Y.trim()?Y:"ACP task session",sourceProjectPath:H,isolation:X}):void 0,$=Z?.metadata.projectPath??H;F.info(`[BladeAgent] Creating new session: ${J}`),F.debug(`[BladeAgent] Session cwd: ${$}`);let G=new L(J,$,this.connection,this.clientCapabilities,{mcpServers:z.mcpServers,...Z?.taskWorktree?{taskWorktree:Z.taskWorktree}:{},...Z?.metadata.taskIsolation?{taskIsolation:Z.metadata.taskIsolation}:{}});try{await G.initialize(),this.assertNotDestroyed()}catch(V){throw await G.destroy().catch(()=>{return}),V}return this.sessions.set(J,G),F.info(`[BladeAgent] Session ${J} created, scheduling available commands update`),G.sendAvailableCommandsDelayed(),this.buildChildSessionResponse(J,Z?.metadata)}async unstable_listSessions(z){if(z.cwd!=null&&!S.isAbsolute(z.cwd))throw Error("ACP session list cwd must be absolute");let J=await j.listSessionPage({cwd:z.cwd??void 0,cursor:z.cursor??void 0,limit:50,includeSubagents:!1});return{sessions:J.sessions.map((H)=>({sessionId:H.sessionId,cwd:H.projectPath,title:H.title??null,updatedAt:H.lastMessageTime,_meta:{"blade/taskStatus":H.taskStatus,...H.taskStatusReason?{"blade/taskStatusReason":H.taskStatusReason}:{},...H.taskStartedAt?{"blade/taskStartedAt":H.taskStartedAt}:{},...H.taskCompletedAt?{"blade/taskCompletedAt":H.taskCompletedAt}:{},...H.taskIsolation?{"blade/taskIsolation":H.taskIsolation}:{},...H.taskSourceProjectPath?{"blade/taskSourceProjectPath":H.taskSourceProjectPath}:{},...H.taskWorktreeBranch?{"blade/taskWorktreeBranch":H.taskWorktreeBranch}:{},...H.taskBaseCommit?{"blade/taskBaseCommit":H.taskBaseCommit}:{},...H.taskDiffStat?{"blade/taskDiffStat":H.taskDiffStat}:{},...H.taskQueuePosition?{"blade/taskQueuePosition":H.taskQueuePosition}:{},...H.taskQueueDepth!==void 0?{"blade/taskQueueDepth":H.taskQueueDepth}:{},...H.taskConcurrencyLimit!==void 0?{"blade/taskConcurrencyLimit":H.taskConcurrencyLimit}:{}}})),nextCursor:J.nextCursor}}async unstable_forkSession(z){if(this.assertNotDestroyed(),!S.isAbsolute(z.cwd))throw Error("ACP session fork cwd must be absolute");let J=await j.forkSession(z.sessionId,{sourceProjectPath:z.cwd,targetProjectPath:z.cwd});this.assertNotDestroyed();let H=new L(J.sessionId,z.cwd,this.connection,this.clientCapabilities,{initialMessages:J.messages,mcpServers:z.mcpServers});try{await H.initialize(),this.assertNotDestroyed()}catch(Q){throw await H.destroy().catch(()=>{return}),Q}return this.sessions.set(J.sessionId,H),H.sendAvailableCommandsDelayed(),this.buildChildSessionResponse(J.sessionId)}async loadSession(z){this.assertNotDestroyed(),F.info(`[BladeAgent] Loading session: ${z.sessionId}`);let H=(this.sessionLoadQueues.get(z.sessionId)??Promise.resolve()).then(()=>this.replaceSession(z)),Q=H.then(()=>{return},()=>{return});this.sessionLoadQueues.set(z.sessionId,Q);try{return await H}finally{if(this.sessionLoadQueues.get(z.sessionId)===Q)this.sessionLoadQueues.delete(z.sessionId)}}async replaceSession(z){this.assertNotDestroyed();let J=this.sessions.get(z.sessionId);if(J)try{await J.destroy()}finally{if(this.sessions.get(z.sessionId)===J)this.sessions.delete(z.sessionId)}let H=await j.loadSession(z.sessionId,z.cwd),Q=new L(z.sessionId,z.cwd,this.connection,this.clientCapabilities,{initialMessages:H,mcpServers:z.mcpServers});try{await Q.initialize(),await Q.replayHistory(),this.assertNotDestroyed()}catch(X){throw await Q.destroy().catch(()=>{return}),X}return this.sessions.set(z.sessionId,Q),Q.sendAvailableCommandsDelayed(),this.buildSessionSetup()}buildChildSessionResponse(z,J){return{sessionId:z,...this.buildSessionSetup(),...J?{_meta:{"blade/taskIsolation":J.taskIsolation,"blade/taskSourceProjectPath":J.taskSourceProjectPath,"blade/taskProjectPath":J.projectPath,...J.taskWorktreeBranch?{"blade/taskWorktreeBranch":J.taskWorktreeBranch}:{},...J.taskBaseCommit?{"blade/taskBaseCommit":J.taskBaseCommit}:{}}}:{}}}assertNotDestroyed(){if(this.destroyed)throw Error("BladeAgent is destroyed")}buildSessionSetup(){let z=k(),J=z?.models||[],H=z?.currentModelId||J[0]?.id,Q=J.map((Y)=>({modelId:Y.id,name:u(Y),description:`${Y.provider}/${Y.model}`}));return{modes:{availableModes:[{id:"default",name:"Default",description:"Ask for confirmation before all file edits and commands"},{id:"auto-edit",name:"Auto Edit",description:"Auto-approve file edits, ask for shell commands"},{id:"yolo",name:"Full Auto",description:"Auto-approve everything without confirmation"},{id:"plan",name:"Plan Only",description:"Read-only mode, no file changes or commands"}],currentModeId:"default"},models:Q.length>0?{availableModels:Q,currentModelId:H}:void 0}}async prompt(z){let J=this.sessions.get(z.sessionId);if(!J)throw Error(`Session not found: ${z.sessionId}`);return J.prompt(z)}async cancel(z){F.info(`[BladeAgent] Cancel notification received for session: ${z.sessionId}`);let J=this.sessions.get(z.sessionId);if(J)F.info("[BladeAgent] Found session, calling session.cancel()"),J.cancel();else F.warn(`[BladeAgent] Session not found for cancel: ${z.sessionId}`)}async setSessionMode(z){F.info(`[BladeAgent] Setting session mode: ${z.modeId}`);let J=this.sessions.get(z.sessionId);if(J)await J.setMode(z.modeId);return{}}async unstable_setSessionModel(z){F.info(`[BladeAgent] Setting session model: ${z.modelId}`);let J=this.sessions.get(z.sessionId);if(!J)throw Error(`Session not found: ${z.sessionId}`);return await J.setModel(z.modelId),{}}async destroy(){this.destroyed=!0,await Promise.all([...this.sessionLoadQueues.values()]),this.sessionLoadQueues.clear();let z;for(let J of this.sessions.values())try{await J.destroy()}catch(H){z??=H}this.sessions.clear();try{await c.getInstance().disconnectAll()}catch(J){z??=J}if(z!==void 0)throw z}}async function Nz(){let z=i.toWeb(process.stdout),J=l.toWeb(process.stdin),H=E.ndJsonStream(z,J);await new E.AgentSideConnection((X)=>new P(X),H).closed}export{Nz as runAcpIntegration};
@@ -1,4 +1,4 @@
1
- import{a as Q,b as R,c as T,d as W}from"./chunk-zns65xsy.js";import"./chunk-1x3846v7.js";import"./chunk-qwfqp465.js";import"./chunk-eycs00af.js";import"./chunk-kne7h7p5.js";import"./chunk-6jq8h5s9.js";import"./chunk-fpdqvnmq.js";import{ya as J}from"./chunk-8fp3q919.js";import"./chunk-j14rn2dx.js";import"./chunk-11s7t9dp.js";import{Ma as M}from"./chunk-887qxhn5.js";import"./chunk-6avkjdjc.js";import"./chunk-p4yrmzyr.js";import"./chunk-f3pvwxp8.js";import"./chunk-0z5qe4m2.js";import"./chunk-81p4kz0b.js";import"./chunk-rxjt7ma7.js";import"./chunk-5fw9k1ff.js";import"./chunk-9xvnrq7m.js";import"./chunk-0g9cb41d.js";import"./chunk-w4xcmzjm.js";import b from"chalk";import H from"open";var $=`
1
+ import{a as Q,b as R,c as T,d as W}from"./chunk-8dqvnx7n.js";import"./chunk-bc6wbcrs.js";import"./chunk-b10vr4xj.js";import"./chunk-bfgm5k3e.js";import"./chunk-z0qxaky4.js";import"./chunk-jyr9417h.js";import"./chunk-aq7wf2zt.js";import{za as J}from"./chunk-rrg9bw8r.js";import"./chunk-9ax02vtg.js";import"./chunk-8vemqfe4.js";import"./chunk-n9tgxfvw.js";import"./chunk-5nye3k5w.js";import"./chunk-wtxwny0p.js";import"./chunk-x548f12z.js";import"./chunk-1v2n922p.js";import"./chunk-fpr6d8zc.js";import"./chunk-8vtznxpq.js";import"./chunk-acegy4td.js";import"./chunk-mpkr3s6b.js";import{Vb as M}from"./chunk-45bme7n9.js";import"./chunk-enk621t7.js";import"./chunk-936ft6kq.js";import"./chunk-w3me85va.js";import"./chunk-2fbwmdvg.js";import"./chunk-gdm1xzvp.js";import"./chunk-ppyg431d.js";import b from"chalk";import H from"open";var $=`
2
2
  ____ _ _
3
3
  | __ )| | __ _ __| | ___
4
4
  | _ \\| |/ _\` |/ _\` |/ _ \\
@@ -1,2 +1,2 @@
1
1
  import{nanoid as q}from"nanoid";var u=/^[A-Za-z0-9][A-Za-z0-9._-]*$/;function B(j="session",m=21){if(!u.test(j))throw Error(`Invalid session ID prefix: ${j}`);return`${j}-${q(m)}`}
2
- export{B as Eb};
2
+ export{B as Db};
@@ -1,3 +1,3 @@
1
- import{dc as j}from"./chunk-0g9cb41d.js";import{appendFileSync as E,existsSync as O,mkdirSync as R,readdirSync as U,statSync as B,unlinkSync as k}from"node:fs";import W from"node:path";var X;((H)=>{H[H.DEBUG=0]="DEBUG";H[H.INFO=1]="INFO";H[H.WARN=2]="WARN";H[H.ERROR=3]="ERROR"})(X||={});var T=null,_=null,$=!1;function m(q){if(T!==q)T=q}async function I(){}function w(){if($)return _;$=!0;try{let q=W.join(j(),"logs");if(!O(q))R(q,{recursive:!0,mode:493});if(B(q).uid===0&&process.getuid&&process.getuid()!==0)return console.error(""),console.error("[FAIL] 权限错误:~/.blade/logs 目录属于 root 用户"),console.error(""),console.error("这通常是因为您曾经使用 sudo 运行过 blade。"),console.error(""),console.error("解决方法:"),console.error(" sudo chown -R $USER:$USER ~/.blade/"),console.error(""),console.error("然后重新运行 blade(不要使用 sudo)"),console.error(""),null;return z(q,30),_=q,q}catch(q){return console.error("[Logger] 无法创建日志目录:",q),null}}function z(q,G){try{let J=U(q),K=Date.now(),H=G*24*60*60*1000;for(let Q of J){if(!Q.startsWith("blade-")||!Q.endsWith(".log")&&!Q.endsWith(".jsonl"))continue;let Y=W.join(q,Q);try{let Z=B(Y);if(K-Z.mtimeMs>H)k(Y)}catch(Z){}}}catch(J){}}function F(){let q=w();if(!q)return null;let G=T||"default";return W.join(q,`blade-${G}.jsonl`)}function A(q,G,J){let K=F();if(!K)return;try{let H={timestamp:new Date().toISOString(),level:X[G],category:q,message:J};E(K,JSON.stringify(H)+`
1
+ import{Fc as j}from"./chunk-gdm1xzvp.js";import{appendFileSync as E,existsSync as O,mkdirSync as R,readdirSync as U,statSync as B,unlinkSync as k}from"node:fs";import W from"node:path";var X;((H)=>{H[H.DEBUG=0]="DEBUG";H[H.INFO=1]="INFO";H[H.WARN=2]="WARN";H[H.ERROR=3]="ERROR"})(X||={});var T=null,_=null,$=!1;function m(q){if(T!==q)T=q}async function I(){}function w(){if($)return _;$=!0;try{let q=W.join(j(),"logs");if(!O(q))R(q,{recursive:!0,mode:493});if(B(q).uid===0&&process.getuid&&process.getuid()!==0)return console.error(""),console.error("[FAIL] 权限错误:~/.blade/logs 目录属于 root 用户"),console.error(""),console.error("这通常是因为您曾经使用 sudo 运行过 blade。"),console.error(""),console.error("解决方法:"),console.error(" sudo chown -R $USER:$USER ~/.blade/"),console.error(""),console.error("然后重新运行 blade(不要使用 sudo)"),console.error(""),null;return z(q,30),_=q,q}catch(q){return console.error("[Logger] 无法创建日志目录:",q),null}}function z(q,G){try{let J=U(q),K=Date.now(),H=G*24*60*60*1000;for(let Q of J){if(!Q.startsWith("blade-")||!Q.endsWith(".log")&&!Q.endsWith(".jsonl"))continue;let Y=W.join(q,Q);try{let Z=B(Y);if(K-Z.mtimeMs>H)k(Y)}catch(Z){}}}catch(J){}}function F(){let q=w();if(!q)return null;let G=T||"default";return W.join(q,`blade-${G}.jsonl`)}function A(q,G,J){let K=F();if(!K)return;try{let H={timestamp:new Date().toISOString(),level:X[G],category:q,message:J};E(K,JSON.stringify(H)+`
2
2
  `)}catch(H){}}class M{static globalDebugConfig=null;enabled;minLevel;category;constructor(q={}){if(q.enabled!==void 0)this.enabled=q.enabled;else if(M.globalDebugConfig!==null)this.enabled=Boolean(M.globalDebugConfig);else this.enabled=!1;this.minLevel=q.minLevel??0,this.category=q.category??"General"}static setGlobalDebug(q){M.globalDebugConfig=q}static clearGlobalDebug(){M.globalDebugConfig=null}setEnabled(q){this.enabled=q}parseDebugFilter(q){if(!q)return{enabled:!1};if(q===!0||q==="true"||q==="1")return{enabled:!0};let G=String(q).trim();if(!G)return{enabled:!0};if(G.startsWith("!"))return{enabled:!0,filter:{mode:"exclude",categories:G.split(",").map((H)=>H.trim().replace(/^!/,"")).filter(Boolean)}};return{enabled:!0,filter:{mode:"include",categories:G.split(",").map((K)=>K.trim()).filter(Boolean)}}}shouldLogCategory(q){if(!q)return!0;let G=this.category.toLowerCase();if(q.mode==="include")return q.categories.some((J)=>G.includes(J.toLowerCase()));return!q.categories.some((J)=>G.includes(J.toLowerCase()))}shouldLogToConsole(q){if(M.globalDebugConfig!==null){let{enabled:G,filter:J}=this.parseDebugFilter(M.globalDebugConfig);if(!G)return!1;if(q<this.minLevel)return!1;return this.shouldLogCategory(J)}return this.enabled&&q>=this.minLevel}log(q,...G){let J=G.map((K)=>typeof K==="object"?JSON.stringify(K):String(K)).join(" ");if(A(this.category,q,J),this.shouldLogToConsole(q)){let K=X[q],H=`[${this.category}] [${K}]`;console.error(H,...G)}}debug(...q){this.log(0,...q)}info(...q){this.log(1,...q)}warn(...q){this.log(2,...q)}error(...q){this.log(3,...q)}}function V(q,G){return new M({...G,category:q})}var h=new M({category:"General"});
3
- export{m as Sb,I as Tb,M as Ub,V as Vb,h as Wb};
3
+ export{m as sc,I as tc,M as uc,V as vc,h as wc};
@@ -0,0 +1 @@
1
+ import{a as y,b as A,c as C,d as D}from"./chunk-8dqvnx7n.js";import"./chunk-bc6wbcrs.js";import"./chunk-b10vr4xj.js";import"./chunk-bfgm5k3e.js";import"./chunk-z0qxaky4.js";import"./chunk-jyr9417h.js";import"./chunk-aq7wf2zt.js";import{za as q}from"./chunk-rrg9bw8r.js";import"./chunk-9ax02vtg.js";import"./chunk-8vemqfe4.js";import"./chunk-n9tgxfvw.js";import"./chunk-5nye3k5w.js";import"./chunk-wtxwny0p.js";import"./chunk-x548f12z.js";import"./chunk-1v2n922p.js";import"./chunk-fpr6d8zc.js";import"./chunk-8vtznxpq.js";import"./chunk-acegy4td.js";import"./chunk-mpkr3s6b.js";import"./chunk-45bme7n9.js";import"./chunk-enk621t7.js";import"./chunk-936ft6kq.js";import"./chunk-w3me85va.js";import"./chunk-2fbwmdvg.js";import"./chunk-gdm1xzvp.js";import"./chunk-ppyg431d.js";import H from"chalk";var R={command:"serve",describe:"Start a headless Blade server (no browser)",builder:y,handler:async(E)=>{let f=A(E);if(await q(),!process.env.BLADE_SERVER_PASSWORD)console.log(H.yellow("Warning: BLADE_SERVER_PASSWORD is not set; server is unsecured."));let b=await D.listenAsync(f);if(console.log(`Blade server listening on http://${b.hostname}:${b.port}`),f.hostname==="0.0.0.0"){let F=C();for(let G of F)console.log(` Network: http://${G}:${b.port}`)}await new Promise(()=>{}),await b.stop()}};export{R as serveCommand};
@@ -1,2 +1,2 @@
1
- var e={name:"blade-code",version:"0.8.2",private:!1,description:"🗡️ Blade Code - 智能代码助手命令行工具",type:"module",bin:{blade:"dist/blade.js"},files:["dist","vendor/ripgrep/**","README.md"],scripts:{dev:"node scripts/run-bun.js --watch src/blade.tsx","dev:serve":"node scripts/run-bun.js --watch src/blade.tsx serve --port 4097",build:"rm -rf dist && node scripts/run-bun.js run scripts/build.ts",start:"node scripts/run-bun.js 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:real-api":"node scripts/test.js realApi","test:cli":"node scripts/test.js cli","test:headless-core":"node scripts/test.js headlessCore","test:e2e":"node scripts/test.js e2e","test:performance":"node scripts/test.js performance","test:snapshot":"node scripts/test.js snapshot","test:security":"node scripts/test.js security","test:coverage":"node scripts/test.js all --coverage","test:watch":"vitest --watch --config vitest.config.ts","qualify:local":"node scripts/run-bun.js run scripts/qualify.ts local","qualify:production":"node scripts/run-bun.js run scripts/qualify.ts production","benchmark:repo":"node scripts/run-bun.js run scripts/run-real-repo-benchmark.ts","test:update-snapshots":"node scripts/test.js snapshot --update",lint:"biome lint src tests","lint:fix":"biome lint --write src tests","type-check":"tsc --noEmit","format:check":"biome format src tests",ready:"node scripts/run-bun.js run scripts/qualify.ts production","detect-unused":"node scripts/run-bun.js run scripts/detect-unused.ts",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"},keywords:["cli","blade","ai","assistant","agent","llm"],author:"echoVic",license:"MIT",engines:{node:">=22.19.0"},optionalDependencies:{"@vscode/ripgrep":"^1.17.0","bun-pty":"^0.4.8","node-pty":"1.0.0"},dependencies:{"@agentclientprotocol/sdk":"^0.12.0","@anthropic-ai/sandbox-runtime":"0.0.67","@earendil-works/pi-ai":"0.83.0","@inkjs/ui":"^2.0.0","@modelcontextprotocol/sdk":"^1.17.4",ahooks:"^3.9.6","ansi-escapes":"^7.2.0","async-mutex":"^0.5.0",axios:"^1.12.2",chalk:"^5.4.1",diff:"^8.0.2","fast-glob":"^3.3.3","fuse.js":"^7.1.0","gray-matter":"^4.0.3",hono:"^4.7.10",ink:"npm:@jrichman/ink@6.4.10","ink-big-text":"^2.0.0","ink-gradient":"^3.0.0","ink-select-input":"^6.2.0","ink-spinner":"^5.0.0","ink-text-input":"^6.0.0","js-tiktoken":"^1.0.21","lodash-es":"^4.17.21",lowlight:"^3.3.0","lru-cache":"^11.2.4",nanoid:"^5.1.6",open:"^10.1.2",openai:"^6.2.0",picomatch:"^4.0.3",react:"^19.1.1","react-dom":"^19.1.1",semver:"^7.7.3","string-width":"^8.1.0",undici:"^7.16.0","write-file-atomic":"^7.0.0",ws:"^8.18.0",yaml:"^2.8.1",yargs:"^18.0.0",typebox:"1.3.7",zustand:"^5.0.9"},devDependencies:{"@biomejs/biome":"^2.2.4","@types/bun":"^1.3.4","@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.1","@types/react-dom":"^19.1.1","@types/semver":"^7.7.1","@types/write-file-atomic":"^4.0.3","@types/ws":"^8.5.12","@types/yargs":"^17.0.33","@vitest/coverage-v8":"^3.0.0",jsdom:"^26.0.0",typescript:"^5.9.2",vitest:"^3.0.0"}};function r(){return{name:e.name,version:e.version,description:e.description}}function n(){return e.version}function o(){return e.name}function c(){return e.description}function d(){return`v${e.version}`}function a(){return`v${e.version} © 2025 Blade Code`}
2
- export{r as La,n as Ma,o as Na,c as Oa,d as Pa,a as Qa};
1
+ var e={name:"blade-code",version:"0.9.0",private:!1,description:"🗡️ Blade Code - 智能代码助手命令行工具",type:"module",bin:{blade:"dist/blade.js"},files:["dist","vendor/ripgrep/**","README.md"],scripts:{dev:"node scripts/run-bun.js --watch src/blade.tsx","dev:serve":"node scripts/run-bun.js --watch src/blade.tsx serve --port 4097",build:"rm -rf dist && node scripts/run-bun.js run scripts/build.ts",start:"node scripts/run-bun.js 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:real-api":"node scripts/test.js realApi","test:cli":"node scripts/test.js cli","test:headless-core":"node scripts/test.js headlessCore","test:e2e":"node scripts/test.js e2e","test:performance":"node scripts/test.js performance","test:snapshot":"node scripts/test.js snapshot","test:security":"node scripts/test.js security","test:coverage":"node scripts/test.js all --coverage","test:watch":"vitest --watch --config vitest.config.ts","qualify:local":"node scripts/run-bun.js run scripts/qualify.ts local","qualify:production":"node scripts/run-bun.js run scripts/qualify.ts production","benchmark:repo":"node scripts/run-bun.js run scripts/run-real-repo-benchmark.ts","test:update-snapshots":"node scripts/test.js snapshot --update",lint:"biome lint src tests","lint:fix":"biome lint --write src tests","type-check":"tsc --noEmit","format:check":"biome format src tests",ready:"node scripts/run-bun.js run scripts/qualify.ts production","detect-unused":"node scripts/run-bun.js run scripts/detect-unused.ts",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"},keywords:["cli","blade","ai","assistant","agent","llm"],author:"echoVic",license:"MIT",engines:{node:">=22.19.0"},optionalDependencies:{"@vscode/ripgrep":"^1.17.0","better-sqlite3":"^11.8.1","bun-pty":"^0.4.8","node-pty":"1.0.0"},dependencies:{"@agentclientprotocol/sdk":"^0.12.0","@anthropic-ai/sandbox-runtime":"0.0.67","@earendil-works/pi-ai":"0.83.0","@inkjs/ui":"^2.0.0","@modelcontextprotocol/sdk":"^1.17.4",ahooks:"^3.9.6","ansi-escapes":"^7.2.0","async-mutex":"^0.5.0",axios:"^1.12.2",chalk:"^5.4.1",diff:"^8.0.2","fast-glob":"^3.3.3","fuse.js":"^7.1.0","gray-matter":"^4.0.3",hono:"^4.7.10",ink:"npm:@jrichman/ink@6.4.10","ink-big-text":"^2.0.0","ink-gradient":"^3.0.0","ink-select-input":"^6.2.0","ink-spinner":"^5.0.0","ink-text-input":"^6.0.0","js-tiktoken":"^1.0.21","lodash-es":"^4.17.21",lowlight:"^3.3.0","lru-cache":"^11.2.4",nanoid:"^5.1.6",open:"^10.1.2",openai:"^6.2.0",picomatch:"^4.0.3",react:"^19.1.1","react-dom":"^19.1.1",semver:"^7.7.3","string-width":"^8.1.0",undici:"^7.16.0","write-file-atomic":"^7.0.0",ws:"^8.18.0",yaml:"^2.8.1",yargs:"^18.0.0",typebox:"1.3.7",zustand:"^5.0.9"},devDependencies:{"@biomejs/biome":"^2.2.4","@types/bun":"^1.3.4","@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.1","@types/react-dom":"^19.1.1","@types/semver":"^7.7.1","@types/write-file-atomic":"^4.0.3","@types/ws":"^8.5.12","@types/yargs":"^17.0.33","@vitest/coverage-v8":"^3.0.0",jsdom:"^26.0.0",typescript:"^5.9.2",vitest:"^3.0.0"}};function r(){return{name:e.name,version:e.version,description:e.description}}function n(){return e.version}function o(){return e.name}function c(){return e.description}function d(){return`v${e.version}`}function a(){return`v${e.version} © 2025 Blade Code`}
2
+ export{r as Ub,n as Vb,o as Wb,c as Xb,d as Yb,a as Zb};
@@ -1,4 +1,4 @@
1
- import{$ as f,M as m,V as g,W as c,Z as d}from"./chunk-eycs00af.js";import{Kb as u}from"./chunk-rxjt7ma7.js";async function R(){if((await g().initialize(u(),[])).plugins.length>0)await c()}async function x(t){let e=t.message||t._?.[0];if(typeof e==="string"&&e.trim())return e;let n=t.stdin??process.stdin;if(!n.isTTY){let a=[];for await(let l of n)a.push(l);return Buffer.concat(a).toString("utf-8").trim()}if(t.defaultMessage!==void 0)return t.defaultMessage;throw Error("No input provided")}async function P(t){if(!d(t))return{mode:"agent",content:t};let e=await f(t,{cwd:u(),workspaceRoot:u()});if(!e.success)return{mode:"output",content:`Error: ${e.error||"未知错误"}`,exitCode:1};let n=e.data;if(n?.action==="invoke_skill"){let{skillName:a,skillArgs:l}=n;return{mode:"agent",content:l?`Please use the "${a}" skill to help me with: ${l}`:`Please use the "${a}" skill.`}}if(n?.action==="invoke_custom_command"||n?.action==="invoke_plugin_command"){let a=n.processedContent;return{mode:"agent",content:`# Custom Command: /${n.commandName}
1
+ import{M as g,N as c,Q as d,S as f}from"./chunk-bfgm5k3e.js";import{Tb as m}from"./chunk-mpkr3s6b.js";import{rc as u}from"./chunk-w3me85va.js";async function R(){if((await g().initialize(u(),[])).plugins.length>0)await c()}async function x(t){let e=t.message||t._?.[0];if(typeof e==="string"&&e.trim())return e;let n=t.stdin??process.stdin;if(!n.isTTY){let a=[];for await(let l of n)a.push(l);return Buffer.concat(a).toString("utf-8").trim()}if(t.defaultMessage!==void 0)return t.defaultMessage;throw Error("No input provided")}async function P(t){if(!d(t))return{mode:"agent",content:t};let e=await f(t,{cwd:u(),workspaceRoot:u()});if(!e.success)return{mode:"output",content:`Error: ${e.error||"未知错误"}`,exitCode:1};let n=e.data;if(n?.action==="invoke_skill"){let{skillName:a,skillArgs:l}=n;return{mode:"agent",content:l?`Please use the "${a}" skill to help me with: ${l}`:`Please use the "${a}" skill.`}}if(n?.action==="invoke_custom_command"||n?.action==="invoke_plugin_command"){let a=n.processedContent;return{mode:"agent",content:`# Custom Command: /${n.commandName}
2
2
 
3
3
  ${a}`}}return{mode:"output",content:e.content||e.message||"",exitCode:0}}function r(t){if(!(t instanceof Error))return!1;return t.message.includes("未找到会话")||t.message.includes("ENOENT")||t.message.includes("no such file")}async function i(t){try{return await m.loadSession(t,u())}catch(e){if(r(e))return null;throw e}}async function y(t){if(t.resume===!0||t.resume==="true")throw Error("--resume without a session ID is only supported in interactive UI mode");if(typeof t.resume==="string"&&t.resume.length>0){if(t.forkSession){let e=u();return m.forkSession(t.resume,{newSessionId:t.sessionId,sourceProjectPath:e,targetProjectPath:e})}return{sessionId:t.resume,messages:await m.loadSession(t.resume)}}if(t.continue){let e=t.forkSession?await m.listSessions({cwd:u()}):await m.listSessions();if(e.length>0){let n=e[0].sessionId;if(t.forkSession){let a=u();return m.forkSession(n,{newSessionId:t.sessionId,sourceProjectPath:a,targetProjectPath:a})}return{sessionId:n,messages:await m.loadSession(n)}}if(t.forkSession)throw Error("Cannot fork: no sessions are available to continue")}if(t.sessionId)return{sessionId:t.sessionId,messages:await i(t.sessionId)??[]};return{sessionId:`${t.fallbackSessionPrefix}-${Date.now()}`,messages:[]}}
4
- export{R as q,x as r,P as s,y as t};
4
+ export{R as l,x as m,P as n,y as o};
@@ -1 +1 @@
1
- function f(x){return x!==void 0&&typeof x.pattern==="string"&&typeof x.search_path==="string"}function b(x){return x!==void 0&&x.kind==="edit"&&typeof x.matches_found==="number"}function h(x){return x==="readonly"}var v="__aborted__";export{f as rb,b as sb,h as tb,v as ub};
1
+ function f(x){return x!==void 0&&typeof x.pattern==="string"&&typeof x.search_path==="string"}function b(x){return x!==void 0&&x.kind==="edit"&&typeof x.matches_found==="number"}function h(x){return x==="readonly"}var v="__aborted__";export{f as qb,b as rb,h as sb,v as tb};
@@ -0,0 +1,2 @@
1
+ import{$ as W}from"./chunk-z0qxaky4.js";import{Cb as H,xb as F,zb as k}from"./chunk-x548f12z.js";import{Fb as V}from"./chunk-fpr6d8zc.js";var $=k.String({minLength:1,maxLength:128,pattern:"^[A-Za-z0-9][A-Za-z0-9_-]*$"}),Q=k.Array(k.String({minLength:1,maxLength:200,pattern:".*\\S.*"}),{maxItems:128}),b=k.Object({description:k.String({minLength:1,maxLength:4096,pattern:".*\\S.*"}),prompt:k.String({minLength:1,maxLength:1e5,pattern:".*\\S.*"}),tools:k.Optional(Q),disallowedTools:k.Optional(Q),model:k.Optional(k.String({minLength:1,maxLength:200,pattern:".*\\S.*"})),permissionMode:k.Optional(H(["default","acceptEdits","dontAsk","bypassPermissions","plan","ignore"])),maxTurns:k.Optional(k.Integer({minimum:1,maximum:V})),isolation:k.Optional(H(["none","worktree"]))},{additionalProperties:!1});function O(Y){let w;try{w=JSON.parse(Y)}catch{throw Error("Invalid JSON provided to --agents")}if(w===null||Array.isArray(w)||typeof w!=="object")throw Error("--agents must be a JSON object");let I=Object.entries(w);if(I.length>64)throw Error("--agents supports at most 64 definitions");return I.map(([z,Z])=>{if(!F($,z).success)throw Error(`Invalid --agents name "${z}": use letters, numbers, hyphens, or underscores`);let K=F(b,Z);if(!K.success)throw Error(`Invalid --agents definition for "${z}"`);let q=K.data;return{name:z,description:q.description.trim(),systemPrompt:q.prompt.trim(),tools:q.tools?[...new Set(q.tools.map((B)=>B.trim()))]:void 0,disallowedTools:q.disallowedTools?[...new Set(q.disallowedTools.map((B)=>B.trim()))]:void 0,model:q.model?.trim(),permissionMode:q.permissionMode===void 0?void 0:W(q.permissionMode),maxTurns:q.maxTurns,isolation:q.isolation,source:"flag"}})}
2
+ export{O as _};
@@ -0,0 +1,2 @@
1
+ import{e as u4,f as l4}from"./chunk-bc6wbcrs.js";import{p as R4}from"./chunk-b10vr4xj.js";import{A as P,B as j0,C as k4,E as l0,F as _0,G as d0,I as a0,J as t0,L as I4,U as o4,r as t4,t as P4,u as h0,v as r0,x as M0,y as W0,z as h}from"./chunk-bfgm5k3e.js";import{ba as Z0}from"./chunk-jyr9417h.js";import{Aa as G4,Ba as N4,Ca as X4,Fa as V0,ya as Y0}from"./chunk-rrg9bw8r.js";import{Ta as c4,Va as k0,bb as u0}from"./chunk-n9tgxfvw.js";import{tb as b4}from"./chunk-5nye3k5w.js";import{Ab as L,Bb as H0,Cb as R,xb as l,zb as V}from"./chunk-x548f12z.js";import{Db as g0}from"./chunk-1v2n922p.js";import{Mb as O0}from"./chunk-acegy4td.js";import{Sb as f4,Tb as f}from"./chunk-mpkr3s6b.js";import{Vb as U0}from"./chunk-45bme7n9.js";import{rc as T}from"./chunk-w3me85va.js";import{vc as I}from"./chunk-2fbwmdvg.js";import{Ac as M4,Ec as O4}from"./chunk-gdm1xzvp.js";import{Hc as s0}from"./chunk-ppyg431d.js";var L5={port:{type:"number",describe:"Port to listen on (0 for auto)",default:0},hostname:{type:"string",describe:"Hostname to listen on",default:"127.0.0.1"},cors:{type:"array",describe:"Additional domains to allow for CORS",default:[]}};function E5($){return{port:$.port??0,hostname:$.hostname??"127.0.0.1",cors:$.cors??[]}}import{existsSync as O$,readFileSync as S0}from"node:fs";import{createServer as _5}from"node:http";import{networkInterfaces as j5}from"node:os";import{dirname as K5,extname as z5,join as X0}from"node:path";import{fileURLToPath as w5}from"node:url";import{Hono as D5}from"hono";import{cors as A5}from"hono/cors";import{WebSocketServer as H5}from"ws";class m extends Error{code;statusCode;constructor($,J,Y=500){super(J);this.code=$;this.statusCode=Y;this.name="BladeServerError"}toObject(){return{error:{code:this.code,message:this.message}}}}class v extends m{constructor($,J){super("NOT_FOUND",J?`${$} not found: ${J}`:`${$} not found`,404)}}class q extends m{constructor($){super("BAD_REQUEST",$,400)}}class g extends m{constructor($){super("CONFLICT",$,409)}}class D0 extends m{constructor($){super("TOO_MANY_REQUESTS",$,429)}}class s extends m{constructor(){super("AMBIGUOUS_SESSION","Multiple workspaces contain this session ID; projectPath is required",409)}}class p extends m{constructor($="Internal server error"){super("INTERNAL_ERROR",$,500)}}var b5=V.Object({error:V.Object({code:V.String(),message:V.String()})});import{Hono as N$}from"hono";var v0=I("Service"),X$=V.Object({updates:V.Record(V.String(),V.Any()),options:V.Optional(V.Object({scope:V.Optional(R(["local","project","global"])),immediate:V.Optional(V.Boolean())}))});function U$($){return{currentModelId:$.currentModelId,permissionMode:$.permissionMode,language:$.language,theme:$.theme,uiTheme:$.uiTheme,autoSaveSessions:$.autoSaveSessions,notifyBuild:$.notifyBuild,notifyErrors:$.notifyErrors,notifySounds:$.notifySounds,privacyTelemetry:$.privacyTelemetry,privacyCrash:$.privacyCrash,maxConcurrentTasks:$.maxConcurrentTasks,maxQueuedTasks:$.maxQueuedTasks}}var Y4=()=>{let $=new N$;return $.get("/",async(J)=>{try{let Y=Y0();return J.json(Y?U$(Y):{})}catch(Y){return v0.error("[ConfigRoutes] Failed to get config:",Y),J.json({})}}),$.put("/",async(J)=>{try{let Y=await J.req.json(),Z=l(X$,Y);if(!Z.success)throw new q("Invalid config update format");let{updates:x,options:G}=Z.data;return await V0().updateConfig(x,G),J.json({success:!0,updates:x})}catch(Y){throw v0.error("[ConfigRoutes] Failed to update config:",Y),Y}}),$.get("/permissions",async(J)=>{try{let Y=Y0();return J.json(Y?.permissions||{})}catch(Y){return v0.error("[ConfigRoutes] Failed to get permissions:",Y),J.json({})}}),$};import{Hono as _$}from"hono";import{streamSSE as j$}from"hono/streaming";var K$=15000,z$=new Set(["task.status"]),w$=new Set(["queued","running","completed","failed","cancelled","interrupted"]);function D$($){if(!$||typeof $!=="object"||Array.isArray($))return;let J=$,Y=["changedFiles","additions","deletions","commits"];if(Y.some((Z)=>typeof J[Z]!=="number"||!Number.isInteger(J[Z])||J[Z]<0))return;return Object.fromEntries(Y.map((Z)=>[Z,J[Z]]))}function F0($,J){return typeof $==="number"&&Number.isInteger($)&&$>=J?$:void 0}var Z4=()=>{let $=new _$;return $.get("/",(J)=>j$(J,async(Y)=>{let Z,x,G=!1,N=()=>{if(x!==void 0)clearInterval(x),x=void 0;Z?.(),Z=void 0},A=()=>{if(G)return;G=!0,N()};Y.onAbort(A),Z=P.subscribe((K)=>{if(!z$.has(K.type))return;let H=K.properties.taskStatus;if(typeof H!=="string"||!w$.has(H))return;let F=D$(K.properties.taskDiffStat),E=F0(K.properties.taskQueuePosition,1),C=F0(K.properties.taskQueueDepth,0),c=F0(K.properties.taskConcurrencyLimit,1),O=F0(K.properties.taskInFlight,0);Y.writeSSE({data:JSON.stringify({type:K.type,properties:{sessionId:K.sessionId,projectPath:K.projectPath,taskStatus:H,...typeof K.properties.taskStatusReason==="string"?{taskStatusReason:K.properties.taskStatusReason}:{},...typeof K.properties.taskStartedAt==="string"?{taskStartedAt:K.properties.taskStartedAt}:{},...typeof K.properties.taskCompletedAt==="string"?{taskCompletedAt:K.properties.taskCompletedAt}:{},...typeof K.properties.updatedAt==="string"?{updatedAt:K.properties.updatedAt}:{},...F?{taskDiffStat:F}:{},...E!==void 0?{taskQueuePosition:E}:{},...C!==void 0?{taskQueueDepth:C}:{},...c!==void 0?{taskConcurrencyLimit:c}:{},...O!==void 0?{taskInFlight:O}:{}}})}).catch(A)});try{if(Y.aborted||G)return;if(await Y.writeSSE({data:JSON.stringify({type:"connected",properties:{timestamp:Date.now()}})}),Y.aborted||G)return;x=setInterval(()=>{if(Y.aborted||G)return;Y.writeSSE({data:JSON.stringify({type:"heartbeat",properties:{timestamp:Date.now()}})}).catch(A)},K$);while(!Y.aborted&&!G)await new Promise((K)=>setTimeout(K,1000))}finally{A()}})),$};import{Hono as A$}from"hono";var Q4=()=>{let $=new A$;return $.get("/health",(J)=>{return J.json({healthy:!0,version:U0()})}),$.get("/info",(J)=>{let Y=T(),Z=Y0();if(Z)_0.configure(Z.maxConcurrentTasks,Z.maxQueuedTasks);return J.json({version:U0(),platform:process.platform,arch:process.arch,nodeVersion:process.version,cwd:Y,gitBranch:O4(Y),taskAdmission:_0.getStats()})}),$};import{Hono as H$}from"hono";var A0=I("Service"),x4=()=>{let $=new H$;return $.get("/",async(J)=>{try{let Z=Z0.getInstance().getAllServers(),x=Array.from(Z.entries()).map(([G,N])=>({id:G,name:G,status:N.status==="connected"?"connected":N.status==="connecting"?"connecting":N.lastError?"error":"offline",endpoint:N.config.command?`${N.config.command} ${(N.config.args||[]).join(" ")}`.trim():N.config.url||"Unknown",description:`MCP server: ${G}`,tools:N.tools.map((A)=>A.name),connectedAt:N.connectedAt?.toISOString(),error:N.lastError?.message}));return J.json(x)}catch(Y){return A0.error("[McpRoutes] Failed to get MCP servers:",Y),J.json([])}}),$.post("/:name/connect",async(J)=>{try{let Y=J.req.param("name");return await Z0.getInstance().connectServer(Y),J.json({success:!0})}catch(Y){return A0.error("[McpRoutes] Failed to connect MCP server:",Y),J.json({success:!1,error:Y.message},500)}}),$.post("/:name/disconnect",async(J)=>{try{let Y=J.req.param("name");return await Z0.getInstance().disconnectServer(Y),J.json({success:!0})}catch(Y){return A0.error("[McpRoutes] Failed to disconnect MCP server:",Y),J.json({success:!1,error:Y.message},500)}}),$.delete("/:name",async(J)=>{try{let Y=J.req.param("name");await Z0.getInstance().unregisterServer(Y);let x=Y0();if(x?.mcpServers){let{[Y]:G,...N}=x.mcpServers;await V0().updateConfig({mcpServers:N})}return J.json({success:!0})}catch(Y){return A0.error("[McpRoutes] Failed to delete MCP server:",Y),J.json({success:!1,error:Y.message},500)}}),$.post("/",async(J)=>{try{let Y=await J.req.json(),{name:Z,config:x}=Y;if(!Z||!x)return J.json({success:!1,error:"Missing name or config"},400);await Z0.getInstance().registerServer(Z,x);let N=Y0();return await V0().updateConfig({mcpServers:{...N?.mcpServers,[Z]:x}}),J.json({success:!0})}catch(Y){return A0.error("[McpRoutes] Failed to add MCP server:",Y),J.json({success:!1,error:Y.message},500)}}),$};import{Hono as W$}from"hono";var L0=I("Service");function B$($,J){return{id:$.id,displayName:$.displayName,provider:$.provider,model:$.model,overrides:$.overrides,fallbackModels:$.fallbackModels,contextWindow:J.contextWindow,maxTokens:J.maxTokens,reasoning:J.reasoning,input:J.input}}function q$($){let J={displayName:$.displayName||void 0,overrides:$.overrides||void 0};if($.model)J.model=$.model;return J}var U4=()=>{let $=new W$;return $.get("/",async(J)=>{try{let Y=G4(),Z=N4(),x=O0(),G=(N)=>B$(N,x.resolveConfig(N));return J.json({configured:Y.map(G),current:Z?G(Z):null})}catch(Y){return L0.error("[ModelsRoutes] Failed to get models:",Y),J.json({configured:[],current:null})}}),$.post("/",async(J)=>{try{let Y=await J.req.json(),{provider:Z,displayName:x,model:G,overrides:N,apiKey:A}=Y;if(!Z||!G)throw new q("provider and model are required");if(O0().getModel(Z,G),A?.trim())await O0().setApiKey(Z,A.trim());let K=await V0().addModel({provider:Z,displayName:x||void 0,model:G,overrides:N||void 0});return J.json({success:!0,model:K})}catch(Y){throw L0.error("[ModelsRoutes] Failed to add model:",Y),Y}}),$.put("/:modelId",async(J)=>{try{let Y=J.req.param("modelId"),Z=await J.req.json(),{displayName:x,overrides:G,model:N}=Z,A=X4(Y);if(!A)throw new q("model config not found");if(N)O0().getModel(A.provider,N);return await V0().updateModel(Y,q$({displayName:x,overrides:G,model:N})),J.json({success:!0})}catch(Y){throw L0.error("[ModelsRoutes] Failed to update model:",Y),Y}}),$.delete("/:modelId",async(J)=>{try{let Y=J.req.param("modelId");return await V0().removeModel(Y),J.json({success:!0})}catch(Y){throw L0.error("[ModelsRoutes] Failed to delete model:",Y),Y}}),$};import{Hono as t$}from"hono";import E4 from"node:path";import{Mutex as k$}from"async-mutex";import{Hono as I$}from"hono";import{streamSSE as R$}from"hono/streaming";import{LRUCache as h$}from"lru-cache";import{nanoid as K0}from"nanoid";var T0=L(R(["default","autoEdit","yolo","plan"]));var y0=L(R(["user","assistant","system","tool"])),F$=L(V.Union([V.Object({type:V.Literal("text"),text:V.String()}),V.Object({type:V.Literal("image_url"),image_url:V.Object({url:V.String()})})])),j4=V.Union([V.String(),V.Array(F$)]),G1=L(V.Object({id:V.String(),role:y0,content:j4,timestamp:V.Number(),metadata:V.Optional(V.Record(V.String(),V.Unknown())),thinkingContent:V.Optional(V.String()),tool_call_id:V.Optional(V.String()),name:V.Optional(V.String()),tool_calls:V.Optional(V.Unknown())})),L$=L(R(["queued","running","completed","failed","cancelled","interrupted"])),K4=L(R(["local","worktree"])),E$=L(V.Object({changedFiles:V.Integer({minimum:0}),additions:V.Integer({minimum:0}),deletions:V.Integer({minimum:0}),commits:V.Integer({minimum:0})})),C$=L(V.Object({path:V.String({minLength:1}),patch:V.String({maxLength:2097152}),additions:V.Integer({minimum:0}),deletions:V.Integer({minimum:0}),binary:V.Boolean(),truncated:V.Boolean()})),z4=L(V.Object({sessionId:V.String(),projectPath:V.String(),baseCommit:V.String(),files:V.Array(C$,{maxItems:100}),truncated:V.Boolean()})),w4=L(V.Object({sessionId:V.String(),projectPath:V.String(),title:V.Optional(V.String()),gitBranch:V.Optional(V.String()),rootId:V.String(),parentId:V.Optional(V.String()),relationType:V.Optional(R(["subagent","fork"])),resumedFrom:V.Optional(V.String()),rootAgentId:V.Optional(V.String()),resumeDepth:V.Optional(V.Integer({minimum:0})),taskStatus:H0(L$,"completed"),taskStatusReason:V.Optional(V.String()),taskStartedAt:V.Optional(V.String()),taskCompletedAt:V.Optional(V.String()),taskPromptSummary:V.Optional(V.String()),taskIsolation:V.Optional(K4),taskSourceProjectPath:V.Optional(V.String()),taskWorktreePath:V.Optional(V.String()),taskWorktreeBranch:V.Optional(V.String()),taskBaseCommit:V.Optional(V.String()),taskDiffStat:V.Optional(E$),taskQueuePosition:V.Optional(V.Integer({minimum:1})),taskQueueDepth:V.Optional(V.Integer({minimum:0})),taskConcurrencyLimit:V.Optional(V.Integer({minimum:1})),messageCount:V.Number(),firstMessageTime:V.String(),lastMessageTime:V.String(),hasErrors:V.Boolean()})),N1=L(V.Object({version:V.Literal(1),sessionId:V.String(),goalId:V.String(),objective:V.String(),status:R(["active","paused","blocked","usage_limited","budget_limited","complete"]),tokenBudget:V.Optional(V.Number()),tokensUsed:V.Number(),timeUsedSeconds:V.Number(),continuationCount:V.Number(),statusReason:V.Optional(V.String()),createdAt:V.String(),updatedAt:V.String()})),D4=L(V.Object({role:y0,content:j4,metadata:V.Optional(V.Unknown()),reasoningContent:V.Optional(V.String()),thinkingContent:V.Optional(V.String()),tool_call_id:V.Optional(V.String()),name:V.Optional(V.String()),tool_calls:V.Optional(V.Unknown())})),X1=L(V.Object({session:w4,messages:V.Array(D4)})),A4=L(R(["conversation","code","both"])),M$=L(V.Object({messageId:V.String(),preview:V.String(),createdAt:V.String(),fileCount:V.Integer({minimum:0})})),H4=L(V.Object({targetMessageId:V.String({minLength:1}),mode:H0(A4,"conversation")})),U1=L(V.Object({checkpoint:M$,mode:A4,removedTurns:V.Integer({minimum:1}),restoredFiles:V.Array(V.String()),messages:V.Array(D4)})),b$=R(["running","completed","failed","cancelled"]),_4=L(V.Object({id:V.String(),subagentType:V.String(),description:V.String(),status:b$,rootAgentId:V.String(),resumedFrom:V.Optional(V.String()),resumeDepth:V.Integer({minimum:0}),createdAt:V.Number(),lastActiveAt:V.Number(),completedAt:V.Optional(V.Number()),result:V.Optional(V.Object({success:V.Boolean(),message:V.String(),error:V.Optional(V.String()),verificationCommands:V.Optional(V.Array(V.String()))})),stats:V.Optional(V.Object({tokens:V.Optional(V.Number()),toolCalls:V.Optional(V.Number()),duration:V.Optional(V.Number())}))})),W4=L(V.Object({prompt:V.String({minLength:1,maxLength:32000,pattern:"\\S"})})),_1=L(V.Object({source:_4,session:_4})),j1=L(V.Object({sessionId:V.String(),projectPath:V.String()})),K1=L(V.Object({type:V.String(),seq:V.Optional(V.Number()),properties:V.Record(V.String(),V.Unknown())})),B4=V.Object({type:R(["file","image","url"]),path:V.Optional(V.String()),url:V.Optional(V.String()),content:V.Optional(V.String()),mimeType:V.Optional(V.String()),name:V.Optional(V.String())}),q4=L(V.Object({prompt:V.String({minLength:1,maxLength:32000,pattern:"\\S"}),title:V.Optional(V.String({minLength:1,maxLength:200})),projectPath:V.Optional(V.String()),isolation:H0(K4,"worktree"),permissionMode:H0(T0,"default"),attachments:V.Optional(V.Array(B4))})),F4=L(V.Object({session:w4,runId:V.String(),messageId:V.String(),status:R(["queued","running"]),queuePosition:V.Optional(V.Integer({minimum:1})),queueDepth:V.Optional(V.Integer({minimum:0})),maxConcurrentTasks:V.Optional(V.Integer({minimum:1}))})),L4=L(V.Object({content:V.String(),projectPath:V.Optional(V.String()),permissionMode:V.Optional(T0),attachments:V.Optional(V.Array(B4))})),z1=L(V.Object({messageId:V.String(),role:y0,content:V.String(),timestamp:V.String()})),w1=L(V.Object({approved:V.Boolean(),remember:V.Optional(V.Boolean()),scope:V.Optional(R(["once","session","project"])),targetMode:V.Optional(T0),feedback:V.Optional(V.String()),answers:V.Optional(V.Record(V.String(),V.Union([V.String(),V.Array(V.String())])))})),D1=L(V.Object({id:V.String(),displayName:V.Optional(V.String()),provider:V.String(),model:V.String(),contextWindow:V.Optional(V.Number()),maxTokens:V.Optional(V.Number()),reasoning:V.Optional(V.Boolean()),input:V.Optional(V.Array(R(["text","image"]))),overrides:V.Optional(V.Object({baseUrl:V.Optional(V.String()),temperature:V.Optional(V.Number()),maxOutputTokens:V.Optional(V.Number()),timeout:V.Optional(V.Number())}))})),A1=L(R(["vs-dark","vs-light","hc-black"])),P$=L(R(["light","dark","system"])),f$=L(V.Object({language:V.String(),theme:V.String(),uiTheme:P$,autoSaveSessions:V.Boolean(),notifyBuild:V.Boolean(),notifyErrors:V.Boolean(),notifySounds:V.Boolean(),privacyTelemetry:V.Boolean(),privacyCrash:V.Boolean()})),H1=L(V.Partial(f$));var M=I("Service"),S$=V.Object({title:V.Optional(V.String()),projectPath:V.Optional(V.String())}),v$=L4,T$=V.Object({title:V.Optional(V.String()),projectPath:V.Optional(V.String())}),y$=V.Object({projectPath:V.String()}),m$=V.Object({objective:V.String({minLength:1}),tokenBudget:V.Optional(V.Integer({minimum:1})),permissionMode:V.Optional(R(["default","autoEdit","plan","yolo"]))}),g$=V.Union([V.Object({action:V.Literal("pause")}),V.Object({action:V.Literal("resume")}),V.Object({action:V.Literal("edit"),objective:V.String({minLength:1})})]),y=new Map,J0=new Map,f0=new h$({max:100,ttl:1800000});function u$($){return{sessionId:$.sessionId,projectPath:$.projectPath}}function o($){if(!$)return;return J0.get($)??f0.get($)}function l$($){if(J0.get($.id)!==$)return;J0.delete($.id),f0.set($.id,$)}function d$($){J0.delete($),f0.delete($)}function G0($){return $?.status==="queued"||$?.status==="running"||$?.status==="waiting_permission"}function P0($,J="user-cancel"){if($.status==="cancelled"||$.status==="completed"||$.status==="failed")return!1;let Y=$.pendingPermission;return $.pendingPermission=void 0,Y?.resolve({approved:!1,reason:b4}),$.abortController.abort(J),$.status="cancelled",P.publish(u$($),"run.cancelled",{runId:$.id}),!0}function h4($,J=!1){let{permissionId:Y,details:Z}=$;if(Z.type==="askUserQuestion"&&Z.questions)return{type:"question.required",properties:{requestId:Y,toolCallId:Y,questions:Z.questions,details:Z,...J?{replayed:!0}:{}}};return{type:"permission.asked",properties:{requestId:Y,toolName:Z.toolName,description:Z.message,args:Z.args,details:Z,...J?{replayed:!0}:{}}}}function c$(){for(let $ of J0.values())P0($,"route-reset");J0.clear(),f0.clear(),y.clear()}var S4=($)=>{if(!$||typeof $!=="object")return $;let J={...$},Y=200000;if(typeof J.oldContent==="string"&&J.oldContent.length>Y)delete J.oldContent;if(typeof J.newContent==="string"&&J.newContent.length>Y)delete J.newContent;return J};function p$($,J,Y){switch(Y.kind){case"tool_start":if("function"in Y.toolCall)P.publish($,"subagent.update",{subagentSessionId:J,toolName:Y.toolCall.function.name}),P.publish($,"subagent.tool.start",{subagentSessionId:J,toolCallId:Y.toolCall.id,toolName:Y.toolCall.function.name,arguments:Y.toolCall.function.arguments,toolKind:Y.toolKind});break;case"tool_result":if("function"in Y.toolCall)P.publish($,"subagent.tool.result",{subagentSessionId:J,toolCallId:Y.toolCall.id,toolName:Y.toolCall.function.name,success:!Y.result.error,summary:Y.result.metadata?.summary,output:t0(a0(Y.toolCall.function.name,Y.result)),metadata:S4(Y.result.metadata)});break;case"content_delta":P.publish($,"subagent.delta",{subagentSessionId:J,delta:Y.delta});break;case"thinking_delta":P.publish($,"subagent.thinking.delta",{subagentSessionId:J,delta:Y.delta});break;case"stream_end":P.publish($,"subagent.stream.end",{subagentSessionId:J});break;default:break}}function b0($,J="projectPath"){if(!E4.isAbsolute($))throw new q(`${J} must be absolute`);return E4.resolve($)}function c0($){try{M4($)}catch(J){throw new q(J instanceof Error?J.message:`Invalid session ID: ${$}`)}}function d($){return{sessionId:$.id,projectPath:$.projectPath}}function E0($,J,Y){return{id:$.sessionId,projectPath:$.projectPath,title:$.title??`Session ${$.sessionId.slice(0,6)}`,createdAt:new Date($.firstMessageTime),updatedAt:new Date($.lastMessageTime),rootId:$.rootId,parentId:$.parentId,relationType:$.relationType,taskStatus:$.taskStatus,taskStatusReason:$.taskStatusReason,taskStartedAt:$.taskStartedAt,taskCompletedAt:$.taskCompletedAt,taskPromptSummary:$.taskPromptSummary,taskIsolation:$.taskIsolation,taskSourceProjectPath:$.taskSourceProjectPath,taskWorktreePath:$.taskWorktreePath,taskWorktreeBranch:$.taskWorktreeBranch,taskBaseCommit:$.taskBaseCommit,taskDiffStat:$.taskDiffStat,taskQueuePosition:$.taskQueuePosition,taskQueueDepth:$.taskQueueDepth,taskConcurrencyLimit:$.taskConcurrencyLimit,taskWorktree:Y,messages:J}}function v4($,J){$.taskStatus=J.taskStatus,$.taskStatusReason=J.taskStatusReason,$.taskStartedAt=J.taskStartedAt,$.taskCompletedAt=J.taskCompletedAt,$.taskPromptSummary=J.taskPromptSummary,$.taskIsolation=J.taskIsolation,$.taskSourceProjectPath=J.taskSourceProjectPath,$.taskWorktreePath=J.taskWorktreePath,$.taskWorktreeBranch=J.taskWorktreeBranch,$.taskBaseCommit=J.taskBaseCommit,$.taskDiffStat=J.taskDiffStat,$.taskQueuePosition=J.taskQueuePosition,$.taskQueueDepth=J.taskQueueDepth,$.taskConcurrencyLimit=J.taskConcurrencyLimit,$.updatedAt=new Date(J.lastMessageTime)}async function m0($){let J=await f.findSessionMetadata($.id,$.projectPath);if(J)v4($,J)}function C0($){let J=o($.currentRunId),Y=J?.status==="waiting_permission"?"running":J?.status??$.taskStatus;return{sessionId:$.id,projectPath:$.projectPath,title:$.title,rootId:$.rootId,parentId:$.parentId,relationType:$.relationType,status:void 0,taskStatus:Y,taskStatusReason:$.taskStatusReason,taskStartedAt:$.taskStartedAt,taskCompletedAt:$.taskCompletedAt,taskPromptSummary:$.taskPromptSummary,taskIsolation:$.taskIsolation,taskSourceProjectPath:$.taskSourceProjectPath,taskWorktreePath:$.taskWorktreePath,taskWorktreeBranch:$.taskWorktreeBranch,taskBaseCommit:$.taskBaseCommit,taskDiffStat:$.taskDiffStat,taskQueuePosition:J?.status==="queued"?J.taskQueuePosition:Y==="queued"?$.taskQueuePosition:void 0,taskQueueDepth:J?.status==="queued"?J.taskQueueDepth:Y==="queued"?$.taskQueueDepth:void 0,taskConcurrencyLimit:J?.taskConcurrencyLimit??$.taskConcurrencyLimit,agentType:void 0,model:void 0,messageCount:$.messages.length,firstMessageTime:$.createdAt.toISOString(),lastMessageTime:$.updatedAt.toISOString(),hasErrors:!1,isActive:!0}}async function $0($,J){if(c0($),J!==void 0){let Z=W0({sessionId:$,projectPath:b0(J)});if(y.has(h(Z)))return Z;let x=await f.findSessionMetadata(Z.sessionId,Z.projectPath);if(!x)throw new v("Session",$);return W0({sessionId:x.sessionId,projectPath:x.projectPath})}let Y=new Map;for(let Z of y.values()){if(Z.id!==$)continue;let x=d(Z);Y.set(h(x),x)}for(let Z of await f.listSessions()){if(Z.sessionId!==$)continue;let x=W0({sessionId:Z.sessionId,projectPath:Z.projectPath});Y.set(h(x),x)}if(Y.size===0)try{let Z=await f.findSessionMetadata($);if(!Z)throw new v("Session",$);return W0({sessionId:Z.sessionId,projectPath:Z.projectPath})}catch(Z){if(Z instanceof v)throw Z;if(Z instanceof Error&&Z.message.startsWith("Ambiguous session ID:"))throw new s;throw Z}if(Y.size>1)throw new s;return Y.values().next().value}function p0($){if(typeof $==="string")return $;return $.filter((J)=>J.type==="text").map((J)=>J.text).join(`
2
+ `)}function C4($,J){let Y=(J??[]).filter((x)=>x.type==="image"&&typeof x.content==="string").map((x)=>({type:"image_url",image_url:{url:x.content}}));if(Y.length===0)return $;let Z=[];if($.trim())Z.push({type:"text",text:$});return Z.push(...Y),Z}var T4=()=>{c$();let $=new I$;$.onError((O,X)=>{if(O instanceof m)return X.json(O.toObject(),O.statusCode);return M.error("[SessionRoutes] Unhandled route error:",O),X.json({error:{code:"INTERNAL_ERROR",message:"Internal server error"}},500)});let J=new Map,Y=new Map,Z=new Map,x=new Map,G=(O)=>{let X=h(O),Q=x.get(X);if(!Q)Q=new k$,x.set(X,Q);return Q},N=async(O)=>{let X=h(d(O)),Q=J.get(X);if(Q)return Q;let U=Y.get(X);if(!U)U=d0.create({sessionId:O.id,workspaceRoot:O.projectPath,...O.taskWorktree?{taskWorktree:O.taskWorktree}:{},...O.taskIsolation?{taskIsolation:O.taskIsolation}:{}}),Y.set(X,U);try{let _=await U;return J.set(X,_),_}finally{if(Y.get(X)===U)Y.delete(X)}},A=async(O)=>{let X=h(O),Q=y.get(X);if(Q)return Q;let U=Z.get(X);if(!U)U=(async()=>{let _=await f.findSessionMetadata(O.sessionId,O.projectPath);if(!_)throw new v("Session",O.sessionId);let[j,w]=await Promise.all([f.loadSession(O.sessionId,O.projectPath),f.findSessionTaskWorktree(O.sessionId,O.projectPath)]),W=E0(_,j,w);return y.set(X,W),W})(),Z.set(X,U);try{return await U}finally{if(Z.get(X)===U)Z.delete(X)}},K=async(O,X)=>{return A(await $0(O,X))},H=(O,X,Q,U={})=>{let _=K0(12),j={id:_,sessionId:O.id,projectPath:O.projectPath,status:"running",abortController:new AbortController,createdAt:new Date};if(U.taskRuntime){let w=U.taskRuntime,W=_0.admit({key:`${O.projectPath}\x00${O.id}`,...w.getTaskAdmissionLimits(),signal:j.abortController.signal,onUpdate:(z)=>{j.status=z.state,j.taskQueuePosition=z.queuePosition,j.taskQueueDepth=z.queueDepth,j.taskConcurrencyLimit=z.maxConcurrent,O.taskStatus=z.state,O.taskQueuePosition=z.queuePosition,O.taskQueueDepth=z.queueDepth,O.taskConcurrencyLimit=z.maxConcurrent,j.taskAdmissionUpdate=(j.taskAdmissionUpdate??Promise.resolve()).then(async()=>{await w.setTaskAdmission(z)}).catch((B)=>{M.warn(`[SessionRoutes] Failed to persist admission for ${O.id}:`,B)})}});j.taskAdmission=W;let D=W.getSnapshot();j.status=D.state,j.taskQueuePosition=D.queuePosition,j.taskQueueDepth=D.queueDepth,j.taskConcurrencyLimit=D.maxConcurrent}return J0.set(_,j),O.currentRunId=_,j.completion=a$(j,O,X,Q,N,{pendingInputOnly:U.pendingInputOnly,preparedInputTurn:U.preparedInputTurn,goalContinuationOnly:U.goalContinuationOnly,taskAdmission:j.taskAdmission}).catch((w)=>{M.error(`[SessionRoutes] Run ${_} failed:`,w)}),j},F=async(O)=>{let X=g0("task",12),Q=b0(O.sourceProjectPath),U,_;try{let j=await R4.createSessionTask({sessionId:X,prompt:O.prompt,title:O.title,sourceProjectPath:Q,isolation:O.isolation}),{metadata:w}=j;U=j.taskWorktree,_=E0(w,[],U);let W=d(_);y.set(h(W),_),P.publish(W,"task.status",{taskStatus:w.taskStatus,updatedAt:w.lastMessageTime});let D=C4(O.prompt,O.attachments),z=await N(_),B=await z.prepareInputTurn(D);if(!B.accepted)throw new g(`Task prompt was not accepted: ${B.reason}`);let k=H(_,D,O.permissionMode,{preparedInputTurn:B,taskRuntime:z});return await k.taskAdmissionUpdate,{session:C0(_),runId:k.id,messageId:B.messageId,status:k.status==="queued"?"queued":"running",queuePosition:k.taskQueuePosition,queueDepth:k.taskQueueDepth,maxConcurrentTasks:k.taskConcurrencyLimit}}catch(j){if(j instanceof l0&&_){let w=d(_),W=h(w);if(U)await j0.exit({sessionId:_.id,action:"remove",discardChanges:!0}).catch(()=>{return});throw await J.get(W)?.dispose().catch(()=>{return}),J.delete(W),await f.deleteSession(_.id,_.projectPath).catch(()=>{return}),y.delete(W),new D0("Task admission queue is full")}if(_){let w=await f.findSessionMetadata(_.id,_.projectPath).catch(()=>{return});if(!w||w.taskStatus==="queued"){let W=await f.updateSessionMetadata(_.id,_.projectPath,{taskStatus:"failed",taskStatusReason:"Task dispatch failed",taskCompletedAt:new Date().toISOString(),taskOwnerPid:null}).catch(()=>{return});_.taskStatus=W?.taskStatus??"failed",_.taskStatusReason=W?.taskStatusReason??"Task dispatch failed",_.taskCompletedAt=W?.taskCompletedAt}else _.taskStatus=w.taskStatus,_.taskStatusReason=w.taskStatusReason,_.taskCompletedAt=w.taskCompletedAt}throw j}},E=async(O,X)=>{let Q=await K(O,X);if(!Q.taskWorktree)throw new q("Session does not have a task worktree");try{await j0.restoreSession(Q.taskWorktree);let U=await j0.getDiffArtifact(Q.id);if(!U)throw new g("Task diff artifact is unavailable");return{sessionId:Q.id,projectPath:Q.projectPath,...U}}catch(U){if(U instanceof g)throw U;throw M.error("[SessionRoutes] Failed to load task diff artifact:",U),new g("Task diff artifact is unavailable")}},C=async(O)=>{let X=o(O.currentRunId);if(G0(X))return;let Q=await N(O),U=o(O.currentRunId);if(G0(U))return;let _=Q.getPendingSteeringCount()>0,w=(_?null:await Q.getGoal())?.status==="active";if(!_&&!w||Q.hasTurnOwner())return;H(O,"","default",{pendingInputOnly:_,goalContinuationOnly:w,...O.taskIsolation?{taskRuntime:Q}:{}})},c=async()=>{let O={scheduled:0,failed:0,deferred:0},X=(await f.listSessions()).filter((Q)=>Q.taskStatus==="queued"&&Q.taskIsolation!==void 0).sort((Q,U)=>Q.firstMessageTime.localeCompare(U.firstMessageTime)||Q.projectPath.localeCompare(U.projectPath)||Q.sessionId.localeCompare(U.sessionId));for(let[Q,U]of X.entries()){let _={sessionId:U.sessionId,projectPath:U.projectPath};try{if(!await d0.hasPendingInbox(U.projectPath,U.sessionId)){await f.updateSessionMetadata(U.sessionId,U.projectPath,{taskStatus:"failed",taskStatusReason:"Queued task input is missing",taskCompletedAt:new Date().toISOString(),taskOwnerPid:null,taskQueuePosition:null,taskQueueDepth:null}),O.failed++;continue}let j=await A(_);if(await C(j),j.currentRunId)O.scheduled++}catch(j){if(j instanceof l0){O.deferred+=X.length-Q;break}M.warn(`[SessionRoutes] Failed to recover queued task ${U.sessionId}:`,j),O.deferred++}}return O};return $.get("/",async(O)=>{try{let X=await f.listSessions(),Q=new Set(X.filter((z)=>z.relationType==="subagent").map((z)=>h({sessionId:z.sessionId,projectPath:z.projectPath}))),U=Array.from(y.values()).filter((z)=>!Q.has(h(d(z)))&&z.relationType!=="subagent").map((z)=>C0(z)),_=new Set(U.map((z)=>h({sessionId:z.sessionId,projectPath:z.projectPath}))),j=X.filter((z)=>{if(z.relationType==="subagent")return!1;return!_.has(h({sessionId:z.sessionId,projectPath:z.projectPath}))}),w=new Set(_),W=j.filter((z)=>{let B=h({sessionId:z.sessionId,projectPath:z.projectPath});if(w.has(B))return!1;return w.add(B),!0}),D=[...U,...W];return O.json(D)}catch(X){throw M.error("[SessionRoutes] Failed to list sessions:",X),new p("Failed to list sessions")}}),$.post("/",async(O)=>{try{let X=await O.req.json(),Q=l(S$,X);if(!Q.success)throw new q("Invalid request body");let{title:U,projectPath:_}=Q.data,j=g0("web",12),w=b0(_||O.get("directory")||T(),_?"projectPath":"directory"),W=await f.createSessionMetadata(j,w,{title:U}),D=E0(W,[]),z=d(D);return y.set(h(z),D),P.publish(z,"task.status",{taskStatus:W.taskStatus,updatedAt:W.lastMessageTime}),O.json({...C0(D),status:void 0,agentType:void 0,model:void 0})}catch(X){if(M.error("[SessionRoutes] Failed to create session:",X),X instanceof q)throw X;throw new p("Failed to create session")}}),$.post("/:sessionId/fork",async(O)=>{let X=O.req.param("sessionId");try{c0(X);let Q=await O.req.json(),U=l(y$,Q);if(!U.success)throw new q("Invalid request body");let _=b0(U.data.projectPath),j=await f.findSessionMetadata(X,_);if(!j)throw new v("Session",X);let w=await f.forkSession(X,{sourceProjectPath:j.projectPath,targetProjectPath:j.projectPath}),W=E0(w.metadata,w.messages),D=d(W);return y.set(h(D),W),P.publish(D,"task.status",{taskStatus:w.metadata.taskStatus,...w.metadata.taskCompletedAt?{taskCompletedAt:w.metadata.taskCompletedAt}:{},updatedAt:w.metadata.lastMessageTime}),O.json({session:w.metadata,messages:w.messages},201)}catch(Q){if(Q instanceof q||Q instanceof v||Q instanceof g)throw Q;if(Q instanceof f4)throw new g("Session has no durable creation record");throw M.error("[SessionRoutes] Failed to fork session:",Q),new p("Failed to fork session")}}),$.get("/:sessionId",async(O)=>{let X=O.req.param("sessionId");try{let Q=await $0(X,O.req.query("projectPath")),U=y.get(h(Q));if(U)return O.json(C0(U));let _=await f.findSessionMetadata(Q.sessionId,Q.projectPath);if(!_)throw new v("Session",X);return O.json(_)}catch(Q){if(Q instanceof q||Q instanceof v||Q instanceof s)throw Q;throw M.error("[SessionRoutes] Failed to get session:",Q),new p("Failed to get session")}}),$.patch("/:sessionId",async(O)=>{let X=O.req.param("sessionId");try{let Q=await O.req.json(),U=l(T$,Q);if(!U.success)throw new q("Invalid request body");if(U.data.title===void 0)throw new q("title is required");let _=await $0(X,U.data.projectPath),j=await f.updateSessionMetadata(_.sessionId,_.projectPath,{title:U.data.title}),w=y.get(h(_));if(w)w.title=j.title??w.title,w.updatedAt=new Date(j.lastMessageTime);return O.json({success:!0,title:j.title})}catch(Q){if(M.error("[SessionRoutes] Failed to update session:",Q),Q instanceof q||Q instanceof v||Q instanceof s)throw Q;throw new p("Failed to update session")}}),$.get("/:sessionId/rewind",async(O)=>{let X=await K(O.req.param("sessionId"),O.req.query("projectPath")),Q=await N(X);return O.json({checkpoints:await Q.listRewindCheckpoints()})}),$.post("/:sessionId/rewind",async(O)=>{let X=l(H4,await O.req.json());if(!X.success)throw new q("Invalid rewind request");let Q=await K(O.req.param("sessionId"),O.req.query("projectPath")),U=d(Q);return G(U).runExclusive(async()=>{let _=o(Q.currentRunId);if(G0(_))throw new g("Cannot rewind while a run is active");let j=await N(Q),w;try{w=await j.rewindSession(X.data)}catch(W){if(W instanceof Error&&W.message.startsWith("Cannot rewind while"))throw new g(W.message);throw W}return Q.messages=[...w.messages],Q.updatedAt=new Date,P.publish(U,"session.rewound",{targetMessageId:w.checkpoint.messageId,mode:w.mode,removedTurns:w.removedTurns,restoredFiles:w.restoredFiles,messages:w.messages}),O.json(w)})}),$.get("/:sessionId/subagents",async(O)=>{let X=await K(O.req.param("sessionId"),O.req.query("projectPath")),Q=await N(X);return O.json({subagents:Q.listSubagents().map(M0)})}),$.post("/:sessionId/subagents/:agentId/resume",async(O)=>{c0(O.req.param("agentId"));let X=W4.safeParse(await O.req.json());if(!X.success)throw new q("Invalid subagent resume request");let Q=await K(O.req.param("sessionId"),O.req.query("projectPath")),U=d(Q);return G(U).runExclusive(async()=>{let _=o(Q.currentRunId);if(G0(_))throw new g("Cannot resume a subagent while a parent run is active");let j=await N(Q),w=!1,W,D=(B)=>{P.publish(U,"subagent.complete",{subagentSessionId:B.id,success:B.status==="completed",status:B.status,summary:B.result?.message?.slice(0,500),resumedFrom:B.resumedFrom,rootAgentId:B.rootAgentId,resumeDepth:B.resumeDepth})},z;try{z=j.resumeSubagent({agentId:O.req.param("agentId"),prompt:X.data.prompt,onEvent:(B,k)=>{p$(U,k,B)},onCompleted:(B)=>{if(w)D(B);else W=B}})}catch(B){if(B instanceof Error&&(B.message.startsWith("Cannot resume")||B.message.startsWith("Subagent cannot")))throw new g(B.message);if(B instanceof Error&&B.message.startsWith("Subagent not found"))throw new v(B.message);throw B}if(P.publish(U,"subagent.start",{subagentSessionId:z.session.id,type:z.session.subagentType,description:z.session.description,resumedFrom:z.source.id,rootAgentId:z.session.rootAgentId,resumeDepth:z.session.resumeDepth}),w=!0,W)D(W);return O.json({source:M0(z.source),session:M0(z.session)})})}),$.get("/:sessionId/goal",async(O)=>{let X=await K(O.req.param("sessionId"),O.req.query("projectPath"));return O.json({goal:await new P4(X.projectPath,X.id).get()})}),$.put("/:sessionId/goal",async(O)=>{let X=l(m$,await O.req.json());if(!X.success)throw new q("Invalid goal request");let Q=await K(O.req.param("sessionId"),O.req.query("projectPath")),U=d(Q);return G(U).runExclusive(async()=>{let _=o(Q.currentRunId);if(G0(_))return O.json({status:"rejected",reason:"run_active"},409);let j=await N(Q),w=await j.createGoal(X.data);P.publish(U,"goal.updated",{goal:w});let W=X.data.permissionMode??"default",D=H(Q,"",W,{goalContinuationOnly:!0,...Q.taskIsolation?{taskRuntime:j}:{}});return await D.taskAdmissionUpdate,O.json({status:D.status==="queued"?"queued":"running",runId:D.id,goal:w,queuePosition:D.taskQueuePosition,queueDepth:D.taskQueueDepth,maxConcurrentTasks:D.taskConcurrencyLimit},202)})}),$.patch("/:sessionId/goal",async(O)=>{let X=l(g$,await O.req.json());if(!X.success)throw new q("Invalid goal update");let Q=await K(O.req.param("sessionId"),O.req.query("projectPath")),U=d(Q);return G(U).runExclusive(async()=>{let _=await N(Q),j;if(X.data.action==="pause")j=await _.pauseGoal();else if(X.data.action==="edit")j=await _.editGoal(X.data.objective);else j=await _.resumeGoal();if(P.publish(U,"goal.updated",{goal:j}),j.status==="active"&&!G0(o(Q.currentRunId))){let w=H(Q,"","default",{goalContinuationOnly:!0,...Q.taskIsolation?{taskRuntime:_}:{}});return await w.taskAdmissionUpdate,O.json({status:w.status==="queued"?"queued":"running",runId:w.id,goal:j,queuePosition:w.taskQueuePosition,queueDepth:w.taskQueueDepth,maxConcurrentTasks:w.taskConcurrencyLimit},202)}return O.json({status:j.status,goal:j})})}),$.delete("/:sessionId/goal",async(O)=>{let X=await K(O.req.param("sessionId"),O.req.query("projectPath")),Q=d(X),_=await(await N(X)).clearGoal();if(_)P.publish(Q,"goal.cleared",{});return O.json({cleared:_})}),$.delete("/:sessionId",async(O)=>{let X=O.req.param("sessionId"),Q=O.req.query("projectPath");try{let U=await $0(X,Q),_=h(U),j=y.get(_),w=J.get(_),W=j?.taskWorktree??await f.findSessionTaskWorktree(U.sessionId,U.projectPath),D;if(j?.currentRunId){let z=o(j.currentRunId);if(z)P0(z),await z.completion,D=z.id}if(w)await w.clearGoal().catch((z)=>{M.warn("[SessionRoutes] Failed to clear session goal:",z)});if(await f.deleteSession(U.sessionId,U.projectPath),D)d$(D);if(y.delete(_),Z.delete(_),Y.delete(_),x.delete(_),w){if(await w.dispose(),J.delete(_),J.size===0)await Z0.getInstance().disconnectAll()}if(W)try{await j0.restoreSession(W),await j0.exit({sessionId:U.sessionId,action:"remove",discardChanges:!0})}catch(z){M.warn(`[SessionRoutes] Failed to remove deleted task worktree ${U.sessionId}:`,z)}return O.json({success:!0})}catch(U){if(M.error("[SessionRoutes] Failed to delete session:",U),U instanceof q||U instanceof v||U instanceof s)throw U;throw new p("Failed to delete session")}}),$.get("/:sessionId/message",async(O)=>{let X=O.req.param("sessionId");try{let Q=await $0(X,O.req.query("projectPath")),U=y.get(h(Q)),_=U?.messages?U.messages:await f.loadSession(Q.sessionId,Q.projectPath);return O.json(_)}catch(Q){if(M.error("[SessionRoutes] Failed to get messages:",Q),Q instanceof q||Q instanceof v||Q instanceof s)throw Q;throw new p("Failed to get messages")}}),$.get("/:sessionId/events",async(O)=>{let X=O.req.param("sessionId"),Q=await $0(X,O.req.query("projectPath")),U=await A(Q),_=O.req.header("Last-Event-ID")??O.req.query("lastEventId"),j=_?Number.parseInt(_,10):Number.NaN,w=Number.isInteger(j)?j+1:void 0;return R$(O,async(W)=>{let z,B,k=!1,a=()=>{if(B!==void 0)clearInterval(B),B=void 0;z?.(),z=void 0},i=()=>{if(k)return;k=!0,a()},t=new Set;W.onAbort(i),z=P.subscribe((b)=>{if(b.sessionId!==Q.sessionId||b.projectPath!==Q.projectPath)return;let r=b.properties.requestId;if((b.type==="permission.asked"||b.type==="question.required")&&typeof r==="string"){if(t.has(r))return;t.add(r)}W.writeSSE({...typeof b.seq==="number"?{id:String(b.seq)}:{},data:JSON.stringify({type:b.type,...typeof b.seq==="number"?{seq:b.seq}:{},properties:{...b.properties,sessionId:b.sessionId,projectPath:b.projectPath}})}).catch(i)});try{if(W.aborted||k)return;if(await W.writeSSE({data:JSON.stringify({type:"connected",properties:{sessionId:Q.sessionId,projectPath:Q.projectPath,timestamp:Date.now()}})}).catch((S)=>{throw i(),S}),W.aborted||k)return;if(w!==void 0){if(await k4.for(Q.sessionId,Q.projectPath).replay({onCommitted:(n)=>{if(W.aborted||k)return;W.writeSSE({...typeof n.seq==="number"?{id:String(n.seq)}:{},data:JSON.stringify({type:`committed.${n.type}`,...typeof n.seq==="number"?{seq:n.seq}:{},properties:{event:n,sessionId:Q.sessionId,projectPath:Q.projectPath}})})}},w),W.aborted||k)return}let r=o(U.currentRunId)?.pendingPermission;if(r){t.add(r.permissionId);let S=h4(r,!0);await W.writeSSE({data:JSON.stringify({type:S.type,properties:{...S.properties,sessionId:Q.sessionId,projectPath:Q.projectPath}})})}C(U).catch((S)=>{M.error(`[SessionRoutes] Failed to resume pending input for ${X}:`,S)}),B=setInterval(()=>{if(!W.aborted)W.writeSSE({data:JSON.stringify({type:"heartbeat",properties:{timestamp:Date.now()}})}).catch(i)},15000);while(!W.aborted&&!k)await new Promise((S)=>setTimeout(S,1000))}finally{i()}})}),$.post("/:sessionId/message",async(O)=>{let X=O.req.param("sessionId"),Q=await O.req.json(),U=l(v$,Q);if(!U.success)throw new q("Invalid message format");let{content:_,attachments:j,permissionMode:w,projectPath:W}=U.data,D=w||"default",z=C4(_,j),B=await K(X,W??O.req.query("projectPath")),k=d(B);return G(k).runExclusive(async()=>{let a=o(B.currentRunId);if(G0(a)){let S=await(await N(B)).enqueueSteering(z,{allowBeforeTurn:!0});if(!S.accepted)return O.json({status:"rejected",reason:S.reason??"turn_unavailable"},409);let n=S.messageId??K0(12),J4=S.queued;P.publish(k,"message.created",{messageId:n,role:"user",content:p0(z)});let x$=S.delivery==="next_turn"?"follow_up.queued":"steering.queued";if(P.publish(k,x$,{runId:a.id,messageId:n,queued:J4}),S.delivery==="next_turn"&&a.status!=="running"&&a.status!=="waiting_permission")C(B).catch((G$)=>{M.error(`[SessionRoutes] Failed to wake queued follow-up for ${X}:`,G$)});if(S.delivery==="next_turn")a.pendingFollowUpRequested=!0;return O.json({runId:a.id,messageId:n,status:S.delivery==="next_turn"?"follow_up_queued":"steering_queued",queued:J4},202)}let i=await N(B),t=await i.prepareInputTurn(z);if(!t.accepted)return O.json({status:"rejected",reason:t.reason},t.reason==="queue_full"?429:409);let b=H(B,z,D,{preparedInputTurn:t,...B.taskIsolation?{taskRuntime:i}:{}});return await b.taskAdmissionUpdate,O.json({runId:b.id,messageId:t.messageId,status:b.status==="queued"?"queued":"running",queuePosition:b.taskQueuePosition,queueDepth:b.taskQueueDepth,maxConcurrentTasks:b.taskConcurrencyLimit},202)})}),$.post("/:sessionId/abort",async(O)=>{let X=O.req.param("sessionId"),Q=await $0(X,O.req.query("projectPath")),U=y.get(h(Q));if(U?.currentRunId){let _=o(U.currentRunId);if(_)P0(_),await _.completion}return O.json({success:!0})}),$.get("/:sessionId/status",async(O)=>{let X=O.req.param("sessionId"),Q=await $0(X,O.req.query("projectPath")),U=y.get(h(Q));if(!U?.currentRunId)return O.json({sessionId:X,projectPath:Q.projectPath,status:"idle"});let _=o(U.currentRunId);return O.json({sessionId:X,projectPath:Q.projectPath,runId:U.currentRunId,status:_?.status||"idle"})}),{app:$,dispatchTask:F,getTaskDiff:E,recoverQueuedTasks:c}};async function a$($,J,Y,Z,x,G={}){let{abortController:N,sessionId:A,id:K}=$,H=G.preparedInputTurn?.messageId??K0(12),E=G.pendingInputOnly===!0||G.preparedInputTurn?.mode==="pending"||G.goalContinuationOnly===!0?void 0:K0(12),C,c=d(J),O=(X,Q)=>{P.publish(c,X,Q)};try{if(G.taskAdmission){if(await G.taskAdmission.ready,await $.taskAdmissionUpdate,N.signal.aborted)throw Error(String(N.signal.reason||"Task run cancelled"))}if(J.taskStatus="running",J.taskStatusReason=void 0,J.taskStartedAt=new Date().toISOString(),J.taskCompletedAt=void 0,!G.pendingInputOnly&&!G.goalContinuationOnly)O("message.created",{messageId:H,role:"user",content:p0(Y)});if(O("session.status",{status:"running"}),E)O("message.created",{messageId:E,role:"assistant",content:""});C=await x(J);let X=C,Q=await I4.createWithRuntime(X,{sessionId:A,...J.taskWorktree?{toolBlacklist:["EnterWorktree","ExitWorktree"]}:{}}),U=async(D)=>{let z=K0(12),B=300000;$.status="waiting_permission";let k=new Promise((b)=>{let r=setTimeout(()=>{M.warn(`[SessionRoutes] Permission ${z} timed out after 300000ms`),O("permission.timeout",{requestId:z}),b({approved:!1,reason:"timeout"})},300000);$.pendingPermission={permissionId:z,resolve:(S)=>{clearTimeout(r),b(S)},details:D}}),a=$.pendingPermission;if(!a)throw Error("Permission request was not registered");let i=h4(a);O(i.type,i.properties),M.info(`[SessionRoutes] Permission request created: ${z}, runId: ${K}`);let t=await k;if(M.info(`[SessionRoutes] Permission response received: ${z}, approved: ${t.approved}`),!N.signal.aborted)$.status="running";if($.pendingPermission===a)$.pendingPermission=void 0;return t},_={messages:[...J.messages],userId:"web-user",sessionId:A,workspaceRoot:J.projectPath,signal:N.signal,permissionMode:Z,...J.taskWorktree?{worktreeActive:!0}:{},confirmationHandler:{requestConfirmation:U}},j=()=>{if(!E)E=K0(12),O("message.created",{messageId:E,role:"assistant",content:""});return E},w=async(D)=>{switch(D.kind){case"content_delta":O("message.delta",{messageId:j(),delta:D.delta});break;case"thinking_delta":O("thinking.delta",{delta:D.delta});break;case"tool_start":if("function"in D.toolCall)O("tool.start",{messageId:j(),toolName:D.toolCall.function.name,toolCallId:D.toolCall.id,arguments:D.toolCall.function.arguments,toolKind:D.toolKind});break;case"tool_result":if("function"in D.toolCall)O("tool.result",{messageId:j(),toolName:D.toolCall.function.name,toolCallId:D.toolCall.id,success:D.result.success,summary:D.result.metadata?.summary,output:t0(a0(D.toolCall.function.name,D.result)),metadata:S4(D.result.metadata)});break;case"token_usage":O("token.usage",{...D.usage});break;case"turn_start":O("turn.started",{turn:D.turn,maxTurns:D.maxTurns});break;case"steering_applied":O("steering.applied",{runId:K,messageIds:D.messageIds,count:D.count,recovered:D.recovered,delivery:D.delivery,queued:X.getPendingSteeringCount()});break;case"follow_up_started":{if(E)O("message.complete",{messageId:E}),E=void 0;for(let z of D.messages){if(!z.recovered||z.persisted)continue;O("message.created",{messageId:z.id,role:"user",content:p0(z.content),recovered:!0})}O("follow_up.started",{runId:K,queued:D.queued,recovered:D.recovered}),j();break}case"goal_updated":O("goal.updated",{goal:D.goal});break;case"goal_continuation_started":O("goal.continuation.started",{goal:D.goal,continuation:D.continuation}),j();break;case"compaction":O(D.phase==="start"?"compaction.started":"compaction.completed",{});break;case"model_fallback":O("model.fallback",{});break;case"task_update":O("task.updated",{tasks:D.tasks});break;default:break}},W=await u0(Q.chatStream(Y,_,{stream:!0,pendingInputOnly:G.pendingInputOnly,preparedInputTurn:G.preparedInputTurn,goalContinuationOnly:G.goalContinuationOnly,taskAdmission:G.taskAdmission}),w);if(!W.success)throw Error(W.error?.message??"Agent run failed");for(let D=0;D<20;D++){let z=$.pendingFollowUpRequested===!0;if($.pendingFollowUpRequested=!1,X.getPendingSteeringCount()===0){if(!z)break;continue}if(N.signal.aborted)break;if(W=await u0(Q.chatStream("",_,{stream:!0,pendingInputOnly:!0,taskAdmission:G.taskAdmission}),w),!W.success)throw Error(W.error?.message??"Agent follow-up failed")}if(J.messages=[..._.messages],J.updatedAt=new Date,await m0(J),N.signal.aborted||$.status==="cancelled"){J.taskStatus="cancelled",J.taskCompletedAt??=new Date().toISOString(),O("session.status",{status:"idle"});return}if(E)O("message.complete",{messageId:E});O("thinking.completed",{}),$.status="completed",J.taskStatus="completed",J.taskCompletedAt??=new Date().toISOString(),O("session.completed",{runId:K,outputTruncated:W.metadata?.outputTruncated??!1}),O("session.status",{status:"idle"})}catch(X){if(C&&G.preparedInputTurn)await C.finishTurn(G.preparedInputTurn.handle).catch(()=>{return});if(N.signal.aborted||$.status==="cancelled"){if(P0($,"runtime-abort"),J.taskIsolation)await(C??await x(J).catch(()=>{return}))?.setTaskStatus("cancelled",String(N.signal.reason||"Task run cancelled")).catch(()=>{return});await m0(J).catch(()=>{return}),J.taskStatus="cancelled",J.taskCompletedAt??=new Date().toISOString(),O("session.status",{status:"idle"});return}if(await m0(J).catch(()=>{return}),M.error("[SessionRoutes] Agent execution error:",X),$.status="failed",J.taskStatus="failed",J.taskStatusReason??="Agent execution failed",J.taskCompletedAt??=new Date().toISOString(),J.taskIsolation){let Q=C?await C.setTaskStatus("failed",J.taskStatusReason).catch(()=>{return}):await f.updateSessionMetadata(J.id,J.projectPath,{taskStatus:"failed",taskStatusReason:J.taskStatusReason,taskCompletedAt:J.taskCompletedAt,taskOwnerPid:null,taskQueuePosition:null,taskQueueDepth:null}).catch(()=>{return});if(Q)v4(J,Q)}O("session.error",{error:X instanceof Error?X.message:"Unknown error"}),O("session.status",{status:"error"})}finally{if(G.taskAdmission?.release(),G.taskAdmission){let X=_0.getStats();O("task.status",{taskStatus:J.taskStatus,...J.taskStatusReason?{taskStatusReason:J.taskStatusReason}:{},...J.taskStartedAt?{taskStartedAt:J.taskStartedAt}:{},...J.taskCompletedAt?{taskCompletedAt:J.taskCompletedAt}:{},...J.taskDiffStat?{taskDiffStat:J.taskDiffStat}:{},taskQueueDepth:X.queued,taskConcurrencyLimit:X.maxConcurrent,taskInFlight:X.inFlight,updatedAt:new Date().toISOString()})}l$($)}}function y4($,J,Y){M.info(`[SessionRoutes] Looking for permission ${J} in session ${$.sessionId}`),M.info(`[SessionRoutes] Active runs: ${J0.size}`);for(let[Z,x]of J0.entries())if(M.info(`[SessionRoutes] Checking run ${Z}: sessionId=${x.sessionId}, projectPath=${x.projectPath}, pendingPermission=${x.pendingPermission?.permissionId}`),x.sessionId===$.sessionId&&x.projectPath===$.projectPath&&x.pendingPermission?.permissionId===J)return x.pendingPermission.resolve(Y),M.info(`[SessionRoutes] Permission ${J} responded, runId: ${x.id}`),!0;return M.error(`[SessionRoutes] Permission not found: ${J}`),!1}var o0=I("Service"),o$=V.Object({approved:V.Boolean(),remember:V.Optional(V.Boolean()),scope:V.Optional(R(["once","session","project"])),targetMode:V.Optional(R(["default","autoEdit","plan","yolo"])),feedback:V.Optional(V.String()),answers:V.Optional(V.Record(V.String(),V.Union([V.String(),V.Array(V.String())])))}),m4=()=>{let $=new t$;return $.post("/:permissionId",async(J)=>{let Y=J.req.param("permissionId"),Z=J.req.query("sessionId"),x=J.req.query("projectPath");o0.info(`[PermissionRoutes] Received permission response: permissionId=${Y}, sessionId=${Z}`);try{let G=await J.req.json(),N=l(o$,G);if(!N.success)throw new q("Invalid permission response format");let{approved:A,remember:K,scope:H,targetMode:F,feedback:E,answers:C}=N.data;if(!Z)throw new q("sessionId query parameter is required");let c=await $0(Z,x);if(!y4(c,Y,{approved:A,reason:E,scope:H,targetMode:F,feedback:E,answers:C}))throw new v("Permission request",Y);return o0.info(`[PermissionRoutes] Permission ${Y} ${A?"approved":"denied"}`),J.json({success:!0,approved:A,remember:K})}catch(G){if(o0.error("[PermissionRoutes] Failed to respond to permission:",G),G instanceof q||G instanceof s||G instanceof v||G instanceof m)throw G;throw G}}),$};import{Hono as i$}from"hono";var g4=I("Service"),d4=()=>{let $=new i$;return $.get("/",async(J)=>{try{let Y=await u4();return J.json(Y)}catch(Y){return g4.error("[ProviderRoutes] Failed to list providers:",Y),J.json([])}}),$.get("/:provider/models",async(J)=>{let Y=J.req.param("provider");try{let Z=await l4(Y);return J.json(Z)}catch(Z){return g4.error("[ProviderRoutes] Failed to list models:",Z),J.json([])}}),$.put("/:provider/credential",async(J)=>{let Y=J.req.param("provider"),Z=await J.req.json();if(!Z.apiKey?.trim())throw new q("apiKey is required");return await O0().setApiKey(Y,Z.apiKey.trim()),J.json({success:!0})}),$.delete("/:provider/credential",async(J)=>{return await O0().clearCredential(J.req.param("provider")),J.json({success:!0})}),$};import{Hono as r$}from"hono";import*as Q0 from"node:fs/promises";import{homedir as n$}from"node:os";import*as I0 from"node:path";var N0=I("Service"),i0=I0.join(n$(),".blade","skills-config.json");async function p4(){try{let $=await Q0.readFile(i0,"utf-8");return JSON.parse($)}catch{return{disabled:[]}}}async function s$($){await Q0.mkdir(I0.dirname(i0),{recursive:!0}),await Q0.writeFile(i0,JSON.stringify($,null,2))}async function e$($,J){let Y=await p4();if(J)Y.disabled=Y.disabled.filter((Z)=>Z!==$);else if(!Y.disabled.includes($))Y.disabled.push($);await s$(Y)}var z0=null,$5=300000;async function V5(){if(z0&&Date.now()-z0.timestamp<$5)return z0.data;try{let $=await fetch("https://api.github.com/repos/anthropics/skills/contents/skills",{headers:{Accept:"application/vnd.github.v3+json","User-Agent":"Blade-Skills-Catalog"}});if(!$.ok)return N0.warn(`GitHub API returned ${$.status}`),z0?.data||[];let J=await $.json(),Y=[];for(let Z of J){if(Z.type!=="dir")continue;let x=`Official ${Z.name} skill`;try{let G=await fetch(`https://raw.githubusercontent.com/anthropics/skills/main/skills/${Z.name}/SKILL.md`,{headers:{"User-Agent":"Blade-Skills-Catalog"}});if(G.ok){let A=(await G.text()).match(/^#[^\n]*\n+([^\n#]+)/);if(A)x=A[1].trim().slice(0,100)}}catch{}Y.push({name:Z.name,description:x,tag:"Official",author:"Anthropic"})}return z0={data:Y,timestamp:Date.now()},Y}catch($){return N0.warn("Failed to fetch skills catalog from GitHub:",$),z0?.data||[]}}var a4=()=>{let $=new r$;return $.get("/",async(J)=>{try{let Y=k0();await Y.initialize();let Z=Y.getAll(),x=await p4(),G=Z.map((N)=>({id:N.name,name:N.name,enabled:!x.disabled.includes(N.name),description:N.description||"",version:N.version||"1.0.0",provider:"Local",location:N.source==="builtin"?"Built-in":N.basePath,capabilities:["prompts"],allowedTools:N.allowedTools||[]}));return J.json(G)}catch(Y){return N0.error("[SkillsRoutes] Failed to get skills:",Y),J.json([])}}),$.post("/:name/toggle",async(J)=>{try{let Y=J.req.param("name"),Z=await J.req.json();return await e$(Y,Z.enabled),J.json({success:!0,enabled:Z.enabled})}catch(Y){return N0.error("[SkillsRoutes] Failed to toggle skill:",Y),J.json({success:!1,error:Y.message},500)}}),$.delete("/:name",async(J)=>{try{let Y=J.req.param("name"),Z=`${process.env.HOME}/.blade/skills/${Y}`;return await Q0.rm(Z,{recursive:!0,force:!0}),await k0().refresh(),J.json({success:!0})}catch(Y){return N0.error("[SkillsRoutes] Failed to uninstall skill:",Y),J.json({success:!1,error:Y.message},500)}}),$.post("/install",async(J)=>{try{let Y=await J.req.json(),Z=c4(),x=k0(),G=!1;if(Y.source==="catalog"&&Y.name){if(G=await Z.installOfficialSkill(Y.name),!G)return J.json({success:!1,error:"Failed to install skill from catalog"},500)}else if(Y.source==="repo"&&Y.url){if(G=await Z.installFromRepo(Y.url,Y.name),!G)return J.json({success:!1,error:"Failed to install skill from repository. Make sure the repo contains a SKILL.md file."},500)}else if(Y.source==="local"&&Y.path){if(G=await Z.installFromLocal(Y.path,Y.name),!G)return J.json({success:!1,error:"Failed to install skill from local path. Make sure the path exists and contains a SKILL.md file."},500)}else return J.json({success:!1,error:"Invalid install parameters. Required: source with corresponding url/path/name"},400);return await x.refresh(),J.json({success:!0})}catch(Y){return N0.error("[SkillsRoutes] Failed to install skill:",Y),J.json({success:!1,error:Y.message},500)}}),$.get("/catalog",async(J)=>{try{let Y=await V5();return J.json(Y)}catch(Y){return N0.error("[SkillsRoutes] Failed to get catalog:",Y),J.json([])}}),$};import J5 from"fast-glob";import{Hono as Y5}from"hono";import{execSync as Z5}from"node:child_process";import{readdir as O5}from"node:fs/promises";import R0 from"node:path";var B0=I("Service"),Q5=($)=>{try{return Z5("git rev-parse --abbrev-ref HEAD",{cwd:$,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()||null}catch{return null}},x5=[...h0.map(($)=>`${$}/**`),...h0,...r0.map(($)=>`**/${$}`)],G5=new Set(["/theme","/model","/permissions","/mcp","/skills","/exit","/resume","/ide","/login","/logout"]),i4=()=>{let $=new Y5;return $.get("/commands",async(J)=>{try{let Y=J.req.query("q")||"",Z=o4(Y).filter((x)=>!G5.has(x.command));return J.json(Z)}catch(Y){return B0.error("[SuggestionsRoutes] Failed to get command suggestions:",Y),J.json([])}}),$.get("/files",async(J)=>{try{let Y=J.req.query("q")||"",Z=J.get("directory")||T(),x=Math.min(Number(J.req.query("limit"))||100,1000),N=(await J5("**/*",{cwd:Z,dot:!1,followSymbolicLinks:!1,onlyFiles:!1,markDirectories:!0,unique:!0,ignore:x5})).map((H)=>H.replace(/\\/g,"/"));if(!Y)return J.json(N.slice(0,x));let A=Y.toLowerCase(),K=N.filter((H)=>H.toLowerCase().includes(A)).slice(0,x);return J.json(K)}catch(Y){return B0.error("[SuggestionsRoutes] Failed to get file suggestions:",Y),J.json([])}}),$.get("/files/tree",async(J)=>{try{let Y=J.get("directory")||T(),Z=J.req.query("path")||"",x=Z?R0.join(Y,Z):Y,N=(await O5(x,{withFileTypes:!0})).map((H)=>({name:H.name,path:Z?`${Z}/${H.name}`:H.name,type:H.isDirectory()?"dir":"file"}));N.sort((H,F)=>{if(H.type!==F.type)return H.type==="dir"?-1:1;return H.name.localeCompare(F.name)});let A=new Set(h0),K=N.filter((H)=>{let F=H.name;if(F.startsWith("."))return!1;if(A.has(F))return!1;for(let E of r0)if(F.match(new RegExp(E.replace("*",".*"))))return!1;return!0});return J.json(K)}catch(Y){return B0.error("[SuggestionsRoutes] Failed to get file tree:",Y),J.json([])}}),$.get("/files/content",async(J)=>{try{let Y=J.req.query("path");if(!Y)return J.json({error:"Missing file path"},400);let Z=J.get("directory")||T(),x=R0.resolve(Z,Y),G=R0.relative(Z,x);if(G.startsWith("..")||R0.isAbsolute(G))return J.json({error:"Invalid file path"},400);let N=t4(),A=await N.stat(x);if(!A?.isFile)return J.json({error:"File not found"},404);let K=200000,H=await N.readTextFile(x),F=H.length>K;return J.json({path:Y,content:F?H.slice(0,K):H,truncated:F,size:A.size})}catch(Y){return B0.error("[SuggestionsRoutes] Failed to get file content:",Y),J.json({error:"Failed to read file"},500)}}),$.get("/git-info",async(J)=>{try{let Y=J.get("directory")||T(),Z=Q5(Y);return J.json({branch:Z})}catch(Y){return B0.error("[SuggestionsRoutes] Failed to get git info:",Y),J.json({branch:null})}}),$};import{Hono as N5}from"hono";var n0=I("Service"),r4=($)=>{let J=new N5;return J.onError((Y,Z)=>{if(Y instanceof m)return Z.json(Y.toObject(),Y.statusCode);return n0.error("[TaskRoutes] Unhandled route error:",Y),Z.json(new p("Failed to dispatch task").toObject(),500)}),J.post("/",async(Y)=>{let Z;try{Z=await Y.req.json()}catch{throw new q("Invalid request body")}let x=l(q4,Z);if(!x.success)throw new q("Invalid task request");try{let G=await $.dispatchTask({prompt:x.data.prompt,title:x.data.title,sourceProjectPath:x.data.projectPath||Y.get("directory")||T(),isolation:x.data.isolation,permissionMode:x.data.permissionMode,attachments:x.data.attachments});return Y.json(F4.parse(G),202)}catch(G){if(G instanceof q||G instanceof g||G instanceof D0)throw G;throw n0.error("[TaskRoutes] Failed to dispatch task:",G),new p("Failed to dispatch task")}}),J.get("/:sessionId/diff",async(Y)=>{try{let Z=await $.getTaskDiff(Y.req.param("sessionId"),Y.req.query("projectPath"));return Y.json(z4.parse(Z))}catch(Z){if(Z instanceof q||Z instanceof v||Z instanceof g)throw Z;throw n0.error("[TaskRoutes] Failed to load task diff:",Z),new p("Failed to load task diff")}}),J};import{Hono as X5}from"hono";var x0=I("Service"),w0=new Map,n4=2097152,s4=65536;function e4(){return typeof globalThis.Bun<"u"}async function U5($,J,Y){if(e4()){let{spawn:G}=await import("bun-pty"),N=G($,J,{name:"xterm-256color",cwd:Y.cwd,env:Y.env});return{pid:N.pid,write:(A)=>N.write(A),resize:(A,K)=>N.resize(A,K),kill:()=>N.kill(),onData:(A)=>N.onData(A),onExit:(A)=>N.onExit(A)}}let x=(await import("node-pty")).spawn($,J,{name:"xterm-256color",cwd:Y.cwd,env:Y.env,cols:80,rows:24});return{pid:x.pid,write:(G)=>x.write(G),resize:(G,N)=>x.resize(G,N),kill:()=>x.kill(),onData:(G)=>{x.onData(G)},onExit:(G)=>{x.onExit(G)}}}var $4=void 0,e0;if(e4())try{let{createBunWebSocket:$}=await import("hono/bun"),J=$();e0=J.upgradeWebSocket,$4=J.websocket}catch($){x0.warn("[Terminal] Failed to initialize Bun WebSocket support:",$)}async function $$($,J){let Y=`term-${Date.now()}`;x0.info(`[Terminal] New connection: ${Y}, cwd: ${$}`);let Z=process.platform==="win32"?"powershell.exe":process.env.SHELL||"/bin/zsh",x=Z.endsWith("sh")?["-l"]:[],G=await U5(Z,x,{cwd:$,env:{...process.env,TERM:"xterm-256color",COLORTERM:"truecolor"}}),N={id:Y,process:G,cwd:$,buffer:"",subscribers:new Set};if(w0.set(Y,N),N.subscribers.add(J),G.onData((A)=>{let K=!1;for(let H of N.subscribers)try{H.send(A),K=!0}catch{N.subscribers.delete(H)}if(K)return;if(N.buffer+=A,N.buffer.length>n4)N.buffer=N.buffer.slice(-n4)}),G.onExit(({exitCode:A})=>{x0.info(`[Terminal] Process exited: ${Y}, code: ${A}`);for(let K of N.subscribers)try{K.close()}catch{}w0.delete(Y)}),N.buffer){let A=N.buffer;N.buffer="";for(let K=0;K<A.length;K+=s4)J.send(A.slice(K,K+s4))}return{session:N,cleanup:()=>{if(x0.info(`[Terminal] Connection closed: ${Y}`),N.subscribers.delete(J),N.subscribers.size===0){try{N.process.kill()}catch{}w0.delete(Y)}}}}function V$($,J){$.on("connection",async(Y,Z)=>{let x=new URL(Z.url||"/",`http://${Z.headers.host}`);if(!x.pathname.endsWith("/terminal/ws")){Y.close();return}let G=x.searchParams.get("cwd")||J()||T();try{let{session:N,cleanup:A}=await $$(G,{send:(K)=>Y.send(K),close:()=>Y.close()});Y.on("message",(K)=>{try{N.process.write(String(K))}catch(H){x0.error("[Terminal] Failed to write to PTY:",H)}}),Y.on("close",A),Y.on("error",A)}catch(N){x0.error("[Terminal] Failed to spawn PTY:",N),Y.close()}})}var J$=()=>{let $=new X5;if($.get("/status",(J)=>{let Y=Array.from(w0.values()).map((Z)=>({id:Z.id,cwd:Z.cwd}));return J.json({active:Y.length,terminals:Y})}),$.post("/kill/:terminalId",(J)=>{let Y=J.req.param("terminalId"),Z=w0.get(Y);if(Z){try{Z.process.kill()}catch{}for(let x of Z.subscribers)x.close();return w0.delete(Y),J.json({success:!0})}return J.json({success:!1,error:"Terminal not found"},404)}),e0)$.get("/ws",e0((J)=>{let Y=J.req.query("cwd")||J.get("directory")||T(),Z;return{async onOpen(x,G){try{Z=await $$(Y,{send:(N)=>G.send(N),close:()=>G.close()})}catch(N){x0.error("[Terminal] Failed to spawn PTY:",N),G.close()}},onMessage(x){if(!Z)return;try{Z.session.process.write(String(x.data))}catch(G){x0.error("[Terminal] Failed to write to PTY:",G)}},onClose(){Z?.cleanup()}}}));else $.get("/ws",(J)=>{return J.json({message:"WebSocket endpoint - connect via ws:// protocol",hint:"Use WebSocket client to connect to this endpoint"})});return $};var u=I("Service"),V4=[],q0;function W5(){let $=K5(w5(import.meta.url)),J=[X0($,"web"),X0(T(),"dist/web"),X0(T(),"packages/cli/dist/web")];for(let Y of J){let Z=X0(Y,"index.html");if(O$(Z)){if(S0(Z,"utf-8").includes("/assets/"))return u.debug(`[Server] Found web dist at: ${Y}`),Y}}return null}function B5(){let $=new D5;$.onError((Z,x)=>{if(u.error("[Server] Request error:",Z),Z instanceof m)return x.json(Z.toObject(),Z.statusCode);let G=Z instanceof Error?Z.message:String(Z);return x.json({error:{code:"INTERNAL_ERROR",message:G}},500)}),$.use(async(Z,x)=>{let G=process.env.BLADE_SERVER_PASSWORD;if(!G)return x();let N=Z.req.path;if(N==="/"||N.startsWith("/assets/")||N.endsWith(".html")||N.endsWith(".js")||N.endsWith(".css"))return x();let A=Z.req.header("Authorization");if(!A?.startsWith("Basic "))return Z.header("WWW-Authenticate",'Basic realm="Blade Server"'),Z.json({error:{code:"UNAUTHORIZED",message:"Authentication required"}},401);let K=Buffer.from(A.slice(6),"base64").toString(),[H,F]=K.split(":"),E=process.env.BLADE_SERVER_USERNAME??"blade";if(H!==E||F!==G)return Z.json({error:{code:"UNAUTHORIZED",message:"Invalid credentials"}},401);return x()}),$.use(async(Z,x)=>{let G=Z.req.path==="/health"||Z.req.path==="/global/health"||Z.req.path.startsWith("/assets/");if(!G)u.debug(`[Server] ${Z.req.method} ${Z.req.path}`);let N=Date.now();if(await x(),!G){let A=Date.now()-N;u.debug(`[Server] ${Z.req.method} ${Z.req.path} - ${Z.res.status} (${A}ms)`)}}),$.use(A5({origin(Z){if(!Z)return;if(Z.startsWith("http://localhost:"))return Z;if(Z.startsWith("http://127.0.0.1:"))return Z;if(Z==="tauri://localhost"||Z==="http://tauri.localhost")return Z;if(V4.includes(Z))return Z;return}})),$.use(async(Z,x)=>{let G=Z.req.query("directory")||Z.req.header("x-blade-directory")||T();try{G=decodeURIComponent(G)}catch{}return Z.set("directory",G),x()});let J=T4();q0=J.recoverQueuedTasks,$.route("/global",Q4()),$.route("/events",Z4()),$.route("/sessions",J.app),$.route("/tasks",r4(J)),$.route("/configs",Y4()),$.route("/permissions",m4()),$.route("/providers",d4()),$.route("/models",U4()),$.route("/suggestions",i4()),$.route("/terminal",J$()),$.route("/mcp",x4()),$.route("/skills",a4()),$.get("/health",(Z)=>{return Z.json({healthy:!0,version:U0()})});let Y=W5();if(Y)u.info(`[Server] Serving static files from ${Y}`),$.get("/assets/*",(Z)=>{let x=X0(Y,Z.req.path);if(!O$(x))return Z.json({error:{code:"NOT_FOUND",message:`File not found: ${Z.req.path}`}},404);let G=S0(x),N=z5(x).toLowerCase(),K={".js":"application/javascript",".css":"text/css",".html":"text/html",".json":"application/json",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".svg":"image/svg+xml",".ico":"image/x-icon",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".eot":"application/vnd.ms-fontobject"}[N]||"application/octet-stream";return new Response(G,{headers:{"Content-Type":K,"Cache-Control":"public, max-age=31536000, immutable"}})}),$.get("/",(Z)=>{let x=X0(Y,"index.html"),G=S0(x,"utf-8");return Z.html(G)}),$.get("*",(Z)=>{let x=Z.req.path;if(x.includes("."))return Z.json({error:{code:"NOT_FOUND",message:`File not found: ${x}`}},404);let G=X0(Y,"index.html"),N=S0(G,"utf-8");return Z.html(N)});else u.warn('[Server] Web UI not found. Run "cd packages/cli/web && bun run build" to enable web interface.'),$.get("/",(Z)=>{return Z.json({message:"Blade API Server",version:U0(),webUI:!1,hint:'Web UI not built. Run "cd packages/cli/web && bun run build" to enable.',endpoints:{health:"/health",sessions:"/sessions",configs:"/configs",permissions:"/permissions",providers:"/providers"}})}),$.all("*",(Z)=>{return Z.json({error:{code:"NOT_FOUND",message:`Route not found: ${Z.req.path}`}},404)});return $}function q5(){let $=j5(),J=[];for(let Y of Object.keys($)){let Z=$[Y];if(!Z)continue;for(let x of Z){if(x.internal||x.family!=="IPv4")continue;if(x.address.startsWith("172."))continue;J.push(x.address)}}return J}function Y$(){return typeof globalThis.Bun<"u"}function Z$($,J){let Y=globalThis.Bun,Z=(G)=>{try{return Y.serve({hostname:J.hostname,port:G,fetch:$.fetch,idleTimeout:0,websocket:$4})}catch(N){u.error("Failed to start Bun server:",N);return}},x=J.port===0?Z(4096)??Z(0):Z(J.port);if(!x)throw Error(`Failed to start Bun server on port ${J.port}`);return{url:x.url,port:x.port,hostname:x.hostname,stop:async()=>{x.stop(!0)}}}function F5($,J){return new Promise((Y,Z)=>{let x=_5(async(H,F)=>{let E=new URL(H.url||"/",`http://${H.headers.host}`),C=new Headers;for(let[X,Q]of Object.entries(H.headers))if(Q)if(Array.isArray(Q))for(let U of Q)C.append(X,U);else C.set(X,Q);let c;if(H.method!=="GET"&&H.method!=="HEAD")c=(await new Promise((Q)=>{let U=[];H.on("data",(_)=>U.push(_)),H.on("end",()=>Q(Buffer.concat(U)))})).toString();let O=new Request(E.toString(),{method:H.method,headers:C,body:c});try{let X=await $.fetch(O);if(F.statusCode=X.status,X.headers.forEach((Q,U)=>{F.setHeader(U,Q)}),X.body){let Q=X.body.getReader(),U=async()=>{let{done:_,value:j}=await Q.read();if(_){F.end();return}return F.write(j),U()};await U()}else{let Q=await X.text();F.end(Q)}}catch(X){u.error("[Server] Node request error:",X),F.statusCode=500,F.end(JSON.stringify({error:{code:"INTERNAL_ERROR",message:"Internal server error"}}))}}),G=new H5({noServer:!0}),N=T();V$(G,()=>N),x.on("upgrade",(H,F,E)=>{if(new URL(H.url||"/",`http://${H.headers.host}`).pathname==="/terminal/ws")G.handleUpgrade(H,F,E,(c)=>{G.emit("connection",c,H)});else F.destroy()});let A=(H)=>{return new Promise((F,E)=>{x.once("error",(C)=>{if(C.code==="EADDRINUSE")E(C);else E(C)}),x.listen(H,J.hostname,()=>{let C=x.address();if(C&&typeof C==="object")F(C.port);else F(H)})})};(async()=>{let H;if(J.port===0)try{H=await A(4096)}catch{H=await A(0)}else H=await A(J.port);let F=new URL(`http://${J.hostname==="0.0.0.0"?"localhost":J.hostname}:${H}`);Y({url:F,port:H,hostname:J.hostname,stop:async()=>{return new Promise((E)=>{G.close(()=>{x.close(()=>E())})})}})})().catch(Z)})}var Q$;((N9)=>{let $,J;function Y(){if(!J)J=B5();return J}N9.getApp=Y;function Z(N){V4=N.cors??[];let A=Y();if(Y$())$=Z$(A,N),u.info(`[Server] Blade server listening on ${$.url} (Bun runtime)`);else throw Error("Blade web server requires Bun runtime. Please run with Bun: `bun run blade web` or install Bun from https://bun.sh");let K=$;return q0?.().catch((H)=>{u.warn("[Server] Failed to recover queued tasks:",H)}),{url:K.url,port:K.port,hostname:K.hostname,stop:async()=>{if($)await $.stop(),$=void 0,J=void 0,q0=void 0,u.info("[Server] Blade server stopped")}}}N9.listen=Z;async function x(N){V4=N.cors??[];let A=Y();if(Y$())$=Z$(A,N),u.info(`[Server] Blade server listening on ${$.url} (Bun runtime)`);else $=await F5(A,N),u.info(`[Server] Blade server listening on ${$.url} (Node.js runtime)`);let K=$;try{await q0?.()}catch(H){u.warn("[Server] Failed to recover queued tasks:",H)}return{url:K.url,port:K.port,hostname:K.hostname,stop:async()=>{if($)await $.stop(),$=void 0,J=void 0,q0=void 0,u.info("[Server] Blade server stopped")}}}N9.listenAsync=x;function G(){return $!==void 0}N9.isRunning=G})(Q$||={});export{L5 as a,E5 as b,q5 as c,Q$ as d};
@@ -0,0 +1 @@
1
+ import{Aa as h,Ba as i,Ca as j,Da as k,Ea as l,Fa as m,ta as a,ua as b,va as c,wa as d,xa as e,ya as f,za as g}from"./chunk-rrg9bw8r.js";import"./chunk-9ax02vtg.js";import"./chunk-1v2n922p.js";import"./chunk-fpr6d8zc.js";import"./chunk-acegy4td.js";import"./chunk-w3me85va.js";import"./chunk-2fbwmdvg.js";import"./chunk-gdm1xzvp.js";import"./chunk-ppyg431d.js";export{a as vanillaStore,c as sessionActions,l as getThinkingModeEnabled,b as getState,j as getModelById,e as getMessages,k as getMcpServers,i as getCurrentModel,f as getConfig,h as getAllModels,g as ensureStoreInitialized,m as configActions,d as appActions};
@@ -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{Mb as r}from"./chunk-acegy4td.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 Qa,n as Ra};
@@ -1,5 +1,5 @@
1
- import{Vb as f}from"./chunk-9xvnrq7m.js";import{fc as x}from"./chunk-0g9cb41d.js";var S={openrouter:{"HTTP-Referer":"https://github.com/echoVic/blade-code","X-Title":"Blade"},cerebras:{"X-Cerebras-3rd-Party-Integration":"blade"}},w=(e)=>S[e]||{};var z=new Set(["user-cancel","interrupt","sibling-error","timeout"]);function g(e){return typeof e==="string"&&z.has(e)}function J(e){if(!e.aborted)return;if(g(e.reason))return e.reason;return"user-cancel"}function Z(e){if(g(e))return!0;if(!(e instanceof Error))return!1;if(e.name==="AbortError")return!0;if(e instanceof DOMException&&e.name==="AbortError")return!0;if(e.message.includes("aborted"))return!0;return!1}function Q(...e){let t=e.filter(Boolean);if(t.length===0)return new AbortController().signal;if(t.length===1)return t[0];let o=AbortSignal;if(typeof o.any==="function")return o.any(t);for(let s of t)if(s.aborted)return s;let r=new AbortController,i=new Map;for(let s of t){let a=()=>{r.abort(s.reason);for(let[l,n]of i)l.removeEventListener("abort",n)};i.set(s,a)}for(let[s,a]of i)s.addEventListener("abort",a,{once:!0});return r.signal}function C(e,t,o){let r=o?.throwOnAbort??!1;if(t?.aborted){if(r)return Promise.reject(new DOMException("Aborted","AbortError"));return Promise.resolve()}return new Promise((i,s)=>{let a,l=setTimeout(()=>{if(t&&a)t.removeEventListener("abort",a);i()},e);if(t)a=()=>{if(clearTimeout(l),r)s(new DOMException("Aborted","AbortError"));else i()},t.addEventListener("abort",a,{once:!0})})}var D=f("Chat"),q={input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}};function k(e){if(typeof e==="string")return e;return e.filter((t)=>t.type==="text").map((t)=>t.text).join(`
1
+ import{Mb as x}from"./chunk-acegy4td.js";import{vc as f}from"./chunk-2fbwmdvg.js";var S={openrouter:{"HTTP-Referer":"https://github.com/echoVic/blade-code","X-Title":"Blade"},cerebras:{"X-Cerebras-3rd-Party-Integration":"blade"}},w=(e)=>S[e]||{};var z=new Set(["user-cancel","interrupt","sibling-error","timeout"]);function g(e){return typeof e==="string"&&z.has(e)}function J(e){if(!e.aborted)return;if(g(e.reason))return e.reason;return"user-cancel"}function Z(e){if(g(e))return!0;if(!(e instanceof Error))return!1;if(e.name==="AbortError")return!0;if(e instanceof DOMException&&e.name==="AbortError")return!0;if(e.message.includes("aborted"))return!0;return!1}function Q(...e){let t=e.filter(Boolean);if(t.length===0)return new AbortController().signal;if(t.length===1)return t[0];let o=AbortSignal;if(typeof o.any==="function")return o.any(t);for(let s of t)if(s.aborted)return s;let r=new AbortController,i=new Map;for(let s of t){let a=()=>{r.abort(s.reason);for(let[l,n]of i)l.removeEventListener("abort",n)};i.set(s,a)}for(let[s,a]of i)s.addEventListener("abort",a,{once:!0});return r.signal}function C(e,t,o){let r=o?.throwOnAbort??!1;if(t?.aborted){if(r)return Promise.reject(new DOMException("Aborted","AbortError"));return Promise.resolve()}return new Promise((i,s)=>{let a,l=setTimeout(()=>{if(t&&a)t.removeEventListener("abort",a);i()},e);if(t)a=()=>{if(clearTimeout(l),r)s(new DOMException("Aborted","AbortError"));else i()},t.addEventListener("abort",a,{once:!0})})}var D=f("Chat"),q={input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}};function k(e){if(typeof e==="string")return e;return e.filter((t)=>t.type==="text").map((t)=>t.text).join(`
2
2
  `)}function j(e){if(!e)return{};try{let t=JSON.parse(e);return t&&typeof t==="object"&&!Array.isArray(t)?t:{}}catch{return D.warn("[PiAIChatService] Invalid historical tool arguments",{value:e}),{}}}function B(e){let t=e.match(/^data:([^;,]+);base64,(.+)$/s);return t?{mimeType:t[1],data:t[2]}:void 0}async function F(e,t){let o=B(e);if(o)return{type:"image",...o};if(!/^https?:\/\//i.test(e))return{type:"text",text:`[Unsupported image source: ${e}]`};let r=await fetch(e,{signal:t});if(!r.ok)throw Error(`Failed to load image ${e}: HTTP ${r.status}`);return{type:"image",mimeType:r.headers.get("content-type")?.split(";")[0]??"image/png",data:Buffer.from(await r.arrayBuffer()).toString("base64")}}async function R(e,t,o,r,i){let s=e.filter((n)=>n.role==="system").map((n)=>k(n.content)).filter(Boolean).join(`
3
3
 
4
4
  `),a=[];for(let n of e){if(n.role==="system")continue;if(n.role==="user"){let p=typeof n.content==="string"?n.content:await Promise.all(n.content.map((c)=>c.type==="text"?Promise.resolve({type:"text",text:c.text}):F(c.image_url.url,r)));a.push({role:"user",content:p,timestamp:Date.now()});continue}if(n.role==="assistant"){let p=[];if(n.reasoningContent?.trim())p.push({type:"thinking",thinking:n.reasoningContent});let c=k(n.content);if(c)p.push({type:"text",text:c});for(let u of n.tool_calls??[]){if(!("function"in u))continue;p.push({type:"toolCall",id:u.id,name:u.function.name,arguments:j(u.function.arguments)})}a.push({role:"assistant",content:p,api:t.api,provider:t.provider,model:t.id,usage:q,stopReason:n.tool_calls?.length?"toolUse":"stop",timestamp:Date.now()});continue}a.push({role:"toolResult",toolCallId:n.tool_call_id??"",toolName:n.name??"unknown",content:[{type:"text",text:k(n.content)}],isError:!1,timestamp:Date.now()})}let l=o?.filter((n)=>!i||n.name===i).map((n)=>({name:n.name,description:n.description,parameters:n.parameters}));return{...s?{systemPrompt:s}:{},messages:a,...l?.length?{tools:l}:{}}}function P(e){let t=[];for(let o=0;o<e.length;o++){let r=e[o];if(r.role==="tool")continue;let i=r.role==="assistant"&&r.tool_calls?.length?r.tool_calls:void 0;if(!i){t.push(r);continue}let s=[],a=o+1;while(a<e.length&&e[a].role==="tool")s.push(e[a++]);let l=new Set(i.map((c)=>c.id)),n=s.filter((c)=>c.tool_call_id&&l.has(c.tool_call_id)),p=new Set(n.map((c)=>c.tool_call_id));if(l.size===i.length&&n.length===l.size&&p.size===l.size)t.push(r,...n);o=a-1}return t}function O(e){return e.some((t)=>t.role==="assistant"&&Boolean(t.tool_calls?.length)&&!t.reasoningContent?.trim())}function A(e,t){return{...e,...t.baseUrl?{baseUrl:t.baseUrl}:{},...t.maxOutputTokens?{maxTokens:t.maxOutputTokens}:{}}}function y(e){let t=x();return{models:t.models,model:A(t.getModel(e.provider,e.model),e)}}function I(e,t){let o=x();return A(o.getModel(t.provider,t.model),e)}function W(e){if(!e.reasoningEnabled)return;return e.reasoningLevel??"high"}function $(e,t,o,r){let i=r?void 0:W(o);if(!i){if(t.api==="anthropic-messages")e.thinkingEnabled=!1;return}switch(t.api){case"anthropic-messages":e.thinkingEnabled=!0,e.effort=i;break;case"google-generative-ai":case"google-vertex":e.thinking={enabled:!0};break;case"bedrock-converse-stream":case"pi-messages":e.reasoning=i;break;default:e.reasoningEffort=i}}function L(e,t,o){if(!o)return;switch(t){case"anthropic-messages":case"bedrock-converse-stream":e.toolChoice={type:"tool",name:o};break;case"openai-completions":case"mistral-conversations":case"pi-messages":e.toolChoice={type:"function",function:{name:o}};break;case"openai-responses":case"openai-codex-responses":case"azure-openai-responses":e.toolChoice={type:"function",name:o};break;case"google-generative-ai":case"google-vertex":e.toolChoice="any";break}}function _(e,t,o,r,i=!1){let s={apiKey:e.apiKey,headers:e.customHeaders,signal:o,temperature:e.temperature??0,maxTokens:e.maxOutputTokens,timeoutMs:e.timeout,maxRetries:0,cacheRetention:e.enablePromptCaching?"short":"none"};if($(s,t,e,i),L(s,t.api,r?.toolChoice?.toolName),t.api==="azure-openai-responses")s.azureBaseUrl=e.baseUrl,s.azureApiVersion=e.apiVersion,s.azureDeploymentName=t.id;return s}function v(e){return{promptTokens:e.input+e.cacheRead+e.cacheWrite,completionTokens:e.output,totalTokens:e.totalTokens,costUsd:e.cost.total,...e.reasoning!==void 0?{reasoningTokens:e.reasoning}:{},...e.cacheWrite>0?{cacheCreationInputTokens:e.cacheWrite}:{},...e.cacheRead>0?{cacheReadInputTokens:e.cacheRead}:{}}}function M(e){let t=e instanceof Error?e.message.toLowerCase():String(e).toLowerCase();if(["prompt_too_long","prompt is too long","maximum context length","context length exceeded","context_length_exceeded","request too large"].some((i)=>t.includes(i)))return!1;if(t.match(/\b(?:status(?:\s+code)?|http)[:\s]+(408|409|429|5\d\d)\b/))return!0;return["timeout","timed out","econnreset","econnrefused","enotfound","eai_again","etimedout","fetch failed","network error","socket hang up"].some((i)=>t.includes(i))}async function*E(e,t,o,r){let i=e.stream(t,o,r),s=0;for await(let a of i)switch(a.type){case"text_delta":yield{content:a.delta};break;case"thinking_delta":yield{reasoningContent:a.delta};break;case"toolcall_end":yield{toolCalls:[{index:s++,id:a.toolCall.id,type:"function",function:{name:a.toolCall.name,arguments:JSON.stringify(a.toolCall.arguments)}}]};break;case"done":yield{finishReason:a.reason,usage:v(a.message.usage)};break;case"error":throw Error(a.error.errorMessage??`Request ${a.reason==="aborted"?"aborted":"failed"}`)}}var N=f("Chat");class T{config;models;model;constructor(e){let t=y(e);this.config={...e,maxContextTokens:t.model.contextWindow,maxOutputTokens:e.maxOutputTokens??t.model.maxTokens},this.models=t.models,this.model=t.model,N.debug("[PiAIChatService] Initialized",{provider:this.model.provider,model:this.model.id,api:this.model.api})}async chat(e,t,o,r){let i="",s="",a=[],l,n;for await(let p of this.streamChat(e,t,o,r)){i+=p.content??"",s+=p.reasoningContent??"";for(let c of p.toolCalls??[])if(c.id&&c.type==="function"&&c.function?.name)a.push(c);l=p.usage??l,n=p.finishReason??n}return{content:i,...s?{reasoningContent:s}:{},...a.length>0?{toolCalls:a}:{},usage:l,finishReason:n}}async*streamChat(e,t,o,r){let i=r?.toolChoice?.toolName;if(i&&!t?.some((m)=>m.name===i))throw Error(`Required tool is unavailable: ${i}`);let s=P(e),a=Boolean(i)||O(s),l=await R(s,this.model,t,o,i),n=(m)=>E(this.models,m,l,_(this.config,m,o,r,a)),p=this.config.maxRetries??2,c,u=!1;for(let m=0;m<=p;m++)try{for await(let d of n(this.model))u=!0,yield d;return}catch(d){if(c=d,await this.handleAbort(o),u||!M(d))throw d;if(m<p)await C(1000*2**m,o,{throwOnAbort:!0})}for(let m of this.config.fallbackModels??[]){yield{modelFallback:!0};let d=!1;try{let h=I(this.config,m);for await(let U of n(h))d=!0,yield U;return}catch(h){if(c=h,await this.handleAbort(o),d||!M(h))throw h}}throw c}async handleAbort(e){if(e?.aborted)await C(0,e,{throwOnAbort:!0})}getConfig(){return{...this.config}}updateConfig(e){let t={...this.config,...e},o=y(t);this.config={...t,maxContextTokens:o.model.contextWindow,maxOutputTokens:t.maxOutputTokens??o.model.maxTokens},this.models=o.models,this.model=o.model}}var V=f("Service");async function xe(e){let t=e;if(t.provider){let o=w(t.provider);if(Object.keys(o).length>0)t={...t,customHeaders:{...o,...t.customHeaders}},V.debug(`Injected ${t.provider} specific headers:`,Object.keys(o))}return G(t)}function G(e){return new T(e)}
5
- export{J as Ob,Z as Pb,Q as Qb,xe as Rb};
5
+ export{J as Ib,Z as Jb,Q as Kb,xe as Lb};
@@ -0,0 +1,2 @@
1
+ import{vc as H}from"./chunk-2fbwmdvg.js";import{promises as X}from"node:fs";import*as O from"fs/promises";import*as K from"path";var D=[".git",".claude","node_modules",".env",".env.local",".env.production",".env.development",".env.test"];class N extends Error{code;constructor(q,G){super(q);this.code=G;this.name="PathSecurityError"}}class Z{static normalize(q,G){let B=K.isAbsolute(q)?q:K.resolve(G,q),J=K.normalize(B),M=K.normalize(G);if(!this.isWithinWorkspace(J,M))throw new N(`Path outside workspace: ${q} (resolved to ${J}, workspace: ${M})`,"PATH_OUTSIDE_WORKSPACE");return J}static checkRestricted(q){let G=q.split(K.sep);for(let B of D)if(G.includes(B))throw new N(`Access denied: "${B}" is a protected directory`,"RESTRICTED_PATH")}static checkTraversal(q){if(q.includes(".."))throw new N(`Path traversal not allowed: ${q}`,"PATH_TRAVERSAL")}static async validatePath(q,G){this.checkTraversal(q);let B=this.normalize(q,G);this.checkRestricted(B);try{await O.access(B)}catch(J){throw new N(`Path not found: ${q}`,"PATH_NOT_FOUND")}return B}static async resolveSymlink(q,G){try{let B=await O.realpath(q),J=await O.realpath(G);if(!this.isWithinWorkspace(B,J))throw new N(`Symlink points outside workspace: ${q} -> ${B}`,"SYMLINK_OUTSIDE_WORKSPACE");return B}catch(B){if(B instanceof N)throw B;return q}}static getRelativePath(q,G){return K.relative(G,q)}static isWithinWorkspace(q,G){let B=K.resolve(q),J=K.resolve(G),M=K.relative(J,B);return M===""||M!==".."&&!M.startsWith(`..${K.sep}`)&&!K.isAbsolute(M)}static async isWithinWorkspaceResolved(q,G){let B=K.resolve(G),J=K.isAbsolute(q)?K.resolve(q):K.resolve(B,q);if(!this.isWithinWorkspace(J,B))return!1;let M;try{M=await O.realpath(B)}catch{return!1}let V=J;while(!0){try{let Y=await O.realpath(V);return this.isWithinWorkspace(Y,M)}catch(Y){let x=Y.code;if(x!=="ENOENT"&&x!=="ENOTDIR")return!1}let $=K.dirname(V);if($===V)return!1;V=$}}static isRestricted(q){let G=q.split(K.sep);return D.some((B)=>G.includes(B))}}var U=H("Tool");class Q{static instance=null;accessedFiles=new Map;constructor(){}static getInstance(){if(!Q.instance)Q.instance=new Q;return Q.instance}async recordFileRead(q,G){try{let B=await X.stat(q),J={filePath:q,accessTime:Date.now(),mtime:B.mtimeMs,sessionId:G,lastOperation:"read"};this.setRecord(J),U.debug(`记录文件读取: ${q}`)}catch(B){U.warn(`记录文件读取失败: ${q}`,B)}}async recordFileEdit(q,G,B="edit"){try{let J=await X.stat(q),M={filePath:q,accessTime:Date.now(),mtime:J.mtimeMs,sessionId:G,lastOperation:B};this.setRecord(M),U.debug(`记录文件${B==="edit"?"编辑":"写入"}: ${q}`)}catch(J){U.warn(`记录文件${B==="edit"?"编辑":"写入"}失败: ${q}`,J)}}hasFileBeenRead(q,G){let B=this.accessedFiles.get(q);if(!B)return!1;return G?B.has(G):B.size>0}async checkFileModification(q,G){let B=this.getFileRecord(q,G);if(!B)return{modified:!1,message:"文件未被跟踪"};try{let J=await X.stat(q);if(Math.abs(J.mtimeMs-B.mtime)>1)return{modified:!0,message:`文件在访问后被修改(访问时间: ${new Date(B.accessTime).toISOString()}, 当前修改时间: ${J.mtime.toISOString()})`};return{modified:!1}}catch(J){let M=J;if(M.code==="ENOENT")return{modified:!0,message:"文件已被删除"};return{modified:!1,message:`无法检查文件状态: ${M.message}`}}}async checkExternalModification(q,G){let B=this.getFileRecord(q,G);if(!B)return{isExternal:!1,message:"文件未被跟踪"};try{let J=await X.stat(q);if(J.mtimeMs-B.mtime>2000)return{isExternal:!0,message:`文件在 ${new Date(B.accessTime).toISOString()} (${B.lastOperation}) 之后被外部程序修改(当前修改时间: ${J.mtime.toISOString()})`};return{isExternal:!1}}catch(J){let M=J;if(M.code==="ENOENT")return{isExternal:!0,message:"文件已被删除"};return U.warn(`检查文件外部修改失败: ${q}`,J),{isExternal:!1,message:`无法检查文件状态: ${M.message}`}}}getFileRecord(q,G){let B=this.accessedFiles.get(q);if(!B)return;if(G)return B.get(G);return[...B.values()].sort((J,M)=>M.accessTime-J.accessTime)[0]}getTrackedRecords(){return[...this.accessedFiles.values()].flatMap((q)=>[...q.values()])}clearFileRecord(q){this.accessedFiles.delete(q)}clearAll(){this.accessedFiles.clear()}clearSession(q,G){for(let[B,J]of this.accessedFiles.entries()){if(G&&!Z.isWithinWorkspace(B,G))continue;if(J.delete(q),J.size===0)this.accessedFiles.delete(B)}}getTrackedFiles(){return Array.from(this.accessedFiles.keys())}getTrackedFileCount(){return this.accessedFiles.size}static resetInstance(){Q.instance=null}setRecord(q){let G=this.accessedFiles.get(q.filePath);if(!G)G=new Map,this.accessedFiles.set(q.filePath,G);G.set(q.sessionId,q)}}
2
+ export{Z as lc,Q as mc};
@@ -0,0 +1,22 @@
1
+ import{Gb as j,Hb as y}from"./chunk-fpr6d8zc.js";import{Mb as x}from"./chunk-acegy4td.js";import{rc as V}from"./chunk-w3me85va.js";import{vc as O}from"./chunk-2fbwmdvg.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 Ga,A as Ha,F as Ia,E as Ja,M as Ka,L as La,w as Ma,U as Na,m as Oa,d as Pa};
@@ -0,0 +1,6 @@
1
+ import{l as A,m as E,n as N,o as f}from"./chunk-5jq01mg6.js";import{G as $,L as b}from"./chunk-bfgm5k3e.js";import{V as D}from"./chunk-rmfk5f9m.js";import{X as L,Y as _,Z as x}from"./chunk-mcnfbhpr.js";import{_ as B}from"./chunk-7pevqbfd.js";import"./chunk-z0qxaky4.js";import"./chunk-jyr9417h.js";import"./chunk-aq7wf2zt.js";import"./chunk-rrg9bw8r.js";import"./chunk-9ax02vtg.js";import"./chunk-8vemqfe4.js";import{bb as Z}from"./chunk-n9tgxfvw.js";import"./chunk-5nye3k5w.js";import"./chunk-wtxwny0p.js";import"./chunk-x548f12z.js";import"./chunk-1v2n922p.js";import{Eb as Y}from"./chunk-fpr6d8zc.js";import"./chunk-8vtznxpq.js";import"./chunk-acegy4td.js";import"./chunk-mpkr3s6b.js";import"./chunk-45bme7n9.js";import"./chunk-enk621t7.js";import"./chunk-936ft6kq.js";import{rc as T}from"./chunk-w3me85va.js";import"./chunk-2fbwmdvg.js";import"./chunk-gdm1xzvp.js";import"./chunk-ppyg431d.js";import h from"yargs";import{hideBin as R}from"yargs/helpers";var w=new Set(Object.values(Y));function X(k){if(k&&w.has(k))return k;return}function M(k){return k.command("* [message]","Print response and exit (useful for pipes)",(F)=>F.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(F)=>{if(!F.p)return;let q=await O(F);process.exit(q)})}async function O(k,F=process){let q;try{await A();let J=await E({message:k.message,_:k._,defaultMessage:"Hello"}),G=await N(J);if(G.mode==="output"){if(G.content)F.stdout.write(`${G.content}
2
+ `);return G.exitCode??0}let Q=G.content,{sessionId:K,messages:U}=await f({sessionId:k.sessionId,continue:k.continue,resume:k.resume,forkSession:k.forkSession,fallbackSessionPrefix:"print"});q=await $.create({sessionId:K,workspaceRoot:T(),modelId:k.model,mcpConfig:k.mcpConfig,strictMcpConfig:k.strictMcpConfig,agents:k.agents?B(k.agents):void 0});let V=await b.createWithRuntime(q,{sessionId:K,systemPrompt:k.systemPrompt,appendSystemPrompt:k.appendSystemPrompt,maxTurns:k.maxTurns,modelId:k.model,permissionMode:X(k.permissionMode),toolWhitelist:k.allowedTools,toolBlacklist:k.disallowedTools,mcpConfig:k.mcpConfig,strictMcpConfig:k.strictMcpConfig}),H=(await Z(V.chatStream(Q,{messages:[...U],userId:"cli-user",sessionId:K,workspaceRoot:T(),permissionMode:X(k.permissionMode)}))).finalMessage||"";if(k.outputFormat==="json")F.stdout.write(`${JSON.stringify({response:H,input:Q,model:k.model,timestamp:new Date().toISOString()},null,2)}
3
+ `);else if(k.outputFormat==="stream-json")F.stdout.write(`${JSON.stringify({type:"response",content:H})}
4
+ `);else F.stdout.write(`${H}
5
+ `);return 0}catch(J){return F.stderr.write(`Error: ${J instanceof Error?J.message:"未知错误"}
6
+ `),1}finally{await q?.dispose()}}async function d(){if(process.argv.slice(2).findIndex((q)=>q==="--print"||q==="-p")===-1)return!1;try{let{print:q,"output-format":J,"include-partial-messages":G,"input-format":Q,"system-prompt":K,"append-system-prompt":U,"max-turns":V,...W}=D,H=h(R(process.argv)).scriptName("blade").strict(!1).options(W).middleware([_,L,x]);return M(H),await H.parse(),!0}catch(q){console.error(`Print mode error: ${q instanceof Error?q.message:"未知错误"}`),process.exit(1)}}export{O as runPrint,d as handlePrintMode};
@@ -0,0 +1,3 @@
1
+ import{Fc as N}from"./chunk-gdm1xzvp.js";import{createModels as W}from"@earendil-works/pi-ai";import{builtinProviders as X}from"@earendil-works/pi-ai/providers/all";import{promises as E}from"node:fs";import L from"node:path";import{Mutex as T}from"async-mutex";import V from"write-file-atomic";class H{filePath;mutex=new T;constructor(q=L.join(N(),"auth.json")){this.filePath=q}async read(q){return(await this.readAll())[q]}async list(){let q=await this.readAll();return Object.entries(q).map(([z,D])=>({providerId:z,type:D.type}))}async modify(q,z){return this.mutex.runExclusive(async()=>{let D=await this.readAll(),J=D[q],G=await z(J);if(G===void 0)return J;return D[q]=G,await this.writeAll(D),G})}async delete(q){await this.mutex.runExclusive(async()=>{let z=await this.readAll();if(!(q in z))return;delete z[q],await this.writeAll(z)})}async readAll(){try{let q=await E.readFile(this.filePath,"utf8"),z=JSON.parse(q);return z&&typeof z==="object"&&!Array.isArray(z)?z:{}}catch(q){if(q.code==="ENOENT")return{};throw q}}async writeAll(q){let z=L.dirname(this.filePath);await E.mkdir(z,{recursive:!0,mode:448}),await E.chmod(z,448),await V(this.filePath,`${JSON.stringify(q,null,2)}
2
+ `,{mode:384}),await E.chmod(this.filePath,384)}}class Q{credentials;models;constructor(q=new H){this.credentials=q,this.models=W({credentials:q});for(let z of X())this.models.setProvider(z)}async listProviders(){return Promise.all(this.models.getProviders().map(async(q)=>{let z=q.getModels();return{id:q.id,name:q.name,modelCount:z.length,defaultBaseUrl:q.baseUrl??z[0]?.baseUrl,supportsApiKey:Boolean(q.auth.apiKey),supportsOAuth:Boolean(q.auth.oauth),configured:Boolean(await this.models.checkAuth(q.id))}}))}listModels(q){return this.models.getModels(q).map((z)=>this.toCatalogEntry(z))}getModel(q,z){let D=this.models.getModel(q,z);if(!D)throw Error(`Unknown pi-ai model: ${q}/${z}`);return D}resolveConfig(q){let z=this.getModel(q.provider,q.model),D=q.overrides;return{...z,...D?.baseUrl?{baseUrl:D.baseUrl}:{},...D?.maxOutputTokens?{maxTokens:D.maxOutputTokens}:{}}}async setApiKey(q,z){this.requireProvider(q),await this.credentials.modify(q,async()=>({type:"api_key",key:z}))}async clearCredential(q){this.requireProvider(q),await this.credentials.delete(q)}async isConfigured(q){return this.requireProvider(q),Boolean(await this.models.checkAuth(q))}requireProvider(q){if(!this.models.getProvider(q))throw Error(`Unknown pi-ai provider: ${q}`)}toCatalogEntry(q){return{id:q.id,name:q.name,provider:q.provider,api:q.api,baseUrl:q.baseUrl,reasoning:q.reasoning,input:[...q.input],contextWindow:q.contextWindow,maxTokens:q.maxTokens,cost:{...q.cost}}}}var O;function U(){return O??=new Q,O}
3
+ export{U as Mb};
@@ -0,0 +1 @@
1
+ import{dc as a,ec as b,fc as c,gc as d,hc as e,ic as f,jc as g,kc as h}from"./chunk-enk621t7.js";import"./chunk-2fbwmdvg.js";import"./chunk-gdm1xzvp.js";import"./chunk-ppyg431d.js";export{d as syncSession,e as syncAll,h as searchProjectionText,c as resetProjectionDbCache,f as removeSessionFromProjection,g as rebuildProjectionIndex,b as getProjectionDb,a as getIndexDbPath};