@fanchaozz/provider-manager 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/README.md +243 -0
- package/README_EN.md +243 -0
- package/commands.ts +313 -0
- package/components.ts +696 -0
- package/forms.ts +622 -0
- package/index.ts +18 -0
- package/package.json +42 -0
- package/store.ts +282 -0
- package/sync.ts +253 -0
- package/test.ts +354 -0
- package/ui.ts +643 -0
package/README.md
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
# provider-manager
|
|
2
|
+
|
|
3
|
+
[English](./README_EN.md) | [简体中文](./README.md)
|
|
4
|
+
|
|
5
|
+
一个 pi 扩展,通过 TUI 仪表盘、`/providers` 斜杠命令和远端同步流程,管理 `~/.pi/agent/models.json` 中的自定义 provider 和 model。
|
|
6
|
+
|
|
7
|
+
> **范围**:只覆盖 `models.json` —— 本扩展**不**管理内置 provider、**不**切换 model、**不**提供登录 UI。这些请用 pi 内置的 `/model` 和 provider 认证流程。
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 安装
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pi install npm:@fanchaozz/provider-manager
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
包托管在 **GitHub Packages**。首次安装时 npm 需要知道这个 registry。把这几行加到用户级 `~/.npmrc`(一次性):
|
|
18
|
+
|
|
19
|
+
```ini
|
|
20
|
+
# ~/.npmrc
|
|
21
|
+
@fanchaozz:registry=https://npm.pkg.github.com/
|
|
22
|
+
//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
token 只需要 `read:packages` scope(包是 public 的)。之后 `npm install` / `pi install` 对所有 `@fanchaozz/*` 包都不用再配置。
|
|
26
|
+
|
|
27
|
+
### 如果没法访问 GitHub Packages
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
git clone https://github.com/fanchaozz/provider-manager.git
|
|
31
|
+
ln -s "$(pwd)/provider-manager" ~/.pi/agent/extensions/provider-manager
|
|
32
|
+
# Windows: mklink /D "%USERPROFILE%\.pi\agent\extensions\provider-manager" "%CD%\provider-manager"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
然后重启 pi。扩展每次重载都从软链目录读。
|
|
36
|
+
|
|
37
|
+
首次启动后,`~/.pi/agent/provider-manager.json` 会自动创建。删掉它就回退到内置默认。
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 快速开始
|
|
42
|
+
|
|
43
|
+
| 想做什么 | 操作 |
|
|
44
|
+
|---|---|
|
|
45
|
+
| 打开仪表盘 | `/providers` |
|
|
46
|
+
| 列出 provider + 它们的 model | `/providers ls`(过滤:`/providers ls kdapi`) |
|
|
47
|
+
| 新增 provider | 仪表盘 Providers 面板按 `n`,或 `/providers add [<id>]` |
|
|
48
|
+
| 新增 model | 仪表盘 `Tab` 切到 Models 面板按 `n`,或 `/providers model <pid> add` |
|
|
49
|
+
| 编辑 provider / model | 仪表盘按 `e` |
|
|
50
|
+
| 删除 | 仪表盘按 `d`(确认对话框) |
|
|
51
|
+
| 从 provider 的 API 拉取新 model 列表 | 仪表盘按 `y`,或 `/providers sync [<pid>]` |
|
|
52
|
+
| 探测 auth + 可达性 + 1-token 测试调用 | 仪表盘 `t`(当前 model)或 `T`(provider 内全部) |
|
|
53
|
+
| 从最近 `.bak` 恢复 | `/providers reset` |
|
|
54
|
+
| 打印命令帮助 | `/providers help` |
|
|
55
|
+
| 关闭仪表盘 | `q` 或 `Esc` |
|
|
56
|
+
|
|
57
|
+
`sync` 命令是给全新 provider 填充 model 列表最快的方式:拉取远端 model 列表,显示 checklist,把选中的写回。
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 仪表盘
|
|
62
|
+
|
|
63
|
+
`/providers` 打开两栏 TUI:
|
|
64
|
+
|
|
65
|
+
- **左栏** —— provider(id + model 数)
|
|
66
|
+
- **右栏** —— 选中 provider 的 model(id + `[R]` reasoning / `[I]` image 标记 + ctx / max)
|
|
67
|
+
- **详情条** —— 选中行的原始 JSON
|
|
68
|
+
- **底栏** —— 当前按键说明
|
|
69
|
+
|
|
70
|
+
### 按键绑定
|
|
71
|
+
|
|
72
|
+
| 键 | 行为 |
|
|
73
|
+
|---|---|
|
|
74
|
+
| `↑↓` / `j k` | 在当前面板上下移动 |
|
|
75
|
+
| `g` / `G` | 跳到顶 / 底 |
|
|
76
|
+
| `Tab` | 切换 Providers ↔ Models 面板 |
|
|
77
|
+
| `n` | 新增:Providers 面板下加 provider,Models 面板下加 model |
|
|
78
|
+
| `e` | 编辑选中的 provider / model |
|
|
79
|
+
| `d` | 删除(带确认对话框) |
|
|
80
|
+
| `y` | 同步(拉取选中 provider 的远端 model 列表) |
|
|
81
|
+
| `t` / `T` | 探测当前 model / provider 内全部 model |
|
|
82
|
+
| `?` | 切换帮助覆盖层 |
|
|
83
|
+
| `q` / `Esc` | 关闭仪表盘 |
|
|
84
|
+
|
|
85
|
+
provider 列表为空时,在 Models 面板按 `n` 会切到 Providers 面板并提示先创建一个。
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 同步流程
|
|
90
|
+
|
|
91
|
+
`sync` 是批量加 model 最快的方式。它会拉取选中 provider 的远端 model 列表并显示 checklist。
|
|
92
|
+
|
|
93
|
+
checklist **展示该 provider 的所有 model —— existing + remote new 都有**:
|
|
94
|
+
|
|
95
|
+
- 已有 model 标 `<id> (existing)`,默认勾选。取消勾选 = 删除。
|
|
96
|
+
- 远端新 model 只标 `<id>`,默认不勾选。勾选 = 添加。
|
|
97
|
+
|
|
98
|
+
按 `Enter` 写入结果,按 `Esc` 取消。保存时,最终 `models.json` 是(勾选的 existing)+(勾选的 new)的并集;如果某 model 同时被远端和 local 都有并都被勾选,优先用远端定义(这样能拉到最新的 `reasoning` / `input` / `ctx` / `maxTokens` / `thinkingLevelMap` 来自默认 model 配置)。
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 用户配置 — `provider-manager.json`
|
|
103
|
+
|
|
104
|
+
`~/.pi/agent/provider-manager.json` 控制以下场景的默认值:
|
|
105
|
+
- 在新增 model 表单回答 "yes" 到 "Use default config?"
|
|
106
|
+
- 从远端 API 同步新 model
|
|
107
|
+
|
|
108
|
+
首次启动自动创建。删掉就回退到代码默认。
|
|
109
|
+
|
|
110
|
+
### Schema
|
|
111
|
+
|
|
112
|
+
```jsonc
|
|
113
|
+
{
|
|
114
|
+
"_defaultModel": "自由格式注释,运行时忽略",
|
|
115
|
+
"defaultModel": {
|
|
116
|
+
"reasoning": true,
|
|
117
|
+
"input": ["text", "image"],
|
|
118
|
+
"contextWindow": 128000,
|
|
119
|
+
"maxTokens": 16384,
|
|
120
|
+
"thinkingLevelMap": {
|
|
121
|
+
"off": null,
|
|
122
|
+
"minimal": null,
|
|
123
|
+
"low": null,
|
|
124
|
+
"medium": "medium",
|
|
125
|
+
"high": null,
|
|
126
|
+
"xhigh": null,
|
|
127
|
+
"max": null
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### 字段规则
|
|
134
|
+
|
|
135
|
+
- **`reasoning`** — boolean。`true` 表示该 model 支持扩展思考,`thinkingLevelMap` 才生效。
|
|
136
|
+
- **`input`** — 非空数组,内容是 `"text"` 和/或 `"image"`。`"text" | "image"` 表示 model 接受该模态。
|
|
137
|
+
- **`contextWindow`** / **`maxTokens`** — 正整数(token 数)。
|
|
138
|
+
- **`thinkingLevelMap`** — object。7 个 key(`off` / `minimal` / `low` / `medium` / `high` / `xhigh` / `max`)的任意子集。`string` 值(如 `"medium"`)表示该 thinking level 启用,字符串发给 provider;`null` 表示禁用。缺失的 key 当 `null` 处理。
|
|
139
|
+
|
|
140
|
+
如果文件缺失、JSON 损坏或校验失败,扩展会静默 fallback 到上面展示的内置默认。
|
|
141
|
+
|
|
142
|
+
### 为什么 `medium` 是默认勾选的
|
|
143
|
+
|
|
144
|
+
同步的 model 若 `reasoning: true` 且 `thinkingLevelMap.medium = "medium"`,pi 的 Shift+Tab 思考级别循环会默认落到 `medium`。根据你上游实际支持的级别选 — 不支持的填 `null` 禁用即可。
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## 表单编辑器(新增/编辑 model/provider)
|
|
149
|
+
|
|
150
|
+
`addProviderFlow` / `editProviderFlow` / `addModelFlow` / `editModelFlow` / `deleteProviderFlow` / `deleteModelFlow` 都共用一个 TUI 表单(`components.ts:FormEditor`)。
|
|
151
|
+
|
|
152
|
+
### 字段类型
|
|
153
|
+
|
|
154
|
+
| 类型 | 行为 |
|
|
155
|
+
|---|---|
|
|
156
|
+
| `text` | 自由文本输入 |
|
|
157
|
+
| `secret` | 自由文本,TUI 渲染时遮罩 |
|
|
158
|
+
| `number` | 自由数字输入,提交时校验 |
|
|
159
|
+
| `select` | 选项列表;按 `e` 进 edit 模式,`Space` 选中,`↑↓`/`jk` 导航,`Enter` 确认 |
|
|
160
|
+
| `multiselect` | 类似 `select` 但可多选;`Space` 切换每项 |
|
|
161
|
+
| `levelmap` | 7 行(`off` / `minimal` / `low` / `medium` / `high` / `xhigh` / `max`);`Space` 切换每项;提交时归一化缺失的 key 为 `null` |
|
|
162
|
+
| `readonly` | 仅展示,不可编辑 |
|
|
163
|
+
|
|
164
|
+
### 按键绑定
|
|
165
|
+
|
|
166
|
+
| 键 | 行为 |
|
|
167
|
+
|---|---|
|
|
168
|
+
| `e` / `E` | 进入 edit 模式(仅 `select` / `levelmap` / `multiselect`) |
|
|
169
|
+
| `Esc` / `q` | edit 中:退出 edit(commit 当前值)。其他:取消整个表单 |
|
|
170
|
+
| `s` | 保存整个表单。仅在 non-typeable 字段生效 — `s` 在 `text` / `secret` / `number` / `json` 里是字符 |
|
|
171
|
+
| `Enter` | edit 中(非输入字段):commit 并退出 edit。typeable 字段:commit + 移到下一字段。readonly 字段:保存表单 |
|
|
172
|
+
| `Space` | edit 中(非输入字段):切换当前选项 |
|
|
173
|
+
| `↑↓` / `j k` | 字段间导航;edit 中(非输入字段):选项间导航 |
|
|
174
|
+
| `Backspace` | 删最后一个字符(typeable 字段) |
|
|
175
|
+
|
|
176
|
+
### 新增 model 流程:"Use default config?"
|
|
177
|
+
|
|
178
|
+
`addModelFlow` 在 name 之后问一次:
|
|
179
|
+
|
|
180
|
+
- **Yes** — 应用 `DEFAULT_MODEL_CONFIG`(见 [用户配置](#用户配置--provider-managerjson)),跳过剩余问题
|
|
181
|
+
- **No** — 逐个问 reasoning / input / ctx / max / thinking-level-map
|
|
182
|
+
|
|
183
|
+
`Esc` 在任何问题中都能取消整个流程(仪表盘自动恢复)。
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 探测 model(`t` / `T`)
|
|
188
|
+
|
|
189
|
+
`t` 探测当前 model;`T` 探测当前 provider 内全部 model。每个 model 三档检查:
|
|
190
|
+
|
|
191
|
+
| 检查 | 做什么 | 成本 |
|
|
192
|
+
|---|---|---|
|
|
193
|
+
| `auth` | 在 `~/.pi/agent/auth.json`(或环境变量)里查 provider 的 API key | 免费 |
|
|
194
|
+
| `reachable` | `GET {baseUrl}/models`,10s 超时 | 免费 |
|
|
195
|
+
| `generated` | 发 4-token prompt(`"Reply with the single word: ok"`)并检查 `stopReason ∈ {stop, length}` | ~4 token |
|
|
196
|
+
|
|
197
|
+
硬上限:`maxTokens` 钳到 16;超时 10s(用 `PI_PROVIDER_TEST_TIMEOUT` 环境变量覆盖)。结果缓存在进程内,重启 pi 前有效。
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## 文件布局
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
~/.pi/agent/
|
|
205
|
+
├── models.json ← 本扩展编辑的文件
|
|
206
|
+
├── models.json.bak ← 每次写前的自动备份
|
|
207
|
+
└── extensions/
|
|
208
|
+
└── provider-manager/ ← 本扩展(pi install / git clone 安装)
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
本扩展不触碰 `models.json` 和 `models.json.bak` 之外的文件。要回滚,从 `.bak` 恢复:`/providers reset`,或手动:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
cp ~/.pi/agent/models.json.bak ~/.pi/agent/models.json
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## 故障排查
|
|
220
|
+
|
|
221
|
+
**`pi install` 报 `E404` 或 "no such package"。** 你的 npm registry 里没有 GitHub Packages。把它加到 `~/.npmrc`(见 [安装](#安装))或用 git-clone 降级方案。
|
|
222
|
+
|
|
223
|
+
**仪表盘打开是空的。** 你的 `models.json` 里没有自定义 provider。本扩展只管 `models.json` — pi 内置 provider(anthropic / openai / google 等)不显示,用 pi 内置的 `/model`。
|
|
224
|
+
|
|
225
|
+
**Sync 报 `ECONNREFUSED` / `ENOTFOUND`。** 选中 provider 的 `baseUrl` 不通。用 `/providers edit <pid>`(或仪表盘 `e`)改。
|
|
226
|
+
|
|
227
|
+
**Sync 报 `HTTP 500` / `HTTP 401`。** `baseUrl` 错或 `apiKey` 缺失/错。在 provider 编辑表单里核对。
|
|
228
|
+
|
|
229
|
+
**设的 thinking level 一保存就消失。** pi 可能不支持该 level — 换别的,或者填 `null` 禁用。
|
|
230
|
+
|
|
231
|
+
**`provider-manager.json` 里的修改全部失效。** 文件损坏或校验失败(见 [Schema](#schema))。扩展会静默 fallback 默认。校验:`node -e "JSON.parse(require('fs').readFileSync(process.env.HOME+'/.pi/agent/provider-manager.json','utf8'))"`。
|
|
232
|
+
|
|
233
|
+
**Sync 加的 model 字段错(不管什么都 `ctx=128000`)。** model 用的是默认,不是文件。文件没被读。检查路径:必须正好是 `~/.pi/agent/provider-manager.json`(不是 `~/.pi/agent/providers.json` 之类)。
|
|
234
|
+
|
|
235
|
+
**按 `n` / `e` / `d` / `y` 后 Esc 仪表盘消失。** 当前版本不应发生 — 仪表盘会自动恢复。如果发生了,请带 `~/.pi/agent/provider-manager.log` 反馈。
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## 相关
|
|
240
|
+
|
|
241
|
+
- pi 内置 `/model` — 切换当前 model
|
|
242
|
+
- pi 内置 provider auth(`/login` 或环境变量)— 设 API key
|
|
243
|
+
- 备份恢复:`/providers reset` 或 `cp ~/.pi/agent/models.json.bak ~/.pi/agent/models.json`
|
package/README_EN.md
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
# provider-manager
|
|
2
|
+
|
|
3
|
+
[English](./README_EN.md) | [简体中文](./README.md)
|
|
4
|
+
|
|
5
|
+
A pi extension that manages custom providers and models in `~/.pi/agent/models.json` through a TUI dashboard, a `/providers` slash command, and a remote model sync.
|
|
6
|
+
|
|
7
|
+
> **Scope**: only `models.json` is covered — the extension does **not** manage built-in providers, does **not** switch models, and does **not** provide a login UI. Use pi's built-in `/model` and provider auth flow for those.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pi install npm:@fanchaozz/provider-manager
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The package is hosted on **GitHub Packages**. The first time you install, npm needs to know about this registry. Add this once to your user-level `~/.npmrc`:
|
|
18
|
+
|
|
19
|
+
```ini
|
|
20
|
+
# ~/.npmrc
|
|
21
|
+
@fanchaozz:registry=https://npm.pkg.github.com/
|
|
22
|
+
//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The token only needs the `read:packages` scope (it's a public package). After that, `npm install` / `pi install` works for all `@fanchaozz/*` packages without further setup.
|
|
26
|
+
|
|
27
|
+
### If you can't reach GitHub Packages
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
git clone https://github.com/fanchaozz/provider-manager.git
|
|
31
|
+
ln -s "$(pwd)/provider-manager" ~/.pi/agent/extensions/provider-manager
|
|
32
|
+
# or, on Windows: mklink /D "%USERPROFILE%\.pi\agent\extensions\provider-manager" "%CD%\provider-manager"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Then re-launch pi. The extension reads from the symlinked directory on every reload.
|
|
36
|
+
|
|
37
|
+
After the first launch, `~/.pi/agent/provider-manager.json` is auto-created. Delete it to revert to the built-in defaults.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Quick start
|
|
42
|
+
|
|
43
|
+
| Want to… | Do this |
|
|
44
|
+
|---|---|
|
|
45
|
+
| Open the dashboard | `/providers` |
|
|
46
|
+
| List providers + their models | `/providers ls` (filter: `/providers ls kdapi`) |
|
|
47
|
+
| Add a provider | Dashboard, `n` on the Providers pane, or `/providers add [<id>]` |
|
|
48
|
+
| Add a model | Dashboard, switch to Models pane with `Tab`, `n`, or `/providers model <pid> add` |
|
|
49
|
+
| Edit provider / model | Dashboard, `e` |
|
|
50
|
+
| Delete | Dashboard, `d` (confirm dialog) |
|
|
51
|
+
| Pull new model list from a provider's API | Dashboard, `y`, or `/providers sync [<pid>]` |
|
|
52
|
+
| Probe auth + reachability + a 1-token test call | Dashboard, `t` (current model) or `T` (all in provider) |
|
|
53
|
+
| Restore last `.bak` | `/providers reset` |
|
|
54
|
+
| Print command help | `/providers help` |
|
|
55
|
+
| Close dashboard | `q` or `Esc` |
|
|
56
|
+
|
|
57
|
+
The sync command is the fastest way to populate a fresh provider: it fetches the remote model list, shows a checklist, and writes back the ones you select.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Dashboard
|
|
62
|
+
|
|
63
|
+
`/providers` opens a two-pane TUI:
|
|
64
|
+
|
|
65
|
+
- **Left pane** — providers (id + model count)
|
|
66
|
+
- **Right pane** — models of the selected provider (id + `[R]` reasoning / `[I]` image flags + ctx / max)
|
|
67
|
+
- **Detail strip** — raw JSON of the selected row
|
|
68
|
+
- **Footer** — current key bindings
|
|
69
|
+
|
|
70
|
+
### Key bindings
|
|
71
|
+
|
|
72
|
+
| Key | Action |
|
|
73
|
+
|---|---|
|
|
74
|
+
| `↑↓` / `j k` | Navigate in current pane |
|
|
75
|
+
| `g` / `G` | Jump to top / bottom |
|
|
76
|
+
| `Tab` | Switch between Providers ↔ Models pane |
|
|
77
|
+
| `n` | New: add provider on Providers pane, add model on Models pane |
|
|
78
|
+
| `e` | Edit selected provider / model |
|
|
79
|
+
| `d` | Delete (with confirm dialog) |
|
|
80
|
+
| `y` | Sync (fetch remote model list for selected provider) |
|
|
81
|
+
| `t` / `T` | Probe current model / all models in selected provider |
|
|
82
|
+
| `?` | Toggle help overlay |
|
|
83
|
+
| `q` / `Esc` | Close dashboard |
|
|
84
|
+
|
|
85
|
+
When the provider list is empty, pressing `n` on the Models pane switches to the Providers pane and tells you to create one first.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Sync flow
|
|
90
|
+
|
|
91
|
+
`sync` is the fastest way to add a batch of models. It fetches the remote model list for the selected provider and shows a checklist.
|
|
92
|
+
|
|
93
|
+
The checklist **shows every model for that provider — both existing and remote new**:
|
|
94
|
+
|
|
95
|
+
- Existing models are labelled `<id> (existing)`, default checked. Uncheck to delete.
|
|
96
|
+
- Remote new models are labelled `<id>` only, default unchecked. Check to add.
|
|
97
|
+
|
|
98
|
+
Press `Enter` to write the result, `Esc` to cancel. On save, the final `models.json` is the union of (checked existing) + (checked new); remote new is preferred over local if both are checked (so you pick up the fresh `reasoning` / `input` / `ctx` / `maxTokens` / `thinkingLevelMap` from the default model config).
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## User config — `provider-manager.json`
|
|
103
|
+
|
|
104
|
+
`~/.pi/agent/provider-manager.json` controls the defaults used when:
|
|
105
|
+
- you answer "yes" to "Use default config?" in the new-model form
|
|
106
|
+
- you sync new models from a remote API
|
|
107
|
+
|
|
108
|
+
Auto-created on first launch. Delete to revert to code defaults.
|
|
109
|
+
|
|
110
|
+
### Schema
|
|
111
|
+
|
|
112
|
+
```jsonc
|
|
113
|
+
{
|
|
114
|
+
"_defaultModel": "free-form comment, ignored at runtime",
|
|
115
|
+
"defaultModel": {
|
|
116
|
+
"reasoning": true,
|
|
117
|
+
"input": ["text", "image"],
|
|
118
|
+
"contextWindow": 128000,
|
|
119
|
+
"maxTokens": 16384,
|
|
120
|
+
"thinkingLevelMap": {
|
|
121
|
+
"off": null,
|
|
122
|
+
"minimal": null,
|
|
123
|
+
"low": null,
|
|
124
|
+
"medium": "medium",
|
|
125
|
+
"high": null,
|
|
126
|
+
"xhigh": null,
|
|
127
|
+
"max": null
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Field rules
|
|
134
|
+
|
|
135
|
+
- **`reasoning`** — boolean. If `true`, the model supports extended thinking and `thinkingLevelMap` applies.
|
|
136
|
+
- **`input`** — non-empty array of `"text"` and/or `"image"`. `"text" | "image"` means the model accepts that modality.
|
|
137
|
+
- **`contextWindow`** / **`maxTokens`** — positive integers (tokens).
|
|
138
|
+
- **`thinkingLevelMap`** — object. Any subset of the 7 keys (`off` / `minimal` / `low` / `medium` / `high` / `xhigh` / `max`). A `string` value (e.g. `"medium"`) means that thinking level is enabled and the string is sent to the provider; `null` means disabled. Missing keys are treated as `null`.
|
|
139
|
+
|
|
140
|
+
If the file is missing, malformed JSON, or fails any check, the extension silently falls back to the built-in defaults shown above.
|
|
141
|
+
|
|
142
|
+
### Why `medium` is highlighted by default
|
|
143
|
+
|
|
144
|
+
When a synced model has `reasoning: true` and `thinkingLevelMap.medium = "medium"`, pi's Shift+Tab thinking-level cycle lands on `medium` by default. Pick whichever level your upstream actually supports — `null` is fine for providers with no extended-thinking knob.
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Form editor (new model / edit model / new provider)
|
|
149
|
+
|
|
150
|
+
`addProviderFlow` / `editProviderFlow` / `addModelFlow` / `editModelFlow` / `deleteProviderFlow` / `deleteModelFlow` all share one TUI form (`components.ts:FormEditor`).
|
|
151
|
+
|
|
152
|
+
### Field types
|
|
153
|
+
|
|
154
|
+
| Type | Behavior |
|
|
155
|
+
|---|---|
|
|
156
|
+
| `text` | Free text input |
|
|
157
|
+
| `secret` | Free text, rendered masked in the TUI |
|
|
158
|
+
| `number` | Free numeric input, validated on commit |
|
|
159
|
+
| `select` | Options list; press `e` to enter edit mode, `Space` to pick, `↑↓`/`jk` to navigate, `Enter` to commit |
|
|
160
|
+
| `multiselect` | Like `select` but multiple values; `Space` toggles each |
|
|
161
|
+
| `levelmap` | 7 rows (`off` / `minimal` / `low` / `medium` / `high` / `xhigh` / `max`); `Space` toggles each; commit normalizes missing keys to `null` |
|
|
162
|
+
| `readonly` | Display only, cannot edit |
|
|
163
|
+
|
|
164
|
+
### Key bindings
|
|
165
|
+
|
|
166
|
+
| Key | Behavior |
|
|
167
|
+
|---|---|
|
|
168
|
+
| `e` / `E` | Enter edit mode (only on `select` / `levelmap` / `multiselect`) |
|
|
169
|
+
| `Esc` / `q` | If editing: exit edit (commit current value). Otherwise: cancel the form |
|
|
170
|
+
| `s` | Save the whole form. Only on non-typeable fields — `s` is a literal char inside `text` / `secret` / `number` / `json` |
|
|
171
|
+
| `Enter` | If editing on a non-input field: commit and exit edit. On a typeable field: commit + move to next field. On a readonly field: save the form |
|
|
172
|
+
| `Space` | If editing on a non-input field: toggle current option |
|
|
173
|
+
| `↑↓` / `j k` | Navigate fields; inside edit mode of a non-input field: navigate options |
|
|
174
|
+
| `Backspace` | Delete last char (typeable fields) |
|
|
175
|
+
|
|
176
|
+
### New-model flow: "Use default config?"
|
|
177
|
+
|
|
178
|
+
`addModelFlow` asks once after the name:
|
|
179
|
+
|
|
180
|
+
- **Yes** — apply `DEFAULT_MODEL_CONFIG` (see [User config](#user-config--provider-managerjson)) and skip the remaining questions
|
|
181
|
+
- **No** — ask reasoning / input / ctx / max / thinking-level-map one by one
|
|
182
|
+
|
|
183
|
+
`Esc` at any prompt cancels the whole flow (the dashboard is restored automatically).
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Test a model (`t` / `T`)
|
|
188
|
+
|
|
189
|
+
`t` probes the current model; `T` probes all models in the current provider. Three checks per model:
|
|
190
|
+
|
|
191
|
+
| Check | What it does | Cost |
|
|
192
|
+
|---|---|---|
|
|
193
|
+
| `auth` | Looks up `~/.pi/agent/auth.json` (or env) for the provider's API key | free |
|
|
194
|
+
| `reachable` | `GET {baseUrl}/models` with a 10 s timeout | free |
|
|
195
|
+
| `generated` | Sends a 4-token prompt (`"Reply with the single word: ok"`) and checks `stopReason ∈ {stop, length}` | ~4 tokens |
|
|
196
|
+
|
|
197
|
+
Hard caps: `maxTokens` is clamped to 16, timeout 10 s (override with `PI_PROVIDER_TEST_TIMEOUT` env var in seconds). Result is cached in-process until you restart pi.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## File layout
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
~/.pi/agent/
|
|
205
|
+
├── models.json ← the file this extension edits
|
|
206
|
+
├── models.json.bak ← automatic backup taken before every write
|
|
207
|
+
└── extensions/
|
|
208
|
+
└── provider-manager/ ← this extension (installed via pi install / git clone)
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
The extension does not touch anything outside `models.json` and `models.json.bak`. To roll back, restore from `.bak` with `/providers reset` or manually:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
cp ~/.pi/agent/models.json.bak ~/.pi/agent/models.json
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Troubleshooting
|
|
220
|
+
|
|
221
|
+
**`pi install` fails with `E404` or "no such package".** GitHub Packages isn't in your npm registry. Add it to `~/.npmrc` (see [Install](#install)) or use the git-clone fallback.
|
|
222
|
+
|
|
223
|
+
**Dashboard opens but is empty.** Your `models.json` has no custom providers. The extension only manages `models.json` — built-in pi providers (anthropic / openai / google / …) are not shown. Use pi's built-in `/model` for those.
|
|
224
|
+
|
|
225
|
+
**Sync errors with `ECONNREFUSED` / `ENOTFOUND`.** The selected provider's `baseUrl` is unreachable. Edit it with `/providers edit <pid>` (or dashboard `e`).
|
|
226
|
+
|
|
227
|
+
**Sync errors with `HTTP 500` / `HTTP 401`.** Wrong `baseUrl` or missing / wrong `apiKey`. Verify in the provider edit form.
|
|
228
|
+
|
|
229
|
+
**A thinking level I set keeps disappearing.** pi may not support that level on the underlying model — try a different level, or set it to `null` to disable.
|
|
230
|
+
|
|
231
|
+
**All my customizations in `provider-manager.json` are ignored.** The file is malformed or fails validation (see [Schema](#schema)). The extension falls back to defaults silently. Validate with `node -e "JSON.parse(require('fs').readFileSync(process.env.HOME+'/.pi/agent/provider-manager.json','utf8'))"`.
|
|
232
|
+
|
|
233
|
+
**Models added by sync show wrong fields (`ctx=128000` regardless).** The model is using defaults, not the file. The file isn't being read. Check file path: should be exactly `~/.pi/agent/provider-manager.json` (not `~/.pi/agent/providers.json` or similar).
|
|
234
|
+
|
|
235
|
+
**Dashboard disappears after pressing `n` / `e` / `d` / `y` and Esc.** Should not happen in the current version — the dashboard is restored automatically. If it does, please report with `~/.pi/agent/provider-manager.log` output.
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Related
|
|
240
|
+
|
|
241
|
+
- pi's built-in `/model` — switch the active model
|
|
242
|
+
- pi's built-in provider auth (`/login` or env vars) — set up API keys
|
|
243
|
+
- Backup flow: `/providers reset` or `cp ~/.pi/agent/models.json.bak ~/.pi/agent/models.json`
|