@goodandready/dsh-clinebot 0.6.1 → 0.6.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/CHANGELOG.md +7 -0
- package/README.md +6 -14
- package/README.ru.md +2 -13
- package/README.zh.md +2 -13
- package/lib/client.js +9 -139
- package/lib/cline-client.js +0 -102
- package/lib/config.js +0 -8
- package/lib/index.js +7 -201
- package/lib/provider-sync.js +2 -141
- package/lib/routes/accounts.js +1 -37
- package/lib/transport/cline-transport.js +1 -1
- package/package.json +1 -1
- package/lib/proxy-server.js +0 -138
- package/lib/proxy-token.js +0 -187
- package/lib/routes/proxy.js +0 -578
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,13 @@ All notable changes to `@goodandready/dsh-clinebot` will be documented in this f
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.6.2] - 2026-10-21
|
|
9
|
+
|
|
10
|
+
### Removed
|
|
11
|
+
- **Legacy transport removed**: `transport: "pi-ai"`, `proxyMode`, `lib/proxy-server.js`, `lib/proxy-token.js`, `lib/routes/proxy.js`, the `llm/stream` failover hook and `/register` / `/unregister` routes are gone. ClineBot is adapter-only on `ctx.llm`.
|
|
12
|
+
- **Legacy settings surfaces removed**: the transport selector, proxy diagnostics and proxy-mode toggle no longer appear in Settings or the TUI. A one-time cleanup still removes an old `llm-pi-ai.providers.clinebot` entry for users upgrading from 0.6.1.
|
|
13
|
+
- **Legacy tests removed**; the adapter/session-router paths remain covered. Final bundle: 248.9 KB.
|
|
14
|
+
|
|
8
15
|
## [0.6.1] - 2026-10-21
|
|
9
16
|
|
|
10
17
|
### Fixed
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
<h3>Native ClineBot / ClinePass Provider Companion for DeepSeek Harness</h3>
|
|
6
6
|
|
|
7
|
-
<p><b>0.6.
|
|
7
|
+
<p><b>0.6.2</b> is adapter-only: chat runs on the native <code>ctx.llm</code> adapter and requires DSH <code>0.2.1-rc.2</code>. The legacy <code>llm-pi-ai</code>, loopback proxy and <code>llm/stream</code> path have been removed.</p>
|
|
8
8
|
|
|
9
9
|
<p align="center">
|
|
10
10
|
<a href="https://www.npmjs.com/package/@goodandready/dsh-clinebot"><img src="https://img.shields.io/npm/v/@goodandready/dsh-clinebot.svg?style=for-the-badge&color=6366f1&labelColor=1e1b4b" alt="npm version"></a>
|
|
@@ -118,7 +118,7 @@ graph LR
|
|
|
118
118
|
* **`lib/adapter.js`**:
|
|
119
119
|
Registers the `ClineBotAdapter` directly on `ctx.llm`: streaming, model catalogue, reasoning effort, pre-first-token account failover, retry policy, usage accounting and provider metadata.
|
|
120
120
|
* **`lib/transport/cline-transport.js`**:
|
|
121
|
-
OpenAI-compatible SSE transport with connect/idle timeouts, abort handling and upstream error classification.
|
|
121
|
+
OpenAI-compatible SSE transport with connect/idle timeouts, abort handling and upstream error classification.
|
|
122
122
|
* **`lib/models.js`**:
|
|
123
123
|
Dynamic subscription catalogue, curated fallback properties, reasoning efforts, custom models and plan parsing (`parsePlanIncludedModels`, `getAllModels`, `getDynamicModels`).
|
|
124
124
|
* **`lib/model-prices.js`**:
|
|
@@ -128,9 +128,9 @@ graph LR
|
|
|
128
128
|
* **`lib/account-pool.js` / `lib/session-router.js`**:
|
|
129
129
|
Credential discovery, usage-aware least-used and round-robin rotation, sticky sessions and cooldown recovery.
|
|
130
130
|
* **`lib/cline-client.js`**:
|
|
131
|
-
`fetchUsageLimits`, credential save, smoke test
|
|
131
|
+
`fetchUsageLimits`, credential save, smoke test and the model catalogue cache.
|
|
132
132
|
* **`lib/index.js`**:
|
|
133
|
-
Cordis lifecycle: adapter registration, optional HTTP routes, quota warnings, `/cline` command,
|
|
133
|
+
Cordis lifecycle: adapter registration, optional HTTP routes, quota warnings, `/cline` command, one-time cleanup of the old provider entry and TUI section registration.
|
|
134
134
|
* **`lib/tui-settings.js`**:
|
|
135
135
|
`dsh-TUI` section for key, base URL, model filters, active account, context window and output cap.
|
|
136
136
|
* **`lib/client.js`**:
|
|
@@ -144,7 +144,7 @@ graph LR
|
|
|
144
144
|
dsh plugin --profile web add @goodandready/dsh-clinebot
|
|
145
145
|
```
|
|
146
146
|
|
|
147
|
-
Requires **DSH `0.2.1-rc.2`** and Node 22+.
|
|
147
|
+
Requires **DSH `0.2.1-rc.2`** and Node 22+. ClineBot registers directly with `ctx.llm`; there is no transport switch or loopback proxy.
|
|
148
148
|
|
|
149
149
|
Restart your DeepSeek Harness instance and refresh the browser.
|
|
150
150
|
|
|
@@ -191,7 +191,6 @@ dsh-clinebot:
|
|
|
191
191
|
baseUrl: https://api.cline.bot/api/v1
|
|
192
192
|
apiKeyEnv: CLINEBOT_API_KEY
|
|
193
193
|
defaultModel: your-default-model
|
|
194
|
-
proxyMode: true
|
|
195
194
|
disabledModels: []
|
|
196
195
|
customModels: []
|
|
197
196
|
modelReasoningDefaults:
|
|
@@ -218,7 +217,6 @@ dsh-clinebot:
|
|
|
218
217
|
| `customModels` | `array` | `[]` | User-defined gateway models (`[{ id, name, contextLength, maxTokens, category, isReasoning }]`) |
|
|
219
218
|
| `modelReasoningDefaults` | `object` | `{}` | Configured default reasoning effort per model (`low`, `medium`, `high`, `max`) |
|
|
220
219
|
| `modelContextOverrides` | `array` | `[]` | User-defined model context length and max token overrides |
|
|
221
|
-
| `proxyMode` | `boolean` | `true` | Enable local transparent loopback proxy for sticky sessions and automatic 429 failover |
|
|
222
220
|
| `statsPath` | `string` | `"~/.dsh/clinebot-stats.json"` | Persistent on-disk path for token usage analytics |
|
|
223
221
|
| `accounts` | `array` | `[]` | Additional accounts for multi-account failover and quota rotation (`[{ label, apiKeyEnv }]`) |
|
|
224
222
|
| `activeAccount` | `string` | `""` | Manually pinned active account env name (empty for least-used auto routing) |
|
|
@@ -232,7 +230,7 @@ dsh-clinebot:
|
|
|
232
230
|
|
|
233
231
|
## 🌐 HTTP API Endpoints
|
|
234
232
|
|
|
235
|
-
All endpoints are registered under `/dsh-clinebot/*` and protected against untrusted cross-site origins (same-origin and loopback allowed). Control endpoints enforce a 256 KiB request payload limit
|
|
233
|
+
All endpoints are registered under `/dsh-clinebot/*` and protected against untrusted cross-site origins (same-origin and loopback allowed). Control endpoints enforce a 256 KiB request payload limit:
|
|
236
234
|
|
|
237
235
|
### Management & Control Endpoints (Max 256 KiB)
|
|
238
236
|
* `GET /dsh-clinebot/status` — Live status report including provider health, active credential, quota, and session metrics.
|
|
@@ -252,12 +250,6 @@ All endpoints are registered under `/dsh-clinebot/*` and protected against untru
|
|
|
252
250
|
* `GET /dsh-clinebot/update/status` — Query available GitHub releases and plugin updates.
|
|
253
251
|
* `POST /dsh-clinebot/update/apply` — Apply version upgrade with process-group cleanup and lockfile sync.
|
|
254
252
|
|
|
255
|
-
### OpenAI-Compatible Loopback Proxy (Max 64 MiB)
|
|
256
|
-
* `POST /dsh-clinebot/v1/chat/completions` — Transparent local proxy supporting streaming SSE and non-streaming responses, Bearer token authentication, sticky session affinity with least-used quota allocation, body read watchdog (`streamIdleTimeoutMs`), and automatic 429 failover.
|
|
257
|
-
* `GET /dsh-clinebot/v1/models` — OpenAI-compatible catalog listing all active plan and custom models.
|
|
258
|
-
|
|
259
|
-
> **DSH Desktop 2.x & Headless Environments**: The loopback proxy binds an isolated loopback HTTP server on `127.0.0.1` (ephemeral port), completely bypassing `DesktopWebServer` renderer fences (`x-dsh-desktop-renderer`). Automated fence detection (`detectHostWebServerFence`) falls back to direct upstream connection if the loopback server is restricted, and proxy mode can be directly toggled via the Diagnostics settings card.
|
|
260
|
-
|
|
261
253
|
---
|
|
262
254
|
|
|
263
255
|
## Visual verification
|
package/README.ru.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
<h3>Нативное подключение провайдера ClineBot / ClinePass для DeepSeek Harness</h3>
|
|
6
6
|
|
|
7
|
-
<p><b>0.6.
|
|
7
|
+
<p><b>0.6.2</b> работает только через нативный адаптер <code>ctx.llm</code> и требует DSH <code>0.2.1-rc.2</code>. Старые <code>llm-pi-ai</code>, loopback-прокси и <code>llm/stream</code> удалены.</p>
|
|
8
8
|
|
|
9
9
|
<p align="center">
|
|
10
10
|
<a href="https://www.npmjs.com/package/@goodandready/dsh-clinebot"><img src="https://img.shields.io/npm/v/@goodandready/dsh-clinebot.svg?style=for-the-badge&color=6366f1&labelColor=1e1b4b" alt="npm version"></a>
|
|
@@ -84,7 +84,6 @@ graph LR
|
|
|
84
84
|
|
|
85
85
|
subgraph DSHCore [Сервисы DSH]
|
|
86
86
|
Credentials["Сервис credentials (~/.dsh/.credentials.yaml)"]
|
|
87
|
-
PiAi["Настройки: llm-pi-ai.providers.clinebot"]
|
|
88
87
|
end
|
|
89
88
|
|
|
90
89
|
subgraph Upstream [Сервер Cline]
|
|
@@ -99,7 +98,6 @@ graph LR
|
|
|
99
98
|
HttpEndpoints --> Credentials
|
|
100
99
|
HttpEndpoints --> ClientCore
|
|
101
100
|
ClientCore --> ModelCatalog
|
|
102
|
-
HttpEndpoints -->|Атомарная мутация| PiAi
|
|
103
101
|
ClientCore -->|Чат| ClinePass
|
|
104
102
|
ClientCore -->|Квоты| ClineQuota
|
|
105
103
|
ClientCore -->|Тарифный план| ClinePlan
|
|
@@ -115,7 +113,6 @@ graph LR
|
|
|
115
113
|
* `sessionStats` / `recordSessionRequest`: счетчики сессии (запросы, токены, задержка, время).
|
|
116
114
|
* `saveCredentialKey`: атомарная запись ключей в `~/.dsh/.credentials.yaml`.
|
|
117
115
|
* `smokeChat`: замер задержки и тестовый пинг с фиксацией статистики.
|
|
118
|
-
* `buildPiAiProvider`: генерация конфигурации провайдера для `llm-pi-ai` (`api: 'openai-completions'`).
|
|
119
116
|
* **`lib/index.js`**: сервис Cordis, регистрация системных маршрутов (включая `/dsh-clinebot/models/sync`), расчет порогов предупреждения квоты и слэш-команды `/cline`.
|
|
120
117
|
* **`lib/client.js`**: страница конфигурации строки плагина (`plugins.row.config`) с предупреждениями, статистикой сессии, синхронизацией моделей и запасной карточкой (`settings.plugin.item`). Пункта `settings.section` в боковом меню нет.
|
|
121
118
|
|
|
@@ -163,7 +160,6 @@ dsh-clinebot:
|
|
|
163
160
|
baseUrl: https://api.cline.bot/api/v1
|
|
164
161
|
apiKeyEnv: CLINEBOT_API_KEY
|
|
165
162
|
defaultModel: your-default-model
|
|
166
|
-
proxyMode: true
|
|
167
163
|
disabledModels: []
|
|
168
164
|
customModels: []
|
|
169
165
|
modelReasoningDefaults:
|
|
@@ -190,7 +186,6 @@ dsh-clinebot:
|
|
|
190
186
|
| `customModels` | `array` | `[]` | Пользовательские модели шлюза (`[{ id, name, contextLength, maxTokens, category, isReasoning }]`) |
|
|
191
187
|
| `modelReasoningDefaults` | `object` | `{}` | Значения thinking effort по умолчанию для моделей (`low`, `medium`, `high`, `max`) |
|
|
192
188
|
| `modelContextOverrides` | `array` | `[]` | Пользовательские переопределения размера контекста и лимита токенов |
|
|
193
|
-
| `proxyMode` | `boolean` | `true` | Включение локального прозрачного loopback-прокси с сессионным роутингом и failover |
|
|
194
189
|
| `statsPath` | `string` | `"~/.dsh/clinebot-stats.json"` | Путь к файлу персистентной аналитики использования токенов |
|
|
195
190
|
| `accounts` | `array` | `[]` | Дополнительные аккаунты для ротации квоты и failover (`[{ label, apiKeyEnv }]`) |
|
|
196
191
|
| `activeAccount` | `string` | `""` | Принудительно закреплённый аккаунт (пусто для автоматического выбора least-used) |
|
|
@@ -204,7 +199,7 @@ dsh-clinebot:
|
|
|
204
199
|
|
|
205
200
|
## 🌐 Маршруты HTTP API
|
|
206
201
|
|
|
207
|
-
Все маршруты регистрируются с префиксом `/dsh-clinebot/*` и защищены от межсайтовых запросов (разрешены same-origin и loopback). Управляющие эндпоинты ограничены лимитом 256
|
|
202
|
+
Все маршруты регистрируются с префиксом `/dsh-clinebot/*` и защищены от межсайтовых запросов (разрешены same-origin и loopback). Управляющие эндпоинты ограничены лимитом 256 КиБ:
|
|
208
203
|
|
|
209
204
|
### Управляющие эндпоинты (макс. 256 КиБ)
|
|
210
205
|
* `GET /dsh-clinebot/status` — Текущее состояние провайдера, активный аккаунт, квоты и статистика сессий.
|
|
@@ -224,12 +219,6 @@ dsh-clinebot:
|
|
|
224
219
|
* `GET /dsh-clinebot/update/status` — Проверка наличия обновлений плагина.
|
|
225
220
|
* `POST /dsh-clinebot/update/apply` — Обновление плагина с корректным завершением групп процессов и блокировками профиля.
|
|
226
221
|
|
|
227
|
-
### OpenAI-совместимый loopback-прокси (макс. 64 МиБ)
|
|
228
|
-
* `POST /dsh-clinebot/v1/chat/completions` — Прозрачный локальный прокси с поддержкой SSE и нестриминговых ответов, Bearer-аутентификацией, сессионной липкостью и least-used распределением квот, контролем дедлайнов (`streamIdleTimeoutMs`) и автоматическим 429 failover.
|
|
229
|
-
* `GET /dsh-clinebot/v1/models` — Каталог моделей в стандарте OpenAI API.
|
|
230
|
-
|
|
231
|
-
> **DSH Desktop 2.x и автономные окружения**: Прокси поднимает изолированный выделенный HTTP-сервер на `127.0.0.1` (эфемеридный порт), полностью обходя сетевые экраны `DesktopWebServer` (`x-dsh-desktop-renderer`). Встроенный детектор защитных экранов (`detectHostWebServerFence`) автоматически переключает провайдер на прямое соединение с upstream при ограничении loopback-порта, а режим прокси можно переключать напрямую в карточке «Диагностика» в UI.
|
|
232
|
-
|
|
233
222
|
---
|
|
234
223
|
|
|
235
224
|
## 🧪 Тестирование
|
package/README.zh.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
<h3>适用于 DeepSeek Harness 的 ClineBot / ClinePass 原生模型提供商伴侣插件</h3>
|
|
6
6
|
|
|
7
|
-
<p><b>0.6.
|
|
7
|
+
<p><b>0.6.2</b> 仅使用原生 <code>ctx.llm</code> 适配器,需要 DSH <code>0.2.1-rc.2</code>。旧的 <code>llm-pi-ai</code>、回环代理和 <code>llm/stream</code> 已删除。</p>
|
|
8
8
|
|
|
9
9
|
<p align="center">
|
|
10
10
|
<a href="https://www.npmjs.com/package/@goodandready/dsh-clinebot"><img src="https://img.shields.io/npm/v/@goodandready/dsh-clinebot.svg?style=for-the-badge&color=6366f1&labelColor=1e1b4b" alt="npm version"></a>
|
|
@@ -84,7 +84,6 @@ graph LR
|
|
|
84
84
|
|
|
85
85
|
subgraph DSHCore [DSH 核心系统服务]
|
|
86
86
|
Credentials["凭据存储服务 (~/.dsh/.credentials.yaml)"]
|
|
87
|
-
PiAi["模型注册: llm-pi-ai.providers.clinebot"]
|
|
88
87
|
end
|
|
89
88
|
|
|
90
89
|
subgraph Upstream [Cline 官方云端]
|
|
@@ -99,7 +98,6 @@ graph LR
|
|
|
99
98
|
HttpEndpoints --> Credentials
|
|
100
99
|
HttpEndpoints --> ClientCore
|
|
101
100
|
ClientCore --> ModelCatalog
|
|
102
|
-
HttpEndpoints -->|原子级写入| PiAi
|
|
103
101
|
ClientCore -->|模型对话| ClinePass
|
|
104
102
|
ClientCore -->|额度查询| ClineQuota
|
|
105
103
|
ClientCore -->|套餐信息| ClinePlan
|
|
@@ -115,7 +113,6 @@ graph LR
|
|
|
115
113
|
* `sessionStats` / `recordSessionRequest`:内存级会话度量记录器(请求次数、Token 估算、延迟、时间戳)。
|
|
116
114
|
* `saveCredentialKey`:将密钥安全写入 `~/.dsh/.credentials.yaml`。
|
|
117
115
|
* `smokeChat`:毫秒级网络探活与非流式延迟测试,并记录会话指标。
|
|
118
|
-
* `buildPiAiProvider`:构建 DSH `llm-pi-ai` 兼容的服务商定义 (`api: 'openai-completions'`)。
|
|
119
116
|
* **`lib/index.js`**:Cordis 插件主生命周期服务,注册后端 REST API 路由(含 `/dsh-clinebot/models/sync`)、额度预警计算与 `/cline` 聊天斜杠指令。
|
|
120
117
|
* **`lib/client.js`**:插件行配置页(`plugins.row.config`),含预警横幅、会话指标、一键模型同步,以及后备插件卡片(`settings.plugin.item`)。没有 `settings.section` 侧边栏项。
|
|
121
118
|
|
|
@@ -165,7 +162,6 @@ dsh-clinebot:
|
|
|
165
162
|
baseUrl: https://api.cline.bot/api/v1
|
|
166
163
|
apiKeyEnv: CLINEBOT_API_KEY
|
|
167
164
|
defaultModel: your-default-model
|
|
168
|
-
proxyMode: true
|
|
169
165
|
disabledModels: []
|
|
170
166
|
customModels: []
|
|
171
167
|
modelReasoningDefaults:
|
|
@@ -192,7 +188,6 @@ dsh-clinebot:
|
|
|
192
188
|
| `customModels` | `array` | `[]` | 用户自定义网关模型 (`[{ id, name, contextLength, maxTokens, category, isReasoning }]`) |
|
|
193
189
|
| `modelReasoningDefaults` | `object` | `{}` | 各模型默认思考强度配置 (`low`, `medium`, `high`, `max`) |
|
|
194
190
|
| `modelContextOverrides` | `array` | `[]` | 用户自定义模型上下文窗口与最大 Token 数量覆盖 |
|
|
195
|
-
| `proxyMode` | `boolean` | `true` | 启用透明本地环回代理以支持会话粘性路由与 429 自动故障转移 |
|
|
196
191
|
| `statsPath` | `string` | `"~/.dsh/clinebot-stats.json"` | 本地持久化 Token 用量统计文件路径 |
|
|
197
192
|
| `accounts` | `array` | `[]` | 额外轮转账号池 (`[{ label, apiKeyEnv }]`) |
|
|
198
193
|
| `activeAccount` | `string` | `""` | 手动指定的主账号(为空时自动按最低配额消耗优先路由) |
|
|
@@ -206,7 +201,7 @@ dsh-clinebot:
|
|
|
206
201
|
|
|
207
202
|
## 🌐 HTTP API 接口说明
|
|
208
203
|
|
|
209
|
-
所有接口挂载于 `/dsh-clinebot/*` 路径,并受到跨站请求防护(仅放行同源或环回请求)。管理接口限制请求体上限 256 KiB
|
|
204
|
+
所有接口挂载于 `/dsh-clinebot/*` 路径,并受到跨站请求防护(仅放行同源或环回请求)。管理接口限制请求体上限 256 KiB:
|
|
210
205
|
|
|
211
206
|
### 管理与控制接口(上限 256 KiB)
|
|
212
207
|
* `GET /dsh-clinebot/status` — 服务运行状态,包括健康探活、当前凭据名称、配额限制及会话统计。
|
|
@@ -226,12 +221,6 @@ dsh-clinebot:
|
|
|
226
221
|
* `GET /dsh-clinebot/update/status` — 查询插件版本更新状态。
|
|
227
222
|
* `POST /dsh-clinebot/update/apply` — 应用版本更新(支持进程树完全清理与锁文件保护)。
|
|
228
223
|
|
|
229
|
-
### OpenAI 兼容环回代理接口(上限 64 MiB)
|
|
230
|
-
* `POST /dsh-clinebot/v1/chat/completions` — 本地透明代理,支持 SSE 流式与完整响应、会话粘性路由、最低用量负载均衡、响应体超时防护 (`streamIdleTimeoutMs`) 以及 429 自动故障转移。
|
|
231
|
-
* `GET /dsh-clinebot/v1/models` — 符合 OpenAI API 规范的模型列表。
|
|
232
|
-
|
|
233
|
-
> **DSH Desktop 2.x 与无界面环境**:环回代理在 `127.0.0.1` 绑定独立的专用 HTTP 服务(临时端口),彻底绕过桌面端路由防护 (`DesktopWebServer` 的 `x-dsh-desktop-renderer` 限制)。内置防护检测机制 (`detectHostWebServerFence`) 在环回端口受限时自动回退为直连模式,用户亦可在设置页的“诊断”模块中直接切换代理模式。
|
|
234
|
-
|
|
235
224
|
---
|
|
236
225
|
|
|
237
226
|
## 🧪 测试
|
package/lib/client.js
CHANGED
|
@@ -206,19 +206,9 @@ const en = {
|
|
|
206
206
|
'stats.confirm_reset': 'Confirm Reset?',
|
|
207
207
|
'stats.cancel_reset': 'Cancel',
|
|
208
208
|
'diag.title': 'Diagnostics & Auto-Registration',
|
|
209
|
-
'diag.desc': 'ClineBot registers into DSH Models automatically when key is configured. You can run connection smoke test
|
|
209
|
+
'diag.desc': 'ClineBot registers into DSH Models automatically when a key is configured. You can run a connection smoke test here.',
|
|
210
210
|
'diag.smoke_btn': 'Run Smoke Test (Ping)',
|
|
211
211
|
'diag.smoke_testing': 'Testing…',
|
|
212
|
-
'diag.resync_btn': 'Force Re-sync to DSH',
|
|
213
|
-
'diag.resyncing': 'Syncing…',
|
|
214
|
-
'diag.resynced_msg': 'Provider re-synced to DSH Models ({count} models)',
|
|
215
|
-
'diag.unregister_btn': 'Unregister from DSH',
|
|
216
|
-
'diag.unregistering': 'Removing…',
|
|
217
|
-
'diag.unregistered_msg': 'Provider removed from DSH Models',
|
|
218
|
-
'diag.proxy_title': 'Transparent Loopback Proxy',
|
|
219
|
-
'diag.proxy_desc': 'Enables multi-account failover, sticky sessions, and telemetry via local loopback proxy. Disable to connect directly to upstream endpoint.',
|
|
220
|
-
'diag.proxy_enabled': 'Proxy Mode Enabled (Failover & Telemetry Active)',
|
|
221
|
-
'diag.proxy_disabled': 'Direct Mode (Direct Upstream, No Proxy)',
|
|
222
212
|
'update.available': 'Update available: v{latestVersion} (current: v{currentVersion})',
|
|
223
213
|
'update.btn': 'Update Now',
|
|
224
214
|
'update.updating': 'Updating…',
|
|
@@ -262,13 +252,11 @@ const en = {
|
|
|
262
252
|
'settings.web_search': 'Serve web search with ClineBot', 'settings.web_search_hint': 'Use the ClinePass endpoint for the DSH web_search tool.',
|
|
263
253
|
'settings.sidebar_quota': 'Show quota meter in the sidebar', 'settings.sidebar_quota_hint': 'Display the compact plan and rolling-window meter above Settings.',
|
|
264
254
|
'settings.composer_cost': 'Show session cost in the composer', 'settings.composer_cost_hint': 'Display the estimated token cost beside the composer.',
|
|
265
|
-
'settings.
|
|
266
|
-
'settings.advanced': 'Advanced', 'settings.advanced_desc': 'Connection, timeouts, storage paths and the temporary transport switch.',
|
|
255
|
+
'settings.advanced': 'Advanced', 'settings.advanced_desc': 'Connection, timeouts and storage paths.',
|
|
267
256
|
'settings.base_url': 'API base URL', 'settings.base_url_hint': 'ClinePass API root. Remote endpoints must use https://.',
|
|
268
257
|
'settings.timeout': 'Connect timeout (ms)', 'settings.timeout_hint': 'Maximum wait for the upstream response headers.', 'settings.smoke_timeout': 'Smoke-test timeout (ms)', 'settings.smoke_timeout_hint': 'Maximum wait for the diagnostic chat completion.',
|
|
269
258
|
'settings.stream_idle': 'Stream idle timeout (ms)', 'settings.stream_idle_hint': 'Maximum gap between SSE chunks before the stream is treated as dead.', 'settings.max_payload': 'Max multimodal payload (MB)', 'settings.max_payload_hint': 'Oldest images are evicted once the request exceeds this budget.',
|
|
270
259
|
'settings.stats_path': 'Stats file path', 'settings.stats_path_hint': 'Persistent JSON telemetry path (supports ~/).', 'settings.models_cache_path': 'Models cache path', 'settings.models_cache_path_hint': 'Offline model catalogue cache (supports ~/).',
|
|
271
|
-
'settings.transport': 'Transport', 'settings.transport_hint': 'Native ctx.llm adapter (recommended) or the legacy llm-pi-ai + loopback proxy.',
|
|
272
260
|
'providerCard.title': 'ClineBot (ClinePass)',
|
|
273
261
|
'providerCard.hint': 'Paste a ClinePass API key or manage the full account pool in Settings → ClineBot.',
|
|
274
262
|
'providerCard.keyPresent': 'Key configured',
|
|
@@ -495,19 +483,9 @@ const zh = {
|
|
|
495
483
|
'stats.confirm_reset': '确认重置?',
|
|
496
484
|
'stats.cancel_reset': '取消',
|
|
497
485
|
'diag.title': '诊断工具与服务接入',
|
|
498
|
-
'diag.desc': '配置 API 密钥后,ClineBot 会自动向 DSH
|
|
486
|
+
'diag.desc': '配置 API 密钥后,ClineBot 会自动向 DSH 注册模型服务。您可以在此进行连通性测试。',
|
|
499
487
|
'diag.smoke_btn': '执行连通性冒烟测试 (Ping)',
|
|
500
488
|
'diag.smoke_testing': '正在测试…',
|
|
501
|
-
'diag.resync_btn': '强制重新同步到 DSH',
|
|
502
|
-
'diag.resyncing': '正在同步…',
|
|
503
|
-
'diag.resynced_msg': '模型服务已重新同步到 DSH ({count} 个模型)',
|
|
504
|
-
'diag.unregister_btn': '从 DSH 注销该服务',
|
|
505
|
-
'diag.unregistering': '正在注销…',
|
|
506
|
-
'diag.unregistered_msg': '已从 DSH 模型注册表中移除',
|
|
507
|
-
'diag.proxy_title': '本地透明回环代理',
|
|
508
|
-
'diag.proxy_desc': '通过本地回环代理支持多账户故障转移、会话保持与实时统计。关闭后直连上游端点。',
|
|
509
|
-
'diag.proxy_enabled': '代理模式已开启(支持故障转移与遥测)',
|
|
510
|
-
'diag.proxy_disabled': '直连模式(直接连接上游,无本地代理)',
|
|
511
489
|
'update.available': '发现新版本 v{latestVersion}(当前版本 v{currentVersion})',
|
|
512
490
|
'update.btn': '立即更新',
|
|
513
491
|
'update.updating': '正在更新…',
|
|
@@ -551,13 +529,11 @@ const zh = {
|
|
|
551
529
|
'settings.web_search': '使用 ClineBot 提供网页搜索', 'settings.web_search_hint': '为 DSH web_search 工具使用 ClinePass 端点。',
|
|
552
530
|
'settings.sidebar_quota': '在侧边栏显示配额', 'settings.sidebar_quota_hint': '在设置上方显示紧凑的套餐与滚动窗口配额。',
|
|
553
531
|
'settings.composer_cost': '在输入框显示会话成本', 'settings.composer_cost_hint': '在输入框旁显示预估 token 成本。',
|
|
554
|
-
'settings.
|
|
555
|
-
'settings.advanced': '高级', 'settings.advanced_desc': '连接、超时、存储路径和临时传输开关。',
|
|
532
|
+
'settings.advanced': '高级', 'settings.advanced_desc': '连接、超时和存储路径。',
|
|
556
533
|
'settings.base_url': 'API 基础地址', 'settings.base_url_hint': 'ClinePass API 根地址。远程端点必须使用 https://。',
|
|
557
534
|
'settings.timeout': '连接超时(毫秒)', 'settings.timeout_hint': '等待上游响应头的最大时间。', 'settings.smoke_timeout': '烟雾测试超时(毫秒)', 'settings.smoke_timeout_hint': '等待诊断聊天补全的最大时间。',
|
|
558
535
|
'settings.stream_idle': '流空闲超时(毫秒)', 'settings.stream_idle_hint': 'SSE 数据块之间的最大间隔,超过后视为断流。', 'settings.max_payload': '多模态负载上限(MB)', 'settings.max_payload_hint': '请求超过预算时会淘汰最旧的图片。',
|
|
559
536
|
'settings.stats_path': '统计文件路径', 'settings.stats_path_hint': '持久化 JSON 遥测路径(支持 ~/)。', 'settings.models_cache_path': '模型缓存路径', 'settings.models_cache_path_hint': '离线模型目录缓存(支持 ~/)。',
|
|
560
|
-
'settings.transport': '传输方式', 'settings.transport_hint': '原生 ctx.llm 适配器(推荐)或旧版 llm-pi-ai + 回环代理。',
|
|
561
537
|
'providerCard.title': 'ClineBot(ClinePass)',
|
|
562
538
|
'providerCard.hint': '粘贴 ClinePass API 密钥,或前往“设置 → ClineBot”管理完整账户池。',
|
|
563
539
|
'providerCard.keyPresent': '密钥已配置',
|
|
@@ -1637,7 +1613,7 @@ function IntegrationToggle({ id, label, hint, checked, onChange }) {
|
|
|
1637
1613
|
})
|
|
1638
1614
|
}
|
|
1639
1615
|
|
|
1640
|
-
function IntegrationsSection({ draft, onStage,
|
|
1616
|
+
function IntegrationsSection({ draft, onStage, t }) {
|
|
1641
1617
|
const current = draft || {}
|
|
1642
1618
|
return React.createElement(
|
|
1643
1619
|
SettingsGroup,
|
|
@@ -1666,16 +1642,7 @@ function IntegrationsSection({ draft, onStage, transport, t }) {
|
|
|
1666
1642
|
hint: t('settings.composer_cost_hint'),
|
|
1667
1643
|
checked: current.showComposerCost !== false,
|
|
1668
1644
|
onChange: (value) => onStage({ showComposerCost: value }),
|
|
1669
|
-
})
|
|
1670
|
-
transport === 'pi-ai'
|
|
1671
|
-
? React.createElement(IntegrationToggle, {
|
|
1672
|
-
id: 'cb-proxy-mode',
|
|
1673
|
-
label: t('settings.proxy_mode'),
|
|
1674
|
-
hint: t('settings.proxy_mode_hint'),
|
|
1675
|
-
checked: current.proxyMode !== false,
|
|
1676
|
-
onChange: (value) => onStage({ proxyMode: value }),
|
|
1677
|
-
})
|
|
1678
|
-
: null
|
|
1645
|
+
})
|
|
1679
1646
|
)
|
|
1680
1647
|
}
|
|
1681
1648
|
|
|
@@ -1696,7 +1663,7 @@ function AdvancedField({ id, label, hint, value, type, onChange }) {
|
|
|
1696
1663
|
})
|
|
1697
1664
|
}
|
|
1698
1665
|
|
|
1699
|
-
function AdvancedSection({ draft, onStage,
|
|
1666
|
+
function AdvancedSection({ draft, onStage, t }) {
|
|
1700
1667
|
const current = draft || {}
|
|
1701
1668
|
const numeric = (key, minimum) => (raw) => {
|
|
1702
1669
|
if (raw === '') return
|
|
@@ -1763,22 +1730,6 @@ function AdvancedSection({ draft, onStage, transport, t }) {
|
|
|
1763
1730
|
hint: t('settings.models_cache_path_hint'),
|
|
1764
1731
|
value: current.modelsCachePath,
|
|
1765
1732
|
onChange: (value) => onStage({ modelsCachePath: value }),
|
|
1766
|
-
}),
|
|
1767
|
-
React.createElement(SettingRow, {
|
|
1768
|
-
title: t('settings.transport'),
|
|
1769
|
-
description: t('settings.transport_hint'),
|
|
1770
|
-
htmlFor: 'cb-transport',
|
|
1771
|
-
control: React.createElement(
|
|
1772
|
-
'select',
|
|
1773
|
-
{
|
|
1774
|
-
id: 'cb-transport',
|
|
1775
|
-
className: 'cb-select',
|
|
1776
|
-
value: current.transport === 'pi-ai' ? 'pi-ai' : 'adapter',
|
|
1777
|
-
onChange: (event) => onStage({ transport: event.target.value }),
|
|
1778
|
-
},
|
|
1779
|
-
React.createElement('option', { value: 'adapter' }, 'Native adapter'),
|
|
1780
|
-
React.createElement('option', { value: 'pi-ai' }, 'Legacy llm-pi-ai + proxy')
|
|
1781
|
-
),
|
|
1782
1733
|
})
|
|
1783
1734
|
)
|
|
1784
1735
|
}
|
|
@@ -3605,42 +3556,12 @@ function StatsSection({ status, onResetStats, busy, t }) {
|
|
|
3605
3556
|
}
|
|
3606
3557
|
|
|
3607
3558
|
// --- src/client/components/diag-section.js ---
|
|
3608
|
-
function DiagSection({
|
|
3609
|
-
keyPresent,
|
|
3610
|
-
isRegistered,
|
|
3611
|
-
busy,
|
|
3612
|
-
smokeResult,
|
|
3613
|
-
handleSmoke,
|
|
3614
|
-
handleUnregister,
|
|
3615
|
-
handleRegister,
|
|
3616
|
-
proxyMode,
|
|
3617
|
-
onToggleProxy,
|
|
3618
|
-
t,
|
|
3619
|
-
}) {
|
|
3559
|
+
function DiagSection({ keyPresent, busy, smokeResult, handleSmoke, t }) {
|
|
3620
3560
|
return React.createElement(
|
|
3621
3561
|
'section',
|
|
3622
3562
|
{ className: 'cb-section-card' },
|
|
3623
3563
|
React.createElement('div', { className: 'cb-section-title' }, t('diag.title')),
|
|
3624
3564
|
React.createElement('div', { className: 'cb-section-desc' }, t('diag.desc')),
|
|
3625
|
-
React.createElement(SettingRow, {
|
|
3626
|
-
title: t('diag.proxy_title'),
|
|
3627
|
-
description: t('diag.proxy_desc'),
|
|
3628
|
-
control: React.createElement(
|
|
3629
|
-
React.Fragment,
|
|
3630
|
-
null,
|
|
3631
|
-
React.createElement(
|
|
3632
|
-
'span',
|
|
3633
|
-
{ className: proxyMode ? 'cb-state-ok' : 'cb-muted' },
|
|
3634
|
-
proxyMode ? t('diag.proxy_enabled') : t('diag.proxy_disabled')
|
|
3635
|
-
),
|
|
3636
|
-
React.createElement(BooleanControl, {
|
|
3637
|
-
checked: !!proxyMode,
|
|
3638
|
-
disabled: !!busy,
|
|
3639
|
-
label: t('diag.proxy_title'),
|
|
3640
|
-
onChange: (next) => onToggleProxy && onToggleProxy(next),
|
|
3641
|
-
})
|
|
3642
|
-
),
|
|
3643
|
-
}),
|
|
3644
3565
|
React.createElement(
|
|
3645
3566
|
'div',
|
|
3646
3567
|
{ className: 'cb-row cb-row-actions' },
|
|
@@ -3648,34 +3569,11 @@ function DiagSection({
|
|
|
3648
3569
|
'button',
|
|
3649
3570
|
{
|
|
3650
3571
|
type: 'button',
|
|
3651
|
-
className: 'cb-btn',
|
|
3572
|
+
className: 'cb-btn cb-btn-primary',
|
|
3652
3573
|
disabled: !!busy || !keyPresent,
|
|
3653
3574
|
onClick: handleSmoke,
|
|
3654
3575
|
},
|
|
3655
3576
|
busy === 'smoke' ? t('diag.smoke_testing') : t('diag.smoke_btn')
|
|
3656
|
-
),
|
|
3657
|
-
isRegistered
|
|
3658
|
-
? React.createElement(
|
|
3659
|
-
'button',
|
|
3660
|
-
{
|
|
3661
|
-
type: 'button',
|
|
3662
|
-
className: 'cb-btn cb-btn-danger',
|
|
3663
|
-
disabled: !!busy,
|
|
3664
|
-
onClick: handleUnregister,
|
|
3665
|
-
},
|
|
3666
|
-
busy === 'unregister' ? t('diag.unregistering') : t('diag.unregister_btn')
|
|
3667
|
-
)
|
|
3668
|
-
: null,
|
|
3669
|
-
React.createElement('span', { className: 'cb-settings-spacer' }),
|
|
3670
|
-
React.createElement(
|
|
3671
|
-
'button',
|
|
3672
|
-
{
|
|
3673
|
-
type: 'button',
|
|
3674
|
-
className: 'cb-btn cb-btn-primary',
|
|
3675
|
-
disabled: !!busy,
|
|
3676
|
-
onClick: handleRegister,
|
|
3677
|
-
},
|
|
3678
|
-
busy === 'register' ? t('diag.resyncing') : t('diag.resync_btn')
|
|
3679
3577
|
)
|
|
3680
3578
|
),
|
|
3681
3579
|
smokeResult
|
|
@@ -5123,27 +5021,6 @@ function SettingsPage(props) {
|
|
|
5123
5021
|
})
|
|
5124
5022
|
}
|
|
5125
5023
|
|
|
5126
|
-
async function handleRegister() {
|
|
5127
|
-
await performAction('register', async () => {
|
|
5128
|
-
const res = await fetchWithTimeout(`${ROUTE_PREFIX}/register`, { method: 'POST' })
|
|
5129
|
-
const data = await res.json().catch(() => ({}))
|
|
5130
|
-
if (!res.ok || !data.ok) throw new Error(data.error || `HTTP ${res.status}`)
|
|
5131
|
-
const count = status?.availableModels?.filter((m) => !(draft?.disabledModels || []).includes(m.id)).length || 0
|
|
5132
|
-
setMsg(t('diag.resynced_msg', { count }))
|
|
5133
|
-
await load()
|
|
5134
|
-
})
|
|
5135
|
-
}
|
|
5136
|
-
|
|
5137
|
-
async function handleUnregister() {
|
|
5138
|
-
await performAction('unregister', async () => {
|
|
5139
|
-
const res = await fetchWithTimeout(`${ROUTE_PREFIX}/unregister`, { method: 'POST' })
|
|
5140
|
-
const data = await res.json().catch(() => ({}))
|
|
5141
|
-
if (!res.ok || !data.ok) throw new Error(data.error || `HTTP ${res.status}`)
|
|
5142
|
-
setMsg(t('diag.unregistered_msg'))
|
|
5143
|
-
await load()
|
|
5144
|
-
})
|
|
5145
|
-
}
|
|
5146
|
-
|
|
5147
5024
|
async function handleSmoke() {
|
|
5148
5025
|
setSmokeResult(null)
|
|
5149
5026
|
await performAction('smoke', async () => {
|
|
@@ -5372,28 +5249,21 @@ function SettingsPage(props) {
|
|
|
5372
5249
|
React.createElement(IntegrationsSection, {
|
|
5373
5250
|
draft,
|
|
5374
5251
|
onStage: staged.stage,
|
|
5375
|
-
transport: draft?.transport || status?.config?.transport || 'adapter',
|
|
5376
5252
|
t,
|
|
5377
5253
|
}),
|
|
5378
5254
|
|
|
5379
5255
|
// Diagnostics & Sync with DSH
|
|
5380
5256
|
React.createElement(DiagSection, {
|
|
5381
5257
|
keyPresent,
|
|
5382
|
-
isRegistered,
|
|
5383
5258
|
busy,
|
|
5384
5259
|
smokeResult,
|
|
5385
5260
|
handleSmoke,
|
|
5386
|
-
handleUnregister,
|
|
5387
|
-
handleRegister,
|
|
5388
|
-
proxyMode: draft?.proxyMode !== false,
|
|
5389
|
-
onToggleProxy: (value) => staged.stage({ proxyMode: value }),
|
|
5390
5261
|
t,
|
|
5391
5262
|
}),
|
|
5392
5263
|
|
|
5393
5264
|
React.createElement(AdvancedSection, {
|
|
5394
5265
|
draft,
|
|
5395
5266
|
onStage: staged.stage,
|
|
5396
|
-
transport: draft?.transport || status?.config?.transport || 'adapter',
|
|
5397
5267
|
t,
|
|
5398
5268
|
}),
|
|
5399
5269
|
|
package/lib/cline-client.js
CHANGED
|
@@ -18,9 +18,7 @@ import {
|
|
|
18
18
|
DEFAULT_MODEL_ID,
|
|
19
19
|
PROVIDER_ID,
|
|
20
20
|
PROVIDER_DISPLAY_NAME,
|
|
21
|
-
getAllModels,
|
|
22
21
|
parsePlanIncludedModels,
|
|
23
|
-
formatModelDescription,
|
|
24
22
|
} from './models.js'
|
|
25
23
|
|
|
26
24
|
export const DEFAULT_BASE_URL = 'https://api.cline.bot/api/v1'
|
|
@@ -487,103 +485,3 @@ export async function smokeChat(baseUrl, apiKey, {
|
|
|
487
485
|
cancel()
|
|
488
486
|
}
|
|
489
487
|
}
|
|
490
|
-
|
|
491
|
-
/**
|
|
492
|
-
* Shape for llm-pi-ai.providers.clinebot (openai-completions).
|
|
493
|
-
*/
|
|
494
|
-
export function buildPiAiProvider({
|
|
495
|
-
baseUrl = DEFAULT_BASE_URL,
|
|
496
|
-
apiKeyEnv = DEFAULT_API_KEY_ENV,
|
|
497
|
-
apiKey,
|
|
498
|
-
dynamicModels = [],
|
|
499
|
-
modelContextOverrides = [],
|
|
500
|
-
models = [],
|
|
501
|
-
customModels = [],
|
|
502
|
-
existingModels = [],
|
|
503
|
-
displayName = PROVIDER_DISPLAY_NAME,
|
|
504
|
-
} = {}) {
|
|
505
|
-
const allAvailable = getAllModels(dynamicModels, modelContextOverrides, customModels)
|
|
506
|
-
const customModelsMap = new Map((Array.isArray(customModels) ? customModels : []).filter(Boolean).map(cm => [cm.id, cm]))
|
|
507
|
-
const existingMap = new Map((Array.isArray(existingModels) ? existingModels : []).filter(Boolean).map(m => [m.id, m]))
|
|
508
|
-
const explicitOverridesSet = new Set((Array.isArray(modelContextOverrides) ? modelContextOverrides : []).map(o => o?.modelId))
|
|
509
|
-
const hasWildcardOverride = explicitOverridesSet.has('*')
|
|
510
|
-
|
|
511
|
-
const modelList = (Array.isArray(models) && models.length ? models : allAvailable).map((m) => {
|
|
512
|
-
let item
|
|
513
|
-
if (typeof m === 'string') {
|
|
514
|
-
const customMatch = customModelsMap.get(m)
|
|
515
|
-
const baseMatch = allAvailable.find((x) => x.id === m)
|
|
516
|
-
item = customMatch ? { ...baseMatch, ...customMatch } : (baseMatch || { id: m, name: m })
|
|
517
|
-
} else {
|
|
518
|
-
item = m
|
|
519
|
-
}
|
|
520
|
-
const hasImage = item.input?.includes('image') || item.input?.includes('vision')
|
|
521
|
-
|
|
522
|
-
// Preserve manual provider edits if user configured contextWindow or maxTokens in llm-pi-ai without explicit override in clinebot
|
|
523
|
-
const existingEntry = existingMap.get(item.id)
|
|
524
|
-
let ctxWin = Number(item.contextLength || item.contextWindow) || 200000
|
|
525
|
-
let maxTok = Number(item.maxTokens) || 8192
|
|
526
|
-
if (existingEntry && !explicitOverridesSet.has(item.id) && !hasWildcardOverride) {
|
|
527
|
-
if (typeof existingEntry.contextWindow === 'number' && existingEntry.contextWindow > 0) {
|
|
528
|
-
ctxWin = existingEntry.contextWindow
|
|
529
|
-
}
|
|
530
|
-
if (typeof existingEntry.maxTokens === 'number' && existingEntry.maxTokens > 0) {
|
|
531
|
-
maxTok = existingEntry.maxTokens
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
const res = {
|
|
536
|
-
id: item.id,
|
|
537
|
-
name: item.name || item.id,
|
|
538
|
-
description: formatModelDescription(item),
|
|
539
|
-
contextWindow: ctxWin,
|
|
540
|
-
maxTokens: maxTok,
|
|
541
|
-
input: hasImage ? ['text', 'image'] : ['text'],
|
|
542
|
-
provider: PROVIDER_ID,
|
|
543
|
-
}
|
|
544
|
-
const validEfforts = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max']
|
|
545
|
-
let efforts = null
|
|
546
|
-
if (Array.isArray(item.reasoningEfforts) && item.reasoningEfforts.length) {
|
|
547
|
-
efforts = {}
|
|
548
|
-
for (const effort of item.reasoningEfforts) {
|
|
549
|
-
const key = String(effort).trim().toLowerCase()
|
|
550
|
-
if (validEfforts.includes(key)) efforts[key] = key === 'off' ? null : key
|
|
551
|
-
}
|
|
552
|
-
} else if (item.reasoningEfforts && typeof item.reasoningEfforts === 'object' && !Array.isArray(item.reasoningEfforts)) {
|
|
553
|
-
efforts = {}
|
|
554
|
-
for (const [k, v] of Object.entries(item.reasoningEfforts)) {
|
|
555
|
-
const key = String(k).trim().toLowerCase()
|
|
556
|
-
if (validEfforts.includes(key)) efforts[key] = key === 'off' ? (v === undefined ? null : v) : (typeof v === 'string' && v.trim() ? v.trim() : key)
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
const modelCompat = {}
|
|
560
|
-
if (efforts && Object.keys(efforts).length) {
|
|
561
|
-
if (!('off' in efforts)) efforts.off = null
|
|
562
|
-
res.reasoningEfforts = efforts
|
|
563
|
-
modelCompat.supportsReasoningEffort = true
|
|
564
|
-
} else {
|
|
565
|
-
res.reasoningEfforts = false
|
|
566
|
-
}
|
|
567
|
-
if (Object.keys(modelCompat).length > 0) {
|
|
568
|
-
res.compat = modelCompat
|
|
569
|
-
}
|
|
570
|
-
return res
|
|
571
|
-
})
|
|
572
|
-
|
|
573
|
-
return {
|
|
574
|
-
displayName,
|
|
575
|
-
api: 'openai-completions',
|
|
576
|
-
baseURL: normalizeBaseUrl(baseUrl),
|
|
577
|
-
apiKeyEnv: apiKeyEnv || DEFAULT_API_KEY_ENV,
|
|
578
|
-
cacheRetention: 'long',
|
|
579
|
-
compat: {
|
|
580
|
-
supportsReasoningEffort: true,
|
|
581
|
-
supportsLongCacheRetention: true,
|
|
582
|
-
},
|
|
583
|
-
models: modelList,
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|