@oldsuns/pi-switch 0.2.14 → 0.3.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,214 +1,224 @@
1
- # pi-switch
2
-
3
- 维护本地 provider 库并按需同步 [Pi](https://github.com/earendil-works/pi) 配置的终端 TUI:管理 provider / 模型 / 默认模型,以及 Pi session 的列表、预览与删除。
4
-
5
- CLI:`pi-switch` · npm 包:`@oldsuns/pi-switch` · Node 薄壳 + Rust/napi 原生核心
6
-
7
- ## 功能
8
-
9
- - **主页**:provider / model 计数、默认模型、关键路径;启动后台静默检查 npm 新版本,有更新时弹出确认对话框可一键安装
10
- - **配置 (Profiles)**:本地 provider 库与 Pi 启用子集;新建 / 编辑 / 删除 / 复制;在线导入模型
11
- - **会话 (Sessions)**:按工作目录浏览 JSONL session,使用 Tree/Markdown 视图区分用户/Pi消息,支持筛选、复制与删除
12
- - **设置 (Settings)**:语言、models.dev 元数据、默认参数、重载、校验、备份、OpenCode 导入、自动检查更新、手动检查更新
13
- - 完整库保存在 `~/.pi-switch/providers.json`,只有已启用项写入 Pi 的 `models.json`
14
-
15
- ## 要求
16
-
17
- - Node.js `>= 20`
18
- - 预构建原生模块当前仅覆盖 Windows (msvc x64)——直接 `npm install -g` 即装即用
19
- - 本地构建原生模块(仅开发者)需要 Rust 工具链与 `@napi-rs/cli`
20
-
21
- ## 快速开始
22
-
23
- ```bash
24
- # 全局安装
25
- npm install -g @oldsuns/pi-switch
26
-
27
- # 打开 TUI
28
- pi-switch
29
- ```
30
-
31
- 首次运行会自动把现有的 `~/.pi/agent/models.json` 全量导入本地库,**不修改** Pi 配置;随后即可在 Profiles 中勾选要同步到 Pi 的 provider / model。
32
-
33
- CLI:
34
-
35
- ```bash
36
- pi-switch # 打开 TUI(等同 tui)
37
- pi-switch tui
38
- pi-switch doctor # 校验配置与默认模型
39
- pi-switch --version # / -v
40
- pi-switch --help # / -h / help
41
- ```
42
-
43
- Windows 上无需 Rust:预构建原生模块随 npm 包分发,`pi-switch` 开箱即用。本地开发见下文「开发者」。
44
-
45
- ## 开发者
46
-
47
- 从源码构建:
48
-
49
- ```bash
50
- npm install
51
- npm run build:native:debug
52
- node ./bin/pi-switch.js
53
- ```
54
-
55
- 贡献流程见 [CONTRIBUTING.md](./CONTRIBUTING.md)。
56
-
57
- ## 界面与快捷键
58
-
59
- 全局导航:`j/k` 或方向键移动;菜单中 `Enter` / `l` 进入内容,各内容页按自己的方向键切换焦点;`?` 帮助;`q` 退出(多数界面 `Ctrl+C` 也退出,会话预览除外)。
60
-
61
- ### 配置 (Profiles)
62
-
63
- | 键 | 作用 |
64
- |----|------|
65
- | `n` / `e` / `d` / `c` | 新建 / 编辑 / 删除 / 复制当前焦点(provider 或 model) |
66
- | `Space`(provider) | 同步到 Pi / 取消同步;`[x]` 已同步,`[ ]` 不同步 |
67
- | `Space`(model) | 设为默认模型(仅已同步到 Pi 的 provider) |
68
- | `i` | 从当前 provider 在线导入模型 |
69
- | `/` | 筛选 provider |
70
- | `Enter` / `l` | 进入模型列表 |
71
- | `Esc` / `h` | 从模型回到 provider,或从 provider 回菜单 |
72
- | `r` | 从磁盘重载配置 |
73
- | `b` | 浏览备份 |
74
- | `v` | 校验配置(doctor) |
75
-
76
- 新建 provider 默认同步到 Pi,表单可关闭;复制继承源的同步状态。
77
-
78
- Provider 表单:`baseUrl`、`api`(`openai-completions` / `openai-responses` / `anthropic-messages` / `google-generative-ai`)、`apiKey`、`authHeader`、Headers(独立 `User-Agent` + 其余 JSON)、`compat`(含一等开关 Session affinity = `sendSessionAffinityHeaders`)。
79
-
80
- Model 表单:`id`、`name`、API override、reasoning、文本/图像输入、context window、max tokens、thinking levels(`thinkingLevelMap`)。`cost`、`modelOverrides`、OAuth 等未知字段会无损保留。字段语义以 [Pi Custom Models](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/models.md) 为准。
81
-
82
- ### 会话 (Sessions)
83
-
84
- | 键 | 作用 |
85
- |----|------|
86
- | `/` | 筛选 |
87
- | `n` | 仅显示手动命名的 session(不是新建) |
88
- | `r` | 重新扫描磁盘 |
89
- | `u` | 预览仅用户消息 |
90
- | `Right` | 从会话列表进入树预览 |
91
- | 预览 `Left` | 从树预览返回会话列表 |
92
- | 预览 `Up` / `Down` | 按树节点切换,默认定位当前 active leaf |
93
- | 预览 `PageUp` / `PageDown` | 按当前可视区域逐页滚动 |
94
- | 预览 `v` | 切换 Tree 单行预览和完整 Markdown 阅读 |
95
- | 预览 `Tab` | 折叠或展开当前真实分叉点的全部下级 |
96
- | 预览 `Ctrl+Left/Right` | 在视觉分支层级间移动:跳过同 lane 的串行消息,进入上一级/下一级分支段 |
97
- | 预览 `Alt+Left/Right` | 从当前位置切换最近分叉点的相邻分支 |
98
- | 滚轮 | 按行滚动长消息 |
99
- | 预览 `Ctrl+C` | 复制当前消息到剪贴板(不退出) |
100
- | `d` | 删除当前 session(确认后优先 trash) |
101
-
102
- 预览按 Pi 官方 session 的 `id` / `parentId` 构建树。默认 Tree 模式参考 Pi 原生 `/tree`:每个节点只占一行,显示 `User:` / `Pi:` 和单行摘要;只有真实分叉才增加缩进并使用 `├─` / `└─`,串行消息保持同一 lane。深层分支不会为所有消息预留固定宽度;仅在当前节点过深时水平平移树正文,并固定保留左侧光标 gutter。按 `v` 可切换到完整阅读模式,显示完整 Markdown 正文;每条消息按自身树深度分配前缀,树栏最多约占三分之一宽度。`Ctrl+Left/Right` 在分支段层级间移动,`Alt+Left/Right` 切换相邻分支,`Tab` 仅折叠真实分叉点。可见消息挂到最近可见祖先,`session_info`、tool 等 bookkeeping 节点不会伪装成对话消息。黄标题 = 手动命名;白标题 = 使用第一条用户消息。
103
-
104
- Session 根目录优先级:`PI_CODING_AGENT_SESSION_DIR` → `PI_CODING_AGENT_DIR/sessions` `~/.pi/agent/sessions/`。
105
-
106
- 剪贴板:Windows `clip`、macOS `pbcopy`、Linux `wl-copy` / `xclip` / `xsel`。
107
-
108
- ### 设置 (Settings)
109
-
110
- | 项 | 说明 |
111
- |----|------|
112
- | 语言 | English / 中文(`en` / `zh-CN`) |
113
- | 从 models.dev 获取模型信息 | 开关实时元数据(默认开) |
114
- | 自动检查更新 | 启动时后台自动检查 npm `@oldsuns/pi-switch` 新版本(开关,默认开) |
115
- | 检查更新(手动) | 立即检查新版本(绕过 24h 缓存) |
116
- | 默认模型参数 | 仅关闭实时元数据时显示,用于导入缺省 |
117
- | 重载配置 | 从磁盘重读 |
118
- | 验证配置 | doctor |
119
- | 浏览备份 | 恢复 version 2 备份 |
120
- | 从 OpenCode 导入 | 只读导入 `opencode.json` |
121
-
122
- `Enter` / `Space` 执行当前项。
123
-
124
- ## Provider 库与 Pi 同步
125
-
126
- - `~/.pi-switch/providers.json` 是完整本地库;`~/.pi/agent/models.json` 只含当前已同步到 Pi 的子集。
127
- - 首次运行把现有 `models.json` 全量导入本地库,不修改 Pi 配置。
128
- - 已同步 provider 的编辑与 model 变更会同步两份文件;不同步项只更新本地库。
129
- - 在线导入 model **不会**隐式同步到 Pi。
130
- - 启动或手动重载时,以 `models.json` 中同 ID provider 为准回灌本地库;外部从 Pi 删除的 provider 仍作为不同步项保留。
131
- - 从 Pi 移除当前默认 provider 会先确认并清除默认模型;`d` 永久删除本地副本,必要时同时从 Pi 删除。
132
-
133
- ## 模型导入与价格
134
-
135
- 在线导入(Profiles 中 `i`):
136
-
137
- 1. 按 provider 的 `api` / `baseUrl` / 鉴权请求模型列表。
138
- 2. **NewAPI 网关价格(best-effort)**:去掉 `baseUrl` 尾部 `/v1` 后依次尝试
139
- - `GET /api/ratio_config`(可能含 `create_cache_ratio`)
140
- - `GET /api/pricing`
141
- 成功则按 NewAPI 换算覆盖模型 `cost`(`1 USD = 500_000 quota`,每 1M tokens 成本 ≈ `ratio × 2` USD);失败静默忽略。
142
- 3. 若开启 models.dev 元数据:请求 `https://models.dev/api.json`,补全 `contextWindow`、`maxTokens`、`cost`、reasoning 等。
143
- - **在线导入**遇到同 model ID 多源歧义时:**自动取第一个候选**,不弹选择框;缺少可用元数据的模型跳过并提示计数。
144
- - 导入列表会标注价格来源:`ratio_config` 或 `models.dev`。
145
- - 网关价格在 catalog 元数据之上叠加。
146
- 4. 关闭实时元数据:使用 Settings 中的默认参数;空字段回落 Pi 官方默认(context window `128000`、max tokens `16384`、cost `0`)。
147
-
148
- **OpenCode 导入**(Settings):只读 `~/.config/opencode/opencode.json`,可全选或勾选 provider;导入项默认同步到 Pi。若 models.dev 仍有歧义,**需要用户选择候选**。OpenCode 配置本身不会被修改。
149
-
150
- ## 配置路径与 Settings 字段
151
-
152
- | 路径 | 角色 |
153
- |------|------|
154
- | `~/.pi-switch/providers.json` | 完整本地 provider 库(`version: 1`) |
155
- | `~/.pi/agent/models.json` | 已同步到 Pi 的 provider 子集 |
156
- | `~/.pi/agent/settings.json` | 默认模型 + pi-switch 设置 |
157
- | `~/.config/opencode/opencode.json` | OpenCode 只读导入源 |
158
- | `~/.pi-switch/backups/` | version 2 备份(providers + models + settings),最多 10 份 |
159
- | `~/.pi-switch/write.lock` | 写入互斥锁 |
160
- | `~/.pi-switch/update.json` | npm 新版本检查缓存(`lastCheck` + `latest` + `dismissed`,每 24h 最多联网一次) |
161
-
162
- `settings.json` 中与 pi-switch 相关的字段:
163
-
164
- | 字段 | 含义 |
165
- |------|------|
166
- | `defaultProvider` + `defaultModel` | 默认模型(成对存在或同时缺省) |
167
- | `piSwitch.language` | `en` \| `zh-CN` |
168
- | `piSwitch.fetchModelMetadata` | 是否拉 models.dev(默认 `true`) |
169
- | `piSwitch.checkForUpdates` | 是否启动时检查 npm 新版本(默认 `true`) |
170
- | `piSwitch.modelDefaults` | 关闭实时元数据时的导入缺省(context / maxTokens / cost) |
171
-
172
- ## 数据安全
173
-
174
- - 写前备份 `providers.json`、`models.json`、`settings.json` 到 `~/.pi-switch/backups/`(version 2);最多保留最近 10 份。旧版双文件备份不支持恢复。
175
- - 写入使用 `write.lock` 互斥;异常残留锁时 `doctor` 会提示。
176
- - `providers.json` 损坏时归档为 `corrupt-providers-*.json`,再从当前 Pi 配置重建,启动时显示归档路径。
177
- - 原子写入,只 patch 目标字段,保留未知 JSON;格式错误时停止写入并显示错误。
178
- - 支持 Pi `$ENV` / `${ENV}` 插值与 `$$` / `$!` 转义;`!command` 原样保存,在线拉取**不会**执行它。
179
- - Session 删除只作用于选中的 JSONL,并校验路径必须位于 session 根目录内;优先调用系统 `trash`,失败后再永久删除。
180
- - 正常退出、错误和 panic 都会恢复 raw mode、alternate screen 与光标。
181
-
182
- ## 自动更新检查与安装
183
-
184
- 启动时若 Settings 中「自动检查更新」开启(默认开),pi-switch 会在后台线程静默访问 npm registry 查询 `@oldsuns/pi-switch` `latest` 版本,与当前版本对比:
185
-
186
- - 有新版本:弹出确认对话框(显示 `当前 最新`),用户可选择立即安装或跳过。跳过后同一版本不再弹窗,但主页仍显示横幅。手动检查(Settings 中「检查更新」)始终弹窗。
187
- - 无新版本、离线或请求失败:静默无提示,不打扰用户。
188
-
189
- 安装流程:
190
-
191
- 1. 用户在确认对话框按 `Enter/y` 确认 → 后台执行 `npm install -g @oldsuns/pi-switch`,显示加载动画。
192
- 2. 安装成功 → 通知「更新已安装,请重启 pi-switch 生效」。
193
- 3. 安装失败 → 弹出错误通知(如权限不足、网络问题)。
194
- 4. 用户按 `Esc/n` 跳过 记录已跳过的版本到缓存,同一版本不再自动弹窗;主页横幅仍提示有新版本。
195
-
196
- 检查结果缓存在 `~/.pi-switch/update.json`,自动检查每 24h 最多联网一次。后台线程独立于目录导入任务,不阻塞 UI。Settings 中可随时关闭「自动检查更新」。
197
-
198
- ## 验证
199
-
200
- ```bash
201
- cargo test --locked --lib
202
- cargo fmt -- --check
203
- cargo clippy --locked --all-targets -- -D warnings
204
- npm run build:native:debug
205
- npm run pack:check
206
- ```
207
-
208
- ## 许可
209
-
210
- [MIT](./LICENSE)
211
-
212
- ## 致谢
213
-
214
- 感谢 [LINUX DO](https://linux.do) 社区的讨论与反馈。
1
+ # pi-switch
2
+
3
+ 维护本地 provider 库并按需同步 [Pi](https://github.com/earendil-works/pi) 配置的终端 TUI:管理 provider / 模型 / 默认模型,以及 Pi session 的列表、预览与删除。
4
+
5
+ CLI:`pi-switch` · npm 包:`@oldsuns/pi-switch` · Node 薄壳 + Rust/napi 原生核心
6
+
7
+ ## 功能
8
+
9
+ - **主页**:provider / model 计数、默认模型、关键路径;启动后台静默检查 npm 新版本,有更新时弹出确认对话框可一键安装
10
+ - **配置 (Profiles)**:本地 provider 库与 Pi 启用子集;新建 / 编辑 / 删除 / 复制;在线导入模型
11
+ - **会话 (Sessions)**:按工作目录浏览 JSONL session,使用 Tree/Markdown 视图区分用户/Pi消息,支持筛选、复制与删除
12
+ - **设置 (Settings)**:语言、models.dev 元数据、默认参数、重载、校验、备份、OpenCode 导入、自动检查更新、手动检查更新
13
+ - 完整库保存在 `~/.pi-switch/providers.json`,只有已启用项写入 Pi 的 `models.json`
14
+
15
+ ## 要求
16
+
17
+ - Node.js `>= 20`
18
+ - 预构建原生模块当前仅覆盖 Windows (msvc x64)——直接 `npm install -g` 即装即用
19
+ - 本地构建原生模块(仅开发者)需要 Rust 工具链与 `@napi-rs/cli`
20
+
21
+ ## 快速开始
22
+
23
+ ```bash
24
+ # 全局安装
25
+ npm install -g @oldsuns/pi-switch
26
+
27
+ # 打开 TUI
28
+ pi-switch
29
+ ```
30
+
31
+ 首次运行会自动把现有 Pi agent 目录中的 `models.json` 全量导入本地库,**不修改** Pi 配置;随后即可在 Profiles 中勾选要同步到 Pi 的 provider / model。Pi agent 目录使用非空 `PI_CODING_AGENT_DIR`,未设置时为 `~/.pi/agent`。
32
+
33
+ CLI:
34
+
35
+ ```bash
36
+ pi-switch # 打开 TUI(等同 tui)
37
+ pi-switch tui
38
+ pi-switch doctor # 校验配置与默认模型
39
+ pi-switch --version # / -v
40
+ pi-switch --help # / -h / help
41
+ ```
42
+
43
+ Windows 上无需 Rust:预构建原生模块随 npm 包分发,`pi-switch` 开箱即用。本地开发见下文「开发者」。
44
+
45
+ ## 开发者
46
+
47
+ 从源码构建:
48
+
49
+ ```bash
50
+ npm install
51
+ npm run build:native:debug
52
+ node ./bin/pi-switch.js
53
+ ```
54
+
55
+ 贡献流程见 [CONTRIBUTING.md](./CONTRIBUTING.md)。
56
+
57
+ ## 界面与快捷键
58
+
59
+ 全局导航:`j/k` 或方向键移动;菜单中 `Enter` / `l` 进入内容,各内容页按自己的方向键切换焦点;`?` 帮助;`q` 退出(多数界面 `Ctrl+C` 也退出,会话预览除外)。
60
+
61
+ ### 配置 (Profiles)
62
+
63
+ | 键 | 作用 |
64
+ |----|------|
65
+ | `n` / `e` / `d` / `c` | 新建 / 编辑 / 删除 / 复制当前焦点(provider 或 model) |
66
+ | `Space`(provider) | 同步到 Pi / 取消同步;`[x]` 已同步,`[ ]` 不同步 |
67
+ | `Space`(model) | 设为默认模型(仅已同步到 Pi 的 provider) |
68
+ | `i` | 从当前 provider 在线导入模型 |
69
+ | `/` | 筛选 provider |
70
+ | `Enter` / `l` | 进入模型列表 |
71
+ | `Esc` / `h` | 从模型回到 provider,或从 provider 回菜单 |
72
+ | `r` | 从磁盘重载配置 |
73
+ | `b` | 浏览备份 |
74
+ | `v` | 校验配置(doctor) |
75
+
76
+ 新建 provider 默认同步到 Pi,表单可关闭;复制继承源的同步状态。
77
+
78
+ Provider 表单:`baseUrl`、`api`(`openai-completions` / `openai-responses` / `anthropic-messages` / `google-generative-ai`)、`apiKey`、`authHeader`、Headers(独立 `User-Agent` + 其余 JSON)、`compat`(含一等开关 Session affinity = `sendSessionAffinityHeaders`)。
79
+
80
+ Model 表单:`id`、`name`、API override、reasoning、文本/图像输入、context window、max tokens、thinking levels(`thinkingLevelMap`)。`cost`、`modelOverrides`、OAuth 等未知字段会无损保留。字段语义以 [Pi Custom Models](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/models.md) 为准。
81
+
82
+ ### 会话 (Sessions)
83
+
84
+ | 键 | 作用 |
85
+ |----|------|
86
+ | `/` | 筛选 |
87
+ | `n` | 仅显示手动命名的 session(不是新建) |
88
+ | `r` | 重新扫描磁盘 |
89
+ | `u` | 预览仅用户消息 |
90
+ | `Right` | 从会话列表进入树预览 |
91
+ | 预览 `Left` | 从树预览返回会话列表 |
92
+ | 预览 `Up` / `Down` | 按树节点切换,默认定位当前 active leaf |
93
+ | 预览 `PageUp` / `PageDown` | 按当前可视区域逐页滚动 |
94
+ | 预览 `v` | 切换 Tree 单行预览和完整 Markdown 阅读 |
95
+ | 预览 `Tab` | 折叠或展开当前真实分叉点的全部下级 |
96
+ | 预览 `Ctrl+Left/Right` | 在视觉分支层级间移动:跳过同 lane 的串行消息,进入上一级/下一级分支段 |
97
+ | 预览 `Alt+Left/Right` | 从当前位置切换最近分叉点的相邻分支 |
98
+ | 滚轮 | 按行滚动长消息 |
99
+ | 预览 `Ctrl+C` | 复制当前消息到剪贴板(不退出) |
100
+ | `d` | 删除当前 session(确认后优先 trash) |
101
+
102
+ 预览按 Pi 官方 session 的 `id` / `parentId` 构建树。默认 Tree 模式参考 Pi 原生 `/tree`:每个节点只占一行,显示 `User:` / `Pi:` 和单行摘要;只有真实分叉才增加缩进并使用 `├─` / `└─`,串行消息保持同一 lane。深层分支不会为所有消息预留固定宽度;仅在当前节点过深时水平平移树正文,并固定保留左侧光标 gutter。按 `v` 可切换到完整阅读模式,显示完整 Markdown 正文;每条消息按自身树深度分配前缀,树栏最多约占三分之一宽度。`Ctrl+Left/Right` 在分支段层级间移动,`Alt+Left/Right` 切换相邻分支,`Tab` 仅折叠真实分叉点。可见消息挂到最近可见祖先,`session_info`、tool 等 bookkeeping 节点不会伪装成对话消息。黄标题 = 手动命名;白标题 = 使用第一条用户消息。
103
+
104
+ Session 根目录优先级:非空 `PI_CODING_AGENT_SESSION_DIR` → `<Pi agent dir>/sessions`。
105
+
106
+ 剪贴板:Windows `clip`、macOS `pbcopy`、Linux `wl-copy` / `xclip` / `xsel`。
107
+
108
+ ### 设置 (Settings)
109
+
110
+ | 项 | 说明 |
111
+ |----|------|
112
+ | 语言 | English / 中文(`en` / `zh-CN`) |
113
+ | 从 models.dev 获取模型信息 | 开关实时元数据(默认开) |
114
+ | 自动检查更新 | 启动时后台自动检查 npm `@oldsuns/pi-switch` 新版本(开关,默认开) |
115
+ | 检查更新(手动) | 立即检查新版本(绕过 24h 缓存) |
116
+ | 默认模型参数 | 仅关闭实时元数据时显示,用于导入缺省 |
117
+ | 重载配置 | 从磁盘重读 |
118
+ | 验证配置 | doctor |
119
+ | 浏览备份 | 恢复 version 3 或兼容的 version 2 备份 |
120
+ | 从 OpenCode 导入 | 只读导入 `opencode.json` |
121
+
122
+ `Enter` / `Space` 执行当前项。
123
+
124
+ ## Provider 库与 Pi 同步
125
+
126
+ - `~/.pi-switch/providers.json` 是完整本地库;`<Pi agent dir>/models.json` 只含当前已同步到 Pi 的子集。
127
+ - 首次运行把现有 `models.json` 全量导入本地库,不修改 Pi 配置。
128
+ - 已同步 provider 的编辑与 model 变更会同步两份文件;不同步项只更新本地库。
129
+ - 在线导入 model **不会**隐式同步到 Pi。
130
+ - 启动或手动重载时,以 `models.json` 中同 ID provider 为准回灌本地库;外部从 Pi 删除的 provider 仍作为不同步项保留。
131
+ - 从 Pi 移除当前默认 provider 会先确认并清除默认模型;`d` 永久删除本地副本,必要时同时从 Pi 删除。
132
+
133
+ ## 模型导入与价格
134
+
135
+ 在线导入(Profiles 中 `i`):
136
+
137
+ 1. 按 provider 的 `api` / `baseUrl` / 鉴权请求模型列表。
138
+ 2. **NewAPI 网关价格(best-effort)**:去掉 `baseUrl` 尾部 `/v1` 后依次尝试
139
+ - `GET /api/ratio_config`(可能含 `create_cache_ratio`)
140
+ - `GET /api/pricing`
141
+ 成功则按 NewAPI 换算覆盖模型 `cost`(`1 USD = 500_000 quota`,每 1M tokens 成本 ≈ `ratio × 2` USD);失败静默忽略。
142
+ 3. 若开启 models.dev 元数据:请求 `https://models.dev/api.json`,补全 `contextWindow`、`maxTokens`、`cost`、reasoning 等。
143
+ - **在线导入**遇到同 model ID 多源歧义时:**自动取第一个候选**,不弹选择框;缺少可用元数据的模型跳过并提示计数。
144
+ - 导入列表会标注价格来源:`ratio_config` 或 `models.dev`。
145
+ - 网关价格在 catalog 元数据之上叠加。
146
+ 4. 关闭实时元数据:使用 Settings 中的默认参数;空字段回落 Pi 官方默认(context window `128000`、max tokens `16384`、cost `0`)。
147
+
148
+ **OpenCode 导入**(Settings):只读 `~/.config/opencode/opencode.json`,可全选或勾选 provider;导入项默认同步到 Pi。若 models.dev 仍有歧义,**需要用户选择候选**。OpenCode 配置本身不会被修改。
149
+
150
+ ## 配置路径与 Settings 字段
151
+
152
+ `<Pi agent dir>` 使用非空 `PI_CODING_AGENT_DIR`,未设置时为 `~/.pi/agent`。`PI_CODING_AGENT_SESSION_DIR` 只覆盖 Session 根目录,优先级仍高于 `<Pi agent dir>/sessions`。
153
+
154
+ | 路径 | 角色 |
155
+ |------|------|
156
+ | `~/.pi-switch/providers.json` | 完整本地 provider 库(`version: 1`) |
157
+ | `~/.pi-switch/settings.json` | pi-switch 私有设置;无自定义值时可不存在 |
158
+ | `<Pi agent dir>/models.json` | 已同步到 Pi provider 子集 |
159
+ | `<Pi agent dir>/settings.json` | Pi 设置,包括默认 provider / model |
160
+ | `~/.config/opencode/opencode.json` | OpenCode 只读导入源 |
161
+ | `~/.pi-switch/backups/` | version 3 备份(providers + models + Pi settings + pi-switch settings),最多 10 份 |
162
+ | `~/.pi-switch/write.lock` | 写入互斥锁 |
163
+ | `~/.pi-switch/update.json` | npm 新版本检查缓存(`lastCheck` + `latest` + `dismissed`,每 24h 最多联网一次) |
164
+
165
+ Pi `settings.json` 中由 pi-switch 管理的字段:
166
+
167
+ | 字段 | 含义 |
168
+ |------|------|
169
+ | `defaultProvider` + `defaultModel` | 默认模型(成对存在或同时缺省) |
170
+
171
+ `~/.pi-switch/settings.json` 的字段:
172
+
173
+ | 字段 | 含义 |
174
+ |------|------|
175
+ | `language` | `en` \| `zh-CN` |
176
+ | `fetchModelMetadata` | 是否拉 models.dev(默认 `true`) |
177
+ | `checkForUpdates` | 是否启动时检查 npm 新版本(默认 `true`) |
178
+ | `modelDefaults` | 关闭实时元数据时的导入缺省(context / maxTokens / cost) |
179
+
180
+ 升级时若 Pi `settings.json` 仍包含旧 `piSwitch` 对象,启动或重载会自动迁移到 `~/.pi-switch/settings.json`,本地已有字段优先,旧对象只补齐缺失字段;迁移成功后从 Pi settings 删除旧对象。两份文件中的未知字段都会保留。
181
+
182
+ ## 数据安全
183
+
184
+ - 写前备份 `providers.json`、Pi `models.json` / `settings.json` pi-switch `settings.json` 到 `~/.pi-switch/backups/`(version 3);最多保留最近 10 份。现有 version 2 备份仍可恢复并自动拆分设置,version 1 备份不支持恢复。
185
+ - 写入使用 `write.lock` 互斥;异常残留锁时 `doctor` 会提示。
186
+ - `providers.json` 损坏时归档为 `corrupt-providers-*.json`,再从当前 Pi 配置重建,启动时显示归档路径。
187
+ - 原子写入,只 patch 目标字段,保留未知 JSON;格式错误时停止写入并显示错误。
188
+ - 支持 Pi 的 `$ENV` / `${ENV}` 插值与 `$$` / `$!` 转义;`!command` 原样保存,在线拉取**不会**执行它。
189
+ - Session 删除只作用于选中的 JSONL,并校验路径必须位于 session 根目录内;优先调用系统 `trash`,失败后再永久删除。
190
+ - 正常退出、错误和 panic 都会恢复 raw mode、alternate screen 与光标。
191
+
192
+ ## 自动更新检查与安装
193
+
194
+ 启动时若 Settings 中「自动检查更新」开启(默认开),pi-switch 会在后台线程静默访问 npm registry 查询 `@oldsuns/pi-switch` `latest` 版本,与当前版本对比:
195
+
196
+ - 有新版本:弹出确认对话框(显示 `当前 → 最新`),用户可选择立即安装或跳过。跳过后同一版本不再弹窗,但主页仍显示横幅。手动检查(Settings 中「检查更新」)始终弹窗。
197
+ - 无新版本、离线或请求失败:静默无提示,不打扰用户。
198
+
199
+ 安装流程:
200
+
201
+ 1. 用户在确认对话框按 `Enter/y` 确认 → 后台执行 `npm install -g @oldsuns/pi-switch`,显示加载动画。
202
+ 2. 安装成功 通知「更新已安装,请重启 pi-switch 生效」。
203
+ 3. 安装失败 弹出错误通知(如权限不足、网络问题)。
204
+ 4. 用户按 `Esc/n` 跳过 → 记录已跳过的版本到缓存,同一版本不再自动弹窗;主页横幅仍提示有新版本。
205
+
206
+ 检查结果缓存在 `~/.pi-switch/update.json`,自动检查每 24h 最多联网一次。后台线程独立于目录导入任务,不阻塞 UI。Settings 中可随时关闭「自动检查更新」。
207
+
208
+ ## 验证
209
+
210
+ ```bash
211
+ cargo test --locked --lib
212
+ cargo fmt -- --check
213
+ cargo clippy --locked --all-targets -- -D warnings
214
+ npm run build:native:debug
215
+ npm run pack:check
216
+ ```
217
+
218
+ ## 许可
219
+
220
+ [MIT](./LICENSE)
221
+
222
+ ## 致谢
223
+
224
+ 感谢 [LINUX DO](https://linux.do) 社区的讨论与反馈。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oldsuns/pi-switch",
3
- "version": "0.2.14",
3
+ "version": "0.3.1",
4
4
  "description": "A focused terminal UI for Pi provider and model configuration",
5
5
  "type": "module",
6
6
  "bin": {
Binary file
Binary file
Binary file