@qxbyte/muse 0.1.0 → 0.1.1

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/README.md CHANGED
@@ -1,29 +1,19 @@
1
1
  # Muse
2
2
 
3
- > A Claude Code-style agent CLI. Provider-agnostic. First-class support for Chinese / self-hostable LLMs (DeepSeek, Qwen, Kimi, GLM, Ollama, MiMo).
3
+ > A TypeScript agent CLI built around OpenAI-compatible APIs. First-class support for self-hostable and Chinese LLMs (DeepSeek, Qwen, Kimi, GLM, Ollama, MiMo).
4
4
 
5
- **状态:v0.1 MVP 搭建中**。API 不稳定,配置格式可能调整。
5
+ **状态:v0.1 MVP**。API 可能调整,请关注 release notes。
6
6
 
7
7
  ---
8
8
 
9
- ## 是什么
9
+ ## 目录
10
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 / 自建均可)
11
+ - [安装](#安装)
12
+ - [快速开始](#快速开始)
13
+ - [配置详解](#配置详解)
14
+ - [使用](#使用)
15
+ - [常见问题](#常见问题)
16
+ - [License](#license)
27
17
 
28
18
  ---
29
19
 
@@ -36,51 +26,46 @@ npm install -g @qxbyte/muse
36
26
  muse --version
37
27
  ```
38
28
 
39
- > 包名是 `@qxbyte/muse`(scoped),CLI 命令名是 `muse`。需要 Node 20+。
29
+ 需要 **Node.js >= 20**。包名 `@qxbyte/muse`(scoped),CLI 命令名 `muse`。
40
30
 
41
31
  ### 方式 B:从源码
42
32
 
43
33
  ```bash
44
- # 1. 拉源码
45
34
  git clone https://github.com/qxbyte/muse.git
46
35
  cd muse
47
-
48
- # 2. 装依赖
49
36
  npm install
50
-
51
- # 3. 构建(产物在 dist/)
52
37
  npm run build
38
+ node ./dist/cli.js --version
39
+ ```
53
40
 
54
- # 4. 验证
55
- node ./dist/cli.js --version # 应输出 0.1.0
56
- node ./dist/cli.js --help
41
+ 让命令全局可用:
57
42
 
58
- # 5.(可选)全局可用,二选一:
59
- # A) npm link(推荐)—— 在仓库目录下:
43
+ ```bash
44
+ # 在仓库目录
60
45
  npm link
61
46
  muse --version
62
-
63
- # B) shell alias —— 仅当前 shell 生效:
64
- echo 'alias muse="node $(pwd)/dist/cli.js"' >> ~/.zshrc
65
- source ~/.zshrc
66
47
  ```
67
48
 
68
49
  ---
69
50
 
70
- ## 配置
51
+ ## 快速开始
71
52
 
72
- muse 用**两个文件**分工:
53
+ 最少 3 步把 muse 跑起来。
73
54
 
74
- | 文件 | 角色 |
75
- |---|---|
76
- | `~/.muse/models.json` | 模型仓库:你能调用的所有模型 + apiKey |
77
- | `~/.muse/settings.json` | 运行偏好:当前激活哪个 model、UI、权限规则 |
55
+ ### 1. 准备一个 LLM 端点的 apiKey
78
56
 
79
- ### 1. 建 `~/.muse/models.json`
57
+ 任选一个:
80
58
 
81
- 凭证**强烈推荐**放到 `~/.muse/models.local.json`(自动 gitignore 防误传)或用 `${ENV_VAR}` 占位符。
59
+ | Provider | 申请页 | env 变量名(习惯) |
60
+ |---|---|---|
61
+ | DeepSeek | https://platform.deepseek.com | `DEEPSEEK_API_KEY` |
62
+ | Qwen (阿里百炼) | https://bailian.console.aliyun.com | `DASHSCOPE_API_KEY` |
63
+ | Moonshot (Kimi) | https://platform.moonshot.cn | `MOONSHOT_API_KEY` |
64
+ | 智谱 GLM | https://open.bigmodel.cn | `ZHIPU_API_KEY` |
65
+ | OpenAI | https://platform.openai.com | `OPENAI_API_KEY` |
66
+ | Ollama (本地) | https://ollama.com | 不需要 |
82
67
 
83
- #### 示例 A:DeepSeek
68
+ ### 2. 建模型仓库 `~/.muse/models.json`
84
69
 
85
70
  ```bash
86
71
  mkdir -p ~/.muse
@@ -93,57 +78,133 @@ cat > ~/.muse/models.json <<'EOF'
93
78
  "baseUrl": "https://api.deepseek.com/v1",
94
79
  "apiKey": "${DEEPSEEK_API_KEY}",
95
80
  "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
81
  }
104
82
  ],
105
- "availableModels": ["deepseek-chat", "deepseek-reasoner"]
83
+ "availableModels": ["deepseek-chat"]
106
84
  }
107
85
  EOF
86
+ ```
87
+
88
+ ### 3. 设环境变量并启动
108
89
 
109
- export DEEPSEEK_API_KEY=sk-... # 写到 ~/.zshrc 持久化
90
+ ```bash
91
+ export DEEPSEEK_API_KEY=sk-... # 写入 ~/.zshrc 或 ~/.bashrc 持久化
92
+ muse # 进交互模式
110
93
  ```
111
94
 
112
- #### 示例 B:本地 Ollama
95
+ 第一次启动会自动写 `~/.muse/settings.json` 记录默认模型;在 TUI 里输入 `/models` 可以切换。
96
+
97
+ ---
98
+
99
+ ## 配置详解
100
+
101
+ muse 用**两个文件**分工:
102
+
103
+ ```
104
+ ~/.muse/
105
+ ├── models.json # 模型仓库:你能调用的所有模型 + 凭证
106
+ ├── models.local.json # 同名兜底,放明文 apiKey(自动 gitignore,优先级更高)
107
+ ├── settings.json # 运行偏好:当前激活的 model / UI / 权限
108
+ ├── settings.local.json # 同名兜底,仅你本机生效
109
+ ├── sessions/ # 会话 JSONL 历史
110
+ └── logs/ # 日志(运行报错排查用)
111
+ ```
112
+
113
+ ### 模型仓库:`~/.muse/models.json`
114
+
115
+ 完整字段说明:
116
+
117
+ | 字段 | 类型 | 必填 | 说明 |
118
+ |---|---|---|---|
119
+ | `id` | string | ✅ | 模型唯一标识,**你自己起的名字**;slash 命令和 settings.json 用它引用 |
120
+ | `name` | string | | 显示名,缺省 = id |
121
+ | `vendor` | string | | 厂商名,只在 `/models` selector 里分组显示 |
122
+ | `baseUrl` | string | ✅ | OpenAI 兼容协议**基址**(如 `https://api.deepseek.com/v1`);填全 endpoint `.../v1/chat/completions` 也行,会自动剥后缀;别名字段 `url` 等价 |
123
+ | `apiKey` | string | | 凭证;支持 `${ENV_VAR}` 占位符(推荐);本地 Ollama 等可不填 |
124
+ | `supportsToolCall` | bool | | 是否支持 function calling,默认 `true` |
125
+ | `supportsImages` | bool | | 是否支持视觉,默认 `false` |
126
+ | `contextWindow` | number | | 上下文窗口(tokens),用于 `/cost` 估算 |
127
+ | `availableModels` | string[] | | 顶层数组;决定 `/models` selector 里显示哪些 id(不填 = 全部 models) |
128
+
129
+ ### 多 Provider 配置示例
130
+
131
+ 把多个一起放进 `models` 数组,按需在 `availableModels` 里挑:
113
132
 
114
133
  ```json
115
134
  {
116
135
  "models": [
136
+ {
137
+ "id": "deepseek-chat",
138
+ "vendor": "DeepSeek",
139
+ "baseUrl": "https://api.deepseek.com/v1",
140
+ "apiKey": "${DEEPSEEK_API_KEY}",
141
+ "supportsToolCall": true
142
+ },
143
+ {
144
+ "id": "deepseek-reasoner",
145
+ "vendor": "DeepSeek",
146
+ "baseUrl": "https://api.deepseek.com/v1",
147
+ "apiKey": "${DEEPSEEK_API_KEY}",
148
+ "supportsToolCall": false
149
+ },
150
+ {
151
+ "id": "qwen-plus",
152
+ "vendor": "Qwen",
153
+ "baseUrl": "https://dashscope.aliyuncs.com/compatible-mode/v1",
154
+ "apiKey": "${DASHSCOPE_API_KEY}",
155
+ "supportsToolCall": true
156
+ },
157
+ {
158
+ "id": "kimi-k2",
159
+ "vendor": "Moonshot",
160
+ "baseUrl": "https://api.moonshot.cn/v1",
161
+ "apiKey": "${MOONSHOT_API_KEY}",
162
+ "supportsToolCall": true
163
+ },
164
+ {
165
+ "id": "glm-4-plus",
166
+ "vendor": "GLM",
167
+ "baseUrl": "https://open.bigmodel.cn/api/paas/v4",
168
+ "apiKey": "${ZHIPU_API_KEY}",
169
+ "supportsToolCall": true
170
+ },
171
+ {
172
+ "id": "gpt-4o-mini",
173
+ "vendor": "OpenAI",
174
+ "baseUrl": "https://api.openai.com/v1",
175
+ "apiKey": "${OPENAI_API_KEY}",
176
+ "supportsToolCall": true,
177
+ "supportsImages": true
178
+ },
117
179
  {
118
180
  "id": "llama3.1",
119
181
  "vendor": "Ollama",
120
182
  "baseUrl": "http://localhost:11434/v1",
121
183
  "supportsToolCall": true
184
+ },
185
+ {
186
+ "id": "my-self-hosted",
187
+ "vendor": "Custom",
188
+ "baseUrl": "https://my-vllm-gateway.example.com/v1",
189
+ "apiKey": "${MY_GW_KEY}",
190
+ "supportsToolCall": true
122
191
  }
123
192
  ],
124
- "availableModels": ["llama3.1"]
193
+ "availableModels": [
194
+ "deepseek-chat",
195
+ "deepseek-reasoner",
196
+ "qwen-plus",
197
+ "kimi-k2",
198
+ "glm-4-plus",
199
+ "gpt-4o-mini",
200
+ "llama3.1"
201
+ ]
125
202
  }
126
203
  ```
127
204
 
128
- 本地 endpoint 不需要 apiKey。
129
-
130
- #### 字段说明
205
+ ### 运行偏好:`~/.muse/settings.json`
131
206
 
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'
207
+ ```json
147
208
  {
148
209
  "llm": {
149
210
  "model": "deepseek-chat"
@@ -158,28 +219,77 @@ cat > ~/.muse/settings.json <<'EOF'
158
219
  "defaultMode": "ask"
159
220
  }
160
221
  }
161
- EOF
162
222
  ```
163
223
 
164
- settings.json 里的 `llm.model` 必须**匹配**某个 models.json 里的 id;`/models` 选中模型后会自动写回这个字段。
224
+ 字段:
225
+
226
+ | 字段 | 说明 |
227
+ |---|---|
228
+ | `llm.model` | 当前激活的 model id,必须在 models.json 的 models 数组里能找到 |
229
+ | `ui.lang` | UI 文案语言,`zh-CN` / `en` |
230
+ | `ui.showBanner` | 启动是否显示彩虹 banner |
231
+ | `permissions.allow` | 直接放行的工具名列表(如 `Read`、`Bash(npm:*)`) |
232
+ | `permissions.ask` | 调用前要 y/n 确认的工具 |
233
+ | `permissions.deny` | 永远拒绝的工具 |
234
+ | `permissions.defaultMode` | `strict`(未匹配 → ask)、`relaxed`(未匹配 → allow)、`ask`(默认) |
235
+
236
+ > 用 `/models` 切换模型时,muse 会自动写回 `llm.model`,**不需要手动改**。
237
+
238
+ ### 凭证安全
239
+
240
+ 按推荐顺序:
241
+
242
+ 1. **环境变量 + `${VAR}` 占位符**(最安全)
243
+ ```bash
244
+ # ~/.zshrc 或 ~/.bashrc
245
+ export DEEPSEEK_API_KEY=sk-...
246
+ export MOONSHOT_API_KEY=sk-...
247
+ ```
248
+ models.json 里 `"apiKey": "${DEEPSEEK_API_KEY}"`,启动时 muse 展开。
249
+
250
+ 2. **`~/.muse/models.local.json`**(明文 key)
251
+ - 文件名带 `.local.json`,**所有 `*.local.json` 项目级已 gitignore**
252
+ - 推荐 `chmod 600 ~/.muse/models.local.json`
253
+ - 同 id 时 `models.local.json` 覆盖 `models.json`,可以只在 local 里放凭证
254
+
255
+ 3. **`~/.muse/models.json` 直接写明文**(不推荐)
256
+ - 仅当你 100% 确定该机器 + 账号是私有
257
+ - 任何同步盘(iCloud、Dropbox)都会让它扩散
165
258
 
166
- ### 3. (可选)项目级覆盖
259
+ muse 自身的安全保证:
260
+ - 日志里 apiKey **自动脱敏**(前 4 + 后 4,中间打码)
261
+ - 切换 model 时 apiKey 注入 `process.env.MUSE_ACTIVE_API_KEY`,业务代码只透过 env 取,不持有副本
262
+ - 进程退出后 env 不残留,不污染你的 shell
167
263
 
168
- 在你工作目录里建 `.muse/settings.json` 或 `.muse/settings.local.json`,对应字段会覆盖全局 settings。`*.local.json` 已被项目 `.gitignore` 忽略,放凭证安全。
264
+ ### 配置文件加载优先级
265
+
266
+ 由低到高(高的覆盖低的):
267
+
268
+ 1. 内置默认值
269
+ 2. `~/.muse/settings.json`(全局共享)
270
+ 3. `<项目>/.muse/settings.json`(项目级,可入 git)
271
+ 4. `<项目>/.muse/settings.local.json`(项目级,已 gitignore)
272
+ 5. 环境变量 `MUSE_PROVIDER` / `MUSE_MODEL`
273
+ 6. CLI flags `-p` / `-m`
274
+
275
+ `models.json` 同理(仅 `~/.muse/` 层,无项目级)。
169
276
 
170
277
  ---
171
278
 
172
- ## 启动
279
+ ## 使用
280
+
281
+ ### 启动方式
173
282
 
174
283
  ```bash
175
- muse # 交互模式(TUI)
176
- muse "总结一下 src/cli.tsx" # 一次性 prompt 模式
177
- cat bug.log | muse "找出根因" # 管道输入
178
- muse --debug # 详细日志(写到 ~/.muse/logs/<date>.jsonl)
284
+ muse # 交互模式(TUI)
285
+ muse "总结一下 src/cli.tsx" # 一次性 prompt
286
+ cat bug.log | muse "找出根因" # 管道输入
287
+ muse --quiet "..." # 最小输出,适合脚本
288
+ muse --debug # 详细日志到 ~/.muse/logs/<date>.jsonl
179
289
  muse --help
180
290
  ```
181
291
 
182
- CLI flag:
292
+ ### CLI 参数
183
293
 
184
294
  | flag | 说明 |
185
295
  |---|---|
@@ -188,12 +298,13 @@ CLI flag:
188
298
  | `--no-banner` | 不显示启动 banner |
189
299
  | `--quiet` | 最小输出(隐含 `--no-banner`) |
190
300
  | `--debug` | 详细日志 |
301
+ | `--continue` | 恢复上次会话(部分实现) |
302
+ | `-v, --version` | 打印版本 |
303
+ | `-h, --help` | 打印帮助 |
191
304
 
192
- ---
193
-
194
- ## 内置 Slash 命令
305
+ ### Slash 命令
195
306
 
196
- 启动后在 TUI 输入 `/` 会自动弹出补全列表,↑↓ 导航,Tab/Enter 补全。
307
+ 启动后在 TUI 输入 `/` 会弹出补全列表,↑↓ 导航,Tab/Enter 接受。
197
308
 
198
309
  | 命令 | 作用 |
199
310
  |---|---|
@@ -201,117 +312,111 @@ CLI flag:
201
312
  | `/clear` | 清空当前会话 |
202
313
  | `/cost` | 当前会话 token 用量 + 费用估算 |
203
314
  | `/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 真接) |
315
+ | `/models` | 弹出 selector,↑↓ + Enter 切换模型(自动写回 settings.json + 注入 env) |
316
+ | `/config` | 显示 effective 配置(apiKey 脱敏) |
317
+ | `/config reload` | 不重启 muse 热加载所有配置 |
318
+ | `/config path` | 列出配置文件路径 |
207
319
  | `/compact` | 摘要老消息释放上下文(`--keep N` 保留最近 N 条) |
208
320
  | `/resume` | ↑↓ 选历史会话加载;带参 `/resume <id-prefix>` 直接加载 |
321
+ | `/mcp` | MCP server 状态 |
209
322
  | `/quit` / `/exit` | 退出 |
210
323
 
211
- ---
324
+ ### 内置工具
212
325
 
213
- ## 目录结构
326
+ LLM 在执行任务时可调用:
214
327
 
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
- ```
328
+ | 工具 | 作用 |
329
+ |---|---|
330
+ | `Read` | 读文件,支持 offset / limit 分页 |
331
+ | `Write` | 写文件(必须先 Read 过才能 Write,防误覆盖) |
332
+ | `Edit` | 精确字符串替换(比全文重写省 token) |
333
+ | `Grep` | ripgrep 包装 |
334
+ | `Glob` | 文件匹配 |
335
+ | `Bash` | 执行 shell 命令;危险命令(rm -rf / sudo / curl…|sh)硬拒绝 |
232
336
 
233
- ---
337
+ 所有写操作 / Bash 默认走权限弹窗(y/n 确认),权限模式可调(见下)。
234
338
 
235
- ## 凭证安全
339
+ ### 权限模式(Shift+Tab 循环)
236
340
 
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 取,不持有副本
341
+ 底部状态栏显示当前模式:
244
342
 
245
- ---
343
+ | 模式 | 行为 | 何时用 |
344
+ |---|---|---|
345
+ | `default` | 按 settings.permissions 规则判定 | 日常 |
346
+ | `acceptEdits` | Edit / Write 自动放行,其他不变 | 信任的批量改 |
347
+ | `plan` | 只允许只读工具(Read / Grep / Glob),让 LLM"想清楚再动手" | 探索代码、定方案 |
348
+ | `bypassPermissions` | 除 deny 列表与硬拒绝命令外全部放行 | 沙箱环境、CI |
246
349
 
247
- ## 已知限制(v0.1)
350
+ `Shift+Tab` 在四档间循环;不持久化,重启回到 default。
248
351
 
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 占用
352
+ ### 切换模型
257
353
 
258
- ---
354
+ 两种方式:
355
+
356
+ 1. **TUI 内**:输入 `/models` → ↑↓ 选 → Enter,自动写回 settings.json + 注入 env
357
+ 2. **命令行临时**:`muse -m kimi-k2 "..."`(不持久化)
358
+ 3. **手动编辑**:改 `~/.muse/settings.json` 里的 `llm.model`,TUI 里 `/config reload` 热加载
259
359
 
260
- ## 路线图
360
+ ### Markdown 渲染
261
361
 
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 类型
362
+ assistant 回复里的 markdown(标题、列表、代码块、表格、链接)会被渲染成富文本。流式输出过程中是纯文本,本轮结束后自动替换成格式化版本。
267
363
 
268
364
  ---
269
365
 
270
- ## 设计文档
366
+ ## 常见问题
271
367
 
272
- 宏观设计 / 实现日志 / 子规范在 `CLAUDE.md` 关联的文档库(私有 Obsidian vault),代码注释引用对应章节(如 `// 见 muse-design.md §7.2`)。
368
+ ### `/models` 显示 "No models registry found"
273
369
 
274
- ---
370
+ `~/.muse/models.json` 不存在或解析失败。
275
371
 
276
- ## 发布到 npm(维护者)
372
+ - 路径是否正确?`ls ~/.muse/models.json`
373
+ - JSON 格式是否合法?`jq . ~/.muse/models.json`
374
+ - 字段错位?看 `~/.muse/logs/<today>.jsonl` 里的 warn
277
375
 
278
- 发布完全自动化:在 GitHub publish 一个 release,`.github/workflows/release.yml` 会跑 typecheck + build + `npm publish --provenance`。
376
+ ### `Model "..." has no apiKey in env MUSE_ACTIVE_API_KEY`
279
377
 
280
- ### 一次性准备(首次发布前)
378
+ 启动时 apiKey 没注入到 env。检查:
281
379
 
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
380
+ 1. models.json `apiKey` 字段是否填了
381
+ 2. 用了 `${ENV_VAR}` 占位符?对应 env 是否在 shell export 过?
382
+ ```bash
383
+ echo $DEEPSEEK_API_KEY # 应有值
384
+ ```
385
+ 3. 改完 `~/.zshrc` 后是否 `source ~/.zshrc`?
288
386
 
289
- ### 每次发布
387
+ ### 启动时一段 zod warn JSON
290
388
 
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
389
+ `~/.muse/settings.json` 字段不匹配 schema。看 warn 里的 `path` 列就知道哪个字段错了,照着改。
294
390
 
295
- # 2. 推 commit + tag
296
- git push && git push --tags
391
+ ### Ollama 本地模型连不上
297
392
 
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
- ```
393
+ - Ollama 服务跑没?`curl http://localhost:11434/api/tags`
394
+ - `baseUrl` 必须填 `http://localhost:11434/v1`(带 `/v1`),不能只填 host
395
+ - 防火墙 / 端口被占用?
396
+
397
+ ### 国产 provider 工具调用失败
304
398
 
305
- GitHub Actions 会自动触发,可在 repo Actions 页面看进度。校验 tag 必须与 package.json version 一致(不然 workflow 主动 fail,避免发错版本)。
399
+ 部分国产 provider OpenAI function calling 协议的实现有小差异。如果 LLM 看起来"忽略工具"或"乱调":
306
400
 
307
- 发布成功后,所有人能用 `npm install -g @qxbyte/muse` 装上。
401
+ - 试着把 `supportsToolCall` 改成 `false` 强行降级到纯对话
402
+ - 切到 DeepSeek / Qwen / Moonshot 等兼容性较好的 provider 验证
403
+ - 查 `~/.muse/logs/<today>.jsonl` 看 LLM 实际响应内容
308
404
 
309
- ### 失败排查
405
+ ### 想要恢复昨天的会话
310
406
 
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
407
+ ```
408
+ muse # TUI
409
+ /resume # ↑↓ Enter
410
+ ```
411
+
412
+ 会话存在 `~/.muse/sessions/<project-hash>/<uuid>.jsonl`,按 cwd 分目录。
413
+
414
+ ### 如何卸载
415
+
416
+ ```bash
417
+ npm uninstall -g @qxbyte/muse
418
+ rm -rf ~/.muse # 清配置 / 会话 / 日志(可选)
419
+ ```
315
420
 
316
421
  ---
317
422
 
package/dist/cli.js CHANGED
@@ -2887,7 +2887,7 @@ import { jsx as jsx10 } from "react/jsx-runtime";
2887
2887
  var VERSION = "0.1.0";
2888
2888
  async function main() {
2889
2889
  const program = new Command();
2890
- program.name("muse").description("A Claude Code-style agent CLI. Provider-agnostic. First-class support for Chinese / self-hostable LLMs.").version(VERSION, "-v, --version", "print version");
2890
+ program.name("muse").description("A TypeScript agent CLI built around OpenAI-compatible APIs. First-class support for self-hostable and Chinese LLMs.").version(VERSION, "-v, --version", "print version");
2891
2891
  program.argument("[prompt...]", "one-shot prompt (omit for interactive mode)").option("-m, --model <model>", "override model").option("-p, --provider <provider>", "override provider").option("--no-banner", "skip startup banner").option("--quiet", "minimal output (implies --no-banner)").option("--continue", "resume last session in this directory").option("--debug", "verbose logging").action(async (promptArgs, opts) => {
2892
2892
  if (opts.debug) log.setLevel("debug");
2893
2893
  const cwd = process.cwd();