dsh-kenari-plugin 0.1.1 → 0.2.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.en.md +15 -10
- package/README.md +15 -10
- package/client/index.js +125 -14
- package/cordis.patch.yml +19 -22
- package/lib/catalog-view.d.ts +4 -0
- package/lib/catalog-view.d.ts.map +1 -1
- package/lib/catalog-view.js.map +1 -1
- package/lib/catalog.d.ts +18 -4
- package/lib/catalog.d.ts.map +1 -1
- package/lib/catalog.js +19 -5
- package/lib/catalog.js.map +1 -1
- package/lib/default-route.d.ts +24 -0
- package/lib/default-route.d.ts.map +1 -1
- package/lib/default-route.js +59 -1
- package/lib/default-route.js.map +1 -1
- package/lib/index.d.ts +4 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +19 -8
- package/lib/index.js.map +1 -1
- package/lib/llm/candidates.d.ts +4 -1
- package/lib/llm/candidates.d.ts.map +1 -1
- package/lib/llm/candidates.js +9 -5
- package/lib/llm/candidates.js.map +1 -1
- package/lib/llm/recovery.d.ts +19 -7
- package/lib/llm/recovery.d.ts.map +1 -1
- package/lib/llm/recovery.js +97 -12
- package/lib/llm/recovery.js.map +1 -1
- package/lib/llm/retry.d.ts +14 -16
- package/lib/llm/retry.d.ts.map +1 -1
- package/lib/llm/retry.js +20 -15
- package/lib/llm/retry.js.map +1 -1
- package/package.json +4 -2
package/README.en.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# dsh-kenari-plugin
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/dsh-kenari-plugin)
|
|
4
|
+
|
|
3
5
|
English | [中文](README.md)
|
|
4
6
|
|
|
5
7
|
Connects [Kenari](https://kenari.id) to the DeepSeek Harness (dsh):
|
|
@@ -22,13 +24,15 @@ dsh plugin --profile web add @deepseek-ai/dsh-web-fetch-http@0.1.5-rc.1
|
|
|
22
24
|
|
|
23
25
|
## Install
|
|
24
26
|
|
|
27
|
+
The plugin is published on [npmjs](https://www.npmjs.com/package/dsh-kenari-plugin). Install it with dsh's own plugin command:
|
|
28
|
+
|
|
25
29
|
```sh
|
|
26
30
|
dsh plugin --profile web add dsh-kenari-plugin
|
|
27
31
|
dsh --profile web --dump-config | grep -A3 dsh-kenari-plugin # confirm the patch layer applied
|
|
28
32
|
dsh --profile web
|
|
29
33
|
```
|
|
30
34
|
|
|
31
|
-
To work on the plugin source, install from a clone instead: `pnpm install && pnpm build`, then `dsh plugin --profile web add "$PWD"`. The profile links to that directory, so after installing you only rerun `pnpm build` for source changes.
|
|
35
|
+
To pin a version, append it to the name, for example `dsh-kenari-plugin@0.1.1`. To work on the plugin source, install from a clone instead: `pnpm install && pnpm build`, then `dsh plugin --profile web add "$PWD"`. The profile links to that directory, so after installing you only rerun `pnpm build` for source changes.
|
|
32
36
|
|
|
33
37
|
## Set up your key
|
|
34
38
|
|
|
@@ -56,14 +60,14 @@ When the plan cannot be read (no key, a share-page key that gets 403, an account
|
|
|
56
60
|
|
|
57
61
|
| Model id | Display name | Context | Max output | Notes |
|
|
58
62
|
| --- | --- | --- | --- | --- |
|
|
59
|
-
| `deepseek-v4-flash` | DeepSeek v4 Flash | 1M | 64K | reasoning low/high/max |
|
|
60
|
-
| `glm-5-3-flash` | GLM 5.3 Flash | 1M | 64K | vision, reasoning low/high/max |
|
|
61
|
-
| `gpt-5-6-luna` | GPT 5.6 Luna | 872k | 64K | vision + PDF, 6 reasoning levels |
|
|
62
|
-
| `mimo-v2-5` | MiMo v2.5 | 1.05M | 64K | vision + audio + video |
|
|
63
|
+
| `deepseek-v4-flash` | Kenari DeepSeek v4 Flash | 1M | 64K | reasoning low/high/max |
|
|
64
|
+
| `glm-5-3-flash` | Kenari GLM 5.3 Flash | 1M | 64K | vision, reasoning low/high/max |
|
|
65
|
+
| `gpt-5-6-luna` | Kenari GPT 5.6 Luna | 872k | 64K | vision + PDF, 6 reasoning levels |
|
|
66
|
+
| `mimo-v2-5` | Kenari MiMo v2.5 | 1.05M | 64K | vision + audio + video |
|
|
63
67
|
|
|
64
68
|
None of the four is free, so **a new account with no balance hits 402 on its first session**. Add a `:free` model or top up first. `:free` models stay out of the route by default; filter by "free" in the picker to add them.
|
|
65
69
|
|
|
66
|
-
Display names and output caps are derived by the plugin, since the catalog publishes neither. A name is reconstructed from the id
|
|
70
|
+
Display names and output caps are derived by the plugin, since the catalog publishes neither. A name is reconstructed from the id (the few models whose catalog entry carries a `name` keep the vendor's wording). Names **written into the route** additionally carry a `Kenari ` prefix — dsh's model button and session header show the name alone, so without it a Kenari route is indistinguishable from an official DeepSeek model of the same name — while the plugin's own model table stays unprefixed, because that page already is the Kenari section. The output cap is a quarter of the context window, clamped to [1K, 64K]; models without a published window get no cap field. The name is presentation only; a model's identity is always its id.
|
|
67
71
|
|
|
68
72
|
Once you edit the list yourself, your config replaces the preset as a whole (pi-ai's semantics) and the plugin stops touching it.
|
|
69
73
|
|
|
@@ -104,17 +108,17 @@ The `available()` contract forbids network calls, so a Kenari outage only surfac
|
|
|
104
108
|
|
|
105
109
|
A failed session model call on a Kenari route recovers on its own:
|
|
106
110
|
|
|
107
|
-
1. Retry 5 times at a fixed 5 second interval
|
|
111
|
+
1. Retry 5 times at a fixed 5 second interval **on the same route**, with the budget counted per route
|
|
108
112
|
2. When retries run out, switch to a model with at least as large a window, preferring the smallest adequate one in the same provider before crossing providers
|
|
109
113
|
3. If that also fails, fall back to dsh's default provider and model
|
|
110
114
|
|
|
111
|
-
Only when all three fail does the turn error out. Retry and switching happen inside the same step, so the task is never interrupted and the plugin sends no "continue" message. A switched model does not inherit `reasoningEffort` (levels are per model); the switch injects a notice you can disable with `modelSwitchNoticeEnabled`, and
|
|
115
|
+
Only when all three fail does the turn error out. Retry and switching happen inside the same step, so the task is never interrupted and the plugin sends no "continue" message. A switched model does not inherit `reasoningEffort` (levels are per model); the switch injects a notice you can disable with `modelSwitchNoticeEnabled`, and the start of a retry sequence injects one too (during retries the UI shows a single failed attempt, so an unexplained wait is worse), which `modelRetryNoticeEnabled` disables. Picking a model yourself with `/model` clears the automatic switch.
|
|
112
116
|
|
|
113
117
|
`CONTEXT_WINDOW_EXCEEDED` is deliberately not retryable. Retrying the same context on the same model can only fail again, so it goes straight to the model switch, which is often where recovery works.
|
|
114
118
|
|
|
115
119
|
Two limits:
|
|
116
120
|
|
|
117
|
-
- **
|
|
121
|
+
- **Retrying is done by the plugin's own recovery state machine; dsh's `dsh-llm-retry` is deliberately switched off on Kenari routes** (`providers.kenari.retryPolicy.maxRetries: 0` in `cordis.patch.yml`, same for the plugin's own adapter). The reason is that it **fails silently**: `agent/request-error` has no default behaviour, so a listener that does not call `next()` vetoes everything after it, and the plugin cannot observe whether a live reload reordered that chain. Measured on a live session: zero `llm/retry` events and the model switch happened on the first failure — the promised retries never ran. There is therefore exactly one source for the retry budget: `modelRetryMaxRetries` / `modelRetryDelayMs` / `modelRetryableCodes`. If you set that route's `retryPolicy` back above 0, the plugin steps aside and lets dsh own it, so the two never count the same retry twice (the three scenarios in `test/retry-repro.mjs` guard this boundary).
|
|
118
122
|
- **A `TRANSPORT` failure may have completed and been billed on the server**, so retrying can bill twice. Narrow `modelRetryableCodes` if that matters. This is separate from the no-retry-on-timeout rule for generation endpoints.
|
|
119
123
|
|
|
120
124
|
Field defaults are in "Configuration reference".
|
|
@@ -243,9 +247,10 @@ Most fields can be edited under Settings → Kenari. The ones marked (restart) b
|
|
|
243
247
|
| `nativeProviderId` | `kenari-direct` | Route id for that adapter |
|
|
244
248
|
| `modelRecoveryEnabled` | `true` | Master switch for automatic recovery |
|
|
245
249
|
| `modelRecoveryProviders` | `['kenari','kenari-direct']` | Routes covered by recovery |
|
|
246
|
-
| `modelRetryMaxRetries` | `5` | Extra retries
|
|
250
|
+
| `modelRetryMaxRetries` | `5` | Extra retries per route |
|
|
247
251
|
| `modelRetryDelayMs` | `5000` | Fixed wait before each retry |
|
|
248
252
|
| `modelRetryableCodes` | `EMPTY_RESPONSE` `RATE_LIMIT` `SERVER` `TIMEOUT` `TRANSPORT` | Retryable failure codes, must not be empty |
|
|
253
|
+
| `modelRetryNoticeEnabled` | `true` | Inject a notice when retrying starts |
|
|
249
254
|
| `modelSwitchEnabled` | `true` | Whether to switch models |
|
|
250
255
|
| `modelSwitchDelayMs` | `5000` | Wait before a switch or fallback |
|
|
251
256
|
| `modelSwitchSkipCodes` | `AUTH` `INVALID_CREDENTIAL` `MISSING_CREDENTIAL` `QUOTA` | Codes that skip straight to the provider fallback |
|
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# dsh-kenari-plugin
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/dsh-kenari-plugin)
|
|
4
|
+
|
|
3
5
|
[English](README.en.md) | 中文
|
|
4
6
|
|
|
5
7
|
把 [Kenari](https://kenari.id) 接进 DeepSeek Harness(dsh):
|
|
@@ -22,13 +24,15 @@ dsh plugin --profile web add @deepseek-ai/dsh-web-fetch-http@0.1.5-rc.1
|
|
|
22
24
|
|
|
23
25
|
## 安装
|
|
24
26
|
|
|
27
|
+
插件已发布到 [npmjs](https://www.npmjs.com/package/dsh-kenari-plugin),用 dsh 自己的插件命令装:
|
|
28
|
+
|
|
25
29
|
```sh
|
|
26
30
|
dsh plugin --profile web add dsh-kenari-plugin
|
|
27
31
|
dsh --profile web --dump-config | grep -A3 dsh-kenari-plugin # 确认 patch 层生效
|
|
28
32
|
dsh --profile web
|
|
29
33
|
```
|
|
30
34
|
|
|
31
|
-
|
|
35
|
+
要固定版本就在包名后加,例如 `dsh-kenari-plugin@0.1.1`。改插件源码时换成 clone 安装:`pnpm install && pnpm build`,再 `dsh plugin --profile web add "$PWD"`,之后改源码只需重新 `pnpm build`。
|
|
32
36
|
|
|
33
37
|
## 配置密钥
|
|
34
38
|
|
|
@@ -56,14 +60,14 @@ KENARI_API_KEY=kn-...
|
|
|
56
60
|
|
|
57
61
|
| 模型 id | 显示名称 | 上下文 | 最大输出 | 备注 |
|
|
58
62
|
| --- | --- | --- | --- | --- |
|
|
59
|
-
| `deepseek-v4-flash` | DeepSeek v4 Flash | 1M | 64K | reasoning low/high/max |
|
|
60
|
-
| `glm-5-3-flash` | GLM 5.3 Flash | 1M | 64K | 视觉,reasoning low/high/max |
|
|
61
|
-
| `gpt-5-6-luna` | GPT 5.6 Luna | 872k | 64K | 视觉 + PDF,6 档 reasoning |
|
|
62
|
-
| `mimo-v2-5` | MiMo v2.5 | 1.05M | 64K | 视觉 + 音频 + 视频 |
|
|
63
|
+
| `deepseek-v4-flash` | Kenari DeepSeek v4 Flash | 1M | 64K | reasoning low/high/max |
|
|
64
|
+
| `glm-5-3-flash` | Kenari GLM 5.3 Flash | 1M | 64K | 视觉,reasoning low/high/max |
|
|
65
|
+
| `gpt-5-6-luna` | Kenari GPT 5.6 Luna | 872k | 64K | 视觉 + PDF,6 档 reasoning |
|
|
66
|
+
| `mimo-v2-5` | Kenari MiMo v2.5 | 1.05M | 64K | 视觉 + 音频 + 视频 |
|
|
63
67
|
|
|
64
68
|
四个都不是免费模型,**没有余额的新账户第一次会话会拿到 402**,先加一个 `:free` 模型或充值。`:free` 模型默认不进路由,用挑选器里的「免费」筛一下再加。
|
|
65
69
|
|
|
66
|
-
|
|
70
|
+
显示名称与最大输出由插件推导(目录里都没有):名称先还原自 id(目录自己带 `name` 的那几个模型照抄厂商写法);**写进路由**的名字再统一加 `Kenari ` 前缀——dsh 的模型按钮和会话头部只有名字一个字段,不带前缀就分不出它是 Kenari 路由还是官方 DeepSeek 的同名模型;插件自己那一页的模型表不加前缀,整页都在 Kenari 节里,再加一遍是噪音。最大输出取窗口的 1/4 并夹在 [1K, 64K],不公布窗口的模型不写这个字段。名称只用于展示,模型身份始终是 id。
|
|
67
71
|
|
|
68
72
|
你手动改过列表之后,用户配置整份覆盖预设(pi-ai 的语义),插件不再改。
|
|
69
73
|
|
|
@@ -104,17 +108,17 @@ Kenari 有三条线,base URL 形状不同,写错返回 405 而不是 404:
|
|
|
104
108
|
|
|
105
109
|
Kenari 路由上的会话模型调用失败后自动恢复:
|
|
106
110
|
|
|
107
|
-
1. 按固定 5 秒间隔重试 5
|
|
111
|
+
1. 按固定 5 秒间隔重试 5 次,**同一条路由**上重发,预算按路由计算
|
|
108
112
|
2. 用尽后换一个窗口不小于当前模型的模型,先在同一个 provider 内挑最小的够用者,没有候选再跨 provider
|
|
109
113
|
3. 仍失败则回退 dsh 的默认 provider 与模型
|
|
110
114
|
|
|
111
|
-
三步都失败这一轮才报错。重试与换模型都在同一个 step 内,任务不中断,插件不会再发「继续」消息。换模型不继承 `reasoningEffort`(档位按模型定义),换完注入一条说明,可用 `modelSwitchNoticeEnabled`
|
|
115
|
+
三步都失败这一轮才报错。重试与换模型都在同一个 step 内,任务不中断,插件不会再发「继续」消息。换模型不继承 `reasoningEffort`(档位按模型定义),换完注入一条说明,可用 `modelSwitchNoticeEnabled` 关掉;重试开始时也会注入一条说明(重试期间界面上只有一次失败的尝试,不解释就是一个没有理由的等待),可用 `modelRetryNoticeEnabled` 关掉。手动 `/model` 会清除自动切换。
|
|
112
116
|
|
|
113
117
|
`CONTEXT_WINDOW_EXCEEDED` 刻意不在可重试集里:同模型同上下文重试必然再失败,直接进换模型阶段,而这一步往往正是恢复生效的地方。
|
|
114
118
|
|
|
115
119
|
两处限制:
|
|
116
120
|
|
|
117
|
-
-
|
|
121
|
+
- **重试由插件自己的恢复状态机执行,Kenari 路由上 dsh 自带的 `dsh-llm-retry` 被刻意关掉**(`cordis.patch.yml` 里 `providers.kenari.retryPolicy.maxRetries: 0`,插件自带适配器同理)。原因是它**会静默失效**:`agent/request-error` 是没有默认行为的瀑布,不调用 `next()` 的监听器会否决它后面的一切,而插件无法观察自己的注册顺序有没有被 live reload 之类的动作翻过来。实测线上会话里 `llm/retry` 事件数为 0、换模型发生在第一次失败上,承诺的重试从未执行。因此重试的预算只有一个来源:`modelRetryMaxRetries` / `modelRetryDelayMs` / `modelRetryableCodes`。如果你把该路由的 `retryPolicy` 改回大于 0,插件会在这条路由上让位给 dsh,两条机制不会各数一遍(`test/retry-repro.mjs` 的三个场景守着这条边界)。
|
|
118
122
|
- **`TRANSPORT` 类失败在服务端可能已经完成并计费**,重试会重复扣费。介意就把 `modelRetryableCodes` 调小。这与生成类端点的「超时不重试」是两回事。
|
|
119
123
|
|
|
120
124
|
字段与默认值见「配置项」。
|
|
@@ -243,9 +247,10 @@ dsh plugin --profile web remove dsh-kenari-plugin
|
|
|
243
247
|
| `nativeProviderId` | `kenari-direct` | 自带适配器的路由 id |
|
|
244
248
|
| `modelRecoveryEnabled` | `true` | 失败自动恢复总开关 |
|
|
245
249
|
| `modelRecoveryProviders` | `['kenari','kenari-direct']` | 参与恢复的路由 |
|
|
246
|
-
| `modelRetryMaxRetries` | `5` |
|
|
250
|
+
| `modelRetryMaxRetries` | `5` | 每条路由的额外重试次数 |
|
|
247
251
|
| `modelRetryDelayMs` | `5000` | 每次重试前的固定等待 |
|
|
248
252
|
| `modelRetryableCodes` | `EMPTY_RESPONSE` `RATE_LIMIT` `SERVER` `TIMEOUT` `TRANSPORT` | 可重试的失败码,不能为空 |
|
|
253
|
+
| `modelRetryNoticeEnabled` | `true` | 开始重试时注入通知 |
|
|
249
254
|
| `modelSwitchEnabled` | `true` | 是否换模型 |
|
|
250
255
|
| `modelSwitchDelayMs` | `5000` | 换模型或回退前的等待 |
|
|
251
256
|
| `modelSwitchSkipCodes` | `AUTH` `INVALID_CREDENTIAL` `MISSING_CREDENTIAL` `QUOTA` | 跳过同 provider 换模型,直接回退 |
|
package/client/index.js
CHANGED
|
@@ -188,13 +188,15 @@ window.__ModuleLoader__.load({
|
|
|
188
188
|
'catalog.readonly': '设置只读,不能写入。',
|
|
189
189
|
'catalog.settingsReadOnly': '设置只读,改动只能在配置文件里做。',
|
|
190
190
|
'catalog.noNamespace': '设置里没有 {ns} 这一节,先让插件把预设写进去。',
|
|
191
|
+
'catalog.writeRefused': '写入被拒绝,{count} 个模型没进设置。多半是设置刚被别处改过,重新打开面板再试一次。',
|
|
191
192
|
'catalog.plansError': '套餐表读取失败,「套餐内」标签与筛选这次不可用:{message}',
|
|
192
193
|
'catalog.empty': '当前筛选下没有模型。',
|
|
193
194
|
'catalog.summary': '显示 {visible} / {total} 个,待加入 {addable} 个。「套餐内」表示这个付费模型由订阅套餐覆盖,否则走余额。',
|
|
194
195
|
'catalog.footerNote': '加入后立即生效',
|
|
195
196
|
'catalog.submit': '添加所选({count})',
|
|
196
197
|
'catalog.saving': '正在加入…',
|
|
197
|
-
'catalog.added': '已加入 {count}
|
|
198
|
+
'catalog.added': '已加入 {count} 个模型,编辑卡片已刷新。',
|
|
199
|
+
'catalog.addedStale': '已加入 {count} 个模型。模型页的列表要重新展开「编辑」才会刷新。',
|
|
198
200
|
'catalog.chatOnly': '(不支持会话)',
|
|
199
201
|
'catalog.inRoute': '已在路由',
|
|
200
202
|
|
|
@@ -311,13 +313,15 @@ window.__ModuleLoader__.load({
|
|
|
311
313
|
'catalog.readonly': 'Settings are read-only; nothing can be written.',
|
|
312
314
|
'catalog.settingsReadOnly': 'Settings are read-only; changes have to go in the configuration file.',
|
|
313
315
|
'catalog.noNamespace': 'Your settings have no {ns} section yet. Let the plugin write its preset first.',
|
|
316
|
+
'catalog.writeRefused': 'The write was refused and {count} models did not reach your settings. Usually the document changed elsewhere; reopen the panel and try again.',
|
|
314
317
|
'catalog.plansError': 'Could not read the plan table, so the "In plan" tag and filter are unavailable this time: {message}',
|
|
315
318
|
'catalog.empty': 'No model matches these filters.',
|
|
316
319
|
'catalog.summary': 'Showing {visible} of {total}, {addable} ready to add. "In plan" means a subscription covers this paid model; otherwise it is billed to your balance.',
|
|
317
320
|
'catalog.footerNote': 'Applies immediately',
|
|
318
321
|
'catalog.submit': 'Add selected ({count})',
|
|
319
322
|
'catalog.saving': 'Adding…',
|
|
320
|
-
'catalog.added': 'Added {count} models
|
|
323
|
+
'catalog.added': 'Added {count} models; the editor card was refreshed.',
|
|
324
|
+
'catalog.addedStale': 'Added {count} models. The list on the Models page refreshes once you reopen Edit.',
|
|
321
325
|
'catalog.chatOnly': '(not a chat model)',
|
|
322
326
|
'catalog.inRoute': 'Already in the route',
|
|
323
327
|
|
|
@@ -360,6 +364,17 @@ window.__ModuleLoader__.load({
|
|
|
360
364
|
*/
|
|
361
365
|
const TAKEOVER_LABELS = ['添加模型', 'Add model', '获取可用模型', 'Fetch available models']
|
|
362
366
|
|
|
367
|
+
/**
|
|
368
|
+
* The row's own editing toggle, in the locales this build ships.
|
|
369
|
+
*
|
|
370
|
+
* Clicking it is `setEditing(open ? undefined : target)`, and the card itself
|
|
371
|
+
* renders as `open ? <ProviderEditor/> : null` — so collapse unmounts the card
|
|
372
|
+
* and expand mounts a fresh one. Same identity problem as {@link TAKEOVER_LABELS}:
|
|
373
|
+
* the class is a hash and the button carries the same 编辑/Edit text in both
|
|
374
|
+
* locales, so text is what there is to match.
|
|
375
|
+
*/
|
|
376
|
+
const EDIT_LABELS = ['编辑', 'Edit']
|
|
377
|
+
|
|
363
378
|
/**
|
|
364
379
|
* Whether a button's label (already trimmed) belongs to this takeover. An
|
|
365
380
|
* exact match, never a prefix: the Models page carries other 添加… buttons
|
|
@@ -942,6 +957,60 @@ window.__ModuleLoader__.load({
|
|
|
942
957
|
}
|
|
943
958
|
}
|
|
944
959
|
|
|
960
|
+
/**
|
|
961
|
+
* The row's editing toggle, found from the row a taken-over button sits in.
|
|
962
|
+
*
|
|
963
|
+
* Scoped to `closest('li')` — the same per-provider list item the marker
|
|
964
|
+
* lookup uses — so a sibling provider's identical 编辑 button is never claimed.
|
|
965
|
+
* @param row - the provider's list item, or null.
|
|
966
|
+
* @returns the toggle button, or null when this DOM is not the shape we know.
|
|
967
|
+
*/
|
|
968
|
+
function editToggleOf(row) {
|
|
969
|
+
if (row === null || row === undefined || typeof row.querySelectorAll !== 'function') return null
|
|
970
|
+
const buttons = row.querySelectorAll('button')
|
|
971
|
+
for (let index = 0; index < buttons.length; index += 1) {
|
|
972
|
+
const node = buttons[index]
|
|
973
|
+
const label = typeof node.textContent === 'string' ? node.textContent.trim() : ''
|
|
974
|
+
if (EDIT_LABELS.indexOf(label) !== -1) return node
|
|
975
|
+
}
|
|
976
|
+
return null
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
/**
|
|
980
|
+
* Re-mount the editing card this bundle's picker was opened from.
|
|
981
|
+
*
|
|
982
|
+
* Why it is needed: the card seeds its model list once, at mount, and
|
|
983
|
+
* deliberately does not follow a pushed settings refresh — that is what keeps
|
|
984
|
+
* a half-typed API key from being overwritten. A write made from this plugin's
|
|
985
|
+
* modal therefore lands *behind* the card, and its list would stay stale until
|
|
986
|
+
* something remounted it. Collapse-then-expand IS that remount, and it is the
|
|
987
|
+
* card's own control rather than a synthetic dialog close.
|
|
988
|
+
*
|
|
989
|
+
* The draft it discards was already invalid: the card's revision fence is stale
|
|
990
|
+
* after this plugin's write, so its next save would be refused as stale anyway.
|
|
991
|
+
*
|
|
992
|
+
* Fail-open — no toggle found (a dsh release renamed it) returns false and the
|
|
993
|
+
* caller falls back to the copy that tells the user to reopen the card.
|
|
994
|
+
* @param button - the native button the takeover intercepted.
|
|
995
|
+
* @returns whether a remount was started.
|
|
996
|
+
*/
|
|
997
|
+
function refreshProviderEditor(button) {
|
|
998
|
+
if (button === null || button === undefined || typeof button.closest !== 'function') return false
|
|
999
|
+
const row = button.closest('li')
|
|
1000
|
+
const toggle = editToggleOf(row)
|
|
1001
|
+
if (toggle === null || typeof toggle.click !== 'function') return false
|
|
1002
|
+
toggle.click()
|
|
1003
|
+
// The second click must land after React commits the first: collapse is a
|
|
1004
|
+
// state update, and re-reading `open` inside the same click would expand
|
|
1005
|
+
// nothing. The row node survives the collapse (it is keyed by provider), so
|
|
1006
|
+
// the toggle is looked up again there instead of reusing a detached node.
|
|
1007
|
+
setTimeout(() => {
|
|
1008
|
+
const again = editToggleOf(row)
|
|
1009
|
+
if (again !== null && typeof again.click === 'function') again.click()
|
|
1010
|
+
}, 0)
|
|
1011
|
+
return true
|
|
1012
|
+
}
|
|
1013
|
+
|
|
945
1014
|
/**
|
|
946
1015
|
* The Kenari glyph on the settings panel's own nav rail.
|
|
947
1016
|
*
|
|
@@ -1097,7 +1166,7 @@ window.__ModuleLoader__.load({
|
|
|
1097
1166
|
* because a catalog browser that cannot add anything just duplicated it.
|
|
1098
1167
|
*/
|
|
1099
1168
|
function useCatalogPanel(props) {
|
|
1100
|
-
const { routeNs, routeProvider, loadPanel, addModels } = props
|
|
1169
|
+
const { routeNs, routeProvider, loadPanel, addModels, onAdded } = props
|
|
1101
1170
|
const [state, setState] = React.useState({ status: 'loading' })
|
|
1102
1171
|
const [reloads, setReloads] = React.useState(0)
|
|
1103
1172
|
const [query, setQuery] = React.useState('')
|
|
@@ -1160,13 +1229,23 @@ window.__ModuleLoader__.load({
|
|
|
1160
1229
|
setWrite({ status: 'saving' })
|
|
1161
1230
|
addModels({ settingsNs: routeNs, provider: routeProvider }, profiles).then(
|
|
1162
1231
|
(result) => {
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
if (result.ok === true) {
|
|
1167
|
-
setPicked([])
|
|
1168
|
-
setReloads((current) => current + 1)
|
|
1232
|
+
if (result.ok !== true) {
|
|
1233
|
+
setWrite({ status: 'error', message: result.message })
|
|
1234
|
+
return
|
|
1169
1235
|
}
|
|
1236
|
+
// The card behind this modal seeds its list once, at mount, and does not
|
|
1237
|
+
// follow pushed settings refreshes — so it has to be remounted for the
|
|
1238
|
+
// write to show up in it. `onAdded` reports whether that remount was
|
|
1239
|
+
// possible; when it is not, the copy says how to get there by hand.
|
|
1240
|
+
const remounted = typeof onAdded === 'function' && onAdded() === true
|
|
1241
|
+
setWrite({
|
|
1242
|
+
status: 'added',
|
|
1243
|
+
message: remounted
|
|
1244
|
+
? t('catalog.added', { count: profiles.length })
|
|
1245
|
+
: t('catalog.addedStale', { count: profiles.length }),
|
|
1246
|
+
})
|
|
1247
|
+
setPicked([])
|
|
1248
|
+
setReloads((current) => current + 1)
|
|
1170
1249
|
},
|
|
1171
1250
|
(err) => setWrite({ status: 'error', message: String(err && err.message ? err.message : err) }),
|
|
1172
1251
|
)
|
|
@@ -1316,7 +1395,15 @@ window.__ModuleLoader__.load({
|
|
|
1316
1395
|
*/
|
|
1317
1396
|
function ModelCatalogModal(props) {
|
|
1318
1397
|
const { onClose, nativeButton, loadPanel, addModels, routeNs, routeProvider } = props
|
|
1319
|
-
const panel = useCatalogPanel({
|
|
1398
|
+
const panel = useCatalogPanel({
|
|
1399
|
+
routeNs,
|
|
1400
|
+
routeProvider,
|
|
1401
|
+
loadPanel,
|
|
1402
|
+
addModels,
|
|
1403
|
+
// The card this modal was opened from is the row's editing card; remounting
|
|
1404
|
+
// it is what makes the freshly written models visible in its list.
|
|
1405
|
+
onAdded: () => refreshProviderEditor(nativeButton),
|
|
1406
|
+
})
|
|
1320
1407
|
|
|
1321
1408
|
/**
|
|
1322
1409
|
* The way back out: close this dialog, then re-click the button dsh
|
|
@@ -1773,6 +1860,11 @@ window.__ModuleLoader__.load({
|
|
|
1773
1860
|
*/
|
|
1774
1861
|
function apply(ctx) {
|
|
1775
1862
|
const scope = ctx.settingsScope.bind({ namespace: NS })
|
|
1863
|
+
// The route's own scope, held beside this plugin's: writes to the pi-ai
|
|
1864
|
+
// section go through it rather than through a bare `settings.mutate`, and
|
|
1865
|
+
// that is what folds the write answer into the shared settings mirror the
|
|
1866
|
+
// Models page reads. See `addModels`.
|
|
1867
|
+
const routeScope = ctx.settingsScope.bind({ namespace: PI_AI_NS })
|
|
1776
1868
|
|
|
1777
1869
|
// Bind the translator before anything can render: the components below
|
|
1778
1870
|
// call it, and every one of them is reachable from here on.
|
|
@@ -1882,6 +1974,16 @@ window.__ModuleLoader__.load({
|
|
|
1882
1974
|
* list that is currently in effect (user layer when it owns the array,
|
|
1883
1975
|
* else the composition layer the patch pinned) and only append. Without
|
|
1884
1976
|
* that, adding one paid model would silently drop the free presets.
|
|
1977
|
+
*
|
|
1978
|
+
* The write goes through this route's settings scope, not a bare
|
|
1979
|
+
* `settings.mutate`: the scope folds the write answer into the shared
|
|
1980
|
+
* settings mirror the Models page reads, so the editing card this plugin
|
|
1981
|
+
* remounts right after reads the new list. A bare wire write would leave
|
|
1982
|
+
* that mirror waiting for the Host's push, which the remount can outrun.
|
|
1983
|
+
*
|
|
1984
|
+
* The scope reports no failure — a refused or unanswered write reloads the
|
|
1985
|
+
* mirror and settles — so success is decided by the document afterwards,
|
|
1986
|
+
* never by what this function assumed it wrote.
|
|
1885
1987
|
*/
|
|
1886
1988
|
const addModels = async (route, profiles) => {
|
|
1887
1989
|
const read = await readPiAi()
|
|
@@ -1894,13 +1996,20 @@ window.__ModuleLoader__.load({
|
|
|
1894
1996
|
if (model && typeof model.id === 'string') byId.set(model.id, model)
|
|
1895
1997
|
}
|
|
1896
1998
|
for (const profile of profiles) if (!byId.has(profile.id)) byId.set(profile.id, profile)
|
|
1897
|
-
|
|
1898
|
-
route.settingsNs,
|
|
1999
|
+
await routeScope.mutate(
|
|
1899
2000
|
[{ op: 'set', path: ['providers', route.provider, 'models'], value: [...byId.values()] }],
|
|
1900
2001
|
read.view.revision,
|
|
1901
2002
|
)
|
|
1902
|
-
|
|
1903
|
-
|
|
2003
|
+
const after = await readPiAi()
|
|
2004
|
+
const present = new Set(
|
|
2005
|
+
routeModelsOf(after.view, route.provider)
|
|
2006
|
+
.map((model) => (model && typeof model.id === 'string' ? model.id : undefined))
|
|
2007
|
+
.filter((id) => id !== undefined),
|
|
2008
|
+
)
|
|
2009
|
+
const missing = profiles.filter((profile) => !present.has(profile.id)).length
|
|
2010
|
+
return missing === 0
|
|
2011
|
+
? { ok: true }
|
|
2012
|
+
: { ok: false, message: t('catalog.writeRefused', { count: missing }) }
|
|
1904
2013
|
}
|
|
1905
2014
|
|
|
1906
2015
|
const injected = () => ({ scope, loadModels, describeKey })
|
|
@@ -1957,6 +2066,8 @@ window.__ModuleLoader__.load({
|
|
|
1957
2066
|
exports.__internals = {
|
|
1958
2067
|
CAPABILITY_TAGS,
|
|
1959
2068
|
TAKEOVER_LABELS,
|
|
2069
|
+
EDIT_LABELS,
|
|
2070
|
+
refreshProviderEditor,
|
|
1960
2071
|
isTakeoverLabel,
|
|
1961
2072
|
MARKER_ATTR,
|
|
1962
2073
|
pathGet,
|
package/cordis.patch.yml
CHANGED
|
@@ -72,10 +72,16 @@
|
|
|
72
72
|
# src/catalog.ts's `toModelProfile()` writes, so the preset and the computed
|
|
73
73
|
# default produce identical entries for the same ids.
|
|
74
74
|
#
|
|
75
|
-
# Failure recovery:
|
|
76
|
-
#
|
|
77
|
-
#
|
|
78
|
-
#
|
|
75
|
+
# Failure recovery: retries on this route are owned by the plugin's own recovery
|
|
76
|
+
# state machine (src/llm/recovery.ts), which restarts the step itself. `maxRetries:
|
|
77
|
+
# 0` makes dsh's `llm-retry` a deliberate no-op here, so exactly one component owns
|
|
78
|
+
# retrying and the behaviour stops depending on where `llm-retry` lands in the
|
|
79
|
+
# `agent/request-error` waterfall — a live reload can re-register it behind the
|
|
80
|
+
# plugin, and a listener that does not call `next()` vetoes everything after it.
|
|
81
|
+
# Measured on a live session: zero `llm/retry` events and the model switch happened
|
|
82
|
+
# on the first failure, i.e. the promised retries never ran. The budget now comes
|
|
83
|
+
# from the plugin's `modelRetryMaxRetries` / `modelRetryDelayMs` /
|
|
84
|
+
# `modelRetryableCodes`, which is one source of truth instead of two.
|
|
79
85
|
# ---------------------------------------------------------------------------
|
|
80
86
|
- id: llm-pi-ai
|
|
81
87
|
config:
|
|
@@ -85,19 +91,9 @@
|
|
|
85
91
|
apiKeyEnv: KENARI_API_KEY
|
|
86
92
|
api: openai-completions
|
|
87
93
|
baseURL: https://kenari.id/v1
|
|
88
|
-
# A flat 5s between retries: dsh's backoff is `initialDelay * 2^n` capped
|
|
89
|
-
# at `maxDelay`, so making the two equal (and disabling jitter) is the
|
|
90
|
-
# only way to express "wait 5s every time".
|
|
91
|
-
# CONTEXT_WINDOW_EXCEEDED is deliberately left out of the retryable set:
|
|
92
|
-
# retrying the same context on the same model can only fail again, and
|
|
93
|
-
# the plugin's escalation is the thing that can actually fix it.
|
|
94
94
|
retryPolicy:
|
|
95
95
|
mode: normal
|
|
96
|
-
maxRetries:
|
|
97
|
-
backoff:
|
|
98
|
-
initialDelayMs: 5000
|
|
99
|
-
maxDelayMs: 5000
|
|
100
|
-
jitterRatio: 0
|
|
96
|
+
maxRetries: 0
|
|
101
97
|
compat:
|
|
102
98
|
supportsDeveloperRole: false
|
|
103
99
|
maxTokensField: max_tokens
|
|
@@ -109,29 +105,30 @@
|
|
|
109
105
|
models:
|
|
110
106
|
# `name` 填 dsh 模型目录里的「显示名称」(不填就是空框),`maxTokens` 填每请求
|
|
111
107
|
# 输出上限(不填则整条路由共用 pi-ai 的 defaultMaxTokens 32768)。两者都由
|
|
112
|
-
# catalog.ts 的
|
|
113
|
-
#
|
|
114
|
-
#
|
|
108
|
+
# catalog.ts 的 toModelProfile 推导——写模型时用的是同一套规则,所以手动加的
|
|
109
|
+
# 和这里预置的取值口径一致。写进路由的名字一律带 `Kenari ` 前缀(前缀只加在
|
|
110
|
+
# 路由条目上,插件自己那页的模型表不加),与官方 DeepSeek 的同名模型区分开。
|
|
111
|
+
# 窗口的 1/4 夹在 [8192, 65536],这四个的窗口都是 ~1M,所以都取到上限。
|
|
115
112
|
- id: deepseek-v4-flash
|
|
116
|
-
name: DeepSeek v4 Flash
|
|
113
|
+
name: Kenari DeepSeek v4 Flash
|
|
117
114
|
contextWindow: 1048576
|
|
118
115
|
maxTokens: 65536
|
|
119
116
|
input: [text]
|
|
120
117
|
reasoningEfforts: { low: low, high: high, max: max }
|
|
121
118
|
- id: glm-5-3-flash
|
|
122
|
-
name: GLM 5.3 Flash
|
|
119
|
+
name: Kenari GLM 5.3 Flash
|
|
123
120
|
contextWindow: 1000000
|
|
124
121
|
maxTokens: 65536
|
|
125
122
|
input: [text, image]
|
|
126
123
|
reasoningEfforts: { low: low, high: high, max: max }
|
|
127
124
|
- id: gpt-5-6-luna
|
|
128
|
-
name: GPT 5.6 Luna
|
|
125
|
+
name: Kenari GPT 5.6 Luna
|
|
129
126
|
contextWindow: 872000
|
|
130
127
|
maxTokens: 65536
|
|
131
128
|
input: [text, image]
|
|
132
129
|
reasoningEfforts: { off: none, low: low, medium: medium, high: high, xhigh: xhigh, max: max }
|
|
133
130
|
- id: mimo-v2-5
|
|
134
|
-
name: MiMo v2.5
|
|
131
|
+
name: Kenari MiMo v2.5
|
|
135
132
|
contextWindow: 1050000
|
|
136
133
|
maxTokens: 65536
|
|
137
134
|
input: [text, image]
|
package/lib/catalog-view.d.ts
CHANGED
|
@@ -32,6 +32,10 @@ interface ModelView {
|
|
|
32
32
|
* 目录里只有 8 个模型带 `name`,其余 70 多个要按 id 还原(见 `displayNameOf`)。
|
|
33
33
|
* 若这里原样透传,无名模型的 `name` 就等于 id,界面把 id 印两遍;而同一个模型的
|
|
34
34
|
* `profile.name` 又已经是派生名——同一份数据里两个口径,改这里就是为了消掉它。
|
|
35
|
+
*
|
|
36
|
+
* 这一列给的是**模型自己的名字**(不带路由前缀):插件这一页整页都在 Kenari 节里,
|
|
37
|
+
* 每行再写一遍 Kenari 是噪音。前缀只加在 {@link ModelView.profile} 的 `name` 上,
|
|
38
|
+
* 那是写进路由、由 dsh 印在模型按钮与会话头部的那个字符串。
|
|
35
39
|
*/
|
|
36
40
|
name: string;
|
|
37
41
|
ownedBy?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog-view.d.ts","sourceRoot":"","sources":["../src/catalog-view.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAGlD,OAAO,EACyE,cAAc,EAC7F,MAAM,cAAc,CAAA;AACrB,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAe,MAAM,cAAc,CAAA;AAE7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAE/C,yDAAyD;AACzD,eAAO,MAAM,sBAAsB,uBAAuB,CAAA;AAE1D,cAAc;AACd,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;IAC7B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAA;IAC/B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAA;CAC5B;AAED,iDAAiD;AACjD,UAAU,SAAS;IACjB,EAAE,EAAE,MAAM,CAAA;IACV
|
|
1
|
+
{"version":3,"file":"catalog-view.d.ts","sourceRoot":"","sources":["../src/catalog-view.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAGlD,OAAO,EACyE,cAAc,EAC7F,MAAM,cAAc,CAAA;AACrB,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAe,MAAM,cAAc,CAAA;AAE7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAE/C,yDAAyD;AACzD,eAAO,MAAM,sBAAsB,uBAAuB,CAAA;AAE1D,cAAc;AACd,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;IAC7B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAA;IAC/B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAA;CAC5B;AAED,iDAAiD;AACjD,UAAU,SAAS;IACjB,EAAE,EAAE,MAAM,CAAA;IACV;;;;;;;;;;OAUG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,IAAI,EAAE,OAAO,CAAA;IACb,IAAI,EAAE,OAAO,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,OAAO,CAAA;IACpB,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,IAAI,EAAE,aAAa,EAAE,CAAA;IACrB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,OAAO,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAA;CAC3C;AAED,gDAAgD;AAChD,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,SAAS,aAAa,EAAE,CAAA;IAC9B,MAAM,EAAE,SAAS,EAAE,CAAA;CACpB;AAuBD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,eAAe,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAqCxG;AAiBD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,eAAe,GAAG,IAAI,CAS7E"}
|
package/lib/catalog-view.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog-view.js","sourceRoot":"","sources":["../src/catalog-view.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,EACL,eAAe,EAAE,gBAAgB,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,GAC7F,MAAM,cAAc,CAAA;AAErB,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAIvC,yDAAyD;AACzD,MAAM,CAAC,MAAM,sBAAsB,GAAG,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"catalog-view.js","sourceRoot":"","sources":["../src/catalog-view.ts"],"names":[],"mappings":"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"}
|
package/lib/catalog.d.ts
CHANGED
|
@@ -103,14 +103,25 @@ export declare function capabilityTagsOf(model: KenariModel): CapabilityTag[];
|
|
|
103
103
|
*/
|
|
104
104
|
export declare function reasoningEffortsOf(model: KenariModel): Record<string, string> | undefined;
|
|
105
105
|
/**
|
|
106
|
-
*
|
|
106
|
+
* 写进路由的模型名统一带的路由前缀。
|
|
107
|
+
*
|
|
108
|
+
* 只加在**路由条目**上({@link toModelProfile} 的 `name`):那是 dsh 印模型名的地方,
|
|
109
|
+
* 而 dsh 只在 `/` 模型菜单里印所属 provider,composer 的模型按钮与会话头部只有展示名
|
|
110
|
+
* 一个字段 —— Kenari 与官方 DeepSeek 存在同名模型(`deepseek-v4-1-flash` 两边都有),
|
|
111
|
+
* 不写前缀就分不出当前用的是哪条路由。
|
|
112
|
+
*
|
|
113
|
+
* 插件自己那一页的模型表不加:它整页都在 Kenari 节里,每行再写一遍 Kenari 是噪音。
|
|
114
|
+
*/
|
|
115
|
+
export declare const DISPLAY_NAME_PREFIX = "Kenari ";
|
|
116
|
+
/**
|
|
117
|
+
* 一个模型自己的名字:目录给了 `name` 就用它,否则按 id 还原。
|
|
107
118
|
*
|
|
108
119
|
* 目录里只有 8 个模型自带 `name`,而且**都不是会话模型**(语音、图像、视频那几个),
|
|
109
|
-
*
|
|
120
|
+
* 所以会话模型的名字必须能从 id 还原。这里的推导不是猜:Kenari 给出 `name` 的那 8 个
|
|
110
121
|
* 模型与本函数的输出**逐字一致**(Veo 3.1 Lite、MiniMax Speech 2.8 Turbo、
|
|
111
122
|
* Nano Banana Pro…),`test/catalog-view.mjs` 用它们反测。
|
|
112
123
|
*
|
|
113
|
-
*
|
|
124
|
+
* 名字原样给:要写进路由时由 {@link toModelProfile} 加前缀,两处口径不同是故意的。
|
|
114
125
|
*/
|
|
115
126
|
export declare function displayNameOf(model: KenariModel): string;
|
|
116
127
|
/**
|
|
@@ -142,8 +153,11 @@ export declare function recommendedMaxTokens(contextWindow: number | undefined):
|
|
|
142
153
|
* 字段必须逐个来自目录:pi-ai 的 schema 会拒绝多余或拼错的键。
|
|
143
154
|
*
|
|
144
155
|
* `name` 与 `maxTokens` 都写:前者是 dsh 模型目录里那个「显示名称」框(不写就空着),
|
|
145
|
-
* 后者是每请求输出上限(不写则整条路由共用 pi-ai 的
|
|
156
|
+
* 后者是每请求输出上限(不写则整条路由共用 pi-ai 的 defaultMaxTokens 32768,
|
|
146
157
|
* 于是每个模型看到的都是同一个数)。两者的推导见上面两个函数。
|
|
158
|
+
*
|
|
159
|
+
* `name` 是**唯一**带路由前缀的地方:这条 profile 写进 `llm-pi-ai` 之后,就是 dsh 的
|
|
160
|
+
* 模型按钮、会话头部与 `/` 菜单印出来的字符串。
|
|
147
161
|
*/
|
|
148
162
|
export declare function toModelProfile(model: KenariModel): {
|
|
149
163
|
id: string;
|
package/lib/catalog.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"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"}
|