xuanzhu 0.1.3 → 0.1.4

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/LICENSE CHANGED
@@ -1,6 +1,7 @@
1
1
  MIT License
2
2
 
3
3
  Copyright (c) 2026 Oyinlola Olasunkanmi Raymond
4
+ Copyright (c) 2026 amble311 (玄猪 XuanZhu 的改造与衍生部分)
4
5
 
5
6
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
7
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -2,8 +2,18 @@
2
2
 
3
3
  > 专为终端打造的 AI 编码 Agent —— 一条 `xzh` 命令,把 AI 编程助手带进你的终端。
4
4
 
5
+ ## 快速上手
6
+
7
+ ```bash
8
+ npm i -g xuanzhu # 安装(需要 Node.js ≥ 18)
9
+ xzh model # 配置模型:选服务商、填 API Key
10
+ xzh # 启动
11
+ ```
12
+
13
+ ## 简介
14
+
5
15
  玄猪是一个运行在终端里的全屏 AI Agent:它能读懂你的代码库、直接读写文件、执行命令、运行测试,
6
- 并用流式输出向你展示它的每一步思考与工具调用。内核采用了codebuddy的开源代码。
16
+ 并用流式输出向你展示它的每一步思考与工具调用。内核采用了 codebuddy 的开源代码。
7
17
 
8
18
  ```
9
19
  ╭──────────────────────────────────────────────╮
@@ -27,33 +37,35 @@
27
37
 
28
38
  ## 安装
29
39
 
30
- ### 一键安装
40
+ ### 方式一:npm(推荐)
31
41
 
32
- **方式一:从源码目录安装(推荐)**
42
+ ```bash
43
+ npm i -g xuanzhu # 全局安装
44
+ xzh # 启动
45
+ ```
33
46
 
34
- 在仓库目录里直接执行,脚本会识别自身所在位置并**从该目录全局安装**——
35
- 因此**不要求包已发布到 npm**:
47
+ 不想全局安装,也可以免安装试用:
36
48
 
37
49
  ```bash
38
- cd /path/to/xzh
39
- ./install.sh
50
+ npx xuanzhu
40
51
  ```
41
52
 
42
- **方式二:远程一键安装**
53
+ > 若安装后提示 `xzh: command not found`,说明 npm 的全局 `bin` 目录不在 `PATH` 中,
54
+ > 见下方「PATH 配置」。
43
55
 
44
- 适用于包已发布到 npm、或通过环境变量给出可用源的情况:
56
+ ### 方式二:一键脚本
45
57
 
46
- ```bash
47
- # Linux / macOS
48
- curl -fsSL https://raw.githubusercontent.com/<owner>/<repo>/main/install.sh | sh
58
+ **Linux / macOS**
49
59
 
50
- # Windows(PowerShell)
51
- iex (irm https://raw.githubusercontent.com/<owner>/<repo>/main/install.ps1)
60
+ ```bash
61
+ curl -fsSL https://raw.githubusercontent.com/amble311/xuanzhu/main/install.sh | sh
52
62
  ```
53
63
 
54
- > 上面的 `<owner>/<repo>` 请替换为实际仓库路径。
55
- > ⚠️ 包名为 `xuanzhu`,**目前尚未发布到 npm**,因此远程方式在发布前会报 404,
56
- > 请改用方式一,或用 `XZH_PACKAGE` 指定源。
64
+ **Windows(PowerShell)**
65
+
66
+ ```powershell
67
+ iex (irm https://raw.githubusercontent.com/amble311/xuanzhu/main/install.ps1)
68
+ ```
57
69
 
58
70
  脚本会检查 Node.js 版本、全局安装 `xzh`,并在需要时提示补充 PATH。
59
71
 
@@ -64,7 +76,7 @@ iex (irm https://raw.githubusercontent.com/<owner>/<repo>/main/install.ps1)
64
76
  npm config set prefix ~/.npm-global # 然后确保 ~/.npm-global/bin 在 PATH 中
65
77
  ```
66
78
 
67
- ### 安装脚本的环境变量
79
+ **脚本支持的环境变量**
68
80
 
69
81
  | 变量 | 作用 |
70
82
  | --- | --- |
@@ -73,23 +85,29 @@ npm config set prefix ~/.npm-global # 然后确保 ~/.npm-global/bin 在 PATH
73
85
  | `XZH_NPM_ARGS` | 追加给 npm 的参数,如国内镜像 `--registry=https://registry.npmmirror.com` |
74
86
  | `XZH_DRY_RUN=1` | 只打印将要执行的命令,不真正安装 |
75
87
 
76
- ### 从源码手动安装
88
+ ### 方式三:从源码安装(开发用)
77
89
 
78
90
  ```bash
79
- # 安装依赖并构建
91
+ git clone https://github.com/amble311/xuanzhu.git
92
+ cd xuanzhu
80
93
  npm install
81
94
  npm run build
82
-
83
- # 全局链接,使 xzh 命令可用
84
- npm link
95
+ npm link # 使 xzh 命令指向本地源码
85
96
  ```
86
97
 
87
- 安装完成后,即可在任意目录运行:
98
+ 改动源码后执行 `npm run build` 即生效(`npm link` 建立的是软链)。
99
+ 想切回正式发布的版本:
88
100
 
89
101
  ```bash
90
- xzh
102
+ npm unlink -g xuanzhu && npm i -g xuanzhu
91
103
  ```
92
104
 
105
+ ### 环境要求
106
+
107
+ - **Node.js ≥ 18**
108
+ - **真实终端**:TUI 需要交互式终端,在管道、CI 或部分编辑器内置终端中无法运行
109
+ - 首次运行会在**当前工作目录**创建 `.xuanzhu/`(项目记忆与规则),建议写入 `.gitignore`
110
+
93
111
  ## 快速开始
94
112
 
95
113
  ```bash
@@ -467,6 +485,20 @@ npm run typecheck # 类型检查
467
485
  node bin/xzh.js # 本地运行
468
486
  ```
469
487
 
488
+ ## 致谢
489
+
490
+ 本项目站在前人的开源工作上,特别感谢:
491
+
492
+ - **[CodeBuddy](https://github.com/olasunkanmi-SE/codebuddy)** —— 作者
493
+ [Oyinlola Olasunkanmi Raymond](https://github.com/olasunkanmi-SE)。
494
+ 玄猪由该项目改造而来(移除编辑器依赖、改为纯粹的终端形态),
495
+ 并依 MIT 许可**保留其原始版权声明**。
496
+ - **[Playwright](https://github.com/microsoft/playwright)** —— 由 Microsoft 开源。
497
+ 内置的 `playwright` 技能基于它实现浏览器自动化与端到端测试。
498
+
499
+ 同时也感谢所有直接与间接依赖的开源项目,以及 npm 生态中的众多工具
500
+ (完整清单见 `package.json`)。
501
+
470
502
  ## License
471
503
 
472
504
  MIT
package/dist/cli.js CHANGED
@@ -128,7 +128,7 @@ ${e.trim()}`),o}var Lr=1500;function Qn(n){let e="\n\n## \u9879\u76EE\u8BB0\u5FC
128
128
  ${s}`}return e}var he=x(require("path")),es=new Set(["read_file","list_dir","glob","grep"]),ts=/(^|\/)(\.env(\..+)?|\.npmrc|\.netrc|\.git-credentials|\.ssh|\.aws|\.gnupg|\.kube|\.docker|\.xzh|\.xuanzhu|credentials|secrets?)(\/|$)|\.(pem|key|p12|pfx|jks)$|(^|\/)id_(rsa|dsa|ecdsa|ed25519)(\.|$)/i,Dr=400,rs=.5,ns=3,We=class{provider;config;cwd;events;systemPrompt;warnedTightContext=!1;history=[];activeModel;constructor(e,r,s,i,o){this.provider=e,this.config=r,this.cwd=s,this.events=i,this.activeModel=o??Q(r),this.systemPrompt=this.composeSystemPrompt()}getActiveModel(){return this.activeModel}composeSystemPrompt(){return Or(this.cwd,this.config.systemPromptExtra,hr(this.cwd),Ne(this.cwd))}get messages(){return this.history}reset(){this.history=[]}get messageCount(){return this.history.length}getCwd(){return this.cwd}setCwd(e){this.cwd=e,this.systemPrompt=this.composeSystemPrompt()}async run(e,r){let s=e;if(!this.warnedTightContext&&at(this.activeModel?.contextWindow,this.activeModel?.model??"",this.systemPrompt)&&(this.warnedTightContext=!0,this.events.onNotice?.("\u5F53\u524D\u6A21\u578B\u53EF\u7528\u4E0A\u4E0B\u6587\u8FC7\u5C0F\uFF1A\u7CFB\u7EDF\u63D0\u793A\u8BCD\u5DF2\u5360\u53BB\u7EDD\u5927\u90E8\u5206\u7A97\u53E3\uFF0C\u5386\u53F2\u4E0E\u5DE5\u5177\u8F93\u51FA\u5C06\u65E0\u6CD5\u53D1\u9001\u3002\u53EF\u7CBE\u7B80\u9879\u76EE\u89C4\u5219\uFF08.xuanzhu/rules.md\uFF09\u6216 systemPromptExtra\uFF0C\u6216\u6539\u7528\u7A97\u53E3\u66F4\u5927\u7684\u6A21\u578B\uFF08xzh model context <id> <\u5927\u5C0F>\uFF09\u3002")),this.config.intent?.enabled){this.events.onStatus("\u5206\u6790\u610F\u56FE\u4E2D");let c=await this.analyzeIntent(e,r);if(r?.aborted){this.events.onStatus("\u5DF2\u4E2D\u65AD");return}c?(s=c,this.events.onIntent?.(c,e)):this.events.onNotice?.("\u610F\u56FE\u5206\u6790\u672A\u8FD4\u56DE\u5185\u5BB9\uFF0C\u5DF2\u6309\u539F\u59CB\u8F93\u5165\u7EE7\u7EED\u3002")}let i=[{role:"user",content:s}],o=Math.max(1,Math.floor(this.config.maxToolRounds)||1),a=()=>{for(let c of i)this.history.push(c);this.trimHistory()},l=()=>{let c=[];for(let u=0;u<i.length;u++){let d=i[u];if(c.push(d),d.role!=="assistant"||!d.toolCalls?.length)continue;let h=d.toolCalls.length,m=0;for(let p=u+1;p<i.length&&m<h;p++)i[p].role==="tool"&&m++;if(m<h){c.pop();break}}if(c.length>1){for(let u of c)this.history.push(u);this.trimHistory()}};try{for(let c=0;c<o;c++){if(r?.aborted){l(),this.events.onStatus("\u5DF2\u4E2D\u65AD");return}this.trimHistory(),this.events.onStatus("\u601D\u8003\u4E2D",`\u7B2C ${c+1} \u8F6E`);let{text:u,toolCalls:d}=await this.streamAssistant(r,0,new Set,i);if(r?.aborted){l(),this.events.onStatus("\u5DF2\u4E2D\u65AD");return}if(i.push({role:"assistant",content:u,toolCalls:d.length>0?d:void 0}),d.length===0){a(),this.events.onStatus("\u5C31\u7EEA");return}for(let h of d){let m=await this.runTool(h,r);if(i.push({role:"tool",content:m.content,toolCallId:h.id,name:h.name}),this.events.onToolEnd(h,m),r?.aborted){l(),this.events.onStatus("\u5DF2\u4E2D\u65AD");return}}}a(),this.events.onStatus("\u5DF2\u8FBE\u5DE5\u5177\u8C03\u7528\u4E0A\u9650",`\u6700\u591A ${o} \u8F6E`)}catch(c){if(l(),r?.aborted){this.events.onStatus("\u5DF2\u4E2D\u65AD");return}throw c}}async analyzeIntent(e,r){let s=this.config.intent?.prompt?.trim()||Pt,i=At(s,e),o="";try{let l=this.provider.chat({messages:[{role:"user",content:i}],tools:[],temperature:this.config.temperature,signal:r});for await(let c of l)c.type==="text"&&(o+=c.text)}catch(l){return r?.aborted||this.events.onNotice?.(`\u610F\u56FE\u5206\u6790\u8BF7\u6C42\u5931\u8D25\uFF08${H(l).split(`
129
129
  `)[0]}\uFF09\uFF0C\u5DF2\u6309\u539F\u59CB\u8F93\u5165\u7EE7\u7EED\u3002`),null}let a=o.trim();return a.length>0?a:null}async streamAssistant(e,r=0,s=new Set,i=[],o=1){this.activeModel&&s.add(this.activeModel.id);let a=[{role:"system",content:this.systemPrompt},...this.buildConversation(i,o)],l="",c=[],u=!1;try{let d=this.provider.chat({messages:a,tools:Ar(),temperature:this.config.temperature,signal:e,onRetry:(h,m,p)=>{this.events.onStatus(`\u7F51\u7EDC\u4E2D\u65AD\uFF0C\u6B63\u5728\u91CD\u8BD5 (${h}/${m})`,H(p).split(`
130
130
  `)[0])}});for await(let h of d){if(e?.aborted)break;switch(u=!0,h.type){case"text":l+=h.text,this.events.onText(h.text);break;case"reasoning":this.events.onReasoning?.(h.text);break;case"tool_call":c.push(h.toolCall);break;case"done":break}}return{text:l,toolCalls:c}}catch(d){if(e?.aborted)throw d;if(!u&&!e?.aborted&&o>=1&&Ee(d))return this.events.onStatus("\u4E0A\u4E0B\u6587\u8D85\u9650","\u5DF2\u6536\u655B\u5386\u53F2\uFF0C\u6B63\u5728\u91CD\u8BD5"),this.streamAssistant(e,r,s,i,rs);if(this.handleModelFailure(d,s,!u)&&r<ns)return this.streamAssistant(e,r+1,s,i,o);throw d}}handleModelFailure(e,r,s=!0){let i=this.activeModel;if(!i)return!1;let o=H(e).split(`
131
- `)[0];if(Qe(e))return this.events.onNotice?.(`\u26A0 \u6A21\u578B ${i.id} \u7684\u914D\u7F6E\u53EF\u80FD\u6709\u8BEF\uFF08${o}\uFF09\u3002\u5DF2\u8DF3\u8FC7\u6743\u91CD\u8870\u51CF \u2014\u2014 \u8BF7\u68C0\u67E5 provider\u3001API Key \u4E0E baseUrl\u3002`),!1;let a=Lt(this.config,i.id);if(!a||(this.persistConfig(),a.reset?(this.events.onNotice?.(`\u26A0 \u6A21\u578B ${i.id} \u8C03\u7528\u5931\u8D25\uFF08${o}\uFF09\uFF1B\u6240\u6709\u6A21\u578B\u6743\u91CD\u5747\u5DF2\u8017\u5C3D\uFF0C\u5DF2\u628A\u5168\u90E8\u6743\u91CD\u91CD\u7F6E\u4E3A ${T}\u3002`),this.events.onStatus("\u6743\u91CD\u5DF2\u91CD\u7F6E")):this.events.onNotice?.(`\u26A0 \u6A21\u578B ${i.id} \u8C03\u7528\u5931\u8D25\uFF08${o}\uFF09\uFF0C\u6743\u91CD\u964D\u4E3A ${a.weight}\u3002`),this.events.onModelChange?.({provider:i.provider,model:i.model,weight:a.reset?T:a.weight,reason:"\u8C03\u7528\u5931\u8D25\u964D\u6743"}),!s))return!1;let l=Q(this.config,r);if(!l||l.id===i.id)return l&&(this.activeModel=l),!1;try{return this.provider=Ie(this.config,l),this.activeModel=l,this.events.onNotice?.(`\u21BB \u5DF2\u5207\u6362\u5230\u6A21\u578B ${l.id}\uFF08\u6743\u91CD ${l.weight}\uFF09\u91CD\u8BD5\u3002`),this.events.onModelChange?.({provider:l.provider,model:l.model,weight:l.weight,reason:"\u8C03\u7528\u5931\u8D25\u964D\u7EA7"}),!0}catch(c){return this.events.onNotice?.(`\u5207\u6362\u6A21\u578B\u5931\u8D25\uFF1A${H(c)}`),!1}}persistConfig(){try{k(this.config)}catch{}}touchesSensitivePath(e,r){if(!es.has(e))return!1;let s="";try{let a=JSON.parse(r);typeof a.path=="string"&&(s=a.path)}catch{return!1}if(!s)return!1;let i=he.resolve(this.cwd,F(s)),o=he.relative(this.cwd,i);return o&&(o.startsWith("..")||he.isAbsolute(o))?!0:ts.test(i)}async runTool(e,r){let s=$t(e.name);if(!s)return{ok:!1,content:`\u9519\u8BEF\uFF1A\u672A\u77E5\u5DE5\u5177 "${e.name}"`};if(this.touchesSensitivePath(s.name,e.arguments)||!!s.requiresConfirmation&&!this.config.autoApprove){let a=e.arguments;try{a=JSON.stringify(JSON.parse(e.arguments),null,2)}catch{}if(!await this.events.confirm({tool:e.name,title:`\u6267\u884C\u5DE5\u5177\uFF1A${e.name}`,detail:a,danger:!!s.danger}))return{ok:!1,denied:!0,content:"\u7528\u6237\u62D2\u7EDD\u4E86\u6B64\u64CD\u4F5C\u3002"}}if(r?.aborted)return{ok:!1,content:"\u64CD\u4F5C\u5DF2\u88AB\u4E2D\u65AD\u3002"};this.events.onToolStart(e);let o={cwd:this.cwd,autoApprove:this.config.autoApprove,emit:a=>this.events.onNotice?.(a),confirm:a=>this.events.confirm(a),signal:r};return Ir(e.name,e.arguments,o)}conversationBudget(){return ot(this.activeModel?.contextWindow,this.activeModel?.model??"",this.systemPrompt)}buildConversation(e,r=1){let s=[...this.history,...e],i=s.length>Dr?s.slice(-Dr):s,o=Math.max(1,Math.floor(this.conversationBudget()*r));return Pe(i,o)}trimHistory(){let e=Pe(this.history,this.conversationBudget());if(e.length===this.history.length)return 0;let r=this.history.length-e.length;return this.history=e,r}};var we="0.1.3";var t={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",italic:"\x1B[3m",underline:"\x1B[4m",inverse:"\x1B[7m",black:"\x1B[30m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",cyan:"\x1B[36m",white:"\x1B[37m",gray:"\x1B[90m",brightRed:"\x1B[91m",brightGreen:"\x1B[92m",brightYellow:"\x1B[93m",brightBlue:"\x1B[94m",brightMagenta:"\x1B[95m",brightCyan:"\x1B[96m",brightWhite:"\x1B[97m",bgRed:"\x1B[41m",bgGreen:"\x1B[42m",bgYellow:"\x1B[43m",bgBlue:"\x1B[44m",bgMagenta:"\x1B[45m",bgCyan:"\x1B[46m",bgGray:"\x1B[100m"},N={hide:"\x1B[?25l",show:"\x1B[?25h",up:(n=1)=>`\x1B[${n}A`,down:(n=1)=>`\x1B[${n}B`,right:(n=1)=>`\x1B[${n}C`,left:(n=1)=>`\x1B[${n}D`,to:(n,e)=>`\x1B[${n};${e}H`,col:n=>`\x1B[${n}G`,clearLine:"\x1B[2K",clearToEnd:"\x1B[0K",clearScreen:"\x1B[2J"},Fe={enterAlt:"\x1B[?1049h",exitAlt:"\x1B[?1049l",save:"\x1B[s",restore:"\x1B[u"};function ss(n){return n>=4352&&n<=4447||n>=11904&&n<=12350||n>=12353&&n<=13311||n>=13312&&n<=19903||n>=19968&&n<=40959||n>=40960&&n<=42191||n>=44032&&n<=55203||n>=63744&&n<=64255||n>=65072&&n<=65103||n>=65280&&n<=65376||n>=65504&&n<=65510||n>=127744&&n<=129791||n>=131072&&n<=262141}function P(n){let e=0;for(let r=0;r<n.length;r++){let s=n.codePointAt(r);if(s!==void 0){if(s===27){let i=/^\x1b\[[0-9;?]*[ -/]*[@-~]/.exec(n.slice(r));if(i){r+=i[0].length-1;continue}let o=/^\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)?/.exec(n.slice(r));if(o){r+=o[0].length-1;continue}}if(s>65535&&r++,s===9){e+=8-e%8;continue}s<32||s>=768&&s<=879||s>=8400&&s<=8447||s>=65024&&s<=65039||(e+=ss(s)?2:1)}}return e}function ve(n,e){let r=[];for(let s of n.split(`
131
+ `)[0];if(Qe(e))return this.events.onNotice?.(`\u26A0 \u6A21\u578B ${i.id} \u7684\u914D\u7F6E\u53EF\u80FD\u6709\u8BEF\uFF08${o}\uFF09\u3002\u5DF2\u8DF3\u8FC7\u6743\u91CD\u8870\u51CF \u2014\u2014 \u8BF7\u68C0\u67E5 provider\u3001API Key \u4E0E baseUrl\u3002`),!1;let a=Lt(this.config,i.id);if(!a||(this.persistConfig(),a.reset?(this.events.onNotice?.(`\u26A0 \u6A21\u578B ${i.id} \u8C03\u7528\u5931\u8D25\uFF08${o}\uFF09\uFF1B\u6240\u6709\u6A21\u578B\u6743\u91CD\u5747\u5DF2\u8017\u5C3D\uFF0C\u5DF2\u628A\u5168\u90E8\u6743\u91CD\u91CD\u7F6E\u4E3A ${T}\u3002`),this.events.onStatus("\u6743\u91CD\u5DF2\u91CD\u7F6E")):this.events.onNotice?.(`\u26A0 \u6A21\u578B ${i.id} \u8C03\u7528\u5931\u8D25\uFF08${o}\uFF09\uFF0C\u6743\u91CD\u964D\u4E3A ${a.weight}\u3002`),this.events.onModelChange?.({provider:i.provider,model:i.model,weight:a.reset?T:a.weight,reason:"\u8C03\u7528\u5931\u8D25\u964D\u6743"}),!s))return!1;let l=Q(this.config,r);if(!l||l.id===i.id)return l&&(this.activeModel=l),!1;try{return this.provider=Ie(this.config,l),this.activeModel=l,this.events.onNotice?.(`\u21BB \u5DF2\u5207\u6362\u5230\u6A21\u578B ${l.id}\uFF08\u6743\u91CD ${l.weight}\uFF09\u91CD\u8BD5\u3002`),this.events.onModelChange?.({provider:l.provider,model:l.model,weight:l.weight,reason:"\u8C03\u7528\u5931\u8D25\u964D\u7EA7"}),!0}catch(c){return this.events.onNotice?.(`\u5207\u6362\u6A21\u578B\u5931\u8D25\uFF1A${H(c)}`),!1}}persistConfig(){try{k(this.config)}catch{}}touchesSensitivePath(e,r){if(!es.has(e))return!1;let s="";try{let a=JSON.parse(r);typeof a.path=="string"&&(s=a.path)}catch{return!1}if(!s)return!1;let i=he.resolve(this.cwd,F(s)),o=he.relative(this.cwd,i);return o&&(o.startsWith("..")||he.isAbsolute(o))?!0:ts.test(i)}async runTool(e,r){let s=$t(e.name);if(!s)return{ok:!1,content:`\u9519\u8BEF\uFF1A\u672A\u77E5\u5DE5\u5177 "${e.name}"`};if(this.touchesSensitivePath(s.name,e.arguments)||!!s.requiresConfirmation&&!this.config.autoApprove){let a=e.arguments;try{a=JSON.stringify(JSON.parse(e.arguments),null,2)}catch{}if(!await this.events.confirm({tool:e.name,title:`\u6267\u884C\u5DE5\u5177\uFF1A${e.name}`,detail:a,danger:!!s.danger}))return{ok:!1,denied:!0,content:"\u7528\u6237\u62D2\u7EDD\u4E86\u6B64\u64CD\u4F5C\u3002"}}if(r?.aborted)return{ok:!1,content:"\u64CD\u4F5C\u5DF2\u88AB\u4E2D\u65AD\u3002"};this.events.onToolStart(e);let o={cwd:this.cwd,autoApprove:this.config.autoApprove,emit:a=>this.events.onNotice?.(a),confirm:a=>this.events.confirm(a),signal:r};return Ir(e.name,e.arguments,o)}conversationBudget(){return ot(this.activeModel?.contextWindow,this.activeModel?.model??"",this.systemPrompt)}buildConversation(e,r=1){let s=[...this.history,...e],i=s.length>Dr?s.slice(-Dr):s,o=Math.max(1,Math.floor(this.conversationBudget()*r));return Pe(i,o)}trimHistory(){let e=Pe(this.history,this.conversationBudget());if(e.length===this.history.length)return 0;let r=this.history.length-e.length;return this.history=e,r}};var we="0.1.4";var t={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",italic:"\x1B[3m",underline:"\x1B[4m",inverse:"\x1B[7m",black:"\x1B[30m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",cyan:"\x1B[36m",white:"\x1B[37m",gray:"\x1B[90m",brightRed:"\x1B[91m",brightGreen:"\x1B[92m",brightYellow:"\x1B[93m",brightBlue:"\x1B[94m",brightMagenta:"\x1B[95m",brightCyan:"\x1B[96m",brightWhite:"\x1B[97m",bgRed:"\x1B[41m",bgGreen:"\x1B[42m",bgYellow:"\x1B[43m",bgBlue:"\x1B[44m",bgMagenta:"\x1B[45m",bgCyan:"\x1B[46m",bgGray:"\x1B[100m"},N={hide:"\x1B[?25l",show:"\x1B[?25h",up:(n=1)=>`\x1B[${n}A`,down:(n=1)=>`\x1B[${n}B`,right:(n=1)=>`\x1B[${n}C`,left:(n=1)=>`\x1B[${n}D`,to:(n,e)=>`\x1B[${n};${e}H`,col:n=>`\x1B[${n}G`,clearLine:"\x1B[2K",clearToEnd:"\x1B[0K",clearScreen:"\x1B[2J"},Fe={enterAlt:"\x1B[?1049h",exitAlt:"\x1B[?1049l",save:"\x1B[s",restore:"\x1B[u"};function ss(n){return n>=4352&&n<=4447||n>=11904&&n<=12350||n>=12353&&n<=13311||n>=13312&&n<=19903||n>=19968&&n<=40959||n>=40960&&n<=42191||n>=44032&&n<=55203||n>=63744&&n<=64255||n>=65072&&n<=65103||n>=65280&&n<=65376||n>=65504&&n<=65510||n>=127744&&n<=129791||n>=131072&&n<=262141}function P(n){let e=0;for(let r=0;r<n.length;r++){let s=n.codePointAt(r);if(s!==void 0){if(s===27){let i=/^\x1b\[[0-9;?]*[ -/]*[@-~]/.exec(n.slice(r));if(i){r+=i[0].length-1;continue}let o=/^\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)?/.exec(n.slice(r));if(o){r+=o[0].length-1;continue}}if(s>65535&&r++,s===9){e+=8-e%8;continue}s<32||s>=768&&s<=879||s>=8400&&s<=8447||s>=65024&&s<=65039||(e+=ss(s)?2:1)}}return e}function ve(n,e){let r=[];for(let s of n.split(`
132
132
  `)){if(s===""){r.push("");continue}let i="",o=0,a=s.match(/\x1b\[[0-9;?]*[A-Za-z]|./gu)??[];for(let l of a){let c=P(l);o+c>e&&i!==""&&(r.push(i),i="",o=0),i+=l,o+=c}r.push(i)}return r}function K(n,e){if(P(n)<=e)return n;let r=n.match(/\x1b\[[0-9;?]*[A-Za-z]|[\s\S]/gu)??[],s="",i=0,o=Math.max(0,e-1);for(let a of r){let l=P(a);if(i+l>o)break;s+=a,i+=l}return`${s}${t.reset}\u2026`}function Nr(n,e){let r=P(n);return n+" ".repeat(Math.max(0,e-r))}function me(n){return n&&n.replace(/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)?/g,"").replace(/\x1b\[[0-9;?]*[ -/]*[@-~]/g,"").replace(/\x1b[@-Z\\-_]/g,"").replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g,"")}var ze=class{buffer="";inCodeBlock=!1;codeLang="";push(e){this.buffer+=e;let r=[],s=this.buffer.indexOf(`
133
133
  `);for(;s!==-1;){let i=this.buffer.slice(0,s);this.buffer=this.buffer.slice(s+1),r.push(this.renderLine(i)),s=this.buffer.indexOf(`
134
134
  `)}return r}peek(){return this.buffer?this.inCodeBlock?`${t.cyan}${this.buffer}${t.reset}`:this.buffer:""}flush(){if(this.buffer.length===0)return this.inCodeBlock=!1,this.codeLang="",[];let e=this.buffer;this.buffer="";let r=this.renderLine(e);return this.inCodeBlock=!1,this.codeLang="",[r]}renderLine(e){let r=e.replace(/\r$/,""),s=r.trimStart();if(s.startsWith("```")){if(!this.inCodeBlock){this.inCodeBlock=!0,this.codeLang=s.slice(3).trim();let a=this.codeLang?` ${this.codeLang} `:"";return`${t.gray}\u250C\u2500${a}${"\u2500".repeat(Math.max(0,6-a.length))}${t.reset}`}return this.inCodeBlock=!1,this.codeLang="",`${t.gray}\u2514\u2500\u2500${t.reset}`}if(this.inCodeBlock)return`${t.cyan}${r}${t.reset}`;let i=/^(#{1,6})\s+(.*)$/.exec(s);if(i){let a=i[2];return i[1].length<=2?`${t.bold}${t.brightWhite}${a}${t.reset}`:`${t.bold}${a}${t.reset}`}if(s.startsWith("> "))return`${t.gray}\u2502 ${s.slice(2)}${t.reset}`;let o=/^(\s*)([-*+]|\d+\.)\s+(.*)$/.exec(r);return o?`${o[1]}${t.blue}${o[2]}${t.reset} ${o[3]}`:/^(-{3,}|\*{3,}|_{3,})$/.test(s)?`${t.gray}${"\u2500".repeat(20)}${t.reset}`:this.renderInline(r)}renderInline(e){let r=e;return r=r.replace(/`([^`]+)`/g,(s,i)=>`${t.cyan}${i}${t.reset}`),r=r.replace(/\*\*([^*]+)\*\*/g,(s,i)=>`${t.bold}${i}${t.reset}`),r=r.replace(/(^|\s)\*([^*\s][^*]*)\*(?=\s|$)/g,"$1$2"),r}};var Br=require("child_process"),pe=x(require("fs")),qe=x(require("os")),U=x(require("path"));var Kr=2e3,is=8192,os=1200,He=class{lines=[];partial="";running;killTimer;cwd;onChange;parseState="text";parseSeq="";constructor(e,r){this.cwd=e,this.onChange=r,this.pushLine(`${t.gray}\u7EC8\u7AEF\u5C31\u7EEA \xB7 \u547D\u4EE4\u5728\u5F53\u524D\u9879\u76EE\u76EE\u5F55\u4E0B\u6267\u884C${t.reset}`)}getCwd(){return this.cwd}isRunning(){return this.running!==void 0}setCwd(e){this.cwd=e,this.pushLine(`${t.gray}\u2500\u2500 \u5DE5\u4F5C\u76EE\u5F55\u5DF2\u5207\u6362\uFF1A${e}${t.reset}`),this.onChange()}clear(){this.lines=[],this.partial="",this.onChange()}notice(e){this.pushLine(e),this.onChange()}visibleLines(){return this.partial?[...this.lines,this.partial]:this.lines}run(e){let r=e.trim();if(!r)return;if(this.running){this.pushLine(`${t.yellow}\u26A0 \u4E0A\u4E00\u6761\u547D\u4EE4\u4ECD\u5728\u8FD0\u884C\uFF0C\u8BF7\u5148 Ctrl+C \u4E2D\u65AD${t.reset}`),this.onChange();return}if(r==="clear"||r==="cls"){this.clear();return}if(this.handleCd(r))return;this.flushPartial(),this.pushLine(`${t.brightGreen}\u276F${t.reset} ${t.bold}${r}${t.reset}`);let s=process.env.SHELL||"/bin/bash",i;try{i=(0,Br.spawn)(s,["-c",r],{cwd:this.cwd,env:{...process.env,TERM:"xterm-256color",CLICOLOR_FORCE:"1",FORCE_COLOR:"1"},stdio:["ignore","pipe","pipe"],detached:!0})}catch(a){this.pushLine(`${t.red}\u2717 \u542F\u52A8\u5931\u8D25\uFF1A${a instanceof Error?a.message:String(a)}${t.reset}`),this.onChange();return}this.running=i;let o=a=>this.feed(a.toString("utf8"));i.stdout?.on("data",o),i.stderr?.on("data",o),i.on("error",a=>{this.flushPartial(),this.pushLine(`${t.red}\u2717 \u6267\u884C\u51FA\u9519\uFF1A${a.message}${t.reset}`),this.running=void 0,this.onChange()}),i.on("close",(a,l)=>{this.flushPartial(),l?this.pushLine(`${t.yellow}\u23F9 \u5DF2\u4E2D\u65AD\uFF08${l}\uFF09${t.reset}`):a===0?this.pushLine(`${t.gray}\u2713 \u5B8C\u6210${t.reset}`):this.pushLine(`${t.red}\u2717 \u9000\u51FA\u7801 ${a}${t.reset}`),this.running=void 0,this.onChange()}),this.onChange()}interrupt(){let e=this.running;if(!e||e.pid===void 0)return;let r=e.pid,s=i=>{try{process.kill(-r,i)}catch{try{e.kill(i)}catch{}}};s("SIGINT"),this.killTimer&&clearTimeout(this.killTimer),this.killTimer=setTimeout(()=>{this.killTimer=void 0,this.running===e&&s("SIGKILL")},os)}dispose(){this.killTimer&&(clearTimeout(this.killTimer),this.killTimer=void 0);let e=this.running;if(this.running=void 0,!(!e||e.pid===void 0))try{process.kill(-e.pid,"SIGKILL")}catch{try{e.kill("SIGKILL")}catch{}}}handleCd(e){let r=/^cd(?:\s+([\s\S]*))?$/.exec(e);if(!r)return!1;let s=(r[1]??"").trim().replace(/^['"]|['"]$/g,""),i;if(!s||s==="~")i=qe.homedir();else{let o=s.startsWith("~/")?U.join(qe.homedir(),s.slice(2)):s;i=U.isAbsolute(o)?o:U.resolve(this.cwd,o)}try{if(!pe.statSync(i).isDirectory())return this.pushLine(`${t.red}cd: \u4E0D\u662F\u76EE\u5F55\uFF1A${i}${t.reset}`),this.onChange(),!0}catch{return this.pushLine(`${t.red}cd: \u76EE\u5F55\u4E0D\u5B58\u5728\uFF1A${i}${t.reset}`),this.onChange(),!0}return this.cwd=i,this.flushPartial(),this.pushLine(`${t.gray}cd ${this.cwd}${t.reset}`),this.onChange(),!0}feed(e){let r=e.replace(/\r\n/g,`
package/package.json CHANGED
@@ -1,17 +1,26 @@
1
1
  {
2
2
  "name": "xuanzhu",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "玄猪(XuanZhu)— 专为终端打造的 AI 编码 Agent",
5
5
  "keywords": [
6
6
  "ai",
7
7
  "agent",
8
- "terminal",
9
- "tui",
10
8
  "cli",
11
- "coding-assistant"
9
+ "tui",
10
+ "coding-assistant",
11
+ "llm",
12
+ "terminal"
12
13
  ],
13
14
  "license": "MIT",
14
15
  "author": "amble311",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/amble311/xuanzhu.git"
19
+ },
20
+ "homepage": "https://github.com/amble311/xuanzhu#readme",
21
+ "bugs": {
22
+ "url": "https://github.com/amble311/xuanzhu/issues"
23
+ },
15
24
  "main": "./dist/cli.js",
16
25
  "bin": {
17
26
  "xzh": "bin/xzh.js"