blade-code 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/blade.js +4 -3084
- package/dist/chunk-1en8fh5f.js +6 -0
- package/dist/chunk-2tpgtpcp.js +49 -0
- package/dist/chunk-3wnjpk9b.js +1 -0
- package/dist/chunk-3xqfqpa7.js +2 -0
- package/dist/chunk-4nsh53k6.js +4 -0
- package/dist/chunk-52k9k0w8.js +1 -0
- package/dist/chunk-5mtjqqav.js +8 -0
- package/dist/chunk-7ycmx7c2.js +2 -0
- package/dist/chunk-93b0x9b4.js +157 -0
- package/dist/chunk-akr185xe.js +2 -0
- package/dist/chunk-bhjw4b73.js +1 -0
- package/dist/chunk-d7zcd9xp.js +1 -0
- package/dist/chunk-dq65yfh6.js +1 -0
- package/dist/chunk-e2vtbvda.js +24 -0
- package/dist/chunk-ena4sxgr.js +41 -0
- package/dist/chunk-esnkk33h.js +21 -0
- package/dist/chunk-g5pasj7t.js +1 -0
- package/dist/chunk-j25kww7j.js +582 -0
- package/dist/chunk-j2ag7hh6.js +2 -0
- package/dist/chunk-j79jvd54.js +2063 -0
- package/dist/chunk-m99qhdkf.js +76 -0
- package/dist/chunk-n6e89s1v.js +6 -0
- package/dist/chunk-nx2zqct5.js +6 -0
- package/dist/chunk-q52j8tp4.js +1 -0
- package/dist/chunk-qwfywxs2.js +2 -0
- package/dist/chunk-set7v1rf.js +3 -0
- package/dist/chunk-t3zaj1t7.js +4 -0
- package/dist/chunk-th432d0b.js +1 -0
- package/dist/chunk-tmjmp9gq.js +1 -0
- package/dist/chunk-vd38synx.js +1 -0
- package/dist/chunk-vfdhz37s.js +3 -0
- package/dist/chunk-vwn39c84.js +2 -0
- package/dist/chunk-w7h3v075.js +10 -0
- package/dist/chunk-wr7w4af5.js +2 -0
- package/dist/chunk-wxp0yadf.js +1 -0
- package/dist/chunk-yddnm9n2.js +1 -0
- package/dist/chunk-z6tkw0b6.js +13 -0
- package/dist/chunk-zxf08z5f.js +34 -0
- package/dist/chunk-zyc1whnr.js +6 -0
- package/dist/web/assets/CodeBlockHighlighter-C86flFwh.js +1 -0
- package/dist/web/assets/FilePreview-BLcxez_T.js +7 -0
- package/dist/web/assets/MarkdownRenderer-BkQt-J8a.js +1 -0
- package/dist/web/assets/McpModal-B4ReoSE5.js +5 -0
- package/dist/web/assets/SettingsModal-QzwdsQwR.js +1 -0
- package/dist/web/assets/SettingsStore-E-aIqvyl.js +1 -0
- package/dist/web/assets/SkillsModal-CzE0m00G.js +1 -0
- package/dist/web/assets/TerminalPanel-DXA1C6Cg.js +1 -0
- package/dist/web/assets/dialog-CSpPttY0.js +1 -0
- package/dist/web/assets/index-DehGtSvJ.js +10 -0
- package/dist/web/assets/index-DmXmCQOW.css +1 -0
- package/dist/web/assets/useRequest-P_-JRihD.js +1 -0
- package/dist/web/assets/vendor-icons-DlzC8I7m.js +166 -0
- package/dist/web/assets/vendor-markdown-DIcugY1e.js +36 -0
- package/dist/web/assets/vendor-monaco-w6PwaWGP.js +11 -0
- package/dist/web/assets/vendor-radix-CKNFO4jS.js +45 -0
- package/dist/web/assets/vendor-react-Dm1xU4bP.js +49 -0
- package/dist/web/assets/vendor-xterm-9CEnUXvW.css +32 -0
- package/dist/web/assets/vendor-xterm-DuYZoU4T.js +49 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/web/assets/index-CVfbjhXj.js +0 -11
- package/dist/web/assets/index-C_uNajWk.js +0 -360
- package/dist/web/assets/index-QhJxewcm.css +0 -32
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import{Ia as KQ,Ka as A}from"./chunk-e2vtbvda.js";import{Bb as FQ}from"./chunk-set7v1rf.js";import{nanoid as rQ}from"nanoid";import{devtools as lQ,subscribeWithSelector as cQ}from"zustand/middleware";import{createStore as iQ}from"zustand/vanilla";var OQ={name:"ayu-dark",colors:{primary:"#ffcc66",secondary:"#bae67e",accent:"#73d0ff",success:"#bae67e",warning:"#ffcc66",error:"#ff3333",info:"#73d0ff",light:"#f0f0f0",dark:"#000000",muted:"#5c6773",highlight:"#2d323b",text:{primary:"#e6e1cf",secondary:"#bae67e",muted:"#5c6773",light:"#ffffff"},background:{primary:"#0f1419",secondary:"#14191f",dark:"#000000"},border:{light:"#2d323b",dark:"#000000"},syntax:{comment:"#5c6773",string:"#bae67e",number:"#ffcc66",keyword:"#ff8f40",function:"#73d0ff",variable:"#e6e1cf",operator:"#f29e74",type:"#73d0ff",tag:"#ff8f40",attr:"#ffd580",default:"#e6e1cf"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(0, 0, 0, 0.2)",base:"0 1px 3px 0 rgba(0, 0, 0, 0.3), 0 1px 2px 0 rgba(0, 0, 0, 0.2)",lg:"0 10px 15px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -2px rgba(0, 0, 0, 0.2)"}},xQ={name:"dracula",colors:{primary:"#bd93f9",secondary:"#ffb86c",accent:"#ff79c6",success:"#50fa7b",warning:"#f1fa8c",error:"#ff5555",info:"#8be9fd",light:"#f8f8f2",dark:"#282a36",muted:"#6272a4",highlight:"#44475a",text:{primary:"#f8f8f2",secondary:"#f1fa8c",muted:"#6272a4",light:"#ffffff"},background:{primary:"#282a36",secondary:"#44475a",dark:"#21222c"},border:{light:"#44475a",dark:"#000000"},syntax:{comment:"#6272a4",string:"#f1fa8c",number:"#bd93f9",keyword:"#ff79c6",function:"#50fa7b",variable:"#f8f8f2",operator:"#ff79c6",type:"#8be9fd",tag:"#ff79c6",attr:"#50fa7b",default:"#f8f8f2"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(40, 42, 54, 0.2)",base:"0 1px 3px 0 rgba(40, 42, 54, 0.3), 0 1px 2px 0 rgba(40, 42, 54, 0.2)",lg:"0 10px 15px -3px rgba(40, 42, 54, 0.3), 0 4px 6px -2px rgba(40, 42, 54, 0.2)"}},BQ={name:"monokai",colors:{primary:"#66d9ef",secondary:"#a6e22e",accent:"#f92672",success:"#a6e22e",warning:"#e6db74",error:"#f92672",info:"#66d9ef",light:"#f8f8f2",dark:"#272822",muted:"#75715e",highlight:"#3e3d32",text:{primary:"#f8f8f2",secondary:"#e6db74",muted:"#75715e",light:"#ffffff"},background:{primary:"#272822",secondary:"#3e3d32",dark:"#1e1f1c"},border:{light:"#3e3d32",dark:"#000000"},syntax:{comment:"#75715e",string:"#e6db74",number:"#ae81ff",keyword:"#f92672",function:"#a6e22e",variable:"#f8f8f2",operator:"#f92672",type:"#66d9ef",tag:"#f92672",attr:"#a6e22e",default:"#f8f8f2"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(39, 40, 34, 0.2)",base:"0 1px 3px 0 rgba(39, 40, 34, 0.3), 0 1px 2px 0 rgba(39, 40, 34, 0.2)",lg:"0 10px 15px -3px rgba(39, 40, 34, 0.3), 0 4px 6px -2px rgba(39, 40, 34, 0.2)"}},wQ={name:"nord",colors:{primary:"#88c0d0",secondary:"#81a1c1",accent:"#b48ead",success:"#a3be8c",warning:"#ebcb8b",error:"#bf616a",info:"#88c0d0",light:"#eceff4",dark:"#2e3440",muted:"#4c566a",highlight:"#434c5e",text:{primary:"#eceff4",secondary:"#d8dee9",muted:"#4c566a",light:"#ffffff"},background:{primary:"#2e3440",secondary:"#3b4252",dark:"#242933"},border:{light:"#434c5e",dark:"#000000"},syntax:{comment:"#616e88",string:"#a3be8c",number:"#b48ead",keyword:"#81a1c1",function:"#88c0d0",variable:"#d8dee9",operator:"#81a1c1",type:"#8fbcbb",tag:"#81a1c1",attr:"#8fbcbb",default:"#eceff4"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(46, 52, 64, 0.2)",base:"0 1px 3px 0 rgba(46, 52, 64, 0.3), 0 1px 2px 0 rgba(46, 52, 64, 0.2)",lg:"0 10px 15px -3px rgba(46, 52, 64, 0.3), 0 4px 6px -2px rgba(46, 52, 64, 0.2)"}},_Q={name:"solarized-light",colors:{primary:"#268bd2",secondary:"#2aa198",accent:"#d33682",success:"#859900",warning:"#cb4b16",error:"#dc322f",info:"#268bd2",light:"#fdf6e3",dark:"#073642",muted:"#93a1a1",highlight:"#eee8d5",text:{primary:"#586e75",secondary:"#657b83",muted:"#93a1a1",light:"#002b36"},background:{primary:"#fdf6e3",secondary:"#eee8d5",dark:"#073642"},border:{light:"#eee8d5",dark:"#073642"},syntax:{comment:"#93a1a1",string:"#2aa198",number:"#d33682",keyword:"#859900",function:"#268bd2",variable:"#657b83",operator:"#859900",type:"#b58900",tag:"#268bd2",attr:"#93a1a1",default:"#657b83"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(253, 246, 227, 0.2)",base:"0 1px 3px 0 rgba(253, 246, 227, 0.3), 0 1px 2px 0 rgba(253, 246, 227, 0.2)",lg:"0 10px 15px -3px rgba(253, 246, 227, 0.3), 0 4px 6px -2px rgba(253, 246, 227, 0.2)"}},AQ={name:"solarized-dark",colors:{primary:"#268bd2",secondary:"#2aa198",accent:"#d33682",success:"#859900",warning:"#b58900",error:"#dc322f",info:"#268bd2",light:"#fdf6e3",dark:"#073642",muted:"#586e75",highlight:"#073642",text:{primary:"#839496",secondary:"#93a1a1",muted:"#586e75",light:"#fdf6e3"},background:{primary:"#002b36",secondary:"#073642",dark:"#001f29"},border:{light:"#073642",dark:"#000000"},syntax:{comment:"#586e75",string:"#2aa198",number:"#d33682",keyword:"#859900",function:"#268bd2",variable:"#839496",operator:"#859900",type:"#b58900",tag:"#268bd2",attr:"#93a1a1",default:"#839496"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(0, 43, 54, 0.2)",base:"0 1px 3px 0 rgba(0, 43, 54, 0.3), 0 1px 2px 0 rgba(0, 43, 54, 0.2)",lg:"0 10px 15px -3px rgba(0, 43, 54, 0.3), 0 4px 6px -2px rgba(0, 43, 54, 0.2)"}},DQ={name:"tokyo-night",colors:{primary:"#7aa2f7",secondary:"#7dcfff",accent:"#bb9af7",success:"#9ece6a",warning:"#e0af68",error:"#f7768e",info:"#7aa2f7",light:"#c0caf5",dark:"#1a1b26",muted:"#565f89",highlight:"#292e42",text:{primary:"#a9b1d6",secondary:"#c0caf5",muted:"#565f89",light:"#ffffff"},background:{primary:"#1a1b26",secondary:"#292e42",dark:"#16161e"},border:{light:"#292e42",dark:"#000000"},syntax:{comment:"#565f89",string:"#9ece6a",number:"#ff9e64",keyword:"#bb9af7",function:"#7aa2f7",variable:"#c0caf5",operator:"#89ddff",type:"#7dcfff",tag:"#f7768e",attr:"#7aa2f7",default:"#a9b1d6"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(26, 27, 38, 0.2)",base:"0 1px 3px 0 rgba(26, 27, 38, 0.3), 0 1px 2px 0 rgba(26, 27, 38, 0.2)",lg:"0 10px 15px -3px rgba(26, 27, 38, 0.3), 0 4px 6px -2px rgba(26, 27, 38, 0.2)"}},LQ={name:"github",colors:{primary:"#0969da",secondary:"#8250df",accent:"#bc4c00",success:"#1a7f37",warning:"#bc4c00",error:"#d1242f",info:"#0969da",light:"#f6f8fa",dark:"#24292f",muted:"#6e7781",highlight:"#ddf4ff",text:{primary:"#24292f",secondary:"#57606a",muted:"#6e7781",light:"#ffffff"},background:{primary:"#ffffff",secondary:"#f6f8fa",dark:"#24292f"},border:{light:"#d0d7de",dark:"#24292f"},syntax:{comment:"#6e7781",string:"#0a3069",number:"#0550ae",keyword:"#cf222e",function:"#8250df",variable:"#24292f",operator:"#cf222e",type:"#0550ae",tag:"#116329",attr:"#0550ae",default:"#24292f"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(255, 255, 255, 0.2)",base:"0 1px 3px 0 rgba(255, 255, 255, 0.3), 0 1px 2px 0 rgba(255, 255, 255, 0.2)",lg:"0 10px 15px -3px rgba(255, 255, 255, 0.3), 0 4px 6px -2px rgba(255, 255, 255, 0.2)"}},vQ={name:"gruvbox",colors:{primary:"#83a598",secondary:"#8ec07c",accent:"#d3869b",success:"#b8bb26",warning:"#fabd2f",error:"#fb4934",info:"#83a598",light:"#fbf1c7",dark:"#282828",muted:"#928374",highlight:"#3c3836",text:{primary:"#ebdbb2",secondary:"#d5c4a1",muted:"#928374",light:"#ffffff"},background:{primary:"#282828",secondary:"#3c3836",dark:"#1d2021"},border:{light:"#3c3836",dark:"#000000"},syntax:{comment:"#928374",string:"#b8bb26",number:"#d3869b",keyword:"#fb4934",function:"#8ec07c",variable:"#ebdbb2",operator:"#fe8019",type:"#fabd2f",tag:"#fb4934",attr:"#b8bb26",default:"#ebdbb2"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(40, 40, 40, 0.2)",base:"0 1px 3px 0 rgba(40, 40, 40, 0.3), 0 1px 2px 0 rgba(40, 40, 40, 0.2)",lg:"0 10px 15px -3px rgba(40, 40, 40, 0.3), 0 4px 6px -2px rgba(40, 40, 40, 0.2)"}},EQ={name:"one-dark",colors:{primary:"#61afef",secondary:"#c678dd",accent:"#e5c07b",success:"#98c379",warning:"#e5c07b",error:"#e06c75",info:"#56b6c2",light:"#abb2bf",dark:"#282c34",muted:"#5c6370",highlight:"#3e4451",text:{primary:"#abb2bf",secondary:"#c6c8d0",muted:"#5c6370",light:"#ffffff"},background:{primary:"#282c34",secondary:"#3e4451",dark:"#21252b"},border:{light:"#3e4451",dark:"#000000"},syntax:{comment:"#5c6370",string:"#98c379",number:"#d19a66",keyword:"#c678dd",function:"#61afef",variable:"#e06c75",operator:"#56b6c2",type:"#e5c07b",tag:"#e06c75",attr:"#d19a66",default:"#abb2bf"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(40, 44, 52, 0.2)",base:"0 1px 3px 0 rgba(40, 44, 52, 0.3), 0 1px 2px 0 rgba(40, 44, 52, 0.2)",lg:"0 10px 15px -3px rgba(40, 44, 52, 0.3), 0 4px 6px -2px rgba(40, 44, 52, 0.2)"}},yQ={name:"catppuccin",colors:{primary:"#89b4fa",secondary:"#cba6f7",accent:"#f5c2e7",success:"#a6e3a1",warning:"#f9e2af",error:"#f38ba8",info:"#89dceb",light:"#cdd6f4",dark:"#11111b",muted:"#6c7086",highlight:"#181825",text:{primary:"#cdd6f4",secondary:"#bac2de",muted:"#6c7086",light:"#ffffff"},background:{primary:"#1e1e2e",secondary:"#181825",dark:"#11111b"},border:{light:"#181825",dark:"#000000"},syntax:{comment:"#6c7086",string:"#a6e3a1",number:"#fab387",keyword:"#cba6f7",function:"#89b4fa",variable:"#cdd6f4",operator:"#89dceb",type:"#f5c2e7",tag:"#f38ba8",attr:"#89b4fa",default:"#cdd6f4"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(30, 30, 46, 0.2)",base:"0 1px 3px 0 rgba(30, 30, 46, 0.3), 0 1px 2px 0 rgba(30, 30, 46, 0.2)",lg:"0 10px 15px -3px rgba(30, 30, 46, 0.3), 0 4px 6px -2px rgba(30, 30, 46, 0.2)"}},CQ={name:"rose-pine",colors:{primary:"#9ccfd8",secondary:"#c4a7e7",accent:"#f6c177",success:"#31748f",warning:"#f6c177",error:"#eb6f92",info:"#9ccfd8",light:"#e0def4",dark:"#191724",muted:"#6e6a86",highlight:"#1f1d2e",text:{primary:"#e0def4",secondary:"#cecacd",muted:"#6e6a86",light:"#ffffff"},background:{primary:"#191724",secondary:"#1f1d2e",dark:"#12101a"},border:{light:"#1f1d2e",dark:"#000000"},syntax:{comment:"#6e6a86",string:"#9ccfd8",number:"#ea9a97",keyword:"#c4a7e7",function:"#31748f",variable:"#e0def4",operator:"#f6c177",type:"#9ccfd8",tag:"#eb6f92",attr:"#f6c177",default:"#e0def4"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(25, 23, 36, 0.2)",base:"0 1px 3px 0 rgba(25, 23, 36, 0.3), 0 1px 2px 0 rgba(25, 23, 36, 0.2)",lg:"0 10px 15px -3px rgba(25, 23, 36, 0.3), 0 4px 6px -2px rgba(25, 23, 36, 0.2)"}},PQ={name:"kanagawa",colors:{primary:"#8ba4b0",secondary:"#a292a3",accent:"#c47fd5",success:"#76946a",warning:"#c0a36e",error:"#c34043",info:"#7e9cd8",light:"#dcd7ba",dark:"#1f1f28",muted:"#727169",highlight:"#2a2a37",text:{primary:"#dcd7ba",secondary:"#c8c093",muted:"#727169",light:"#ffffff"},background:{primary:"#1f1f28",secondary:"#2a2a37",dark:"#16161d"},border:{light:"#2a2a37",dark:"#000000"},syntax:{comment:"#727169",string:"#98bb6c",number:"#d27e99",keyword:"#957fb8",function:"#7e9cd8",variable:"#dcd7ba",operator:"#c0a36e",type:"#7aa89f",tag:"#c34043",attr:"#7fb4ca",default:"#dcd7ba"}},spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(31, 31, 40, 0.2)",base:"0 1px 3px 0 rgba(31, 31, 40, 0.3), 0 1px 2px 0 rgba(31, 31, 40, 0.2)",lg:"0 10px 15px -3px rgba(31, 31, 40, 0.3), 0 4px 6px -2px rgba(31, 31, 40, 0.2)"}},a=[{id:"ayu-dark",label:"Ayu Dark",theme:OQ,tags:["dark","popular"]},{id:"dracula",label:"Dracula",theme:xQ,tags:["dark","popular"]},{id:"monokai",label:"Monokai",theme:BQ,tags:["dark","classic"]},{id:"nord",label:"Nord",theme:wQ,tags:["dark","minimal"]},{id:"solarized-light",label:"Solarized Light",theme:_Q,tags:["light"]},{id:"solarized-dark",label:"Solarized Dark",theme:AQ,tags:["dark"]},{id:"tokyo-night",label:"Tokyo Night",theme:DQ,tags:["dark","popular"]},{id:"github",label:"GitHub",theme:LQ,tags:["light","minimal"]},{id:"gruvbox",label:"Gruvbox",theme:vQ,tags:["dark","warm"]},{id:"one-dark",label:"One Dark",theme:EQ,tags:["dark","popular"]},{id:"catppuccin",label:"Catppuccin",theme:yQ,tags:["dark","pastel"]},{id:"rose-pine",label:"Rose Pine",theme:CQ,tags:["dark","elegant"]},{id:"kanagawa",label:"Kanagawa",theme:PQ,tags:["dark","japanese"]}];var t={primary:"#0066cc",secondary:"#6c757d",accent:"#e83e8c",success:"#28a745",warning:"#ffc107",error:"#dc3545",info:"#17a2b8",light:"#f8f9fa",dark:"#343a40",muted:"#6c757d",highlight:"#fff3cd",text:{primary:"#212529",secondary:"#6c757d",muted:"#6c757d",light:"#ffffff"},background:{primary:"#ffffff",secondary:"#f8f9fa",dark:"#343a40"},border:{light:"#dee2e6",dark:"#495057"},syntax:{comment:"#6c757d",string:"#28a745",number:"#e83e8c",keyword:"#007bff",function:"#17a2b8",variable:"#495057",operator:"#ffc107",type:"#007bff",tag:"#dc3545",attr:"#ffc107",default:"#212529"}},p={name:"default",colors:t,spacing:{xs:0.25,sm:0.5,md:1,lg:1.5,xl:2},typography:{fontSize:{xs:0.75,sm:0.875,base:1,lg:1.125,xl:1.25,"2xl":1.5,"3xl":1.875},fontWeight:{light:300,normal:400,medium:500,semibold:600,bold:700}},borderRadius:{sm:0.125,base:0.25,lg:0.5,xl:0.75},boxShadow:{sm:"0 1px 2px 0 rgba(0, 0, 0, 0.05)",base:"0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)",lg:"0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)"}},RQ={...p,name:"dark",colors:{...t,text:{primary:"#ffffff",secondary:"#e2e8f0",muted:"#94a3b8",light:"#000000"},background:{primary:"#1e293b",secondary:"#334155",dark:"#0f172a"},border:{light:"#475569",dark:"#64748b"},syntax:{comment:"#94a3b8",string:"#34d399",number:"#f472b6",keyword:"#60a5fa",function:"#06b6d4",variable:"#e2e8f0",operator:"#fbbf24",type:"#60a5fa",tag:"#fb7185",attr:"#fbbf24",default:"#ffffff"}}};class e{currentTheme=p;themes=new Map;constructor(){this.themes.set("default",p),this.themes.set("dark",RQ);for(let Q of a)this.themes.set(Q.id,Q.theme)}setTheme(Q){let Z=this.themes.get(Q);if(Z)this.currentTheme=Z;else throw Error(`Theme '${Q}' not found`)}getTheme(){return this.currentTheme}getAvailableThemes(){return Array.from(this.themes.keys())}getCurrentThemeName(){return this.currentTheme.name}getThemeByName(Q){return this.themes.get(Q)}hasTheme(Q){return this.themes.has(Q)}}var QQ=new e;var IQ={initializationStatus:"idle",initializationError:null,activeModal:"none",sessionSelectorData:void 0,modelEditorTarget:null,tasks:[],awaitingSecondCtrlC:!1,thinkingModeEnabled:!1,subagentProgress:null},g=(Q)=>({...IQ,actions:{setInitializationStatus:(Z)=>{Q((X)=>({app:{...X.app,initializationStatus:Z}}))},setInitializationError:(Z)=>{Q((X)=>({app:{...X.app,initializationError:Z}}))},setActiveModal:(Z)=>{Q((X)=>({app:{...X.app,activeModal:Z}}))},showSessionSelector:(Z)=>{Q((X)=>({app:{...X.app,activeModal:"sessionSelector",sessionSelectorData:Z}}))},showModelEditWizard:(Z)=>{Q((X)=>({app:{...X.app,activeModal:"modelEditWizard",modelEditorTarget:Z}}))},closeModal:()=>{Q((Z)=>({app:{...Z.app,activeModal:"none",sessionSelectorData:void 0,modelEditorTarget:null}}))},setTasks:(Z)=>{Q((X)=>({app:{...X.app,tasks:Z}}))},updateTask:(Z)=>{Q((X)=>({app:{...X.app,tasks:X.app.tasks.map(($)=>$.id===Z.id?Z:$)}}))},setAwaitingSecondCtrlC:(Z)=>{Q((X)=>({app:{...X.app,awaitingSecondCtrlC:Z}}))},setThinkingModeEnabled:(Z)=>{Q((X)=>({app:{...X.app,thinkingModeEnabled:Z}}))},toggleThinkingMode:()=>{Q((Z)=>({app:{...Z.app,thinkingModeEnabled:!Z.app.thinkingModeEnabled}}))},startSubagentProgress:(Z,X,$)=>{Q((Y)=>({app:{...Y.app,subagentProgress:{id:Z,type:X,description:$,status:"running",startTime:Date.now()}}}))},updateSubagentTool:(Z)=>{Q((X)=>{if(!X.app.subagentProgress)return X;return{app:{...X.app,subagentProgress:{...X.app.subagentProgress,currentTool:Z}}}})},completeSubagentProgress:(Z)=>{Q((X)=>{if(!X.app.subagentProgress)return X;return{app:{...X.app,subagentProgress:{...X.app.subagentProgress,status:Z?"completed":"failed",currentTool:void 0}}}}),setTimeout(()=>{Q((X)=>({app:{...X.app,subagentProgress:null}}))},1500)}}});var TQ={isProcessing:!1,abortController:null,pendingCommands:[]},d=(Q,Z)=>({...TQ,actions:{setProcessing:(X)=>{Q(($)=>({command:{...$.command,isProcessing:X}}))},createAbortController:()=>{let X=Z().command.abortController;if(X&&!X.signal.aborted)X.abort("interrupted-by-new-command");let $=new AbortController;return Q((Y)=>({command:{...Y.command,abortController:$}})),$},getAbortController:()=>{return Z().command.abortController},clearAbortController:(X)=>{let $=Z().command.abortController;if(X!==void 0&&$!==X)return;Q((Y)=>({command:{...Y.command,abortController:null}}))},abort:(X)=>{let{abortController:$}=Z().command;if($&&!$.signal.aborted)$.abort(X??"user-cancel");Q((Y)=>({command:{...Y.command,isProcessing:!1,pendingCommands:[]}}))},enqueueCommand:(X)=>{Q(($)=>({command:{...$.command,pendingCommands:[...$.command.pendingCommands,X]}}))},dequeueCommand:()=>{let{pendingCommands:X}=Z().command;if(X.length===0)return;let[$,...Y]=X;return Q((V)=>({command:{...V.command,pendingCommands:Y}})),$},clearQueue:()=>{Q((X)=>({command:{...X.command,pendingCommands:[]}}))}}});var MQ={config:null},m=(Q)=>({...MQ,actions:{setConfig:(Z)=>{Q((X)=>({config:{...X.config,config:Z}}))},updateConfig:(Z)=>{Q((X)=>{if(!X.config.config)throw Error(`[ConfigSlice] Config not initialized. Cannot update: ${JSON.stringify(Z)}`);return{config:{...X.config,config:{...X.config.config,...Z}}}})}}});var bQ={currentFocus:"main-input",previousFocus:null},r=(Q)=>({...bQ,actions:{setFocus:(Z)=>{Q((X)=>({focus:{...X.focus,currentFocus:Z,previousFocus:X.focus.currentFocus}}))},restorePreviousFocus:()=>{Q((Z)=>({focus:{...Z.focus,currentFocus:Z.focus.previousFocus||"main-input",previousFocus:null}}))}}});import{nanoid as fQ}from"nanoid";var W={codeBlock:/^```(\w+)?\s*$/,heading:/^ *(#{1,4}) +(.+)/,blockquote:/^(>+)\s?(.*)/,ulItem:/^([ \t]*)([-*+]) +(.+)/,olItem:/^([ \t]*)(\d+)\. +(.+)/,hr:/^ *([-*_] *){3,} *$/,table:/^\|(.+)\|$/,tableSeparator:/^\|[\s]*:?-+:?[\s]*(\|[\s]*:?-+:?[\s]*)+\|?$/,diffStart:/^<<<DIFF>>>$/,diffEnd:/^<<<\/DIFF>>>$/,commandMessage:/<command-message>(.*?)<\/command-message>/};function $X(Q){let Z=[],X=Q.split(/\r?\n/),$=!1,Y=[],V=null,J=0,U=!1,G=[],z=[],K=!1,E=[],y=!1,B=[],H=0,j=!0;for(let D=0;D<X.length;D++){let O=X[D];if(K){if(O.match(W.diffEnd)){try{let w=JSON.parse(E.join(`
|
|
2
|
+
`));Z.push({type:"diff",content:"",diffData:{patch:w.patch,startLine:w.startLine,matchLine:w.matchLine}})}catch(w){Z.push({type:"text",content:E.join(`
|
|
3
|
+
`)})}K=!1,E=[],j=!1;continue}E.push(O);continue}if(O.match(W.diffStart)){K=!0,E=[],j=!1;continue}if($){let w=O.match(W.codeBlock),L=O.trim()==="```";if(w&&w[1])J++,Y.push(O);else if(L)if(J>0)J--,Y.push(O);else{let qQ=Y.join(`
|
|
4
|
+
`);Z.push({type:"code",content:qQ,language:V||void 0}),$=!1,Y=[],V=null,J=0,j=!1}else Y.push(O);continue}let n=O.match(W.codeBlock);if(n){$=!0,V=n[1]||null,J=0,j=!1;continue}let T=O.match(W.table),WQ=O.match(W.tableSeparator);if(T&&!U){if(D+1<X.length){if(X[D+1].match(W.tableSeparator)){U=!0,G=T[1].split("|").map((L)=>L.trim()).filter((L)=>L.length>0),z=[],j=!1;continue}}}if(U&&WQ)continue;if(U&&T){let w=T[1].split("|").map((L)=>L.trim()).filter((L)=>L.length>0);while(w.length<G.length)w.push("");if(w.length>G.length)w.length=G.length;z.push(w);continue}if(U&&!T){if(G.length>0&&z.length>0)Z.push({type:"table",content:"",tableData:{headers:G,rows:z}});U=!1,G=[],z=[]}let S=O.match(W.blockquote);if(S){let w=S[1].length,L=S[2]||"";if(y&&w===H)B.push(L);else{if(y)Z.push({type:"blockquote",content:B.join(`
|
|
5
|
+
`),blockquoteLevel:H,blockquoteLines:[...B]});y=!0,H=w,B=[L]}j=!1;continue}if(y)Z.push({type:"blockquote",content:B.join(`
|
|
6
|
+
`),blockquoteLevel:H,blockquoteLines:[...B]}),y=!1,B=[],H=0;let u=O.match(W.heading);if(u){Z.push({type:"heading",content:u[2],level:u[1].length}),j=!1;continue}let h=O.match(W.ulItem);if(h){Z.push({type:"list",content:h[3],listType:"ul",marker:h[2],indentation:h[1].length}),j=!1;continue}let k=O.match(W.olItem);if(k){Z.push({type:"list",content:k[3],listType:"ol",marker:k[2],indentation:k[1].length}),j=!1;continue}if(O.match(W.hr)){Z.push({type:"hr",content:""}),j=!1;continue}if(O.trim().length===0){if(!j)Z.push({type:"empty",content:""}),j=!0;continue}let s=O.match(W.commandMessage);if(s){Z.push({type:"command-message",content:s[1]}),j=!1;continue}Z.push({type:"text",content:O}),j=!1}if($){let D=Y.join(`
|
|
7
|
+
`);Z.push({type:"code",content:D,language:V||void 0})}if(U&&G.length>0&&z.length>0)Z.push({type:"table",content:"",tableData:{headers:G,rows:z}});if(y&&B.length>0)Z.push({type:"blockquote",content:B.join(`
|
|
8
|
+
`),blockquoteLevel:H,blockquoteLines:[...B]});while(Z.length>0&&Z[Z.length-1].type==="empty")Z.pop();return Z}var C=new Map;function NQ(){return{inCodeBlock:!1,codeBlockContent:[],codeBlockLang:null,codeBlockDepth:0,inTable:!1,tableHeaders:[],tableRows:[],inDiff:!1,diffContent:[],inBlockquote:!1,blockquoteLines:[],blockquoteLevel:0,lastLineEmpty:!0,pendingTableHeader:null}}function hQ(Q){let Z=C.get(Q);if(Z)return Z;let X={state:NQ(),blocks:[],pendingLine:"",finalized:!1};return C.set(Q,X),X}function XQ(Q){return Q.endsWith("\r")?Q.slice(0,-1):Q}function ZQ(Q,Z){if(Q.tableHeaders.length>0&&Q.tableRows.length>0)Z.push({type:"table",content:"",tableData:{headers:Q.tableHeaders,rows:Q.tableRows}});Q.inTable=!1,Q.tableHeaders=[],Q.tableRows=[]}function l(Q,Z){if(Q.blockquoteLines.length>0)Z.push({type:"blockquote",content:Q.blockquoteLines.join(`
|
|
9
|
+
`),blockquoteLevel:Q.blockquoteLevel,blockquoteLines:[...Q.blockquoteLines]});Q.inBlockquote=!1,Q.blockquoteLines=[],Q.blockquoteLevel=0}function $Q(Q,Z){let X=Q.codeBlockContent.join(`
|
|
10
|
+
`);Z.push({type:"code",content:X,language:Q.codeBlockLang||void 0}),Q.inCodeBlock=!1,Q.codeBlockContent=[],Q.codeBlockLang=null,Q.codeBlockDepth=0,Q.lastLineEmpty=!1}function c(Q,Z,X=!0){let{state:$,blocks:Y}=Z;if($.pendingTableHeader!==null){if(Q.match(W.tableSeparator)){$.inTable=!0,$.tableHeaders=$.pendingTableHeader.slice(1,-1).split("|").map((H)=>H.trim()).filter((H)=>H.length>0),$.tableRows=[],$.pendingTableHeader=null,$.lastLineEmpty=!1;return}Y.push({type:"text",content:$.pendingTableHeader}),$.pendingTableHeader=null,$.lastLineEmpty=!1}if($.inDiff){if(Q.match(W.diffEnd)){try{let H=JSON.parse($.diffContent.join(`
|
|
11
|
+
`));Y.push({type:"diff",content:"",diffData:{patch:H.patch,startLine:H.startLine,matchLine:H.matchLine}})}catch(H){Y.push({type:"text",content:$.diffContent.join(`
|
|
12
|
+
`)})}$.inDiff=!1,$.diffContent=[],$.lastLineEmpty=!1;return}$.diffContent.push(Q);return}if(Q.match(W.diffStart)){$.inDiff=!0,$.diffContent=[],$.lastLineEmpty=!1;return}if($.inCodeBlock){let H=Q.match(W.codeBlock),j=Q.trim()==="```";if(H&&H[1])$.codeBlockDepth++,$.codeBlockContent.push(Q);else if(j)if($.codeBlockDepth>0)$.codeBlockDepth--,$.codeBlockContent.push(Q);else $Q($,Y);else $.codeBlockContent.push(Q);return}let V=Q.match(W.codeBlock);if(V){$.inCodeBlock=!0,$.codeBlockLang=V[1]||null,$.codeBlockDepth=0,$.lastLineEmpty=!1;return}let J=Q.match(W.table),U=Q.match(W.tableSeparator);if(J&&!$.inTable){$.pendingTableHeader=Q;return}if($.inTable&&U)return;if($.inTable&&J){let H=J[1].split("|").map((j)=>j.trim()).filter((j)=>j.length>0);while(H.length<$.tableHeaders.length)H.push("");if(H.length>$.tableHeaders.length)H.length=$.tableHeaders.length;$.tableRows.push(H);return}if($.inTable&&!J){if(ZQ($,Y),X){c(Q,Z,!1);return}}let G=Q.match(W.blockquote);if(G){let H=G[1].length,j=G[2]||"";if($.inBlockquote&&H===$.blockquoteLevel)$.blockquoteLines.push(j);else{if($.inBlockquote)l($,Y);$.inBlockquote=!0,$.blockquoteLevel=H,$.blockquoteLines=[j]}$.lastLineEmpty=!1;return}if($.inBlockquote)l($,Y);let z=Q.match(W.heading);if(z){Y.push({type:"heading",content:z[2],level:z[1].length}),$.lastLineEmpty=!1;return}let K=Q.match(W.ulItem);if(K){Y.push({type:"list",content:K[3],listType:"ul",marker:K[2],indentation:K[1].length}),$.lastLineEmpty=!1;return}let E=Q.match(W.olItem);if(E){Y.push({type:"list",content:E[3],listType:"ol",marker:E[2],indentation:E[1].length}),$.lastLineEmpty=!1;return}if(Q.match(W.hr)){Y.push({type:"hr",content:""}),$.lastLineEmpty=!1;return}if(Q.trim().length===0){if(!$.lastLineEmpty)Y.push({type:"empty",content:""}),$.lastLineEmpty=!0;return}let B=Q.match(W.commandMessage);if(B){Y.push({type:"command-message",content:B[1]}),$.lastLineEmpty=!1;return}Y.push({type:"text",content:Q}),$.lastLineEmpty=!1}function JX(Q,Z){if(!Q||!Z)return;let X=hQ(Q);if(X.finalized)return;let $=X.pendingLine+Z,Y=$.split(`
|
|
13
|
+
`),V=$.endsWith(`
|
|
14
|
+
`),J=V?Y:Y.slice(0,-1);X.pendingLine=V?"":Y[Y.length-1]??"";for(let U of J)c(XQ(U),X)}function UX(Q){let Z=C.get(Q);if(!Z||Z.finalized)return;if(Z.pendingLine)c(XQ(Z.pendingLine),Z),Z.pendingLine="";if(Z.state.pendingTableHeader!==null)Z.blocks.push({type:"text",content:Z.state.pendingTableHeader}),Z.state.pendingTableHeader=null;if(Z.state.inCodeBlock)$Q(Z.state,Z.blocks);if(Z.state.inTable)ZQ(Z.state,Z.blocks);if(Z.state.inBlockquote)l(Z.state,Z.blocks);if(Z.state.inDiff)Z.blocks.push({type:"text",content:Z.state.diffContent.join(`
|
|
15
|
+
`)}),Z.state.inDiff=!1,Z.state.diffContent=[];while(Z.blocks.length>0&&Z.blocks[Z.blocks.length-1].type==="empty")Z.blocks.pop();Z.finalized=!0}function GX(Q){let Z=C.get(Q);if(!Z||!Z.finalized)return null;return Z.blocks}function jX(Q){let Z=C.get(Q);if(!Z)return null;return Z.blocks}function kQ(Q){let Z=C.get(Q);if(!Z)return null;let X=[],$=Z.state;if($.inDiff)X.push("<<<DIFF>>>"),X.push(...$.diffContent);else if($.inCodeBlock){let Y=$.codeBlockLang?`\`\`\`${$.codeBlockLang}`:"```";X.push(Y),X.push(...$.codeBlockContent)}else if($.inTable){if($.tableHeaders.length>0){X.push(`| ${$.tableHeaders.join(" | ")} |`),X.push(`| ${$.tableHeaders.map(()=>"---").join(" | ")} |`);for(let Y of $.tableRows)X.push(`| ${Y.join(" | ")} |`)}}else if($.inBlockquote){let Y=">".repeat($.blockquoteLevel)+" ";for(let V of $.blockquoteLines)X.push(Y+V)}else if($.pendingTableHeader)X.push($.pendingTableHeader);if(Z.pendingLine)X.push(Z.pendingLine);return X.length>0?X:null}function HX(Q){let Z=C.get(Q);if(!Z)return null;let X="text";if(Z.state.inDiff)X="diff";else if(Z.state.inCodeBlock)X="code";else if(Z.state.inTable||Z.state.pendingTableHeader)X="table";let $=kQ(Q);if(!$||$.length===0)return null;return{lines:$,mode:X}}function zX(Q){C.delete(Q)}function f(){C.clear()}var YQ=2000,M=[];function SQ(){let Q=M;return M=[],Q}var JQ={inputTokens:0,outputTokens:0,totalTokens:0,maxContextTokens:200000},VQ={sessionId:fQ(),messages:[],restoredContextMessages:null,restoredVisibleMessageCount:0,isCompacting:!1,currentCommand:null,error:null,isActive:!0,tokenUsage:{...JQ},currentThinkingContent:null,thinkingExpanded:!1,clearCount:0,historyExpanded:!1,expandedMessageCount:100,currentStreamingMessageId:null,currentStreamingChunks:[],currentStreamingLines:[],currentStreamingTail:"",currentStreamingLineCount:0,currentStreamingVersion:0,finalizingStreamingMessageId:null},i=(Q,Z)=>({...VQ,actions:{addMessage:(X)=>{Q(($)=>({session:{...$.session,messages:[...$.session.messages,X],error:null}}))},addUserMessage:(X)=>{let $={id:`user-${Date.now()}-${Math.random()}`,role:"user",content:X,timestamp:Date.now()};Z().session.actions.addMessage($)},addAssistantMessage:(X,$)=>{let Y={id:`assistant-${Date.now()}-${Math.random()}`,role:"assistant",content:X,timestamp:Date.now(),thinkingContent:$};Z().session.actions.addMessage(Y)},addAssistantMessageAndClearThinking:(X)=>{let $=Z().session.currentThinkingContent,Y={id:`assistant-${Date.now()}-${Math.random()}`,role:"assistant",content:X,timestamp:Date.now(),thinkingContent:$||void 0};Q((V)=>({session:{...V.session,messages:[...V.session.messages,Y],currentThinkingContent:null,error:null}}))},addToolMessage:(X,$)=>{let Y={id:`tool-${Date.now()}-${Math.random()}`,role:"tool",content:X,timestamp:Date.now(),metadata:$};Z().session.actions.addMessage(Y)},setCompacting:(X)=>{Q(($)=>({session:{...$.session,isCompacting:X}}))},setCommand:(X)=>{Q(($)=>({session:{...$.session,currentCommand:X}}))},setError:(X)=>{Q(($)=>({session:{...$.session,error:X}}))},clearMessages:()=>{f(),Q((X)=>({session:{...X.session,messages:[],restoredContextMessages:null,restoredVisibleMessageCount:0,error:null,clearCount:X.session.clearCount+1}}))},resetSession:()=>{f(),Q((X)=>({session:{...X.session,...VQ,sessionId:X.session.sessionId,isActive:!0}}))},restoreSession:(X,$,Y)=>{f(),Q((V)=>({session:{...V.session,sessionId:X,messages:$,restoredContextMessages:Y??null,restoredVisibleMessageCount:Y?$.length:0,error:null,isActive:!0}}))},updateTokenUsage:(X)=>{Q(($)=>({session:{...$.session,tokenUsage:{...$.session.tokenUsage,...X}}}))},resetTokenUsage:()=>{Q((X)=>({session:{...X.session,tokenUsage:{...JQ}}}))},setCurrentThinkingContent:(X)=>{if(Z().session.currentThinkingContent===X)return;Q(($)=>({session:{...$.session,currentThinkingContent:X}}))},appendThinkingContent:(X)=>{Q(($)=>({session:{...$.session,currentThinkingContent:($.session.currentThinkingContent||"")+X}}))},setThinkingExpanded:(X)=>{Q(($)=>({session:{...$.session,thinkingExpanded:X}}))},toggleThinkingExpanded:()=>{Q((X)=>({session:{...X.session,thinkingExpanded:!X.session.thinkingExpanded}}))},setHistoryExpanded:(X)=>{Q(($)=>({session:{...$.session,historyExpanded:X}}))},toggleHistoryExpanded:()=>{Q((X)=>({session:{...X.session,historyExpanded:!X.session.historyExpanded}}))},setExpandedMessageCount:(X)=>{Q(($)=>({session:{...$.session,expandedMessageCount:X}}))},incrementClearCount:()=>{Q((X)=>({session:{...X.session,clearCount:X.session.clearCount+1}}))},startStreamingAssistantMessage:()=>{let X=`assistant-${Date.now()}-${Math.random()}`,$={id:X,role:"assistant",content:"",timestamp:Date.now()};return M=[],Q((Y)=>({session:{...Y.session,messages:[...Y.session.messages,$],currentStreamingMessageId:X,currentStreamingChunks:[],currentStreamingLines:[],currentStreamingTail:"",currentStreamingLineCount:0,currentStreamingVersion:0,error:null}})),X},appendAssistantContent:(X)=>{let $=Z().session.currentStreamingMessageId,Y=$??`assistant-${Date.now()}-${Math.random()}`;return M.push(X),Q((V)=>{let J=(D)=>D.endsWith("\r")?D.slice(0,-1):D,U=$?V.session.currentStreamingLines:[],G=$?V.session.currentStreamingTail:"",z=$?V.session.currentStreamingLineCount:0,K=$?V.session.currentStreamingVersion:0,y=(G+X).split(`
|
|
16
|
+
`),B=y.slice(0,-1).map(J),H=J(y[y.length-1]??""),j=U;if(B.length>0){if(j=[...U,...B],j.length>YQ){let D=j.length-YQ;j=j.slice(D)}}return{session:{...V.session,currentStreamingMessageId:Y,currentStreamingLines:j,currentStreamingTail:H,currentStreamingLineCount:z+B.length,currentStreamingVersion:K+1,error:null}}}),Y},finalizeStreamingMessage:(X,$)=>{let Y=SQ();Q((V)=>{let J=V.session.currentStreamingMessageId,G=Y.join("")+(X||""),z=(V.session.currentThinkingContent||"")+($||"");if(G.length>0){let K={id:J||`assistant-${Date.now()}-${Math.random()}`,role:"assistant",content:G,timestamp:Date.now(),thinkingContent:z||void 0};return{session:{...V.session,messages:[...V.session.messages,K],currentStreamingMessageId:null,currentStreamingChunks:[],currentStreamingLines:[],currentStreamingTail:"",currentStreamingLineCount:0,currentStreamingVersion:0,currentThinkingContent:null,finalizingStreamingMessageId:K.id}}}return{session:{...V.session,currentStreamingMessageId:null,currentStreamingChunks:[],currentStreamingLines:[],currentStreamingTail:"",currentStreamingLineCount:0,currentStreamingVersion:0,currentThinkingContent:null,finalizingStreamingMessageId:null}}})},clearFinalizingStreamingMessageId:()=>{Q((X)=>({session:{...X.session,finalizingStreamingMessageId:null}}))},discardStreamingMessage:()=>{M=[],Q((X)=>({session:{...X.session,currentStreamingMessageId:null,currentStreamingChunks:[],currentStreamingLines:[],currentStreamingTail:"",currentStreamingLineCount:0,currentStreamingVersion:0,finalizingStreamingMessageId:null}}))}}});import{nanoid as mQ}from"nanoid";import{promises as _}from"node:fs";import*as F from"node:path";import{fileURLToPath as uQ}from"node:url";import{nanoid as pQ}from"nanoid";var UQ={proposal:"proposal.md",spec:"spec.md",requirements:"requirements.md",design:"design.md",tasks:"tasks.md",meta:".meta.json"},P={SPECS:"specs",CHANGES:"changes",ARCHIVE:"archive",STEERING:"steering",SPEC_DELTA:"specs"},R={CONSTITUTION:"constitution.md",PRODUCT:"product.md",TECH:"tech.md",STRUCTURE:"structure.md"};var b={init:["requirements"],requirements:["design","tasks"],design:["tasks"],tasks:["implementation"],implementation:["done","tasks"],done:[]},OX={init:"初始化",requirements:"需求定义",design:"架构设计",tasks:"任务分解",implementation:"实现中",done:"已完成"},GQ={init:"proposal",requirements:"requirements",design:"design",tasks:"tasks",implementation:"tasks",done:null};var gQ=uQ(import.meta.url),dQ=F.dirname(gQ),jQ=F.join(dQ,"templates");class N{workspaceRoot;bladeDir;constructor(Q){this.workspaceRoot=Q,this.bladeDir=F.join(Q,".blade")}getSpecsDir(){return F.join(this.bladeDir,P.SPECS)}getChangesDir(){return F.join(this.bladeDir,P.CHANGES)}getArchiveDir(){return F.join(this.bladeDir,P.ARCHIVE)}getSteeringDir(){return F.join(this.bladeDir,P.STEERING)}getChangePath(Q){return F.join(this.getChangesDir(),Q)}getChangeFilePath(Q,Z){return F.join(this.getChangePath(Q),UQ[Z])}async initializeDirectories(){await _.mkdir(this.getChangesDir(),{recursive:!0,mode:493})}async createChangeDir(Q){let Z=this.getChangePath(Q);return await _.mkdir(Z,{recursive:!0,mode:493}),await _.mkdir(F.join(Z,P.SPEC_DELTA),{recursive:!0,mode:493}),Z}async readFile(Q){try{return await _.readFile(Q,"utf-8")}catch(Z){if(Z.code==="ENOENT")return null;throw Z}}async writeFile(Q,Z){let X=F.dirname(Q);await _.mkdir(X,{recursive:!0,mode:493}),await _.writeFile(Q,Z,"utf-8")}async fileExists(Q){try{return await _.access(Q),!0}catch{return!1}}async dirExists(Q){try{return(await _.stat(Q)).isDirectory()}catch{return!1}}createMetadata(Q,Z){let X=new Date().toISOString();return{id:pQ(),name:Q,description:Z,phase:"init",createdAt:X,updatedAt:X,tasks:[]}}async readMetadata(Q){let Z=this.getChangeFilePath(Q,"meta"),X=await this.readFile(Z);if(!X)return null;try{return JSON.parse(X)}catch{return null}}async writeMetadata(Q,Z){let X=this.getChangeFilePath(Q,"meta");Z.updatedAt=new Date().toISOString(),await this.writeFile(X,JSON.stringify(Z,null,2))}async updatePhase(Q,Z){let X=await this.readMetadata(Q);if(!X)return null;return X.phase=Z,await this.writeMetadata(Q,X),X}async readSpecFile(Q,Z){let X=this.getChangeFilePath(Q,Z);return this.readFile(X)}async writeSpecFile(Q,Z,X){let $=this.getChangeFilePath(Q,Z);await this.writeFile($,X);let Y=await this.readMetadata(Q);if(Y)await this.writeMetadata(Q,Y)}async getPhaseContent(Q,Z){let X=GQ[Z];if(!X)return null;return this.readSpecFile(Q,X)}async readSteeringContext(){let Q=this.getSteeringDir(),[Z,X,$,Y]=await Promise.all([this.readFile(F.join(Q,R.CONSTITUTION)),this.readFile(F.join(Q,R.PRODUCT)),this.readFile(F.join(Q,R.TECH)),this.readFile(F.join(Q,R.STRUCTURE))]);return{constitution:Z||void 0,product:X||void 0,tech:$||void 0,structure:Y||void 0}}async writeSteeringFile(Q,Z){let X=F.join(this.getSteeringDir(),R[Q]);await this.writeFile(X,Z)}async hasSteeringDocs(){let Q=this.getSteeringDir();if(!await this.dirExists(Q))return!1;return(await _.readdir(Q)).length>0}async listActiveChanges(){let Q=this.getChangesDir();if(!await this.dirExists(Q))return[];return(await _.readdir(Q,{withFileTypes:!0})).filter((X)=>X.isDirectory()).map((X)=>X.name)}async listArchivedChanges(){let Q=this.getArchiveDir();if(!await this.dirExists(Q))return[];return(await _.readdir(Q,{withFileTypes:!0})).filter((X)=>X.isDirectory()).map((X)=>X.name)}async changeExists(Q){return this.dirExists(this.getChangePath(Q))}async archiveChange(Q){let Z=this.getChangePath(Q),X=F.join(this.getArchiveDir(),Q);await _.mkdir(F.dirname(X),{recursive:!0,mode:493}),await _.rename(Z,X)}async restoreChange(Q){let Z=F.join(this.getArchiveDir(),Q),X=this.getChangePath(Q);await _.rename(Z,X)}async listSpecDomains(){let Q=this.getSpecsDir();if(!await this.dirExists(Q))return[];return(await _.readdir(Q,{withFileTypes:!0})).filter((X)=>X.isDirectory()).map((X)=>X.name)}async readAuthorativeSpec(Q){let Z=F.join(this.getSpecsDir(),Q,"spec.md");return this.readFile(Z)}async writeAuthorativeSpec(Q,Z){let X=F.join(this.getSpecsDir(),Q,"spec.md");await this.writeFile(X,Z)}async mergeSpecDeltas(Q){let Z=F.join(this.getChangePath(Q),P.SPEC_DELTA);if(!await this.dirExists(Z))return[];let X=[],$=await _.readdir(Z,{withFileTypes:!0});for(let Y of $){if(!Y.isDirectory())continue;let V=F.join(Z,Y.name,"spec.md"),J=await this.readFile(V);if(J){let U=await this.readAuthorativeSpec(Y.name),G=U?`${U}
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
<!-- Merged from ${Q} -->
|
|
21
|
+
|
|
22
|
+
${J}`:J;await this.writeAuthorativeSpec(Y.name,G),X.push(Y.name)}}return X}static TEMPLATE_NAMES={proposal:"proposal.md.template",spec:"spec.md.template",requirements:"requirements.md.template",design:"design.md.template",tasks:"tasks.md.template",meta:""};static STEERING_TEMPLATE_NAMES={CONSTITUTION:"steering/constitution.md.template",PRODUCT:"steering/product.md.template",TECH:"steering/tech.md.template",STRUCTURE:"steering/structure.md.template"};async readTemplate(Q){let Z=N.TEMPLATE_NAMES[Q];if(!Z)return null;let X=F.join(jQ,Z);return this.readFile(X)}async readSteeringTemplate(Q){let Z=N.STEERING_TEMPLATE_NAMES[Q],X=F.join(jQ,Z);return this.readFile(X)}fillTemplate(Q,Z){let X=Q;for(let[$,Y]of Object.entries(Z))X=X.replace(new RegExp(`\\{\\{${$}\\}\\}`,"g"),Y);return X}async createFromTemplate(Q,Z,X){let $=await this.readTemplate(Z);if(!$)return null;let Y=this.fillTemplate($,{name:Q,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString(),...X});return await this.writeSpecFile(Q,Z,Y),Y}async createSteeringFromTemplate(Q,Z={}){let X=await this.readSteeringTemplate(Q);if(!X)return null;let $=this.fillTemplate(X,{createdAt:new Date().toISOString(),...Z});return await this.writeSteeringFile(Q,$),$}async initializeSteeringDocs(){let Q=[],Z=this.getSteeringDir();for(let[X,$]of Object.entries(R)){let Y=F.join(Z,$);if(!await this.fileExists(Y))await this.createSteeringFromTemplate(X),Q.push($)}return Q}}class x{static instance=null;fileManager=null;workspaceRoot=null;constructor(){}static getInstance(){if(!x.instance)x.instance=new x;return x.instance}static resetInstance(){x.instance=null}async initialize(Q){if(this.workspaceRoot===Q&&this.fileManager)return;this.workspaceRoot=Q,this.fileManager=new N(Q),await this.fileManager.initializeDirectories()}getFileManager(){if(!this.fileManager)throw Error("SpecService not initialized. Call initialize() first.");return this.fileManager}async readSteeringContext(){return this.getFileManager().readSteeringContext()}async readSpecMetadata(Q){return this.getFileManager().readMetadata(Q)}async specExists(Q){return this.getFileManager().changeExists(Q)}getSpecPath(Q){return this.getFileManager().getChangePath(Q)}async createSpec(Q,Z){let X=this.getFileManager();if(await X.changeExists(Q))return{success:!1,message:`Spec "${Q}" already exists`,error:"SPEC_EXISTS"};let $=await X.createChangeDir(Q),Y=X.createMetadata(Q,Z);await X.writeMetadata(Q,Y);let V=this.generateProposalTemplate(Q,Z);return await X.writeSpecFile(Q,"proposal",V),{success:!0,message:`Spec "${Q}" created successfully`,data:{spec:Y,path:$}}}async loadSpec(Q){let Z=this.getFileManager(),X=await Z.readMetadata(Q);if(!X)return{success:!1,message:`Spec "${Q}" not found`,error:"SPEC_NOT_FOUND"};let $=Z.getChangePath(Q);return{success:!0,message:`Spec "${Q}" loaded successfully`,data:{spec:X,path:$}}}canTransitionPhase(Q,Z){return b[Q].includes(Z)}getAllowedTransitions(Q){return b[Q]}async updatePhase(Q,Z){return this.getFileManager().updatePhase(Q,Z)}createTask(Q,Z,X){return{id:mQ(8),title:Q,description:Z,status:"pending",dependencies:X?.dependencies||[],affectedFiles:X?.affectedFiles||[],complexity:X?.complexity||"medium"}}async saveMetadata(Q,Z){await this.getFileManager().writeMetadata(Q,Z)}getNextTask(Q){return Q.find((Z)=>{if(Z.status!=="pending")return!1;return Z.dependencies.every((X)=>{return Q.find((Y)=>Y.id===X)?.status==="completed"})})||null}getTaskProgress(Q){if(Q.length===0)return{total:0,completed:0,percentage:0};let Z=Q.length,X=Q.filter((Y)=>Y.status==="completed").length,$=Math.round(X/Z*100);return{total:Z,completed:X,percentage:$}}async listActiveSpecs(){return this.getFileManager().listActiveChanges()}async listArchivedSpecs(){return this.getFileManager().listArchivedChanges()}async archiveSpec(Q){let Z=this.getFileManager();return await Z.mergeSpecDeltas(Q),await Z.updatePhase(Q,"done"),await Z.archiveChange(Q),{success:!0,message:`Spec "${Q}" archived successfully`}}async validateSpec(Q){let Z=this.getFileManager(),X=[],$=[],[Y,V,J,U,G]=await Promise.all([Z.readSpecFile(Q.name,"proposal"),Z.readSpecFile(Q.name,"spec"),Z.readSpecFile(Q.name,"requirements"),Z.readSpecFile(Q.name,"design"),Z.readSpecFile(Q.name,"tasks")]),z={proposal:!!Y,spec:!!V,requirements:!!J,design:!!U,tasks:!!G};if(Q.phase==="requirements"&&!z.requirements)X.push({severity:"warning",file:"requirements",message:"Requirements document is missing"}),$.push("Generate requirements using EARS format");if(Q.phase==="design"&&!z.design)X.push({severity:"warning",file:"design",message:"Design document is missing"}),$.push("Create architecture diagrams and API contracts");if(Q.phase==="tasks"&&Q.tasks.length===0)X.push({severity:"warning",file:"tasks",message:"No tasks defined"}),$.push("Break down the spec into atomic tasks");if(Q.phase==="implementation"){let K=this.getTaskProgress(Q.tasks);if(K.completed<K.total)X.push({severity:"info",file:"tasks",message:`${K.total-K.completed} tasks remaining`})}return{valid:X.filter((K)=>K.severity==="error").length===0,phase:Q.phase,completeness:z,issues:X,suggestions:$}}generateProposalTemplate(Q,Z){return`# ${Q}
|
|
23
|
+
|
|
24
|
+
## Summary
|
|
25
|
+
|
|
26
|
+
${Z}
|
|
27
|
+
|
|
28
|
+
## Background
|
|
29
|
+
|
|
30
|
+
<!-- Why is this change needed? What problem does it solve? -->
|
|
31
|
+
|
|
32
|
+
## Goals
|
|
33
|
+
|
|
34
|
+
<!-- What are the specific objectives of this change? -->
|
|
35
|
+
|
|
36
|
+
- [ ] Goal 1
|
|
37
|
+
- [ ] Goal 2
|
|
38
|
+
|
|
39
|
+
## Non-Goals
|
|
40
|
+
|
|
41
|
+
<!-- What is explicitly out of scope? -->
|
|
42
|
+
|
|
43
|
+
## Risks and Mitigations
|
|
44
|
+
|
|
45
|
+
<!-- What could go wrong? How will you address it? -->
|
|
46
|
+
|
|
47
|
+
| Risk | Mitigation |
|
|
48
|
+
|------|------------|
|
|
49
|
+
| | |
|
|
50
|
+
|
|
51
|
+
## Open Questions
|
|
52
|
+
|
|
53
|
+
<!-- What needs to be clarified before proceeding? -->
|
|
54
|
+
|
|
55
|
+
1.
|
|
56
|
+
`}}var HQ=FQ("Spec"),zQ={currentSpec:null,specPath:null,isActive:!1,steeringContext:null,recentSpecs:[],isLoading:!1,error:null,workspaceRoot:null},o=(Q,Z)=>({...zQ,actions:{initialize:async(X)=>{let $=x.getInstance();await $.initialize(X);let Y=await $.readSteeringContext();Q((V)=>({spec:{...V.spec,workspaceRoot:X,steeringContext:Y}}))},createSpec:async(X,$)=>{let V=await x.getInstance().createSpec(X,$);if(V.success&&V.data){let{spec:J,path:U}=V.data,G=Z().spec.recentSpecs.filter((z)=>z!==X);G.unshift(X),Q((z)=>({spec:{...z.spec,currentSpec:J,specPath:U,isActive:!0,recentSpecs:G.slice(0,10)}}))}return V},loadSpec:async(X)=>{let Y=await x.getInstance().loadSpec(X);if(Y.success&&Y.data){let{spec:V,path:J}=Y.data,U=Z().spec.recentSpecs.filter((G)=>G!==X);U.unshift(X),Q((G)=>({spec:{...G.spec,currentSpec:V,specPath:J,isActive:!0,recentSpecs:U.slice(0,10)}}))}return Y},closeSpec:()=>{Q((X)=>({spec:{...X.spec,currentSpec:null,specPath:null,isActive:!1}}))},exitSpecMode:()=>{Z().spec.actions.closeSpec()},transitionPhase:async(X)=>{let $=Z().spec.currentSpec;if(!$)return{success:!1,message:"No active spec",error:"NO_ACTIVE_SPEC"};let Y=x.getInstance();if(!Y.canTransitionPhase($.phase,X))return{success:!1,message:`Cannot transition from "${$.phase}" to "${X}"`,error:"INVALID_TRANSITION"};let V=await Y.updatePhase($.name,X);if(!V)return{success:!1,message:"Failed to update phase",error:"UPDATE_FAILED"};if(Q((J)=>({spec:{...J.spec,currentSpec:V}})),X==="done")try{let{config:J}=Z();if(J.actions)J.actions.updateConfig({permissionMode:"default"});HQ.info("Spec 已完成,已自动退出 Spec 模式")}catch(J){HQ.error("自动退出 Spec 模式失败:",J)}return{success:!0,message:`Transitioned to "${X}" phase`,data:{spec:V,phase:X}}},getAllowedTransitions:()=>{let X=Z().spec.currentSpec;if(!X)return[];return b[X.phase]},addTask:async(X,$,Y)=>{let V=Z().spec.currentSpec;if(!V)return{success:!1,message:"No active spec",error:"NO_ACTIVE_SPEC"};let J=x.getInstance(),U=J.createTask(X,$,Y),G={...V,tasks:[...V.tasks,U],updatedAt:new Date().toISOString()};return await J.saveMetadata(V.name,G),Q((z)=>({spec:{...z.spec,currentSpec:G}})),{success:!0,message:`Task "${X}" added`,data:{task:U}}},updateTaskStatus:async(X,$)=>{let Y=Z().spec.currentSpec;if(!Y)return{success:!1,message:"No active spec",error:"NO_ACTIVE_SPEC"};let V=Y.tasks.find((K)=>K.id===X);if(!V)return{success:!1,message:`Task "${X}" not found`,error:"TASK_NOT_FOUND"};let J={...V,status:$,completedAt:$==="completed"?new Date().toISOString():V.completedAt},U=Y.tasks.map((K)=>K.id===X?J:K),G={...Y,tasks:U,currentTaskId:$==="in_progress"?X:Y.currentTaskId===X?void 0:Y.currentTaskId,updatedAt:new Date().toISOString()};return await x.getInstance().saveMetadata(Y.name,G),Q((K)=>({spec:{...K.spec,currentSpec:G}})),{success:!0,message:`Task status updated to "${$}"`,data:{task:J}}},getNextTask:()=>{let X=Z().spec.currentSpec;if(!X)return null;return x.getInstance().getNextTask(X.tasks)},getTaskProgress:()=>{let X=Z().spec.currentSpec;if(!X)return{total:0,completed:0,percentage:0};return x.getInstance().getTaskProgress(X.tasks)},listSpecs:async(X)=>{let $=x.getInstance(),Y=[],V=await $.listActiveSpecs();for(let J of V){let U=await $.readSpecMetadata(J);if(!U)continue;if(X?.phase&&U.phase!==X.phase)continue;if(X?.tags&&!X.tags.some((z)=>U.tags?.includes(z)))continue;if(X?.query&&!U.name.toLowerCase().includes(X.query.toLowerCase())&&!U.description.toLowerCase().includes(X.query.toLowerCase()))continue;let G=$.getTaskProgress(U.tasks);Y.push({name:U.name,description:U.description,phase:U.phase,updatedAt:U.updatedAt,path:$.getSpecPath(J),isArchived:!1,taskProgress:{total:G.total,completed:G.completed}})}if(X?.includeArchived){let J=await $.listArchivedSpecs();for(let U of J)Y.push({name:U,description:"(archived)",phase:"done",updatedAt:"",path:`archive/${U}`,isArchived:!0,taskProgress:{total:0,completed:0}})}return Y.sort((J,U)=>{if(J.isArchived!==U.isArchived)return J.isArchived?1:-1;return new Date(U.updatedAt).getTime()-new Date(J.updatedAt).getTime()}),Y},archiveCurrentSpec:async()=>{let X=Z().spec.currentSpec;if(!X)return{success:!1,message:"No active spec",error:"NO_ACTIVE_SPEC"};let Y=await x.getInstance().archiveSpec(X.name);if(Y.success)Z().spec.actions.closeSpec();return Y},validateCurrentSpec:async()=>{let X=Z().spec.currentSpec;if(!X)return{valid:!1,phase:"init",completeness:{proposal:!1,spec:!1,requirements:!1,design:!1,tasks:!1},issues:[{severity:"error",file:"meta",message:"No active spec"}],suggestions:["Create a new spec with /spec proposal <name>"]};return x.getInstance().validateSpec(X)},getSteeringContextString:async()=>{let X=Z().spec.steeringContext;if(!X)return null;let $=[];if(X.constitution)$.push(`## Constitution (Project Governance)
|
|
57
|
+
|
|
58
|
+
${X.constitution}`);if(X.product)$.push(`## Product Vision
|
|
59
|
+
|
|
60
|
+
${X.product}`);if(X.tech)$.push(`## Technology Stack
|
|
61
|
+
|
|
62
|
+
${X.tech}`);if(X.structure)$.push(`## Code Structure
|
|
63
|
+
|
|
64
|
+
${X.structure}`);return $.length>0?$.join(`
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
`):null},setError:(X)=>{Q(($)=>({spec:{...$.spec,error:X}}))},setLoading:(X)=>{Q(($)=>({spec:{...$.spec,isLoading:X}}))},reset:()=>{Q((X)=>({spec:{...zQ,actions:X.spec.actions}}))}}});var oQ=iQ()(lQ(cQ((...Q)=>({session:i(...Q),app:g(...Q),config:m(...Q),focus:r(...Q),command:d(...Q),spec:o(...Q)})),{name:"BladeStore",enabled:!0})),q=()=>oQ.getState(),iX=()=>q().session.actions,oX=()=>q().app.actions,nX=()=>q().session.messages,v=()=>q().config.config,I=null;async function sX(){if(v()!==null)return;if(I)return I;return I=(async()=>{try{let X=await KQ.getInstance().initialize();q().config.actions.setConfig(X)}catch(Z){throw I=null,Error(`[FAIL] Store 未初始化且无法自动初始化
|
|
69
|
+
|
|
70
|
+
`+`原因: ${Z instanceof Error?Z.message:"未知错误"}
|
|
71
|
+
|
|
72
|
+
`+`请确保:
|
|
73
|
+
`+`1. 配置文件格式正确 (~/.blade/config.json)
|
|
74
|
+
`+`2. 运行 blade 进行首次配置
|
|
75
|
+
`+"3. 配置文件权限正确")}finally{I=null}})(),I}var aX=()=>q().config.config?.models??[],tX=()=>{let Q=v();if(!Q)return;let Z=Q.currentModelId;return Q.models.find(($)=>$.id===Z)??Q.models[0]},eX=(Q)=>{let Z=v();if(!Z)return;return Z.models.find((X)=>X.id===Q)},QZ=()=>q().config.config?.mcpServers??{},XZ=()=>q().app.thinkingModeEnabled,ZZ=()=>({setPermissionMode:async(Q)=>{q().config.actions.updateConfig({permissionMode:Q})},setTheme:async(Q,Z={})=>{try{QQ.setTheme(Q)}catch{return}q().config.actions.updateConfig({theme:Q}),await A().save({theme:Q},{scope:"global",...Z})},setLanguage:async(Q,Z={})=>{q().config.actions.updateConfig({language:Q}),await A().save({language:Q},{scope:"global",...Z})},setDebug:async(Q,Z={})=>{q().config.actions.updateConfig({debug:Q}),await A().save({debug:Q},{scope:"global",...Z})},setTemperature:async(Q,Z={})=>{q().config.actions.updateConfig({temperature:Q}),await A().save({temperature:Q},{scope:"global",...Z})},updateConfig:async(Q,Z={})=>{let X=v();if(!X)throw Error("Config not initialized");let $={...X};q().config.actions.updateConfig(Q);try{await A().save(Q,Z)}catch(Y){throw q().config.actions.setConfig($),Y}},flush:async()=>{await A().flush()},appendPermissionAllowRule:async(Q,Z={})=>{let X=v();if(!X)throw Error("Config not initialized");let $=X.permissions?.allow||[];if(!$.includes(Q)){let Y=[...$,Q];q().config.actions.updateConfig({permissions:{...X.permissions,allow:Y}})}await A().appendPermissionRule(Q,Z)},appendLocalPermissionAllowRule:async(Q,Z={})=>{let X=v();if(!X)throw Error("Config not initialized");let $=X.permissions?.allow||[];if(!$.includes(Q)){let Y=[...$,Q];q().config.actions.updateConfig({permissions:{...X.permissions,allow:Y}})}await A().appendLocalPermissionRule(Q,Z)},setCurrentModel:async(Q,Z={})=>{let X=v();if(!X)throw Error("Config not initialized");if(!X.models.find((Y)=>Y.id===Q))throw Error(`Model not found: ${Q}`);q().config.actions.updateConfig({currentModelId:Q}),await A().save({currentModelId:Q},{scope:"global",...Z})},addModel:async(Q,Z={})=>{let X=v();if(!X)throw Error("Config not initialized");let $="id"in Q?Q:{id:rQ(),...Q},V={models:[...X.models,$]};if(X.models.length===0)V.currentModelId=$.id;return q().config.actions.updateConfig(V),await A().save(V,{scope:"global",...Z}),$},updateModel:async(Q,Z,X={})=>{let $=v();if(!$)throw Error("Config not initialized");let Y=$.models.findIndex((J)=>J.id===Q);if(Y===-1)throw Error(`Model not found: ${Q}`);let V=[...$.models];V[Y]={...V[Y],...Z},q().config.actions.updateConfig({models:V}),await A().save({models:V},{scope:"global",...X})},removeModel:async(Q,Z={})=>{let X=v();if(!X)throw Error("Config not initialized");if(X.models.length===1)throw Error("Cannot remove the only model");let $=X.models.filter((V)=>V.id!==Q),Y={models:$};if(X.currentModelId===Q)Y.currentModelId=$[0].id;q().config.actions.updateConfig(Y),await A().save(Y,{scope:"global",...Z})},addMcpServer:async(Q,Z,X={})=>{let $=v();if(!$)throw Error("Config not initialized");let V={...$.mcpServers??{},[Q]:Z};q().config.actions.updateConfig({mcpServers:V}),await A().save({mcpServers:V},{scope:"project",...X})},removeMcpServer:async(Q,Z={})=>{let X=v();if(!X)throw Error("Config not initialized");let Y={...X.mcpServers??{}};delete Y[Q],q().config.actions.updateConfig({mcpServers:Y}),await A().save({mcpServers:Y},{scope:"project",...Z})}});
|
|
76
|
+
export{a as ha,QQ as ia,W as ja,$X as ka,JX as la,UX as ma,GX as na,jX as oa,HX as pa,zX as qa,b as ra,OX as sa,N as ta,oQ as ua,q as va,iX as wa,oX as xa,nX as ya,v as za,sX as Aa,aX as Ba,tX as Ca,eX as Da,QZ as Ea,XZ as Fa,ZZ as Ga};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{p as _,q as x,r as E,s as N}from"./chunk-4nsh53k6.js";import{t as A}from"./chunk-wr7w4af5.js";import{v as B,w as D,x as L}from"./chunk-1en8fh5f.js";import{G as $,M as b}from"./chunk-j79jvd54.js";import"./chunk-zxf08z5f.js";import"./chunk-esnkk33h.js";import"./chunk-3xqfqpa7.js";import"./chunk-2tpgtpcp.js";import"./chunk-m99qhdkf.js";import"./chunk-e2vtbvda.js";import{Sa as Z}from"./chunk-j25kww7j.js";import"./chunk-yddnm9n2.js";import"./chunk-ena4sxgr.js";import"./chunk-5mtjqqav.js";import{wb as X,xb as Y}from"./chunk-7ycmx7c2.js";import"./chunk-set7v1rf.js";import"./chunk-j2ag7hh6.js";import f from"yargs";import{hideBin as h}from"yargs/helpers";var R=new Set(Object.values(X));function W(k){if(k&&R.has(k))return k;return}function w(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 M(F);process.exit(q)})}async function M(k,F=process){let q;try{await _();let J=await x({message:k.message,_:k._,defaultMessage:"Hello"}),G=await E(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:T}=await N({sessionId:k.sessionId,continue:k.continue,resume:k.resume,fallbackSessionPrefix:"print"});q=await $.create({sessionId:K,modelId:k.model,mcpConfig:k.mcpConfig,strictMcpConfig:k.strictMcpConfig});let U=await b.createWithRuntime(q,{sessionId:K,systemPrompt:k.systemPrompt,appendSystemPrompt:k.appendSystemPrompt,maxTurns:k.maxTurns,modelId:k.model,permissionMode:W(k.permissionMode),toolWhitelist:k.allowedTools,toolBlacklist:k.disallowedTools,mcpConfig:k.mcpConfig,strictMcpConfig:k.strictMcpConfig}),H=(await Z(U.chatStream(Q,{messages:[...T],userId:"cli-user",sessionId:K,workspaceRoot:Y(),permissionMode:W(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 m(){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":T,"max-turns":U,...V}=A,H=f(h(process.argv)).scriptName("blade").strict(!1).options(V).middleware([B,D,L]);return w(H),await H.parse(),!0}catch(q){console.error(`Print mode error: ${q instanceof Error?q.message:"未知错误"}`),process.exit(1)}}export{M as runPrint,m as handlePrintMode};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{p as z,q as g,r as v,s as p}from"./chunk-4nsh53k6.js";import{t as E}from"./chunk-wr7w4af5.js";import{v as S,w as h,x as c}from"./chunk-1en8fh5f.js";import{G as w,I as F,J as y,L as x,M as C}from"./chunk-j79jvd54.js";import"./chunk-zxf08z5f.js";import"./chunk-esnkk33h.js";import"./chunk-3xqfqpa7.js";import"./chunk-2tpgtpcp.js";import"./chunk-m99qhdkf.js";import"./chunk-e2vtbvda.js";import{Sa as O}from"./chunk-j25kww7j.js";import"./chunk-yddnm9n2.js";import"./chunk-ena4sxgr.js";import"./chunk-5mtjqqav.js";import{wb as H,xb as T}from"./chunk-7ycmx7c2.js";import"./chunk-set7v1rf.js";import"./chunk-j2ag7hh6.js";import bq from"yargs";import{hideBin as Uq}from"yargs/helpers";import{z as b}from"zod";import{z as Q}from"zod";var L=1,V=Q.object({event_version:Q.literal(L)}),i=V.extend({type:Q.literal("content_delta"),delta:Q.string()}),n=V.extend({type:Q.literal("thinking_delta"),delta:Q.string()}),r=V.extend({type:Q.literal("thinking"),content:Q.string()}),s=V.extend({type:Q.literal("stream_end")}),o=V.extend({type:Q.literal("content"),content:Q.string()}),a=V.extend({type:Q.literal("tool_start"),tool_name:Q.string(),summary:Q.string(),target:Q.string().optional(),tool_kind:Q.enum(["readonly","write","execute"]).optional()}),t=V.extend({type:Q.literal("tool_result"),tool_name:Q.string(),summary:Q.string(),target:Q.string().optional(),tool_kind:Q.enum(["readonly","write","execute"]).optional()}),e=V.extend({type:Q.literal("phase"),phase:Q.enum(["turn","searching","inspecting","target_hit","executing","completed"]),status:Q.enum(["ongoing","hit","done"]),message:Q.string(),turn:Q.number().optional(),tool_name:Q.string().optional(),target:Q.string().optional()}),qq=V.extend({type:Q.literal("tool_detail"),tool_name:Q.string(),detail:Q.string()}),Gq=V.extend({type:Q.literal("task_update"),tasks:Q.array(x)}),Qq=V.extend({type:Q.literal("token_usage"),input_tokens:Q.number(),output_tokens:Q.number(),total_tokens:Q.number(),max_context_tokens:Q.number()}),Xq=V.extend({type:Q.literal("compacting"),state:Q.enum(["started","completed"])}),Yq=V.extend({type:Q.literal("turn_limit"),turns_count:Q.number(),action:Q.literal("continue")}),Zq=V.extend({type:Q.literal("output"),content:Q.string(),exit_code:Q.number()}),$q=V.extend({type:Q.literal("error"),message:Q.string()}),Nq=Q.discriminatedUnion("type",[i,n,r,s,o,a,t,e,qq,Gq,Qq,Xq,Yq,Zq,$q]);function N(G,X){return{event_version:L,type:G,...X}}var Kq=b.enum(["text","jsonl"]),Aq=b.object({headless:b.boolean().optional(),message:b.string().optional(),_:b.array(b.union([b.string(),b.number()])).optional(),model:b.string().optional(),systemPrompt:b.string().optional(),appendSystemPrompt:b.string().optional(),maxTurns:b.number().int().refine((G)=>G===-1||G>0,{message:"must be -1 or a positive integer"}).optional(),permissionMode:b.nativeEnum(H).optional(),mcpConfig:b.array(b.string()).optional(),strictMcpConfig:b.boolean().optional(),sessionId:b.string().optional(),allowedTools:b.array(b.string()).optional(),disallowedTools:b.array(b.string()).optional(),continue:b.boolean().optional(),resume:b.union([b.string(),b.boolean()]).optional(),outputFormat:Kq.optional()});class d{openedThinking=!1;wroteAssistantContent=!1;markAssistantContent(){this.wroteAssistantContent=!0}setThinkingOpened(G){this.openedThinking=G}hasOpenThinking(){return this.openedThinking}completeStream(){let G={openedThinking:this.openedThinking,wroteAssistantContent:this.wroteAssistantContent};return this.openedThinking=!1,this.wroteAssistantContent=!1,G}}function Rq(G){return G.issues.map((X)=>`${X.path.join(".")||"options"}: ${X.message}`).join("; ")}function Vq(G){let X=Aq.safeParse(G);if(!X.success)throw Error(`Invalid headless options: ${Rq(X.error)}`);return X.data}function _q(G){return G.command("* [message]","Run full agent loop without Ink UI and print events to the terminal",(X)=>X.positional("message",{describe:"Message to process",type:"string"}).option("headless",{type:"boolean",describe:"Run full agent loop without Ink UI and print events to the terminal"}).option("model",{describe:"Model ID for this run",type:"string"}).option("system-prompt",{describe:"Replace the default system prompt",type:"string"}).option("append-system-prompt",{describe:"Append a system prompt to 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"}).option("output-format",{alias:["outputFormat"],choices:["text","jsonl"],describe:"Headless output format",type:"string"}),async(X)=>{if(!X.headless)return;let Y=await Bq(X);process.exit(Y)})}function _(G,X=""){G.write(`${X}
|
|
2
|
+
`)}function Dq(G){return`[task] [${G.status}] ${G.subject}`}function Mq(){return{requestConfirmation:async(G)=>({approved:!0,reason:"headless-auto-approved",scope:"session"})}}function jq(G){if(!(G instanceof Error))return"Unknown error";let q=G.lastError??G;if(q.responseBody)try{let A=JSON.parse(q.responseBody)?.error?.message;if(A)return q.statusCode?`${A} (HTTP ${q.statusCode})`:A}catch{}let Z=G.message.match(/Last error:\s*(.+)$/);if(Z)return Z[1];return G.message}function fq(G){return G==="jsonl"?"jsonl":"text"}function W(G,X){let Y=(...q)=>{for(let Z of q){let U=X[Z];if(typeof U==="string"&&U.trim()!=="")return U}return};switch(G){case"Read":case"Edit":case"Write":case"UndoEdit":return Y("file_path");case"NotebookEdit":return Y("notebook_path");case"Grep":return Y("path","pattern");case"Glob":return Y("pattern");case"WebFetch":return Y("url");case"WebSearch":return Y("query");case"Bash":return Y("description","command");case"Task":return Y("description");case"LSP":return Y("filePath","operation");default:return}}function Pq(G,X,Y,q){let Z=new Set(["Glob","Grep","WebSearch","LS"]),U=new Set(["Read","WebFetch"]);if(new Set(["Edit","Write","NotebookEdit","Bash","LSP","UndoEdit"]).has(G)&&!q.targetLocked)return{phase:"target_hit",status:"hit",message:`Target locked: ${X}`,shouldLockTarget:!0};if(q.targetLocked)return{phase:"executing",status:"hit",message:Y?`Working within target: ${X}`:`Executing: ${X}`,shouldLockTarget:!1};if(Z.has(G))return{phase:"searching",status:"ongoing",message:`Still searching: ${X}`,shouldLockTarget:!1};if(U.has(G))return{phase:"inspecting",status:"ongoing",message:`Inspecting candidate: ${X}`,shouldLockTarget:!1};return{phase:"executing",status:q.targetLocked?"hit":"ongoing",message:`Executing: ${X}`,shouldLockTarget:!1}}function k(G,X){let Y=(q,Z)=>{G.stdout.write(`${JSON.stringify(N(q,Z))}
|
|
3
|
+
`)};return{contentDelta(q){if(X==="jsonl"){Y("content_delta",{delta:q});return}G.stdout.write(q)},thinkingDelta(q,Z){if(X==="jsonl")return Y("thinking_delta",{delta:q}),Z;if(!Z)G.stderr.write("[thinking] ");return G.stderr.write(q),!0},thinking(q){if(X==="jsonl"){Y("thinking",{content:q});return}_(G.stderr,`[thinking] ${q}`)},streamEnd(q,Z){if(X==="jsonl"){Y("stream_end",{});return}if(Z)G.stderr.write(`
|
|
4
|
+
`);if(q)G.stdout.write(`
|
|
5
|
+
`)},content(q){if(X==="jsonl"){Y("content",{content:q});return}_(G.stdout,q)},toolStart(q,Z,U,A){if(X==="jsonl"){Y("tool_start",{tool_name:q,summary:Z,target:U,tool_kind:A});return}_(G.stderr,`[tool:start] ${Z}`)},toolResult(q,Z,U,A){if(X==="jsonl"){Y("tool_result",{tool_name:q,summary:Z,target:U,tool_kind:A});return}_(G.stderr,`[tool:result] ${Z}`)},phase(q,Z,U,A={}){if(X==="jsonl"){Y("phase",{phase:q,status:Z,message:U,turn:A.turn,tool_name:A.toolName,target:A.target});return}_(G.stderr,`[phase:${q}] ${U}`)},toolDetail(q,Z){if(X==="jsonl"){Y("tool_detail",{tool_name:q,detail:Z});return}_(G.stderr,Z)},taskUpdate(q){if(X==="jsonl"){Y("task_update",{tasks:q});return}for(let Z of q)_(G.stderr,Dq(Z))},tokenUsage(q){if(X==="jsonl"){Y("token_usage",{input_tokens:q.inputTokens,output_tokens:q.outputTokens,total_tokens:q.totalTokens,max_context_tokens:q.maxContextTokens});return}_(G.stderr,`[tokens] in=${q.inputTokens} out=${q.outputTokens} total=${q.totalTokens} / ${q.maxContextTokens}`)},compacting(q){if(X==="jsonl"){Y("compacting",{state:q?"started":"completed"});return}_(G.stderr,q?"[context] compacting started":"[context] compacting completed")},turnLimit(q){if(X==="jsonl"){Y("turn_limit",{turns_count:q,action:"continue"});return}_(G.stderr,`[turn-limit] continuing after ${q} turns`)},output(q,Z=0){if(X==="jsonl"){Y("output",{content:q,exit_code:Z});return}_(Z===0?G.stdout:G.stderr,q)},error(q){if(X==="jsonl"){Y("error",{message:q});return}_(G.stderr,q)}}}async function Bq(G,X={stdout:process.stdout,stderr:process.stderr}){let Y="text",q=k(X,Y),Z=new d,U={targetLocked:!1},A;try{let K=Vq(G);Y=fq(K.outputFormat),q=k(X,Y),await z();let P=await g(K),D=await v(P);if(D.mode==="output"){if(D.content)q.output(D.content,D.exitCode??0);return D.exitCode??0}let J=K.permissionMode??"yolo",{sessionId:I,messages:u}=await p({sessionId:K.sessionId,continue:K.continue,resume:K.resume,fallbackSessionPrefix:"headless"}),m={messages:[...u],userId:"cli-user",sessionId:I,workspaceRoot:T(),permissionMode:J,confirmationHandler:Mq()};A=await w.create({sessionId:I,modelId:K.model,mcpConfig:K.mcpConfig,strictMcpConfig:K.strictMcpConfig});let l=await C.createWithRuntime(A,{sessionId:I,systemPrompt:K.systemPrompt,appendSystemPrompt:K.appendSystemPrompt,maxTurns:K.maxTurns,modelId:K.model,permissionMode:J,toolWhitelist:K.allowedTools,toolBlacklist:K.disallowedTools,mcpConfig:K.mcpConfig,strictMcpConfig:K.strictMcpConfig});if((await O(l.chatStream(D.content,m,{stream:!0,maxTurns:K.maxTurns,onTurnLimitReached:async(R)=>{return q.turnLimit(R.turnsCount),{continue:!0,reason:"headless-auto-continue"}}}),async(R)=>{switch(R.kind){case"content_delta":Z.markAssistantContent(),q.contentDelta(R.delta);break;case"thinking_delta":Z.setThinkingOpened(q.thinkingDelta(R.delta,Z.hasOpenThinking()));break;case"stream_end":{let $=Z.completeStream();q.streamEnd($.wroteAssistantContent,$.openedThinking);break}case"tool_start":{let $=R.toolCall;if(!("function"in $))break;if(["TaskCreate","TaskUpdate","TaskList"].includes($.function.name))break;try{let M=JSON.parse($.function.arguments),j=F($.function.name,M),f=W($.function.name,M),B=Pq($.function.name,j,f,U);if(B.shouldLockTarget)U.targetLocked=!0;q.phase(B.phase,B.status,B.message,{toolName:$.function.name,target:f}),q.toolStart($.function.name,j,f,R.toolKind)}catch{q.phase(U.targetLocked?"executing":"searching",U.targetLocked?"hit":"ongoing",U.targetLocked?`Working within target: ${$.function.name}`:`Still searching: ${$.function.name}`,{toolName:$.function.name}),q.toolStart($.function.name,$.function.name,void 0,R.toolKind)}break}case"tool_result":{let $=R.toolCall;if(!("function"in $))break;let M;try{let f=JSON.parse($.function.arguments);M=W($.function.name,f)}catch{M=void 0}let j=y($.function.name,R.result);if(q.toolResult($.function.name,j.summary,M,void 0),j.detail)q.toolDetail($.function.name,j.detail);break}case"token_usage":q.tokenUsage(R.usage);break;case"compaction":q.compacting(R.phase==="start");break;case"task_update":q.taskUpdate(R.tasks);break;case"model_fallback":break;case"turn_start":if(R.turn===1)U.targetLocked=!1;q.phase("turn",U.targetLocked?"hit":"ongoing",`Turn ${R.turn} started`,{turn:R.turn});break;default:{let $=R}}})).metadata?.outputTruncated)q.error("[warning] 输出因达到 token 上限被截断,部分内容可能不完整。");return q.phase("completed","done","Headless run completed"),0}catch(K){if(Z.hasOpenThinking()&&Y==="text")X.stderr.write(`
|
|
6
|
+
`);return q.error(`Error: ${jq(K)}`),1}finally{await A?.dispose()}}async function vq(){if(!process.argv.slice(2).includes("--headless"))return!1;let{headless:Y,"output-format":q,"system-prompt":Z,"append-system-prompt":U,"max-turns":A,...K}=E,P=bq(Uq(process.argv)).scriptName("blade").strict(!1).options(K).middleware([S,h,c]);return _q(P),await P.parse(),!0}export{Bq as runHeadless,vq as handleHeadlessMode,Aq as HeadlessOptionsSchema};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{t as a,u as b}from"./chunk-wr7w4af5.js";import"./chunk-3xqfqpa7.js";import"./chunk-j2ag7hh6.js";export{a as globalOptions,b as cliConfig};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{Db as y}from"./chunk-j2ag7hh6.js";import*as j from"fs/promises";import*as $ from"path";import b from"semver";import{fileURLToPath as N}from"url";import{ProxyAgent as G,fetch as H}from"undici";function T(){return process.env.HTTPS_PROXY||process.env.HTTP_PROXY||process.env.https_proxy||process.env.http_proxy}function R(){let q=T();if(q)try{return new G(q)}catch(z){console.warn(`[proxyFetch] Invalid proxy URL: ${q}`)}return}async function K(q,z={}){let{timeout:W=30000,signal:Q,...B}=z;if(Q?.aborted)throw new DOMException("The operation was aborted.","AbortError");let J=R(),X=new AbortController,Y=!1,F=setTimeout(()=>{Y=!0,X.abort()},W),w=()=>X.abort();Q?.addEventListener("abort",w);try{let Z={method:B.method,headers:B.headers,body:B.body,signal:X.signal,dispatcher:J};return await H(q.toString(),Z)}catch(Z){if(Z instanceof Error&&Z.name==="AbortError"){if(Y)throw Error(`Request timeout after ${W}ms`);throw Z}throw Z}finally{clearTimeout(F),Q?.removeEventListener("abort",w)}}var D="blade-code",f="https://cdn.jsdelivr.net/npm/blade-code@latest/CHANGELOG.md",M=$.join(process.env.HOME||process.env.USERPROFILE||".",".blade"),S=$.join(M,"version-cache.json"),k=3600000,L=`https://registry.npmjs.org/${D}/latest`;async function x(){try{if(process.env.BLADE_VERSION)return process.env.BLADE_VERSION;let q=N(import.meta.url),z=$.dirname(q),W=[$.join(z,"..","..","package.json"),$.join(z,"..","package.json")];for(let Q of W)try{let B=await j.readFile(Q,"utf-8"),J=JSON.parse(B);if(J.name===D&&J.version)return J.version}catch{}return"unknown"}catch{return"unknown"}}async function I(){try{let q=await j.readFile(S,"utf-8"),z=JSON.parse(q);if(Date.now()-z.checkedAt<k)return z;return{...z,checkedAt:0}}catch{return null}}async function O(q){try{await j.mkdir(M,{recursive:!0,mode:493}),await j.writeFile(S,JSON.stringify(q,null,2))}catch{}}async function P(){try{let q=await K(L,{timeout:5000,headers:{Accept:"application/json"}});if(!q.ok)return null;return(await q.json()).version||null}catch{return null}}async function v(q=!1){let z=await x(),W=f;if(z==="unknown")return{currentVersion:z,latestVersion:null,hasUpdate:!1,shouldPrompt:!1,releaseNotesUrl:W,error:"Unable to determine current version"};let Q=await I(),B=Q?.skipUntilVersion,J=null;if(!q&&Q&&Q.checkedAt>0)J=Q.latestVersion;else if(J=await P(),J)await O({latestVersion:J,checkedAt:Date.now(),skipUntilVersion:B});if(!J)return{currentVersion:z,latestVersion:null,hasUpdate:!1,shouldPrompt:!1,releaseNotesUrl:W,error:"Unable to check for updates"};let X=b.gt(J,z),Y=X;if(X&&B)Y=b.gt(J,B);return{currentVersion:z,latestVersion:J,hasUpdate:X,shouldPrompt:Y,releaseNotesUrl:W}}async function u(q){let z=await I();await O({latestVersion:z?.latestVersion||q,checkedAt:z?.checkedAt||Date.now(),skipUntilVersion:q})}function g(){return`npm install -g ${D}@latest --registry https://registry.npmjs.org`}async function C(){let{spawn:q}=await import("child_process");return new Promise((z)=>{let W=g(),Q=q(W,{stdio:"inherit",shell:!0});Q.on("close",(B)=>{if(B===0)z({success:!0,message:"Upgrade successful! Please restart blade."});else z({success:!1,message:`Upgrade failed (exit code: ${B})`})}),Q.on("error",(B)=>{z({success:!1,message:`Upgrade failed: ${B.message}`})})})}async function d(){try{let q=await v();return q.shouldPrompt?q:null}catch{return null}}
|
|
2
|
+
export{v as g,u as h,g as i,C as j,d as k};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{appendFileSync as Z,existsSync as _,mkdirSync as $,readdirSync as E,statSync as Y,unlinkSync as O}from"node:fs";import k from"node:os";import Q from"node:path";var R;((B)=>{B[B.DEBUG=0]="DEBUG";B[B.INFO=1]="INFO";B[B.WARN=2]="WARN";B[B.ERROR=3]="ERROR"})(R||={});var M=null,W=null,X=!1;function m(j){if(M!==j)M=j}async function I(){}function w(){if(X)return W;X=!0;try{let j=Q.join(k.homedir(),".blade","logs");if(!_(j))$(j,{recursive:!0,mode:493});if(Y(j).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(j,30),W=j,j}catch(j){return console.error("[Logger] 无法创建日志目录:",j),null}}function z(j,q){try{let G=E(j),H=Date.now(),B=q*24*60*60*1000;for(let K of G){if(!K.startsWith("blade-")||!K.endsWith(".log")&&!K.endsWith(".jsonl"))continue;let T=Q.join(j,K);try{let U=Y(T);if(H-U.mtimeMs>B)O(T)}catch(U){}}}catch(G){}}function F(){let j=w();if(!j)return null;let q=M||"default";return Q.join(j,`blade-${q}.jsonl`)}function A(j,q,G){let H=F();if(!H)return;try{let B={timestamp:new Date().toISOString(),level:R[q],category:j,message:G};Z(H,JSON.stringify(B)+`
|
|
2
|
+
`)}catch(B){}}class J{static globalDebugConfig=null;enabled;minLevel;category;constructor(j={}){if(j.enabled!==void 0)this.enabled=j.enabled;else if(J.globalDebugConfig!==null)this.enabled=Boolean(J.globalDebugConfig);else this.enabled=!1;this.minLevel=j.minLevel??0,this.category=j.category??"General"}static setGlobalDebug(j){J.globalDebugConfig=j}static clearGlobalDebug(){J.globalDebugConfig=null}setEnabled(j){this.enabled=j}parseDebugFilter(j){if(!j)return{enabled:!1};if(j===!0||j==="true"||j==="1")return{enabled:!0};let q=String(j).trim();if(!q)return{enabled:!0};if(q.startsWith("!"))return{enabled:!0,filter:{mode:"exclude",categories:q.split(",").map((B)=>B.trim().replace(/^!/,"")).filter(Boolean)}};return{enabled:!0,filter:{mode:"include",categories:q.split(",").map((H)=>H.trim()).filter(Boolean)}}}shouldLogCategory(j){if(!j)return!0;let q=this.category.toLowerCase();if(j.mode==="include")return j.categories.some((G)=>q.includes(G.toLowerCase()));return!j.categories.some((G)=>q.includes(G.toLowerCase()))}shouldLogToConsole(j){if(J.globalDebugConfig!==null){let{enabled:q,filter:G}=this.parseDebugFilter(J.globalDebugConfig);if(!q)return!1;if(j<this.minLevel)return!1;return this.shouldLogCategory(G)}return this.enabled&&j>=this.minLevel}log(j,...q){let G=q.map((H)=>typeof H==="object"?JSON.stringify(H):String(H)).join(" ");if(A(this.category,j,G),this.shouldLogToConsole(j)){let H=R[j],B=`[${this.category}] [${H}]`;console.error(B,...q)}}debug(...j){this.log(0,...j)}info(...j){this.log(1,...j)}warn(...j){this.log(2,...j)}error(...j){this.log(3,...j)}}function V(j,q){return new J({...q,category:j})}var h=new J({category:"General"});
|
|
3
|
+
export{m as yb,I as zb,J as Ab,V as Bb,h as Cb};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{va as Q}from"./chunk-m99qhdkf.js";import{nb as U}from"./chunk-ena4sxgr.js";import{xb as O}from"./chunk-7ycmx7c2.js";import{Bb as N,zb as K}from"./chunk-set7v1rf.js";function Y(){if(process.stdin.isTTY&&typeof process.stdin.setRawMode==="function")try{process.stdin.setRawMode(!1)}catch{}process.stdout.write("\x1B[<u"),process.stdout.write("\x1B[>4;0m"),process.stdout.write("\x1B[?2004l"),process.stdout.write("\x1B[?1l\x1B>"),process.stdout.write("\x1B[?25h"),process.stdout.write("\x1B[0m")}var A=N("Service");function Z(b){switch(b){case"SIGINT":return"ctrl_c";case"esc":return"esc";case"uncaughtException":case"unhandledRejection":return"error";case"SIGTERM":case"normal":default:return"user_exit"}}class D{static instance=null;cleanupHandlers=[];isShuttingDown=!1;initialized=!1;lastSigintTime=0;SIGINT_DOUBLE_CLICK_WINDOW=3000;constructor(){}static getInstance(){if(!D.instance)D.instance=new D;return D.instance}initialize(){if(this.initialized){A.debug("[GracefulShutdown] 已初始化,跳过重复初始化");return}process.on("uncaughtException",(b)=>{this.handleFatalError("uncaughtException",b)}),process.on("unhandledRejection",(b)=>{let q=b instanceof Error?b:Error(String(b));this.handleFatalError("unhandledRejection",q)}),process.on("SIGTERM",()=>{A.info("[GracefulShutdown] 收到 SIGTERM 信号"),this.shutdown("SIGTERM",0)}),process.on("SIGINT",()=>{let b=Date.now();if(b-this.lastSigintTime<this.SIGINT_DOUBLE_CLICK_WINDOW)A.info("[GracefulShutdown] 收到第二次 SIGINT 信号,执行退出"),this.shutdown("SIGINT",0);else A.info("[GracefulShutdown] 收到第一次 SIGINT 信号,再按一次退出"),this.lastSigintTime=b,console.log(`
|
|
2
|
+
再按一次 Ctrl+C 退出
|
|
3
|
+
`)}),this.initialized=!0,A.debug("[GracefulShutdown] 全局错误处理器已初始化")}registerCleanup(b){return this.cleanupHandlers.push(b),A.debug(`[GracefulShutdown] 注册清理函数,当前共 ${this.cleanupHandlers.length} 个`),()=>{let q=this.cleanupHandlers.indexOf(b);if(q!==-1)this.cleanupHandlers.splice(q,1),A.debug(`[GracefulShutdown] 取消注册清理函数,剩余 ${this.cleanupHandlers.length} 个`)}}handleFatalError(b,q){if(this.isShuttingDown){console.error(`[GracefulShutdown] 退出过程中发生额外错误 (${b}):`,q);return}if(console.error(""),console.error("═".repeat(60)),console.error(`Uncaught error (${b})`),console.error("═".repeat(60)),console.error(""),console.error("错误信息:",q.message),console.error(""),q.stack)console.error("堆栈跟踪:"),console.error(q.stack);console.error(""),console.error("═".repeat(60)),console.error(""),this.shutdown(b,1)}async shutdown(b,q=0){if(this.isShuttingDown){A.debug("[GracefulShutdown] 已在退出过程中,跳过重复退出");return}this.isShuttingDown=!0,A.info(`[GracefulShutdown] 开始优雅退出 (原因: ${b})`);try{await K()}catch(z){}try{let z=U.getInstance();if(z.isEnabled()){let F=Q(),W=F.session?.sessionId||"unknown",X=F.config?.config?.permissionMode||"default";await z.executeSessionEndHooks(Z(b),{projectDir:O(),sessionId:W,permissionMode:X})}}catch(z){console.error("[GracefulShutdown] SessionEnd hooks 执行失败:",z)}let B=5000,V=new Promise((z,F)=>{setTimeout(()=>{F(Error(`清理超时 (${B}ms)`))},B)});try{let z=this.runCleanupHandlers();await Promise.race([z,V])}catch(z){console.error("[GracefulShutdown] 清理过程中发生错误:",z)}finally{Y(),setTimeout(()=>{process.exit(q)},100)}}async runCleanupHandlers(){let b=[...this.cleanupHandlers].reverse();for(let q of b)try{let B=q();if(B instanceof Promise)await B}catch(B){console.error("[GracefulShutdown] 清理函数执行失败:",B)}}isExiting(){return this.isShuttingDown}reset(){this.isShuttingDown=!1,this.cleanupHandlers=[],this.initialized=!1}}var J=()=>{return D.getInstance()},H=(b)=>{return J().registerCleanup(b)},P=()=>{J().initialize()},L=(b=0)=>{J().shutdown("normal",b)};
|
|
4
|
+
export{J as l,H as m,P as n,L as o};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{g as a,h as b,i as c,j as d,k as e}from"./chunk-qwfywxs2.js";import"./chunk-j2ag7hh6.js";export{b as setSkipUntilVersion,d as performUpgrade,c as getUpgradeCommand,e as checkVersionOnStartup,a as checkVersion};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{v as a,w as b,x as c}from"./chunk-1en8fh5f.js";import"./chunk-m99qhdkf.js";import"./chunk-e2vtbvda.js";import"./chunk-7ycmx7c2.js";import"./chunk-set7v1rf.js";import"./chunk-j2ag7hh6.js";export{a as validatePermissions,c as validateOutput,b as loadConfiguration};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Aa as g,Ba as h,Ca as i,Da as j,Ea as k,Fa as l,Ga as m,ua as a,va as b,wa as c,xa as d,ya as e,za as f}from"./chunk-m99qhdkf.js";import"./chunk-e2vtbvda.js";import"./chunk-7ycmx7c2.js";import"./chunk-set7v1rf.js";import"./chunk-j2ag7hh6.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};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{Ia as t}from"./chunk-e2vtbvda.js";import{xb as r}from"./chunk-7ycmx7c2.js";import"./chunk-set7v1rf.js";import{Db as s}from"./chunk-j2ag7hh6.js";var m={command:"doctor",describe:"Check the health of your Blade installation",handler:async()=>{console.log(`Running Blade health check...
|
|
2
|
+
`);let e=0;try{await t.getInstance().initialize(),console.log("[OK] Configuration: OK")}catch(o){console.log("[FAIL] Configuration: FAILED"),console.log(` Error: ${o instanceof Error?o.message:"未知错误"}`),e++}let n=process.version;if(parseInt(n.slice(1).split(".")[0])>=18)console.log(`[OK] Node.js version: ${n}`);else console.log(`[WARN] Node.js version: ${n} (recommended: v18+)`),e++;try{let o=await import("fs/promises"),i=r();await o.access(i,(await import("fs")).constants.R_OK|(await import("fs")).constants.W_OK),console.log("[OK] File system permissions: OK")}catch(o){console.log("[FAIL] File system permissions: FAILED"),console.log(" Error: Cannot read/write in current directory"),e++}try{await import("ink"),console.log("[OK] Dependencies: OK")}catch(o){console.log("[FAIL] Dependencies: FAILED"),console.log(" Error: Missing required dependencies"),e++}if(console.log(`
|
|
3
|
+
Health Check Summary:`),e===0)console.log("All checks passed! Blade is ready to use.");else console.log(`Warning: Found ${e} issue(s). Please resolve them for optimal performance.`),process.exit(1)}};export{m as doctorCommands};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{ob as Q,pb as W,qb as Y}from"./chunk-5mtjqqav.js";import{Bb as X}from"./chunk-set7v1rf.js";var J=X("Service"),$="https://models.dev/api.json",j=3600000,G=null,Z=async()=>{if(G&&Date.now()-G.timestamp<j)return G.data;try{J.info("Fetching models.dev data...");let q=await fetch($,{headers:{"User-Agent":"Blade-CLI/1.0"}});if(!q.ok)throw Error(`HTTP ${q.status}: ${q.statusText}`);let x=await q.json();return G={data:x,timestamp:Date.now()},J.info(`Loaded ${Object.keys(x).length} providers from models.dev`),x}catch(q){throw J.error("Failed to fetch models.dev data:",q),q}},y=async()=>{let q=await Z(),x=[];for(let[w,k]of Object.entries(q)){let z=Object.keys(k.models||{}).length;if(z===0)continue;x.push({id:w,name:k.name||w,icon:W[w]||W.default,description:`${z} 个模型`,envVars:k.env||[],docUrl:k.doc,defaultBaseUrl:Y[w]})}return x.sort((w,k)=>{let z=Q.indexOf(w.id),K=Q.indexOf(k.id);if(z!==-1&&K!==-1)return z-K;if(z!==-1)return-1;if(K!==-1)return 1;return w.name.localeCompare(k.name)})},f=async(q)=>{let w=(await Z())[q];if(!w?.models)return J.warn(`No models found for provider: ${q}`),[];return Object.values(w.models).map((k)=>({id:k.id,name:k.name||k.id,contextWindow:k.limit?.context,maxOutput:k.limit?.output,inputCost:k.cost?.input,outputCost:k.cost?.output}))};
|
|
2
|
+
export{y as e,f};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import{a as Q,b as R,c as T,d as W}from"./chunk-akr185xe.js";import"./chunk-vwn39c84.js";import"./chunk-j79jvd54.js";import"./chunk-zxf08z5f.js";import"./chunk-esnkk33h.js";import{ba as M}from"./chunk-3xqfqpa7.js";import"./chunk-2tpgtpcp.js";import{Aa as J}from"./chunk-m99qhdkf.js";import"./chunk-e2vtbvda.js";import"./chunk-j25kww7j.js";import"./chunk-yddnm9n2.js";import"./chunk-ena4sxgr.js";import"./chunk-5mtjqqav.js";import"./chunk-7ycmx7c2.js";import"./chunk-set7v1rf.js";import"./chunk-j2ag7hh6.js";import b from"chalk";import H from"open";var $=`
|
|
2
|
+
____ _ _
|
|
3
|
+
| __ )| | __ _ __| | ___
|
|
4
|
+
| _ \\| |/ _\` |/ _\` |/ _ \\
|
|
5
|
+
| |_) | | (_| | (_| | __/
|
|
6
|
+
|____/|_|\\__,_|\\__,_|\\___|
|
|
7
|
+
`,E={command:"web",describe:"Start Blade server and open web interface",builder:Q,handler:async(X)=>{let F=R(X);if(await J(),!process.env.BLADE_SERVER_PASSWORD)console.log(b.yellow("[WARN] BLADE_SERVER_PASSWORD is not set; server is unsecured.")),console.log(b.gray(` Set this environment variable to enable Basic Auth.
|
|
8
|
+
`));let C=await W.listenAsync(F);if(console.log(b.cyan($)),console.log(b.gray(` v${M()}
|
|
9
|
+
`)),F.hostname==="0.0.0.0"){let q=`http://localhost:${C.port}`;console.log(b.blue.bold(" Local access: "),b.white(q));let Y=T();for(let Z of Y)console.log(b.blue.bold(" Network access: "),b.white(`http://${Z}:${C.port}`));H(q).catch(()=>{})}else{let q=C.url.toString();console.log(b.blue.bold(" Web interface: "),b.white(q)),H(q).catch(()=>{})}console.log(""),console.log(b.gray(` Press Ctrl+C to stop the server.
|
|
10
|
+
`)),await new Promise(()=>{}),await C.stop()}};export{E as webCommand};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{ba as d,da as h}from"./chunk-3xqfqpa7.js";var q={debug:{alias:"d",type:"string",describe:'Enable debug mode with optional category filtering (e.g., "agent,ui" or "!chat,!loop")',group:"Debug Options:"},print:{alias:"p",type:"boolean",describe:"Print response and exit (useful for pipes)",group:"Output Options:"},headless:{type:"boolean",describe:"Run full agent loop without Ink UI and print all events to the terminal",group:"Output Options:"},"output-format":{alias:["outputFormat"],type:"string",choices:["text","json","stream-json","jsonl"],default:"text",describe:"Output format: --print supports text|json|stream-json; --headless supports text|jsonl",group:"Output Options:"},"include-partial-messages":{alias:["includePartialMessages"],type:"boolean",describe:"Include partial message chunks as they arrive",group:"Output Options:"},"input-format":{alias:["inputFormat"],type:"string",choices:["text","stream-json"],default:"text",describe:"Input format",group:"Input Options:"},"replay-user-messages":{alias:["replayUserMessages"],type:"boolean",describe:"Re-emit user messages from stdin",group:"Input Options:"},"allowed-tools":{alias:["allowedTools"],type:"array",string:!0,describe:"Comma or space-separated list of tool names to allow",group:"Security Options:"},"disallowed-tools":{alias:["disallowedTools"],type:"array",string:!0,describe:"Comma or space-separated list of tool names to deny",group:"Security Options:"},"mcp-config":{alias:["mcpConfig"],type:"array",string:!0,describe:"Load MCP servers from JSON files or strings",group:"MCP Options:"},"system-prompt":{alias:["systemPrompt"],type:"string",describe:"System prompt to use for the session (replaces default)",group:"AI Options:"},"append-system-prompt":{alias:["appendSystemPrompt"],type:"string",describe:"Append a system prompt to the default system prompt",group:"AI Options:"},"max-turns":{alias:["maxTurns"],type:"number",describe:"Maximum conversation turns (-1: unlimited, 0: disable chat, N>0: limit to N turns)",group:"AI Options:",default:void 0},"permission-mode":{alias:["permissionMode"],type:"string",choices:["default","autoEdit","yolo","plan"],describe:"Permission mode (default: ask for non-read tools, autoEdit: auto-approve edits, yolo: auto-approve all, plan: reserved)",group:"Security Options:"},yolo:{type:"boolean",describe:"Auto-approve all tools (shortcut for --permission-mode=yolo)",group:"Security Options:"},continue:{alias:"c",type:"boolean",describe:"Continue the most recent conversation",group:"Session Options:"},resume:{alias:"r",describe:"Resume a conversation - provide a session ID or interactively select a conversation to resume",group:"Session Options:",coerce:(b)=>{if(b===void 0||b===!0||b==="")return"true";return String(b)}},"fork-session":{alias:["forkSession"],type:"boolean",describe:"Create a new session ID when resuming",group:"Session Options:"},settings:{type:"string",describe:"Path to a settings JSON file or JSON string",group:"Configuration:"},"add-dir":{alias:["addDir"],type:"array",string:!0,describe:"Additional directories to allow tool access to",group:"Security Options:"},ide:{type:"boolean",describe:"Automatically connect to IDE on startup",group:"Integration:"},acp:{type:"boolean",describe:"Run in ACP (Agent Client Protocol) mode for IDE integration",group:"Integration:"},"strict-mcp-config":{alias:["strictMcpConfig"],type:"boolean",describe:"Only use MCP servers from --mcp-config",group:"MCP Options:"},"session-id":{alias:["sessionId"],type:"string",describe:"Use a specific session ID for the conversation",group:"Session Options:"},agents:{type:"string",describe:"JSON object defining custom agents",group:"AI Options:"},"setting-sources":{alias:["settingSources"],type:"string",describe:"Comma-separated list of setting sources to load",group:"Configuration:"},"plugin-dir":{alias:["pluginDir"],type:"array",string:!0,describe:"Load plugins from specified directories",group:"Plugin Options:"}},w={scriptName:"blade",usage:"$0 [command] [options]",description:h(),version:d(),locale:"en",showHelpOnFail:!0,demandCommand:!1,recommendCommands:!0,strict:!1};
|
|
2
|
+
export{q as t,w as u};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{$a as l,Qa as a,Ra as b,Sa as c,Ta as d,Ua as e,Va as f,Wa as g,Xa as h,Ya as i,Za as j,_a as k,ab as m,bb as n,cb as o,fb as p,gb as q,hb as r}from"./chunk-j25kww7j.js";import"./chunk-yddnm9n2.js";import"./chunk-ena4sxgr.js";import"./chunk-5mtjqqav.js";import"./chunk-7ycmx7c2.js";import"./chunk-set7v1rf.js";import"./chunk-j2ag7hh6.js";export{g as saveUserMessage,i as saveToolUse,j as saveToolResult,k as saveCompaction,h as saveAssistantMessage,a as isRootSystemPrompt,l as handleTaskListUpdate,m as handleSkillActivation,n as extractModelSwitch,r as executeLoopGenerator,c as drainLoop,f as checkStopHook,d as checkOutputRecovery,e as checkIncompleteIntent,q as checkAndCompactInLoop,o as applyToolDomainEffects,p as StreamingToolExecutor,b as ConversationState};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function q(x){return x!==void 0&&typeof x.pattern==="string"&&typeof x.search_path==="string"}function v(x){return x!==void 0&&x.kind==="edit"&&typeof x.matches_found==="number"}function w(x){return x==="readonly"}class b{toolName;params;context;aborted=!1;result;_internal={};constructor(x,f,h){this.toolName=x;this.params=f;this.context=h}shouldAbort(){return this.aborted||(this.context.signal?.aborted??!1)}abort(x,f){this.aborted=!0,this.result={success:!1,llmContent:f?.llmContent||`Tool execution aborted: ${x||"Unknown reason"}`,error:{type:f?.errorType||"execution_error",message:x||"Execution aborted"},metadata:{summary:f?.summary||`执行已中止: ${x||"未知原因"}`,...f?.shouldExitLoop?{shouldExitLoop:!0}:{},...f?.abortedBeforeLaunch?{abortedBeforeLaunch:!0}:{}}}}setResult(x){this.result=x}getResult(){if(!this.result)throw Error("Tool execution result not set");return this.result}}export{q as ib,v as jb,w as kb,b as lb};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import{Y as O}from"./chunk-zxf08z5f.js";import"./chunk-3xqfqpa7.js";import{Ea as J,Ga as L}from"./chunk-m99qhdkf.js";import"./chunk-e2vtbvda.js";import"./chunk-yddnm9n2.js";import{xb as H}from"./chunk-7ycmx7c2.js";import"./chunk-set7v1rf.js";import"./chunk-j2ag7hh6.js";import P from"os";import E from"path";function _(q){return typeof q==="string"?q:void 0}function T(q){if(!Array.isArray(q))return;let z=[];for(let F of q)if(typeof F==="string")z.push(F);else if(F!=null)z.push(String(F));return z}function G(){console.log(`
|
|
2
|
+
blade mcp
|
|
3
|
+
`),console.log(`管理 MCP 服务器
|
|
4
|
+
`),console.log("Commands:"),console.log(" blade mcp add <name> <commandOrUrl> [args...] 添加 MCP 服务器"),console.log(" blade mcp remove <name> 删除 MCP 服务器 [aliases: rm]"),console.log(" blade mcp list 列出所有 MCP 服务器并检查健康状态 [aliases: ls]"),console.log(" blade mcp get <name> 获取服务器详情"),console.log(` blade mcp add-json <name> <json> 从 JSON 字符串添加服务器
|
|
5
|
+
`),console.log("Options:"),console.log(` -h, --help 显示帮助信息 [boolean]
|
|
6
|
+
`),console.log("Examples:"),console.log(" blade mcp list"),console.log(" blade mcp add github npx -y @modelcontextprotocol/server-github"),console.log(" blade mcp add api --transport http http://localhost:3000"),console.log(` blade mcp remove github
|
|
7
|
+
`),console.log(`使用 blade mcp <command> --help 查看各子命令的详细帮助
|
|
8
|
+
`)}function b(q){return q.reduce((z,F)=>{let[K,...B]=F.split("=");return z[K]=B.join("="),z},{})}function R(q){return q.reduce((z,F)=>{let[K,...B]=F.split(":");return z[K.trim()]=B.join(":").trim(),z},{})}var M={command:"add <name> [commandOrUrl] [args...]",describe:"添加 MCP 服务器",builder:(q)=>{return q.positional("name",{type:"string",describe:"服务器名称",demandOption:!0}).positional("commandOrUrl",{type:"string",describe:"stdio: 命令 | http/sse: URL"}).positional("args",{type:"string",array:!0,describe:"stdio 命令参数",default:[]}).option("transport",{alias:"t",choices:["stdio","sse","http"],default:"stdio",describe:"传输类型"}).option("env",{alias:"e",type:"array",describe:"环境变量 (KEY=value)"}).option("header",{alias:"H",type:"array",describe:"HTTP 头 (Key: Value)"}).option("timeout",{type:"number",describe:"超时时间(毫秒)"}).option("global",{alias:"g",type:"boolean",default:!1,describe:"存储到全局配置(~/.blade/config.json)"}).example([["$0 mcp add github -- npx -y @modelcontextprotocol/server-github","Add stdio server (recommended)"],["$0 mcp add github npx @modelcontextprotocol/server-github -e GITHUB_TOKEN=xxx","Add stdio server with env"],['$0 mcp add api --transport http http://localhost:3000 -H "Auth: Bearer token"',"Add HTTP server"]])},handler:async(q)=>{try{let{name:z,commandOrUrl:F,args:K,transport:B,env:Q,header:V,timeout:W}=q,Y=q.global===!0,$=_(z),Z=_(F),N=T(K)||[],k=T(Q),w=T(V),D=typeof W==="number"?W:void 0,I=B==="stdio"||B==="sse"||B==="http"?B:"stdio",x=q["--"];if(Array.isArray(x)&&x.length>0)Z=String(x[0]),N=x.slice(1).map((j)=>String(j));if(!$||!Z)console.error("Error: 缺少必需参数: name 和 commandOrUrl"),console.log(`
|
|
9
|
+
Tip: 用法:`),console.log(" blade mcp add <name> <command> [args...]"),console.log(" blade mcp add <name> -- <command> [args...]"),console.log(`
|
|
10
|
+
示例:`),console.log(" blade mcp add github npx -y @modelcontextprotocol/server-github"),console.log(" blade mcp add github -- npx -y @modelcontextprotocol/server-github"),process.exit(1);let X={type:I};if(I==="stdio"){if(X.command=Z,X.args=N,k)X.env=b(k)}else if(X.url=Z,w)X.headers=R(w);if(D!==void 0)X.timeout=D;await L().addMcpServer($,X,{scope:Y?"global":"project"});let U=Y?E.join(P.homedir(),".blade","config.json"):E.join(H(),".blade","config.json");console.log(`MCP 服务器 "${$}" 已添加`),console.log(` 配置文件: ${U}`)}catch(z){console.error(`Error: 添加失败: ${z instanceof Error?z.message:"未知错误"}`),process.exit(1)}}},C={command:"remove <name>",describe:"删除 MCP 服务器",aliases:["rm"],builder:(q)=>{return q.positional("name",{type:"string",describe:"服务器名称",demandOption:!0}).option("global",{alias:"g",type:"boolean",default:!1,describe:"从全局配置删除(~/.blade/config.json)"}).example([["$0 mcp remove github","Remove the specified MCP server"]])},handler:async(q)=>{try{let z=J(),F=q.global===!0,K=_(q.name);if(!K)console.error("Error: 缺少必需参数: name"),process.exit(1);if(!z[K])console.error(`Error: 服务器 "${K}" 不存在`),process.exit(1);await L().removeMcpServer(K,{scope:F?"global":"project"}),console.log(`MCP 服务器 "${K}" 已删除`)}catch(z){console.error(`Error: 删除失败: ${z instanceof Error?z.message:"未知错误"}`),process.exit(1)}}},A={command:"list",describe:"列出所有 MCP 服务器并检查健康状态",aliases:["ls"],handler:async()=>{try{let q=J();if(console.log(""),Object.keys(q).length===0){console.log("暂无配置的 MCP 服务器");return}console.log(`检查 MCP 服务器健康状态...
|
|
11
|
+
`);let z=O.getInstance(),F=Object.entries(q).map(async([B,Q])=>{try{let V=z.getServerStatus(B);if(!V)await z.registerServer(B,Q),V=z.getServerStatus(B);else if(V.status==="disconnected")await z.connectServer(B);return{name:B,config:Q,serverInfo:V}}catch(V){return{name:B,config:Q,serverInfo:null,error:V}}}),K=await Promise.all(F);for(let{name:B,config:Q,serverInfo:V,error:W}of K){let Y=V?.status||"disconnected",$=Y==="connected"?"[OK]":"[FAIL]",Z=Y==="connected"?"Connected":"Failed";if(console.log(`${B}: ${Q.type==="stdio"?Q.command:Q.url} - ${$} ${Z}`),W&&Y!=="connected")console.log(` 错误: ${W instanceof Error?W.message:String(W)}`)}console.log("");for(let{name:B}of K)try{await z.unregisterServer(B)}catch(Q){}process.exit(0)}catch(q){console.error(`Error: 列表获取失败: ${q instanceof Error?q.message:"未知错误"}`),process.exit(1)}}},h={command:"get <name>",describe:"获取服务器详情",builder:(q)=>{return q.positional("name",{type:"string",describe:"服务器名称",demandOption:!0}).example([["$0 mcp get github","Get details of the specified server"]])},handler:async(q)=>{try{let z=J(),F=_(q.name);if(!F)console.error("Error: 缺少必需参数: name"),process.exit(1);let K=z[F];if(!K)console.error(`Error: 服务器 "${F}" 不存在`),process.exit(1);console.log(`
|
|
12
|
+
服务器: ${F}
|
|
13
|
+
`),console.log(JSON.stringify(K,null,2))}catch(z){console.error(`Error: 获取失败: ${z instanceof Error?z.message:"未知错误"}`),process.exit(1)}}},d={command:"add-json <name> <json>",describe:"从 JSON 字符串添加服务器",builder:(q)=>{return q.positional("name",{type:"string",describe:"服务器名称",demandOption:!0}).positional("json",{type:"string",describe:"JSON 配置字符串",demandOption:!0}).option("global",{alias:"g",type:"boolean",default:!1,describe:"存储到全局配置(~/.blade/config.json)"}).example([[`$0 mcp add-json my-server '{"type":"stdio","command":"npx","args":["-y","@example/server"]}'`,"Add server from JSON string"]])},handler:async(q)=>{try{let z=_(q.json),F=_(q.name);if(!z||!F)throw Error("缺少必需参数: name 或 json");let K=JSON.parse(z),B=q.global===!0;if(!K.type)throw Error('配置必须包含 "type" 字段');await L().addMcpServer(F,K,{scope:B?"global":"project"});let Q=B?E.join(P.homedir(),".blade","config.json"):E.join(H(),".blade","config.json");console.log(`MCP 服务器 "${F}" 已添加`),console.log(` 配置文件: ${Q}`)}catch(z){console.error(`Error: 添加失败: ${z instanceof Error?z.message:"未知错误"}`),process.exit(1)}}},i={command:"mcp",describe:"管理 MCP 服务器",builder:(q)=>{return q.command(M).command(C).command(A).command(h).command(d).demandCommand(0).help(!1).option("help",{alias:"h",type:"boolean",describe:"显示帮助信息"})},handler:(q)=>{let z=["add","remove","list","ls","get","add-json"];if(!(Array.isArray(q._)?q._:[]).some((B)=>typeof B==="string"&&z.includes(B))||q.help)G(),process.exit(0)}};export{i as mcpCommands};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import{ba as S,ca as h}from"./chunk-3xqfqpa7.js";import{kb as M}from"./chunk-yddnm9n2.js";import{Db as c}from"./chunk-j2ag7hh6.js";import{EventEmitter as r}from"events";import{z as L}from"zod";import{isPlainObject as v}from"lodash-es";function b(B){if(B===void 0)return"undefined";if(typeof B==="string")return B;try{let G=JSON.stringify(B);return G===void 0?String(B):G}catch{return String(B)}}class R extends Error{issues;type;constructor(B,G,Q="validation_error"){super(B);this.issues=G;this.type=Q;this.name="ToolValidationError"}}function g(B){let{code:G}=B,Q=B,X=Q.received;switch(G){case"invalid_type":{let Y=Q.expected;return`类型错误:期望 ${b(Y)},实际收到 ${b(X)}`}case"too_small":{let{minimum:Y,inclusive:$}=Q,W=typeof Q.type==="string"?Q.type:void 0;if(W==="string"&&typeof Y==="number")return`长度不能少于 ${Y} 个字符`;if(W==="number"&&typeof Y==="number")return`不能小于${$?"等于":""} ${Y}`;if(W==="array"&&typeof Y==="number")return`数组长度不能少于 ${Y}`;return"值太小"}case"too_big":{let{maximum:Y,inclusive:$}=Q,W=typeof Q.type==="string"?Q.type:void 0;if(W==="string"&&typeof Y==="number")return`长度不能超过 ${Y} 个字符`;if(W==="number"&&typeof Y==="number")return`不能大于${$?"等于":""} ${Y}`;if(W==="array"&&typeof Y==="number")return`数组长度不能超过 ${Y}`;return"值太大"}case"invalid_string":{let Y=Q.validation;if(Y==="email")return"必须是有效的电子邮件地址";if(Y==="url")return"必须是有效的 URL";if(Y==="uuid")return"必须是有效的 UUID";if(v(Y)){let $=Y;if(typeof $.includes==="string")return`必须包含 "${$.includes}"`;if(typeof $.startsWith==="string")return`必须以 "${$.startsWith}" 开头`;if(typeof $.endsWith==="string")return`必须以 "${$.endsWith}" 结尾`}return"字符串格式不正确"}case"invalid_enum_value":{let Y=Q.options;if(Array.isArray(Y))return`必须是以下值之一:${Y.map(($)=>b($)).join(", ")}`;return"必须是枚举允许的值之一"}case"invalid_literal":{let Y=Q.expected;return`必须是字面量值:${b(Y)}`}case"unrecognized_keys":{let Y=Q.keys;if(Array.isArray(Y))return`包含未知的参数:${Y.map(($)=>b($)).join(", ")}`;return"包含未知的参数"}case"invalid_union":return"不符合任何有效的类型定义";case"invalid_date":return"必须是有效的日期";case"custom":return B.message||"自定义验证失败";default:return B.message||"验证失败"}}function u(B){let G=B.issues.map((X)=>{let Y=X.path.join("."),$=g(X),W=X.received;return{field:Y||"root",message:$,value:W}}),Q=G.length===1?`参数验证失败 [${G[0].field}]: ${G[0].message}`:`参数验证失败 (${G.length} 个错误):
|
|
2
|
+
${G.map((X)=>` - ${X.field}: ${X.message}`).join(`
|
|
3
|
+
`)}`;return new R(Q,G)}function y(B,G){let Q=B.safeParse(G);if(!Q.success)throw u(Q.error);return Q.data}import{zodToJsonSchema as l}from"zod-to-json-schema";function H(B){let G=l(B,{target:"jsonSchema7",$refStrategy:"none"});if(G.type==="object"&&G.properties&&!Array.isArray(G.required))G.required=[];return G}class w{toolName;params;executeFn;descriptionFn;affectedPathsFn;constructor(B,G,Q,X,Y){this.toolName=B;this.params=G;this.executeFn=Q;this.descriptionFn=X;this.affectedPathsFn=Y}getDescription(){if(this.descriptionFn)return this.descriptionFn(this.params);return`执行工具: ${this.toolName}`}getAffectedPaths(){if(this.affectedPathsFn)return this.affectedPathsFn(this.params);return[]}async execute(B,G,Q){let X={signal:B,updateOutput:G,...Q};return this.executeFn(this.params,X)}}function k(B){return{name:B.name,displayName:B.displayName,kind:B.kind,isReadOnly:B.isReadOnly??M(B.kind),isConcurrencySafe:B.isConcurrencySafe??!1,strict:B.strict??!1,description:B.description,version:B.version||"1.0.0",category:B.category,tags:B.tags||[],getFunctionDeclaration(){let G=H(B.schema),Q=B.description.short;if(B.description.long)Q+=`
|
|
4
|
+
|
|
5
|
+
${B.description.long}`;if(B.description.usageNotes&&B.description.usageNotes.length>0)Q+=`
|
|
6
|
+
|
|
7
|
+
Usage Notes:
|
|
8
|
+
${B.description.usageNotes.map((X)=>`- ${X}`).join(`
|
|
9
|
+
`)}`;if(B.description.important&&B.description.important.length>0)Q+=`
|
|
10
|
+
|
|
11
|
+
Important:
|
|
12
|
+
${B.description.important.map((X)=>`[WARN] ${X}`).join(`
|
|
13
|
+
`)}`;return{name:B.name,description:Q,parameters:G}},getMetadata(){return{name:B.name,displayName:B.displayName,kind:B.kind,version:B.version||"1.0.0",category:B.category,tags:B.tags||[],description:B.description,schema:H(B.schema)}},build(G){let Q=y(B.schema,G);return new w(B.name,Q,B.execute)},async execute(G,Q,X){return this.build(G).execute(Q||new AbortController().signal,void 0,X)},extractSignatureContent:B.extractSignatureContent?(G)=>B.extractSignatureContent(G):void 0,abstractPermissionRule:B.abstractPermissionRule?(G)=>B.abstractPermissionRule(G):void 0}}function U(B,G,Q,X){let Y;try{Y=J(Q.inputSchema)}catch(W){console.warn(`[createMcpTool] Schema 转换失败,使用降级 schema: ${Q.name}`,W),Y=L.any()}let $=X||Q.name;return k({name:$,displayName:`${G}: ${Q.name}`,kind:"execute",schema:Y,description:{short:Q.description||`MCP Tool: ${Q.name}`,important:[`From MCP server: ${G}`,"Executes external tools; user confirmation required"]},category:"MCP tool",tags:["mcp","external",G],async execute(W,q){try{let F=await B.callTool(Q.name,W),A="";if(F.content&&Array.isArray(F.content)){for(let K of F.content)if(K.type==="text"&&K.text)A+=K.text;else if(K.type==="image")A+=`[image: ${K.mimeType||"unknown"}]
|
|
14
|
+
`;else if(K.type==="resource")A+=`[resource: ${K.mimeType||"unknown"}]
|
|
15
|
+
`}if(F.isError)return{success:!1,llmContent:A||"MCP tool execution failed",error:{type:"execution_error",message:A||"MCP tool execution failed"},metadata:{summary:`MCP ${Q.name} 执行失败`,serverName:G,toolName:Q.name}};return{success:!0,llmContent:A||"Execution succeeded",metadata:{summary:`MCP ${Q.name} 执行成功`,serverName:G,toolName:Q.name,mcpResult:F}}}catch(F){return{success:!1,llmContent:`MCP tool execution failed: ${F.message}`,error:{type:"execution_error",message:F.message},metadata:{summary:`MCP ${Q.name} 执行失败`,serverName:G,toolName:Q.name}}}}})}function J(B){if(B.type==="object"||B.properties){let G={},Q=B.required||[];if(B.properties){for(let[X,Y]of Object.entries(B.properties))if(typeof Y==="object"&&Y!==null){let $=J(Y);if(!Q.includes(X))$=$.optional();G[X]=$}}return L.object(G)}if(B.type==="array"&&B.items){if(typeof B.items==="object"&&!Array.isArray(B.items)&&B.items!==null)return L.array(J(B.items));return L.array(L.any())}if(B.type==="string"){let G=L.string();if(B.minLength!==void 0)G=G.min(B.minLength);if(B.maxLength!==void 0)G=G.max(B.maxLength);if(B.pattern)G=G.regex(new RegExp(B.pattern));if(B.enum)return L.enum(B.enum);return G}if(B.type==="number"||B.type==="integer"){let G=L.number();if(B.minimum!==void 0)G=G.min(B.minimum);if(B.maximum!==void 0)G=G.max(B.maximum);return G}if(B.type==="boolean")return L.boolean();if(B.oneOf&&B.oneOf.length>0){let G=B.oneOf.filter((Q)=>typeof Q==="object"&&Q!==null).map((Q)=>J(Q));if(G.length>=2)return L.union(G)}if(B.anyOf&&B.anyOf.length>0){let G=B.anyOf.filter((Q)=>typeof Q==="object"&&Q!==null).map((Q)=>J(Q));if(G.length>=2)return L.union(G)}return L.any()}import{Client as t}from"@modelcontextprotocol/sdk/client/index.js";import{SSEClientTransport as a}from"@modelcontextprotocol/sdk/client/sse.js";import{StdioClientTransport as s}from"@modelcontextprotocol/sdk/client/stdio.js";import{EventEmitter as n}from"events";import{spawn as m}from"child_process";import*as Z from"crypto";import*as T from"http";import{URL as C}from"url";import{promises as z}from"fs";import f from"os";import P from"path";class x{tokenFilePath;constructor(){let B=f.homedir(),G=P.join(B,".blade");this.tokenFilePath=P.join(G,"mcp-oauth-tokens.json")}async ensureConfigDir(){let B=P.dirname(this.tokenFilePath);try{await z.mkdir(B,{recursive:!0,mode:493})}catch{}}async loadAllCredentials(){let B=new Map;try{let G=await z.readFile(this.tokenFilePath,"utf-8"),Q=JSON.parse(G);for(let X of Q)B.set(X.serverName,X)}catch(G){if(G.code!=="ENOENT")console.warn("[OAuthTokenStorage] 加载令牌失败:",G)}return B}async saveAllCredentials(B){await this.ensureConfigDir();let G=Array.from(B.values());await z.writeFile(this.tokenFilePath,JSON.stringify(G,null,2),{mode:384})}async saveToken(B,G,Q,X){let Y=await this.loadAllCredentials(),$={serverName:B,token:G,clientId:Q,tokenUrl:X,updatedAt:Date.now()};Y.set(B,$),await this.saveAllCredentials(Y)}async getCredentials(B){return(await this.loadAllCredentials()).get(B)||null}async deleteCredentials(B){let G=await this.loadAllCredentials();G.delete(B),await this.saveAllCredentials(G)}async listServers(){let B=await this.loadAllCredentials();return Array.from(B.keys())}isTokenExpired(B){if(!B.expiresAt)return!1;let G=300000;return Date.now()>=B.expiresAt-G}}var V=7777,D="/oauth/callback",I=200;class O{tokenStorage;constructor(B=new x){this.tokenStorage=B}generatePKCEParams(){let B=Z.randomBytes(32).toString("base64url"),G=Z.createHash("sha256").update(B).digest("base64url"),Q=Z.randomBytes(16).toString("base64url");return{codeVerifier:B,codeChallenge:G,state:Q}}buildAuthorizationUrl(B,G){let Q=B.redirectUri||`http://localhost:${V}${D}`,X=new URLSearchParams({client_id:B.clientId,response_type:"code",redirect_uri:Q,state:G.state,code_challenge:G.codeChallenge,code_challenge_method:"S256"});if(B.scopes&&B.scopes.length>0)X.append("scope",B.scopes.join(" "));let Y=new C(B.authorizationUrl);return X.forEach(($,W)=>{Y.searchParams.append(W,$)}),Y.toString()}async startCallbackServer(B){return new Promise((G,Q)=>{let X=T.createServer((Y,$)=>{try{let W=new C(Y.url,`http://localhost:${V}`);if(W.pathname!==D){$.writeHead(404),$.end("Not found");return}let q=W.searchParams.get("code"),F=W.searchParams.get("state"),A=W.searchParams.get("error");if(A){$.writeHead(I,{"Content-Type":"text/html"}),$.end(`
|
|
16
|
+
<html>
|
|
17
|
+
<body>
|
|
18
|
+
<h1>Authentication Failed</h1>
|
|
19
|
+
<p>Error: ${A}</p>
|
|
20
|
+
<p>You can close this window.</p>
|
|
21
|
+
</body>
|
|
22
|
+
</html>
|
|
23
|
+
`),X.close(),Q(Error(`OAuth error: ${A}`));return}if(!q||!F){$.writeHead(400),$.end("Missing code or state parameter");return}if(F!==B){$.writeHead(400),$.end("Invalid state parameter"),X.close(),Q(Error("State mismatch - possible CSRF attack"));return}$.writeHead(I,{"Content-Type":"text/html"}),$.end(`
|
|
24
|
+
<html>
|
|
25
|
+
<body>
|
|
26
|
+
<h1>Authentication Successful!</h1>
|
|
27
|
+
<p>You can close this window and return to Blade.</p>
|
|
28
|
+
<script>window.close();</script>
|
|
29
|
+
</body>
|
|
30
|
+
</html>
|
|
31
|
+
`),X.close(),G(q)}catch(W){X.close(),Q(W)}});X.on("error",Q),X.listen(V,()=>{console.log(`[OAuth] Callback server listening on port ${V}`)}),setTimeout(()=>{X.close(),Q(Error("OAuth callback timeout"))},300000)})}async exchangeCodeForToken(B,G,Q){let X=B.redirectUri||`http://localhost:${V}${D}`,Y=new URLSearchParams({grant_type:"authorization_code",code:G,redirect_uri:X,code_verifier:Q,client_id:B.clientId});if(B.clientSecret)Y.append("client_secret",B.clientSecret);let $=await fetch(B.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:Y.toString()});if(!$.ok){let W=await $.text();throw Error(`Token exchange failed: ${$.status} - ${W}`)}return await $.json()}async refreshAccessToken(B,G){let Q=new URLSearchParams({grant_type:"refresh_token",refresh_token:G,client_id:B.clientId});if(B.clientSecret)Q.append("client_secret",B.clientSecret);if(B.scopes&&B.scopes.length>0)Q.append("scope",B.scopes.join(" "));let X=await fetch(B.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:Q.toString()});if(!X.ok){let Y=await X.text();throw Error(`Token refresh failed: ${X.status} - ${Y}`)}return await X.json()}async authenticate(B,G){if(!G.clientId||!G.authorizationUrl||!G.tokenUrl)throw Error("Missing required OAuth configuration");let Q=this.generatePKCEParams(),X=this.buildAuthorizationUrl(G,Q);console.log(`
|
|
32
|
+
[OAuth] Opening browser for authentication...`),console.log(`
|
|
33
|
+
If the browser does not open automatically, copy and paste this URL:`),console.log(X),console.log("");let Y=this.startCallbackServer(Q.state);try{await this.openAuthorizationUrl(X)}catch(F){console.warn("[OAuth] Failed to open browser automatically:",F)}let $=await Y;console.log("[OAuth] Authorization code received, exchanging for tokens...");let W=await this.exchangeCodeForToken(G,$,Q.codeVerifier),q={accessToken:W.access_token,tokenType:W.token_type||"Bearer",refreshToken:W.refresh_token,scope:W.scope};if(W.expires_in)q.expiresAt=Date.now()+W.expires_in*1000;return await this.tokenStorage.saveToken(B,q,G.clientId,G.tokenUrl),console.log("[OAuth] Authentication successful! Token saved."),q}async openAuthorizationUrl(B){let{command:G,args:Q}=this.getBrowserCommand(B);await new Promise((X,Y)=>{let $=m(G,Q,{stdio:"ignore"});$.once("error",Y),$.once("close",(W)=>{if(W===0||W===null)X();else Y(Error(`Failed to open browser (exit code ${W})`))})})}getBrowserCommand(B){if(process.platform==="darwin")return{command:"open",args:[B]};if(process.platform==="win32")return{command:"cmd",args:["/c","start","",B]};return{command:"xdg-open",args:[B]}}async getValidToken(B,G){let Q=await this.tokenStorage.getCredentials(B);if(!Q)return null;let{token:X}=Q;if(!this.tokenStorage.isTokenExpired(X))return X.accessToken;if(X.refreshToken&&G.clientId&&Q.tokenUrl)try{console.log(`[OAuth] Refreshing expired token for server: ${B}`);let Y=await this.refreshAccessToken(G,X.refreshToken),$={accessToken:Y.access_token,tokenType:Y.token_type,refreshToken:Y.refresh_token||X.refreshToken,scope:Y.scope||X.scope};if(Y.expires_in)$.expiresAt=Date.now()+Y.expires_in*1000;return await this.tokenStorage.saveToken(B,$,G.clientId,Q.tokenUrl),$.accessToken}catch(Y){console.error("[OAuth] Failed to refresh token:",Y),await this.tokenStorage.deleteCredentials(B)}return null}}import{EventEmitter as i}from"events";class E extends i{client;config;checkTimer=null;isChecking=!1;consecutiveFailures=0;lastCheckTime=0;currentStatus="healthy";constructor(B,G={}){super();this.client=B,this.config={interval:G.interval??30000,timeout:G.timeout??1e4,enabled:G.enabled??!1,failureThreshold:G.failureThreshold??3}}start(){if(this.checkTimer){console.warn("[HealthMonitor] 健康监控已在运行");return}if(!this.config.enabled){console.log("[HealthMonitor] 健康监控未启用");return}console.log(`[HealthMonitor] 启动健康监控(间隔: ${this.config.interval}ms)`),this.scheduleNextCheck()}stop(){if(this.checkTimer)clearTimeout(this.checkTimer),this.checkTimer=null,console.log("[HealthMonitor] 停止健康监控")}scheduleNextCheck(){this.checkTimer=setTimeout(async()=>{await this.performHealthCheck(),this.scheduleNextCheck()},this.config.interval)}async performHealthCheck(){if(this.isChecking)return console.warn("[HealthMonitor] 上一次检查仍在进行中"),this.getLastResult();this.isChecking=!0,this.lastCheckTime=Date.now(),this.setStatus("checking");try{let B=this.client.connectionStatus;if(B==="connected"){await this.pingServer(),this.consecutiveFailures=0,this.setStatus("healthy");let G={status:"healthy",timestamp:Date.now(),consecutiveFailures:0};return this.emit("healthCheck",G),G}else throw Error(`连接状态异常: ${B}`)}catch(B){this.consecutiveFailures++;let G=B;console.warn(`[HealthMonitor] 健康检查失败(${this.consecutiveFailures}/${this.config.failureThreshold}):`,G.message);let Q;if(this.consecutiveFailures>=this.config.failureThreshold)Q="unhealthy",this.emit("unhealthy",this.consecutiveFailures,G),console.log("[HealthMonitor] 达到失败阈值,触发重连..."),this.triggerReconnection().catch((Y)=>{console.error("[HealthMonitor] 重连失败:",Y)});else Q="degraded";this.setStatus(Q);let X={status:Q,timestamp:Date.now(),consecutiveFailures:this.consecutiveFailures,lastError:G};return this.emit("healthCheck",X),X}finally{this.isChecking=!1}}async pingServer(){let B=new Promise((Q,X)=>{setTimeout(()=>X(Error("Health check timeout")),this.config.timeout)}),G=(async()=>{if(this.client.availableTools.length===0){if(!this.client.server)throw Error("Server info not available")}})();await Promise.race([G,B])}async triggerReconnection(){try{await this.client.disconnect(),await new Promise((B)=>setTimeout(B,1000)),await this.client.connect(),console.log("[HealthMonitor] 重连成功"),this.consecutiveFailures=0,this.setStatus("healthy"),this.emit("reconnected")}catch(B){throw console.error("[HealthMonitor] 重连失败:",B),B}}setStatus(B){if(this.currentStatus!==B){let G=this.currentStatus;this.currentStatus=B,this.emit("statusChanged",B,G)}}getStatus(){return this.currentStatus}getLastResult(){return{status:this.currentStatus,timestamp:this.lastCheckTime,consecutiveFailures:this.consecutiveFailures}}getStatistics(){return{status:this.currentStatus,consecutiveFailures:this.consecutiveFailures,lastCheckTime:this.lastCheckTime,isChecking:this.isChecking,config:this.config}}async checkNow(){return this.performHealthCheck()}resetFailureCount(){if(this.consecutiveFailures=0,this.currentStatus!=="checking")this.setStatus("healthy")}}function d(B){if(!(B instanceof Error))return{type:"unknown",isRetryable:!1,originalError:Error(String(B))};let G=B.message.toLowerCase();if(["command not found","no such file","permission denied","invalid configuration","malformed","syntax error"].some((Y)=>G.includes(Y)))return{type:"config_error",isRetryable:!1,originalError:B};if(G.includes("unauthorized")||G.includes("401")||G.includes("authentication failed"))return{type:"auth_error",isRetryable:!1,originalError:B};if(["timeout","connection refused","network error","temporary","try again","rate limit","too many requests","service unavailable","socket hang up","econnreset","enotfound","econnrefused","etimedout","503","429"].some((Y)=>G.includes(Y)))return{type:"network_temporary",isRetryable:!0,originalError:B};return{type:"unknown",isRetryable:!0,originalError:B}}class N extends n{config;status="disconnected";sdkClient=null;tools=new Map;serverInfo=null;reconnectAttempts=0;MAX_RECONNECT_ATTEMPTS=5;reconnectTimer=null;isManualDisconnect=!1;oauthProvider=null;serverName;healthMonitor=null;constructor(B,G,Q){super();this.config=B;if(this.serverName=G||"default",B.oauth?.enabled)this.oauthProvider=new O;if(Q?.enabled)this.healthMonitor=new E(this,Q),this.healthMonitor.on("unhealthy",(X,Y)=>{this.emit("unhealthy",X,Y)}),this.healthMonitor.on("reconnected",()=>{this.emit("healthMonitorReconnected")})}get connectionStatus(){return this.status}get availableTools(){return Array.from(this.tools.values())}get server(){return this.serverInfo}get healthCheck(){return this.healthMonitor}async connect(){return this.connectWithRetry(3,1000)}async connectWithRetry(B=3,G=1000){if(this.status!=="disconnected"&&this.status!=="error")throw Error("客户端已连接或正在连接中");if(this.status==="error"){if(this.sdkClient){try{await this.sdkClient.close()}catch{}this.sdkClient=null}this.setStatus("disconnected")}let Q=null;for(let X=1;X<=B;X++)try{await this.doConnect(),this.reconnectAttempts=0;return}catch(Y){Q=Y;let $=d(Y);if(!$.isRetryable)throw console.error("[McpClient] 检测到永久性错误,放弃重试:",$.type),Y;if(X<B){let W=G*Math.pow(2,X-1);console.warn(`[McpClient] 连接失败(${X}/${B}),${W}ms 后重试...`),await new Promise((q)=>setTimeout(q,W))}}throw Q||Error("连接失败")}async doConnect(){try{this.setStatus("connecting"),this.sdkClient=new t({name:h(),version:S()},{capabilities:{roots:{listChanged:!0},sampling:{}}}),this.sdkClient.onclose=()=>{this.handleUnexpectedClose()};let B=await this.createTransport();await this.sdkClient.connect(B);let G=this.sdkClient.getServerVersion();if(this.serverInfo={name:G?.name||"Unknown",version:G?.version||"0.0.0"},await this.loadTools(),this.setStatus("connected"),this.emit("connected",this.serverInfo),this.healthMonitor)this.healthMonitor.start()}catch(B){throw this.setStatus("error"),this.emit("error",B),B}}handleUnexpectedClose(){if(this.isManualDisconnect)return;if(this.status==="connected")console.warn("[McpClient] 检测到意外断连,准备重连..."),this.setStatus("error"),this.emit("error",Error("MCP服务器连接意外关闭")),this.scheduleReconnect()}scheduleReconnect(){if(this.reconnectTimer)clearTimeout(this.reconnectTimer),this.reconnectTimer=null;if(this.reconnectAttempts>=this.MAX_RECONNECT_ATTEMPTS){console.error("[McpClient] 达到最大重连次数,放弃重连"),this.emit("reconnectFailed");return}let B=Math.min(1000*Math.pow(2,this.reconnectAttempts),30000);this.reconnectAttempts++,console.log(`[McpClient] 将在 ${B}ms 后进行第 ${this.reconnectAttempts} 次重连...`),this.reconnectTimer=setTimeout(async()=>{try{if(this.sdkClient){try{await this.sdkClient.close()}catch{}this.sdkClient=null}this.setStatus("disconnected"),await this.doConnect(),console.log("[McpClient] 重连成功"),this.reconnectAttempts=0,this.emit("reconnected")}catch(G){if(console.error("[McpClient] 重连失败:",G),d(G).isRetryable)this.scheduleReconnect();else console.error("[McpClient] 检测到永久性错误,停止重连"),this.emit("reconnectFailed")}},B)}async disconnect(){if(this.isManualDisconnect=!0,this.healthMonitor)this.healthMonitor.stop();if(this.reconnectTimer)clearTimeout(this.reconnectTimer),this.reconnectTimer=null;if(this.sdkClient){try{await this.sdkClient.close()}catch(B){console.warn("[McpClient] 断开连接时出错:",B)}this.sdkClient=null}this.tools.clear(),this.serverInfo=null,this.reconnectAttempts=0,this.setStatus("disconnected"),this.emit("disconnected"),this.isManualDisconnect=!1}async callTool(B,G={}){if(!this.sdkClient)throw Error("客户端未连接到服务器");if(!this.tools.has(B))throw Error(`工具 "${B}" 不存在`);try{return await this.sdkClient.callTool({name:B,arguments:G})}catch(Q){throw console.error(`[McpClient] 调用工具 "${B}" 失败:`,Q),Q}}async createTransport(){let{type:B,command:G,args:Q,env:X,url:Y,headers:$,oauth:W}=this.config,q={...$};if(W?.enabled&&this.oauthProvider&&(B==="sse"||B==="http"))try{let F=await this.oauthProvider.getValidToken(this.serverName,W);if(!F){console.log(`[McpClient] 服务器 "${this.serverName}" 需要 OAuth 认证`);let A=await this.oauthProvider.authenticate(this.serverName,W);q.Authorization=`Bearer ${A.accessToken}`}else q.Authorization=`Bearer ${F}`}catch(F){throw console.error("[McpClient] OAuth 认证失败:",F),Error(`OAuth 认证失败: ${F instanceof Error?F.message:String(F)}`)}if(B==="stdio"){if(!G)throw Error("stdio 传输需要 command 参数");let F={};for(let[A,K]of Object.entries(process.env))if(K!==void 0)F[A]=K;return new s({command:G,args:Q||[],env:{...F,...X},stderr:"ignore"})}else if(B==="sse"){if(!Y)throw Error("sse 传输需要 url 参数");return new a(new URL(Y),{requestInit:{headers:q}})}else if(B==="http"){if(!Y)throw Error("http 传输需要 url 参数");let{StreamableHTTPClientTransport:F}=await import("@modelcontextprotocol/sdk/client/streamableHttp.js");return new F(new URL(Y),{requestInit:{headers:q}})}throw Error(`不支持的传输类型: ${B}`)}async loadTools(){if(!this.sdkClient)return;try{let B=await this.sdkClient.listTools();if(this.tools.clear(),B.tools)for(let G of B.tools)this.tools.set(G.name,G);this.emit("toolsUpdated",this.availableTools)}catch(B){throw console.error("[McpClient] 加载工具失败:",B),B}}setStatus(B){let G=this.status;this.status=B,this.emit("statusChanged",B,G)}async initialize(){return this.connect()}async destroy(){return this.disconnect()}async connectToServer(B){return this.connect()}async disconnectFromServer(B){return this.disconnect()}async listResources(B){if(!this.sdkClient)return[];try{return(await this.sdkClient.listResources()).resources||[]}catch{return[]}}async listTools(B){return this.availableTools}async readResource(B,G){if(!this.sdkClient)throw Error("客户端未连接");return(await this.sdkClient.readResource({uri:B})).contents?.[0]||{uri:B,text:""}}}class _ extends r{static instance=null;servers=new Map;isDiscovering=!1;constructor(){super()}static getInstance(){if(!_.instance)_.instance=new _;return _.instance}async registerServer(B,G){if(this.servers.has(B))throw Error(`MCP服务器 "${B}" 已经注册`);let Q=new N(G,B,G.healthCheck),X={config:G,client:Q,status:"disconnected",tools:[]};this.setupClientEventHandlers(Q,X,B),this.servers.set(B,X),this.emit("serverRegistered",B,X);try{await this.connectServer(B)}catch(Y){console.warn(`MCP服务器 "${B}" 连接失败:`,Y)}}async unregisterServer(B){let G=this.servers.get(B);if(!G)return;try{await G.client.disconnect()}catch(Q){console.warn(`断开MCP服务器 "${B}" 时出错:`,Q)}this.servers.delete(B),this.emit("serverUnregistered",B)}async connectServer(B){let G=this.servers.get(B);if(!G)throw Error(`MCP服务器 "${B}" 未注册`);if(G.status==="connected")return;try{G.status="connecting",await G.client.connect(),G.connectedAt=new Date,G.lastError=void 0,G.tools=G.client.availableTools}catch(Q){throw G.lastError=Q,G.status="error",Q}}async disconnectServer(B){let G=this.servers.get(B);if(!G)return;await G.client.disconnect(),G.connectedAt=void 0}async reconnectServer(B){let G=this.servers.get(B);if(!G)throw Error(`MCP服务器 "${B}" 未注册`);if(G.status==="connected")await G.client.disconnect();try{G.status="connecting",await G.client.connect(),G.connectedAt=new Date,G.lastError=void 0,G.tools=G.client.availableTools}catch(Q){throw G.lastError=Q,G.status="error",Q}}async getAvailableTools(){let B=[],G=new Map;for(let[Q,X]of this.servers)if(X.status==="connected")for(let Y of X.tools){let $=G.get(Y.name)||0;G.set(Y.name,$+1)}for(let[Q,X]of this.servers)if(X.status==="connected")for(let Y of X.tools){let W=(G.get(Y.name)||0)>1?`${Q}__${Y.name}`:Y.name,q=U(X.client,Q,Y,W);B.push(q)}return B}async findTool(B){for(let[G,Q]of this.servers)if(Q.status==="connected"){let X=Q.tools.find((Y)=>Y.name===B);if(X)return U(Q.client,G,X)}return null}getToolsByServer(B){let G=this.servers.get(B);if(!G||G.status!=="connected")return[];return G.tools.map((Q)=>U(G.client,B,Q))}getServerStatus(B){return this.servers.get(B)||null}getAllServers(){return new Map(this.servers)}async refreshAllTools(){let B=[];for(let[G,Q]of this.servers)if(Q.status==="connected")B.push(this.refreshServerTools(G));await Promise.allSettled(B)}async refreshServerTools(B){let G=this.servers.get(B);if(!G||G.status!=="connected")return;try{let Q=G.client.availableTools,X=G.tools.length;G.tools=Q,this.emit("toolsUpdated",B,Q,X)}catch(Q){console.warn(`刷新服务器 "${B}" 工具列表失败:`,Q)}}setupClientEventHandlers(B,G,Q){B.on("connected",(X)=>{G.status="connected",G.connectedAt=new Date,G.tools=B.availableTools,this.emit("serverConnected",Q,X)}),B.on("disconnected",()=>{G.status="disconnected",G.connectedAt=void 0,G.tools=[],this.emit("serverDisconnected",Q)}),B.on("error",(X)=>{G.status="error",G.lastError=X,this.emit("serverError",Q,X)}),B.on("toolsUpdated",(X)=>{let Y=G.tools.length;G.tools=X,this.emit("toolsUpdated",Q,X,Y)}),B.on("statusChanged",(X,Y)=>{G.status=X,this.emit("serverStatusChanged",Q,X,Y)})}async discoverServers(){if(this.isDiscovering)return Array.from(this.servers.values());this.isDiscovering=!0,this.emit("discoveryStarted");try{return Array.from(this.servers.values())}finally{this.isDiscovering=!1,this.emit("discoveryCompleted")}}async registerServers(B){let G=Object.entries(B).map(([Q,X])=>this.registerServer(Q,X).catch((Y)=>{return console.warn(`注册MCP服务器 "${Q}" 失败:`,Y),Y}));await Promise.allSettled(G)}getStatistics(){let B=0,G=0,Q=0;for(let X of this.servers.values())if(X.status==="connected")B++,G+=X.tools.length;else if(X.status==="error")Q++;return{totalServers:this.servers.size,connectedServers:B,errorServers:Q,totalTools:G,isDiscovering:this.isDiscovering}}async disconnectAll(){let B=[];for(let[G,Q]of this.servers)if(Q.status==="connected")B.push(Q.client.disconnect().catch((X)=>{console.warn(`断开 MCP 服务器 "${G}" 时出错:`,X)}));await Promise.allSettled(B),this.servers.clear()}}
|
|
34
|
+
export{k as X,_ as Y};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{A as V,G as f,J as N,K as L,M as T,S as h,U as P,V as R}from"./chunk-j79jvd54.js";import{Y as M}from"./chunk-zxf08z5f.js";import"./chunk-esnkk33h.js";import"./chunk-3xqfqpa7.js";import"./chunk-2tpgtpcp.js";import{za as y}from"./chunk-m99qhdkf.js";import"./chunk-e2vtbvda.js";import{Sa as O}from"./chunk-j25kww7j.js";import"./chunk-yddnm9n2.js";import"./chunk-ena4sxgr.js";import"./chunk-5mtjqqav.js";import{xb as D}from"./chunk-7ycmx7c2.js";import{Bb as W}from"./chunk-set7v1rf.js";import"./chunk-j2ag7hh6.js";import{Readable as K,Writable as k}from"node:stream";import*as _ from"@agentclientprotocol/sdk";import{PROTOCOL_VERSION as I}from"@agentclientprotocol/sdk";import{nanoid as S}from"nanoid";import{nanoid as x}from"nanoid";var X=W("Agent");class B{id;cwd;connection;clientCapabilities;agent=null;runtime=null;pendingPrompt=null;messages=[];mode="default";sessionApprovals=new Set;constructor(z,G,H,Q){this.id=z;this.cwd=G;this.connection=H;this.clientCapabilities=Q}async initialize(){X.debug(`[AcpSession ${this.id}] Initializing...`),V.initializeSession(this.connection,this.id,this.clientCapabilities,this.cwd),X.debug(`[AcpSession ${this.id}] ACP service context initialized`),this.runtime=await f.create({sessionId:this.id}),this.agent=await T.createWithRuntime(this.runtime,{sessionId:this.id}),X.debug(`[AcpSession ${this.id}] Agent created successfully`)}sendAvailableCommandsDelayed(){X.debug(`[AcpSession ${this.id}] Scheduling available commands update (500ms delay)`),setTimeout(()=>{this.sendAvailableCommands()},500)}async handleSlashCommand(z,G){try{X.debug(`[AcpSession ${this.id}] Executing slash command: ${z}`);let H={cwd:this.cwd,signal:G,acp:{sendMessage:(U)=>{this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:U}})},sendToolStart:(U,Y,q)=>{let Z=`tool_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,E=this.mapToolKind(q);this.sendUpdate({sessionUpdate:"tool_call",toolCallId:Z,status:"in_progress",title:`${U}`,content:[{type:"content",content:{type:"text",text:JSON.stringify(Y,null,2)}}],kind:E})},sendToolResult:(U,Y)=>{if(Y.summary)this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:Y.summary}})}}},Q=await P(z,H),J=Q.content||Q.message;if(J)this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:J}});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 X.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=R(),G=["model","permissions","theme","config","exit","ide"],Q=z.filter((J)=>!G.includes(J.name)).map((J)=>{let U;if(J.usage){let Y=J.usage.replace(/^\/\w+\s*/,"").trim();if(Y)U=Y}if(J.aliases?.length){let Y=`Aliases: ${J.aliases.join(", ")}`;U=U?`${U} | ${Y}`:Y}return{name:J.name,description:J.description,input:U?{hint:U}:void 0}});X.info(`[AcpSession ${this.id}] Sending available commands: ${JSON.stringify(Q.map((J)=>J.name))}`),this.sendUpdate({sessionUpdate:"available_commands_update",availableCommands:Q}),X.info(`[AcpSession ${this.id}] Sent ${Q.length} available commands`)}catch(z){X.error(`[AcpSession ${this.id}] Failed to send available commands:`,z)}}async prompt(z){V.setCurrentSession(this.id),this.pendingPrompt?.abort();let G=new AbortController;if(this.pendingPrompt=G,!this.agent)throw Error("Session not initialized");try{let H=this.resolvePrompt(z.prompt);if(X.debug(`[AcpSession ${this.id}] Received prompt: ${H.slice(0,100)}...`),h(H))return await this.handleSlashCommand(H,G.signal);let Q={sessionId:this.id,userId:"acp-user",workspaceRoot:this.cwd,messages:[...this.messages],signal:G.signal,permissionMode:this.mapModeToPermissionMode(),confirmationHandler:{requestConfirmation:async(J)=>{return this.requestPermission(J)}}};if(await O(this.agent.chatStream(H,Q),async(J)=>{switch(J.kind){case"content_delta":this.sendUpdate({sessionUpdate:"agent_message_chunk",content:{type:"text",text:J.delta}});break;case"thinking_delta":this.sendUpdate({sessionUpdate:"agent_thought_chunk",content:{type:"text",text:J.delta}});break;case"tool_start":{let U=J.toolCall,Y="function"in U?U.function.name:U.type,q=this.mapToolKind(J.toolKind);this.sendUpdate({sessionUpdate:"tool_call",toolCallId:U.id,status:"in_progress",title:`Executing ${Y}`,content:[],kind:q});break}case"tool_result":{let{toolCall:U,result:Y}=J,q=[],Z=Y.metadata;if(Z?.kind==="edit"&&typeof Z.file_path==="string"&&typeof Z.oldContent==="string"&&(typeof Z.newContent==="string"||Z.newContent===void 0))q.push({type:"diff",path:Z.file_path,oldText:Z.oldContent,newText:Z.newContent??null});else{let F="function"in U?U.function.name:U.type,j=L(N(F,Y));q.push({type:"content",content:{type:"text",text:j}})}let E=Y.success?"completed":"failed";this.sendUpdate({sessionUpdate:"tool_call_update",toolCallId:U.id,status:E,content:q});break}case"task_update":this.sendPlanUpdate(J.tasks);break;default:break}}),this.messages=[...Q.messages],G.signal.aborted)return{stopReason:"cancelled"};return{stopReason:"end_turn"}}catch(H){if(G.signal.aborted||H instanceof Error&&H.name==="AbortError")return{stopReason:"cancelled"};throw X.error(`[AcpSession ${this.id}] Prompt error:`,H),H}finally{if(this.pendingPrompt===G)this.pendingPrompt=null}}cancel(){if(X.info(`[AcpSession ${this.id}] Cancel requested`),this.pendingPrompt)this.pendingPrompt.abort(),this.pendingPrompt=null,X.info(`[AcpSession ${this.id}] Cancelled successfully`);else X.warn(`[AcpSession ${this.id}] No pending prompt to cancel`)}async setMode(z){let G=["default","auto-edit","yolo","plan"];this.mode=G.includes(z)?z:"default",X.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(X.info(`[AcpSession ${this.id}] Model set to: ${z}`),this.agent)X.warn(`[AcpSession ${this.id}] Runtime model switching not yet implemented`)}async destroy(){if(this.cancel(),this.agent)await this.agent.destroy(),this.agent=null;if(this.runtime)await this.runtime.dispose(),this.runtime=null;V.destroySession(this.id),X.debug(`[AcpSession ${this.id}] Destroyed`)}resolvePrompt(z){let G=[];for(let H of z)if(H.type==="text")G.push(H.text);else if(H.type==="image")G.push(`[Image: ${H.mimeType}]`);else if(H.type==="resource"){let Q=H.resource;if("text"in Q)G.push(`<file path="${Q.uri}">
|
|
2
|
+
${Q.text}
|
|
3
|
+
</file>`)}else if(H.type==="resource_link")G.push(`[Resource: ${H.uri}]`);return G.join(`
|
|
4
|
+
`)}sendUpdate(z){let G={sessionId:this.id,update:z};this.connection.sessionUpdate(G).catch((H)=>{X.warn(`[AcpSession ${this.id}] Failed to send update:`,H)})}sendPlanUpdate(z){let G=z.map((H)=>({content:H.subject,priority:H.priority,status:H.status}));X.debug(`[AcpSession ${this.id}] Sending plan update with ${G.length} entries`),this.sendUpdate({sessionUpdate:"plan",entries:G})}async requestPermission(z){let G=z.kind?.toLowerCase()||"execute";if(this.shouldAutoApprove(G))return X.debug(`[AcpSession ${this.id}] Auto-approving ${G} in mode: ${this.mode}`),{approved:!0};if(this.mode==="plan"&&(G==="write"||G==="execute"))return X.debug(`[AcpSession ${this.id}] Rejecting ${G} in plan mode`),{approved:!1,reason:"Write and execute operations are not allowed in Plan mode"};let H=`${G}:${z.title||"unknown"}`;if(this.sessionApprovals.has(H))return X.debug(`[AcpSession ${this.id}] Using cached approval for: ${H}`),{approved:!0};try{let Q=x(),J=[];if(z.message)J.push({type:"content",content:{type:"text",text:z.message}});if(z.risks&&z.risks.length>0)J.push({type:"content",content:{type:"text",text:`Risks:
|
|
5
|
+
- ${z.risks.join(`
|
|
6
|
+
- `)}`}});let U=this.mapToolKind(G),Y={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:J,kind:U}},Z=(await this.connection.requestPermission(Y)).outcome;if(Z.outcome==="cancelled")return{approved:!1,reason:"User cancelled the permission request"};let E=Z.optionId,F=E==="allow_once"||E==="allow_always";if(E==="allow_always")this.sessionApprovals.add(H),X.debug(`[AcpSession ${this.id}] Cached approval for: ${H}`);return{approved:F,reason:F?void 0:"User denied the operation"}}catch(Q){return X.warn(`[AcpSession ${this.id}] Permission request failed:`,Q),{approved:!1,reason:"Permission request failed"}}}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 $=W("Agent");class w{connection;sessions=new Map;clientCapabilities;constructor(z){this.connection=z}async initialize(z){return $.info("[BladeAgent] Initializing ACP connection"),$.debug(`[BladeAgent] Client capabilities: ${JSON.stringify(z.clientCapabilities)}`),this.clientCapabilities=z.clientCapabilities,{protocolVersion:I,agentCapabilities:{loadSession:!1,promptCapabilities:{image:!0,audio:!1,embeddedContext:!0},mcpCapabilities:{http:!0,sse:!0}}}}async authenticate(z){return}async newSession(z){let G=S();$.info(`[BladeAgent] Creating new session: ${G}`),$.debug(`[BladeAgent] Session cwd: ${z.cwd||D()}`);let H=new B(G,z.cwd||D(),this.connection,this.clientCapabilities);await H.initialize(),this.sessions.set(G,H),$.info(`[BladeAgent] Session ${G} created, scheduling available commands update`),H.sendAvailableCommandsDelayed();let Q=y(),J=Q?.models||[],U=Q?.currentModelId||J[0]?.id,Y=J.map((Z)=>({modelId:Z.id,name:Z.name||Z.id,description:Z.provider?`Provider: ${Z.provider}`:void 0}));return{sessionId:G,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:Y.length>0?{availableModels:Y,currentModelId:U}:void 0}}async prompt(z){let G=this.sessions.get(z.sessionId);if(!G)throw Error(`Session not found: ${z.sessionId}`);return G.prompt(z)}async cancel(z){$.info(`[BladeAgent] Cancel notification received for session: ${z.sessionId}`);let G=this.sessions.get(z.sessionId);if(G)$.info("[BladeAgent] Found session, calling session.cancel()"),G.cancel();else $.warn(`[BladeAgent] Session not found for cancel: ${z.sessionId}`)}async setSessionMode(z){$.info(`[BladeAgent] Setting session mode: ${z.modeId}`);let G=this.sessions.get(z.sessionId);if(G)await G.setMode(z.modeId);return{}}async unstable_setSessionModel(z){$.info(`[BladeAgent] Setting session model: ${z.modelId}`);let G=this.sessions.get(z.sessionId);if(G)await G.setModel(z.modelId);return{}}async destroy(){for(let z of this.sessions.values())await z.destroy();this.sessions.clear(),await M.getInstance().disconnectAll()}}async function Jz(){let z=k.toWeb(process.stdout),G=K.toWeb(process.stdin),H=_.ndJsonStream(z,G);await new _.AgentSideConnection((J)=>new w(J),H).closed}export{Jz as runAcpIntegration};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{j as L}from"./vendor-react-Dm1xU4bP.js";import{S as e,v as p,o as l,b as s,s as h,a as m,d as c,j as a,e as d,f as y,m as g,p as r,h as j,t as x,i as t,y as i}from"./vendor-markdown-DIcugY1e.js";import"./vendor-monaco-w6PwaWGP.js";e.registerLanguage("bash",s);e.registerLanguage("sh",s);e.registerLanguage("shell",s);e.registerLanguage("shell-session",h);e.registerLanguage("css",m);e.registerLanguage("diff",c);e.registerLanguage("javascript",a);e.registerLanguage("js",a);e.registerLanguage("json",d);e.registerLanguage("jsx",y);e.registerLanguage("markdown",g);e.registerLanguage("md",g);e.registerLanguage("python",r);e.registerLanguage("py",r);e.registerLanguage("scss",j);e.registerLanguage("tsx",x);e.registerLanguage("typescript",t);e.registerLanguage("ts",t);e.registerLanguage("yaml",i);e.registerLanguage("yml",i);function S({code:n,language:u,isDark:o}){return L.jsx(e,{style:o?p:l,language:u,PreTag:"div",wrapLongLines:!0,customStyle:{margin:0,padding:"16px",background:"transparent",fontSize:"13px",lineHeight:"1.5"},children:n})}export{S as CodeBlockHighlighter};
|