@qxbyte/muse 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +320 -0
- package/dist/cli.js +3015 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.js +1405 -0
- package/dist/index.js.map +1 -0
- package/package.json +78 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Xue Qiang
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
# Muse
|
|
2
|
+
|
|
3
|
+
> A Claude Code-style agent CLI. Provider-agnostic. First-class support for Chinese / self-hostable LLMs (DeepSeek, Qwen, Kimi, GLM, Ollama, MiMo).
|
|
4
|
+
|
|
5
|
+
**状态:v0.1 MVP 搭建中**。API 不稳定,配置格式可能调整。
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 是什么
|
|
10
|
+
|
|
11
|
+
Claude Code 风格的命令行 Agent,TypeScript + Ink TUI。LLM 后端默认走 OpenAI 兼容协议,国产模型 / 本地模型 / 自部署网关都是一等公民。
|
|
12
|
+
|
|
13
|
+
设计借鉴 Claude Code 的命令体验(slash 命令、目录结构、约定),但不依赖 Anthropic API。适合:
|
|
14
|
+
|
|
15
|
+
- 在国内网络环境下需要 Claude Code 体验
|
|
16
|
+
- 想用 DeepSeek / Qwen / Kimi / GLM / Ollama / 自建 vLLM 等
|
|
17
|
+
- 希望 model 可热切换、凭证不写源码
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 前置要求
|
|
22
|
+
|
|
23
|
+
- **Node.js >= 20**(必须;用了原生 fetch / `node:fs/promises` 等)
|
|
24
|
+
- **npm**(默认;不要换 pnpm / bun,未做兼容测试)
|
|
25
|
+
- **git**
|
|
26
|
+
- 一个 OpenAI 兼容协议的 LLM 端点 + apiKey(DeepSeek / Qwen / MiMo / 自建均可)
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 安装
|
|
31
|
+
|
|
32
|
+
### 方式 A:从 npm(推荐)
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install -g @qxbyte/muse
|
|
36
|
+
muse --version
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
> 包名是 `@qxbyte/muse`(scoped),CLI 命令名是 `muse`。需要 Node 20+。
|
|
40
|
+
|
|
41
|
+
### 方式 B:从源码
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# 1. 拉源码
|
|
45
|
+
git clone https://github.com/qxbyte/muse.git
|
|
46
|
+
cd muse
|
|
47
|
+
|
|
48
|
+
# 2. 装依赖
|
|
49
|
+
npm install
|
|
50
|
+
|
|
51
|
+
# 3. 构建(产物在 dist/)
|
|
52
|
+
npm run build
|
|
53
|
+
|
|
54
|
+
# 4. 验证
|
|
55
|
+
node ./dist/cli.js --version # 应输出 0.1.0
|
|
56
|
+
node ./dist/cli.js --help
|
|
57
|
+
|
|
58
|
+
# 5.(可选)全局可用,二选一:
|
|
59
|
+
# A) npm link(推荐)—— 在仓库目录下:
|
|
60
|
+
npm link
|
|
61
|
+
muse --version
|
|
62
|
+
|
|
63
|
+
# B) shell alias —— 仅当前 shell 生效:
|
|
64
|
+
echo 'alias muse="node $(pwd)/dist/cli.js"' >> ~/.zshrc
|
|
65
|
+
source ~/.zshrc
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 配置
|
|
71
|
+
|
|
72
|
+
muse 用**两个文件**分工:
|
|
73
|
+
|
|
74
|
+
| 文件 | 角色 |
|
|
75
|
+
|---|---|
|
|
76
|
+
| `~/.muse/models.json` | 模型仓库:你能调用的所有模型 + apiKey |
|
|
77
|
+
| `~/.muse/settings.json` | 运行偏好:当前激活哪个 model、UI、权限规则 |
|
|
78
|
+
|
|
79
|
+
### 1. 建 `~/.muse/models.json`
|
|
80
|
+
|
|
81
|
+
凭证**强烈推荐**放到 `~/.muse/models.local.json`(自动 gitignore 防误传)或用 `${ENV_VAR}` 占位符。
|
|
82
|
+
|
|
83
|
+
#### 示例 A:DeepSeek
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
mkdir -p ~/.muse
|
|
87
|
+
cat > ~/.muse/models.json <<'EOF'
|
|
88
|
+
{
|
|
89
|
+
"models": [
|
|
90
|
+
{
|
|
91
|
+
"id": "deepseek-chat",
|
|
92
|
+
"vendor": "DeepSeek",
|
|
93
|
+
"baseUrl": "https://api.deepseek.com/v1",
|
|
94
|
+
"apiKey": "${DEEPSEEK_API_KEY}",
|
|
95
|
+
"supportsToolCall": true
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"id": "deepseek-reasoner",
|
|
99
|
+
"vendor": "DeepSeek",
|
|
100
|
+
"baseUrl": "https://api.deepseek.com/v1",
|
|
101
|
+
"apiKey": "${DEEPSEEK_API_KEY}",
|
|
102
|
+
"supportsToolCall": false
|
|
103
|
+
}
|
|
104
|
+
],
|
|
105
|
+
"availableModels": ["deepseek-chat", "deepseek-reasoner"]
|
|
106
|
+
}
|
|
107
|
+
EOF
|
|
108
|
+
|
|
109
|
+
export DEEPSEEK_API_KEY=sk-... # 写到 ~/.zshrc 持久化
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
#### 示例 B:本地 Ollama
|
|
113
|
+
|
|
114
|
+
```json
|
|
115
|
+
{
|
|
116
|
+
"models": [
|
|
117
|
+
{
|
|
118
|
+
"id": "llama3.1",
|
|
119
|
+
"vendor": "Ollama",
|
|
120
|
+
"baseUrl": "http://localhost:11434/v1",
|
|
121
|
+
"supportsToolCall": true
|
|
122
|
+
}
|
|
123
|
+
],
|
|
124
|
+
"availableModels": ["llama3.1"]
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
本地 endpoint 不需要 apiKey。
|
|
129
|
+
|
|
130
|
+
#### 字段说明
|
|
131
|
+
|
|
132
|
+
| 字段 | 必填 | 说明 |
|
|
133
|
+
|---|---|---|
|
|
134
|
+
| `id` | 是 | 模型唯一标识,自定义;slash 命令引用它 |
|
|
135
|
+
| `vendor` | 否 | 厂商名,只在 selector 里显示 |
|
|
136
|
+
| `baseUrl` | 是 | OpenAI 兼容协议基址(如 `https://api.deepseek.com/v1`);也可填 `url` 别名;若误填 `.../chat/completions` 会自动剥后缀 |
|
|
137
|
+
| `apiKey` | 否 | 凭证;支持 `${ENV_VAR}` 占位符 |
|
|
138
|
+
| `supportsToolCall` | 否 | 工具调用能力,默认 `true` |
|
|
139
|
+
| `supportsImages` | 否 | 视觉能力,默认 `false` |
|
|
140
|
+
| `contextWindow` | 否 | 上下文窗口大小(tokens),用于 `/cost` 估算 |
|
|
141
|
+
| `availableModels` | — | 顶层数组;决定 `/models` selector 里出现哪些 id(不填 = 全部) |
|
|
142
|
+
|
|
143
|
+
### 2. 建 `~/.muse/settings.json`(首次启动会自动写)
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
cat > ~/.muse/settings.json <<'EOF'
|
|
147
|
+
{
|
|
148
|
+
"llm": {
|
|
149
|
+
"model": "deepseek-chat"
|
|
150
|
+
},
|
|
151
|
+
"ui": {
|
|
152
|
+
"lang": "zh-CN",
|
|
153
|
+
"showBanner": true
|
|
154
|
+
},
|
|
155
|
+
"permissions": {
|
|
156
|
+
"allow": ["Read", "Grep", "Glob"],
|
|
157
|
+
"ask": ["Write", "Edit", "Bash"],
|
|
158
|
+
"defaultMode": "ask"
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
EOF
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
settings.json 里的 `llm.model` 必须**匹配**某个 models.json 里的 id;`/models` 选中模型后会自动写回这个字段。
|
|
165
|
+
|
|
166
|
+
### 3. (可选)项目级覆盖
|
|
167
|
+
|
|
168
|
+
在你工作目录里建 `.muse/settings.json` 或 `.muse/settings.local.json`,对应字段会覆盖全局 settings。`*.local.json` 已被项目 `.gitignore` 忽略,放凭证安全。
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 启动
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
muse # 交互模式(TUI)
|
|
176
|
+
muse "总结一下 src/cli.tsx" # 一次性 prompt 模式
|
|
177
|
+
cat bug.log | muse "找出根因" # 管道输入
|
|
178
|
+
muse --debug # 详细日志(写到 ~/.muse/logs/<date>.jsonl)
|
|
179
|
+
muse --help
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
CLI flag:
|
|
183
|
+
|
|
184
|
+
| flag | 说明 |
|
|
185
|
+
|---|---|
|
|
186
|
+
| `-m, --model <id>` | 临时切 model(不写回 settings.json) |
|
|
187
|
+
| `-p, --provider <name>` | 临时切 provider(仅 fallback 路径用) |
|
|
188
|
+
| `--no-banner` | 不显示启动 banner |
|
|
189
|
+
| `--quiet` | 最小输出(隐含 `--no-banner`) |
|
|
190
|
+
| `--debug` | 详细日志 |
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## 内置 Slash 命令
|
|
195
|
+
|
|
196
|
+
启动后在 TUI 输入 `/` 会自动弹出补全列表,↑↓ 导航,Tab/Enter 补全。
|
|
197
|
+
|
|
198
|
+
| 命令 | 作用 |
|
|
199
|
+
|---|---|
|
|
200
|
+
| `/help` | 列出所有命令 |
|
|
201
|
+
| `/clear` | 清空当前会话 |
|
|
202
|
+
| `/cost` | 当前会话 token 用量 + 费用估算 |
|
|
203
|
+
| `/status` | 模型 / cwd / 历史 / token 综合状态 |
|
|
204
|
+
| `/models` | 弹出 selector 切换模型(写回 settings.json + 注入 env) |
|
|
205
|
+
| `/config` | 显示 effective 配置(apiKey 脱敏);`/config reload` 热加载;`/config path` 看路径 |
|
|
206
|
+
| `/mcp` | MCP server 状态(v0.1 占位,v0.3 真接) |
|
|
207
|
+
| `/compact` | 摘要老消息释放上下文(`--keep N` 保留最近 N 条) |
|
|
208
|
+
| `/resume` | ↑↓ 选历史会话加载;带参 `/resume <id-prefix>` 直接加载 |
|
|
209
|
+
| `/quit` / `/exit` | 退出 |
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## 目录结构
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
muse/
|
|
217
|
+
src/
|
|
218
|
+
cli.tsx # CLI 入口(commander + Ink)
|
|
219
|
+
app.tsx # Ink 根组件
|
|
220
|
+
components/ # TUI 组件
|
|
221
|
+
llm/ # LLM 抽象层(providers + pricing)
|
|
222
|
+
loop/ # Agent loop + 上下文压缩
|
|
223
|
+
tools/ # 工具系统 + 内置工具(Read/Write/Edit/Bash/Grep/Glob)
|
|
224
|
+
slash/ # Slash 命令系统
|
|
225
|
+
config/ # 配置加载(settings + models)
|
|
226
|
+
session/ # JSONL 会话持久化
|
|
227
|
+
permission/ # 权限模型(三态 + 4 档 mode)
|
|
228
|
+
mcp/ # MCP 状态查询(占位)
|
|
229
|
+
log/ # logger
|
|
230
|
+
dist/ # 构建产物(不入 git)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## 凭证安全
|
|
236
|
+
|
|
237
|
+
- **绝不**把明文 apiKey 写进 `models.json` 之外的文件,更不要写进源码
|
|
238
|
+
- 凭证有三种推荐放法(优先级从高到低):
|
|
239
|
+
1. 环境变量 `${VAR}` 占位符 + shell 配置(最安全,方便 CI)
|
|
240
|
+
2. `~/.muse/models.local.json`(chmod 600;项目级 `*.local.json` 已 gitignore)
|
|
241
|
+
3. `~/.muse/models.json` 明文(仅当你 100% 确定该机器/账号是私有)
|
|
242
|
+
- muse 日志里 apiKey 自动脱敏(前 4 + 后 4)
|
|
243
|
+
- 切换 model 时,apiKey 注入 `process.env.MUSE_ACTIVE_API_KEY`,业务代码只透过 env 取,不持有副本
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## 已知限制(v0.1)
|
|
248
|
+
|
|
249
|
+
- ❌ MCP 协议接入未实现(v0.3 路线图);`/mcp` 仅显示配置
|
|
250
|
+
- ❌ Skill 加载未实现(v0.2)
|
|
251
|
+
- ❌ Subagent 未实现(v0.2)
|
|
252
|
+
- ❌ Hooks 未实现(v1.0)
|
|
253
|
+
- ❌ 自动上下文压缩未实现(`/compact` 手动可用)
|
|
254
|
+
- ⚠️ Anthropic provider 未实现(只支持 OpenAI 兼容协议族)
|
|
255
|
+
- ⚠️ `--continue` flag 未完整接通
|
|
256
|
+
- ⚠️ TUI 输入框历史导航(↑↓ 翻历史)未实现,被 `/models` autocomplete 占用
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## 路线图
|
|
261
|
+
|
|
262
|
+
- **v0.1 MVP(当前)**:CLI / LLM / Agent loop / Read/Write/Edit/Bash/Grep/Glob / 权限模型 / Session / 9 个 slash 命令
|
|
263
|
+
- **v0.2**:Skill 加载、Slash command 文件加载、Subagent、自动 compact
|
|
264
|
+
- **v0.3**:MCP 客户端、Anthropic provider、多 provider 能力矩阵
|
|
265
|
+
- **v0.4**:长期 Memory、TodoWrite、单二进制分发
|
|
266
|
+
- **v1.0**:Hooks、沙箱(sandbox-exec)、自定义 subagent 类型
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## 设计文档
|
|
271
|
+
|
|
272
|
+
宏观设计 / 实现日志 / 子规范在 `CLAUDE.md` 关联的文档库(私有 Obsidian vault),代码注释引用对应章节(如 `// 见 muse-design.md §7.2`)。
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## 发布到 npm(维护者)
|
|
277
|
+
|
|
278
|
+
发布完全自动化:在 GitHub 上 publish 一个 release,`.github/workflows/release.yml` 会跑 typecheck + build + `npm publish --provenance`。
|
|
279
|
+
|
|
280
|
+
### 一次性准备(首次发布前)
|
|
281
|
+
|
|
282
|
+
1. 在 [npm.com](https://www.npmjs.com/) 注册账号 `qxbyte`(与 GitHub 用户名一致,确保 scope `@qxbyte/` 归属正确)
|
|
283
|
+
2. npm.com → 头像菜单 → **Access Tokens** → **Generate New Token** → **Classic** → 选 **Automation**(CI 专用)
|
|
284
|
+
3. 复制 token(`npm_...` 开头)
|
|
285
|
+
4. GitHub repo → **Settings** → **Secrets and variables** → **Actions** → **New repository secret**
|
|
286
|
+
- Name: `NPM_TOKEN`
|
|
287
|
+
- Value: 粘贴上一步的 token
|
|
288
|
+
|
|
289
|
+
### 每次发布
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
# 1. 改 package.json 的 version(语义化版本:0.1.0 → 0.1.1 / 0.2.0 / 1.0.0)
|
|
293
|
+
npm version patch # 或 minor / major;这条会自动 commit 并打 tag vX.Y.Z
|
|
294
|
+
|
|
295
|
+
# 2. 推 commit + tag
|
|
296
|
+
git push && git push --tags
|
|
297
|
+
|
|
298
|
+
# 3. 到 GitHub Releases 页面(https://github.com/qxbyte/muse/releases/new)
|
|
299
|
+
# - Tag: 选刚 push 的 vX.Y.Z
|
|
300
|
+
# - Title: vX.Y.Z
|
|
301
|
+
# - Description: 写改动说明
|
|
302
|
+
# - 点 "Publish release"
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
GitHub Actions 会自动触发,可在 repo Actions 页面看进度。校验 tag 必须与 package.json version 一致(不然 workflow 主动 fail,避免发错版本)。
|
|
306
|
+
|
|
307
|
+
发布成功后,所有人能用 `npm install -g @qxbyte/muse` 装上。
|
|
308
|
+
|
|
309
|
+
### 失败排查
|
|
310
|
+
|
|
311
|
+
- `403 Forbidden`:NPM_TOKEN 失效 / 没权限 publish `@qxbyte/`
|
|
312
|
+
- `version already published`:package.json 没 bump,重复发了同 version
|
|
313
|
+
- `tag does not match package.json`:tag 是 v0.1.1 但 package.json 还是 0.1.0
|
|
314
|
+
- typecheck/build fail:本地先跑 `npm run typecheck && npm run build` 排错再 push
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## License
|
|
319
|
+
|
|
320
|
+
MIT
|