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