@mars-sea/dsh-commandcode-provider 0.14.1 → 0.14.3
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 +26 -1
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/lib/client.js +205 -122
- package/lib/index.d.ts +10 -4
- package/lib/index.js +75 -19
- package/package.json +2 -1
- package/lib/client.js.map +0 -1
- package/lib/index.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,7 +4,29 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
-
## [
|
|
7
|
+
## [0.14.3] - 2026-10-19
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- **发布包不再携带 sourcemap,体积减少约 16%(tarball 2.9 MB → 2.5 MB,解包 5.1 MB → 3.5 MB;文件数 18 → 16)。** `tsdown.config.ts` 的 `sourcemap: true` 会产出 `lib/index.js.map` 与 `lib/client.js.map`,而 `files` 直接收整个 `lib`,两份 map(1.63 MiB)因此进了 tarball。它们没有任何读取方:`lib/client.js` 是 WebView 直接执行的 CJS 包,`//# sourceMappingURL` 只是尾部注释;`scripts/verify-engine-load.mjs` 的审计用正则匹配 `import`/`require` **语句**,不匹配注释。本地 `npm run build` 照旧产出 map,调试能力不受影响。**用户侧无需做任何事**,运行时行为与公开导出面零变化(`lib/index.d.ts` 的 `export { ... }` 一行未改)。
|
|
12
|
+
|
|
13
|
+
- **长会话的历史分析报告更快(约 −28%~−33%)。** `buildAnalytics` 原先有两处对「事实 × 模型」的重复扫描:每模型小计对整表过滤 N 次,场景矩阵对每个(事实 × 目录模型)都查一次候选价格行(96 个模型共 480,000 次查找,查的是同一批行)。现改为先按模型分桶一次,并把定价算式收进 `cost-facts.requestCost()`、让场景循环把查价提到内层循环之外;`requestRates` 增加可选的高峰时段 memo(由调用方持有,不会活得比它的价格表更久)。两套独立测量给出同一量级:PR 作者脚本 5,000 条事实 × 96 个目录模型 42.17 ms → 30.36 ms,维护者本机用另一套合成数据复测 14.87 ms → 9.90 ms。**输出逐位不变**:分桶顺序与原 `Set` 顺序一致,排序本来就是按唯一 id 的全序(维护者另用 3,000 条确定性事实 × 96 个模型对比两版 JSON 输出,147,944 字节完全一致)。
|
|
14
|
+
|
|
15
|
+
- **图片请求里同一张图只编码一次 base64。** `readImageRequest()` 对每个(附件,编码目标)返回同一个缓存对象,但一条请求里同一张图会出现在多条历史消息中;三个 wire 编解码器原先各自按「出现次数」执行 `Buffer.from(version.data).toString('base64')`(1 MiB 载荷 0.738 ms/次)。现改为以该缓存对象为键的 `WeakMap`,保存原始 base64 与 data URL,副本生命周期跟随宿主自己的版本缓存。命中约 21 ns。
|
|
16
|
+
|
|
17
|
+
- **「查看模型用量、成本与性能分析」入口移到「账户用量」分组标题行**,紧邻「刷新」。它原先裸放在页面说明段与第一个分组之间,既无外边距也不属于任何分组,视觉上像是游离在版式之外;移到「账户用量」标题行后与服务着同一批用量/成本数据的「刷新」并列,也复用了该行既有的 `cc-spacer` 布局,不新增样式类。分析入口仍只在 Host 暴露面板接缝时出现,行为不变(切到面板的「模型分析」页签并打开面板)。
|
|
18
|
+
|
|
19
|
+
- **多账户轮换说明精简 2 处冗余用词**(中文 47 → 43 字,英文同步)。`账户操作立即生效。当前账户达到用量限额或密钥失效时,请求会按列表顺序自动切换到下一个可用账户。` → 去掉「用量」与「自动」后为:`账户操作立即生效。当前账户达到限额或密钥失效时,请求会按列表顺序切换到下一个可用账户。` 「按列表顺序切换」本身已表达自动性,`达到限额` 在账户上下文里仍是额度含意;英文侧 `usage limit` → `limit`,`switch` 原本就没有 `automatically`。**已知取舍**:同页单账户文案 `accountsHint` 仍用「用量限额」,两条说明的术语因此不完全一致。
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- **新增 `.gitattributes`:全部文本文件统一按 LF 检出与提交。** 仓库此前没有该文件,Windows 贡献者按 CRLF 检出后,sourcemap 的 `sourcesContent` 会内嵌带 CRLF 的源码,重建出的 `.map` 与提交里的不再逐字节相同,CI 的 `git diff --exit-code -- lib/` 守卫因此误报「产物过期」(2026-10-17 那次 CI 失败的根因)。实测对照:无该文件时 `core.autocrlf=true` 检出后 `src/adapter.ts` 有 3,482 行 CRLF、`lib/index.js` 有 11,817 行;加上后两者均为 0。图片与压缩包按 `binary` 排除在行尾转换之外。**本次加入时已跟踪文件 100% 是 LF,`git add --renormalize .` 未改写任何文件。**
|
|
24
|
+
|
|
25
|
+
### Removed
|
|
26
|
+
|
|
27
|
+
- 两份 sourcemap(`lib/index.js.map`、`lib/client.js.map`)不再纳入版本控制。它们是 tsdown 产物里唯一在 CRLF 工作树上无法逐字节重建的文件,跟踪它们只会让「产物过期」守卫依赖工作树的行尾;移出 tarball 与版本控制后,该守卫在任意平台都只反映源码与产物的真实一致性。
|
|
28
|
+
|
|
29
|
+
## [0.14.2] - 2026-10-18
|
|
8
30
|
|
|
9
31
|
### Changed
|
|
10
32
|
|
|
@@ -21,6 +43,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
21
43
|
- 复核**无变化**的项:峰谷计价仍是 5 个 DeepSeek 模型、窗口 `01–04 & 06–10 UTC, Mon–Fri` 与本地常量逐值一致;订阅条目与每月额度零变化;`reflection/beam:free` 支持图像输入这一点未被目录宣告,图像能力表保持 70 条;effort 词汇表仍是 `off|low|medium|high|xhigh|max`。
|
|
22
44
|
|
|
23
45
|
- **证据边界**:本轮 `scripts/` 巡检工具的状态为 `incomplete`、`readyToApply=false`、`protocol=not-verified`;唯一一条 error 是 `reflection/beam:free: absent from CLI registry`——该模型只出现在两个目录视图里,`1.84.0` 产物注册表完全不认它,因此 `KNOWN_EFFORTS` 与 `KNOWN_NON_ZDR_MODELS` 里这一行属**目录侧单源证据**(与 `1.82.4` 时 `stealth/cat-jam:free` 的处境相同)。16 个数据源全部返回 HTTP 200。**未做**:真实账号登录、付费生成、浏览器渲染验证,也没有在真实账号上验证价格与订阅额度的页面读数;`?view=client` 与定价页均为公开数据采集。
|
|
46
|
+
- **设置页「模型与上下文」分组改为可折叠,默认收起(issue #94)。**该分组是页面上最长的一组(套餐过滤开关 → 可见模型白名单 → 自定义上下文长度 → 按模型覆盖行),折起后「隐私与安全」与「集成与显示」两个分组不必翻过白名单即可到达。折叠头与「高级设置」共用同一实现(`DisclosureHead`/`CollapsibleGroup`),三条行为两边逐字一致:整行可点、箭头在行尾、状态不跨刷新记忆(组件内 `useState`,既不进配置文档也不进 localStorage——折叠是呈现偏好,不该由设置文档承载)。**「高级设置」呈现与交互零变化**,只是换成共用实现;`cc-groupHead`/`cc-disclosure`/`cc-chevron`/`cc-badgeWarn` 四个既有类原样复用,样式表零改动。**边界:纯呈现层开关**——`filterModelsByPlan`/`visibleModels`/`contextWindow`/`maxOutputTokens`/`contextWindowOverrides` 五个字段的暂存、校验、整批提交与写入所有权一律不变(沿用[《决策记录》第六章第1、2条](docs/决策记录.md#六设置写入所有权)),收起只决定组内 DOM 是否渲染,已暂存的编辑不会丢。**连带处理**:默认收起会把组内的无效数字一并藏起,而保存按钮会因此禁用,故折叠时在标题行显示警告徽标(新 locale 键 `modelsInvalid`,与「高级设置」的既有徽标同形);不新增「已选 N 个模型」式摘要徽标——诉求只是可收起,「非默认」口径需要另行定义。**已知取舍**:折叠头的标题仍是 `span` 而非 `h3`(该分组在标题导航里不再是一个 heading),沿用「高级设置」的既有写法(`button` 内不能放 heading),以换取与它逐字一致的 DOM 与零 CSS 布局风险。新增 `tests/section.test.ts` 12 项 React-free 用例固定两个分组「组内是否有未填好的数字」的判定(含按模型覆盖行分支);检查集与保存守卫走的**同一份 staged plan** 对齐——连 UI 上填不错的 `filterModelsByPlan` 开关也纳入,免得呈现判定比保存条件窄。两组变异对照(删 rows 分支、删 `filterModelsByPlan`)各自精准命中对应用例、恢复后 12/12 全通过,证明用例有判别力。
|
|
47
|
+
|
|
48
|
+
- **设置页「自定义上下文长度」与「单轮输出上限」的界面说明精简约一半。**两段 hint 只留「填什么 → 会怎样」:中文 124 → 61 字、240 → 98 字,英文 325 → 228、686 → 223 字符;删掉的是机制叙述(为何影响压缩与选择器标注、`0` 的动机、二进制换算示例、宿主限定预算的辅助调用),这些在 README 的对应段落里原样保留(**用户选定:README 保持不动**)。**两个信息点不可删**——「影响上下文计量与自动压缩」与「`0` 只在 CLI 与 OpenAI 传输生效,Claude 的 Messages 端点必填该字段」;后者由 `tests/settings.test.ts` 的既有文案护栏守着:首轮精简把它删掉后护栏立即失败(`zh hint names the route that requires the field`),遂以精简措辞加回,同组英文断言随之从 `/sends no such field/` 改为 `/omits the field/`(断言语义不变:文案必须说明 `0` 不发送该字段)。顺带去掉 hint 里的反引号——它经 `.cc-rowDesc` 纯文本渲染,反引号会在界面上原样显示。
|
|
24
49
|
|
|
25
50
|
## [0.14.1] - 2026-10-18
|
|
26
51
|
|
package/README.md
CHANGED
|
@@ -210,7 +210,7 @@ llm-commandcode:
|
|
|
210
210
|
|
|
211
211
|
## Configure
|
|
212
212
|
|
|
213
|
-
**Settings → Command Code** is organized as **Accounts** (keys, sign-in, live quota, pinning, dedicated models), **Models & context** (hide out-of-plan models, visible models, then the **Custom context length** field and the **Per-model overrides** rows right after the allowlist — global and per model, see below), **Privacy & security** (zero data retention, off by default, see below), **Integrations & display** (serve web search with Command Code, show the quota card in the sidebar, off by default), and a collapsed **Advanced** section (API base URL, request/stream timeouts, transport retries, cache-aware image offload). The working directory is no longer on the page; `workingDir` in config still works.
|
|
213
|
+
**Settings → Command Code** is organized as **Accounts** (keys, sign-in, live quota, pinning, dedicated models), a collapsed **Models & context** group (click its heading to unfold: hide out-of-plan models, visible models, then the **Custom context length** field and the **Per-model overrides** rows right after the allowlist — global and per model, see below), **Privacy & security** (zero data retention, off by default, see below), **Integrations & display** (serve web search with Command Code, show the quota card in the sidebar, off by default), and a collapsed **Advanced** section (API base URL, request/stream timeouts, transport retries, cache-aware image offload). Both foldable groups toggle from their whole heading row, and neither remembers its expanded state across visits. The working directory is no longer on the page; `workingDir` in config still works.
|
|
214
214
|
|
|
215
215
|
The same options live in `$DSH_HOME/settings.yaml` (changes apply immediately, no restart):
|
|
216
216
|
|
package/README.zh-CN.md
CHANGED
|
@@ -191,7 +191,7 @@ llm-commandcode:
|
|
|
191
191
|
|
|
192
192
|
## 配置
|
|
193
193
|
|
|
194
|
-
**设置 → Command Code**
|
|
194
|
+
**设置 → Command Code** 分为:**账户**(密钥、网页登录、实时额度、固定账户、专用模型)、**模型与上下文**(默认折叠,点标题展开:隐藏套餐外模型、可见模型,以及紧随白名单之后的**自定义上下文长度**字段与**按模型覆盖**列表,全局与按模型,见下)、**隐私与安全**(零数据保留 ZDR,默认关闭,见下)、**集成与显示**(用 Command Code 承载联网搜索、在侧边栏显示额度卡片,默认关闭),以及默认折叠的**高级设置**(API 地址、请求/流超时、传输重试次数、历史图片缓存优化)。两个可折叠分组都点标题整行展开/收起,展开状态不跨刷新记忆。工作目录已不在页面上显示,配置中的 `workingDir` 仍然有效。
|
|
195
195
|
|
|
196
196
|
同一组选项也位于 `$DSH_HOME/settings.yaml`(修改即刻生效,无需重启):
|
|
197
197
|
|
package/lib/client.js
CHANGED
|
@@ -3129,7 +3129,7 @@ window.__ModuleLoader__.load({
|
|
|
3129
3129
|
visibleModelsStaleHint: "有 {count} 个已选模型在目录中找不到了(可能已下架),不影响其他模型;可清理或保留。",
|
|
3130
3130
|
visibleModelsCleanStale: "清理失效({count})",
|
|
3131
3131
|
contextWindow: "自定义上下文长度",
|
|
3132
|
-
contextWindowHint: "
|
|
3132
|
+
contextWindowHint: "覆盖模型目录公布的上下文窗口(对未单独覆盖的模型生效),影响上下文计量与自动压缩;留空跟随目录。支持 32K、1M 简写。",
|
|
3133
3133
|
contextOverridesTitle: "按模型覆盖",
|
|
3134
3134
|
contextOverridesHint: "为单个模型单独设置上下文长度,优先于上面的全局值;模型下拉只列出模型白名单中的可见模型(显示全部时即整个目录)。",
|
|
3135
3135
|
contextOverrideAdd: "添加模型",
|
|
@@ -3141,7 +3141,7 @@ window.__ModuleLoader__.load({
|
|
|
3141
3141
|
contextWindowTooLarge: "上下文长度不能大于 10,000,000",
|
|
3142
3142
|
contextWindowInvalid: "请输入有效的整数 token 数",
|
|
3143
3143
|
maxOutputTokens: "单轮输出上限",
|
|
3144
|
-
maxOutputTokensHint: "
|
|
3144
|
+
maxOutputTokensHint: "留空=按模型推导(默认);正整数=不超过模型上限与网关上限 131072;0=不发送该字段(仅 CLI 与 OpenAI 有效,Claude 的 Messages 端点必填)。支持 64K 简写。",
|
|
3145
3145
|
maxOutputTokensTooSmall: "输出上限不能小于 0(0 表示不发送该字段)",
|
|
3146
3146
|
maxOutputTokensTooLarge: "输出上限不能大于 131072(网关上限)",
|
|
3147
3147
|
maxOutputTokensInvalid: "请输入 0 或有效的整数 token 数",
|
|
@@ -3237,7 +3237,7 @@ window.__ModuleLoader__.load({
|
|
|
3237
3237
|
cardRouteActive: "已启用",
|
|
3238
3238
|
cardLoadingHint: "正在读取 Command Code 配置…",
|
|
3239
3239
|
cardRegistrationHint: "此卡片由 Command Code 插件提供,正在等待设置页装配,稍后即可显示完整内容。",
|
|
3240
|
-
accountsRotationHint: "
|
|
3240
|
+
accountsRotationHint: "账户操作立即生效。当前账户达到限额或密钥失效时,请求会按列表顺序切换到下一个可用账户。",
|
|
3241
3241
|
accountModeAuto: "使用方式:自动切换(按列表顺序)",
|
|
3242
3242
|
accountModePinned: "使用方式:固定使用「{name}」,不可用时仍会自动切换",
|
|
3243
3243
|
accountStatusPinned: "已固定",
|
|
@@ -3279,6 +3279,7 @@ window.__ModuleLoader__.load({
|
|
|
3279
3279
|
modelCount: "已选 {count} 个模型",
|
|
3280
3280
|
modelCatalogFailed: "模型目录获取失败,暂时无法选择模型;已保存的设置仍会生效。",
|
|
3281
3281
|
modelsTitle: "模型与上下文",
|
|
3282
|
+
modelsInvalid: "模型与上下文中有未填好的数字,请展开修正后再保存。",
|
|
3282
3283
|
privacyTitle: "隐私与安全",
|
|
3283
3284
|
integrationsTitle: "集成与显示",
|
|
3284
3285
|
enrollmentCreating: "正在创建账号",
|
|
@@ -3354,7 +3355,7 @@ window.__ModuleLoader__.load({
|
|
|
3354
3355
|
visibleModelsStaleHint: "{count} selected model(s) are no longer in the catalog (possibly retired); other models are unaffected. Clean them up or keep them.",
|
|
3355
3356
|
visibleModelsCleanStale: "Clean stale ({count})",
|
|
3356
3357
|
contextWindow: "Custom context length",
|
|
3357
|
-
contextWindowHint: "Overrides the context window published by the model catalog
|
|
3358
|
+
contextWindowHint: "Overrides the context window published by the model catalog, for every model without an override of its own below; the context meter and auto-compaction follow it. Empty follows the catalog. Shorthand like 32K or 1M is accepted.",
|
|
3358
3359
|
contextOverridesTitle: "Per-model overrides",
|
|
3359
3360
|
contextOverridesHint: "Set a context length for one model; it wins over the global value above. The picker lists only the models kept by the visible-models allowlist (the whole catalog while showing all).",
|
|
3360
3361
|
contextOverrideAdd: "Add model",
|
|
@@ -3366,7 +3367,7 @@ window.__ModuleLoader__.load({
|
|
|
3366
3367
|
contextWindowTooLarge: "Context length must not exceed 10,000,000",
|
|
3367
3368
|
contextWindowInvalid: "Enter a valid whole-token count",
|
|
3368
3369
|
maxOutputTokens: "Output limit per turn",
|
|
3369
|
-
maxOutputTokensHint: "
|
|
3370
|
+
maxOutputTokensHint: "Empty derives it from the model (default). A positive number never exceeds the model ceiling or the gateway’s 131,072. 0 omits the field (CLI and OpenAI only; Claude’s Messages endpoint requires it). 64K shorthand accepted.",
|
|
3370
3371
|
maxOutputTokensTooSmall: "Output limit must be at least 0 (0 omits the field)",
|
|
3371
3372
|
maxOutputTokensTooLarge: "Output limit must not exceed 131,072 (the gateway cap)",
|
|
3372
3373
|
maxOutputTokensInvalid: "Enter 0 or a valid whole-token count",
|
|
@@ -3462,7 +3463,7 @@ window.__ModuleLoader__.load({
|
|
|
3462
3463
|
cardRouteActive: "Active",
|
|
3463
3464
|
cardLoadingHint: "Loading the Command Code configuration…",
|
|
3464
3465
|
cardRegistrationHint: "This card is contributed by the Command Code plugin and is waiting for the settings page to finish assembling.",
|
|
3465
|
-
accountsRotationHint: "Account actions apply immediately. When the current account hits its
|
|
3466
|
+
accountsRotationHint: "Account actions apply immediately. When the current account hits its limit or its key stops working, requests switch to the next usable account in list order.",
|
|
3466
3467
|
accountModeAuto: "Mode: switch automatically (list order)",
|
|
3467
3468
|
accountModePinned: "Mode: pinned to \"{name}\", still switching when it is unavailable",
|
|
3468
3469
|
accountStatusPinned: "Pinned",
|
|
@@ -3504,6 +3505,7 @@ window.__ModuleLoader__.load({
|
|
|
3504
3505
|
modelCount: "{count} models selected",
|
|
3505
3506
|
modelCatalogFailed: "The model catalog could not be loaded; saved settings still apply.",
|
|
3506
3507
|
modelsTitle: "Models & context",
|
|
3508
|
+
modelsInvalid: "A number in Models & context is not ready to save; expand to fix it.",
|
|
3507
3509
|
privacyTitle: "Privacy & security",
|
|
3508
3510
|
integrationsTitle: "Integrations & display",
|
|
3509
3511
|
enrollmentCreating: "Creating the account",
|
|
@@ -3702,7 +3704,7 @@ window.__ModuleLoader__.load({
|
|
|
3702
3704
|
}
|
|
3703
3705
|
//#endregion
|
|
3704
3706
|
//#region package.json
|
|
3705
|
-
var version = "0.14.
|
|
3707
|
+
var version = "0.14.3";
|
|
3706
3708
|
var repository = {
|
|
3707
3709
|
"type": "git",
|
|
3708
3710
|
"url": "git+https://github.com/Mars-Sea/dsh-commandcode-provider.git"
|
|
@@ -3892,6 +3894,13 @@ window.__ModuleLoader__.load({
|
|
|
3892
3894
|
* below Accounts is a flat group of rows (title/description left, control
|
|
3893
3895
|
* right) inside the staged form the floating save bar writes.
|
|
3894
3896
|
*
|
|
3897
|
+
* Two of those groups fold from their own heading — Models & context (issue
|
|
3898
|
+
* #94) and Advanced — and both start collapsed on every visit, with no
|
|
3899
|
+
* remembered state. While a group is collapsed its rows are not on screen, so
|
|
3900
|
+
* anything inside it that blocks the save is reported on the heading itself
|
|
3901
|
+
* (see `CollapsibleGroup`); the save bar alone would leave the disabled Save
|
|
3902
|
+
* button unexplained.
|
|
3903
|
+
*
|
|
3895
3904
|
* Styles are injected once by the client entry (see src/client/index.ts) and
|
|
3896
3905
|
* class-prefixed `cc-` to stay local.
|
|
3897
3906
|
*/
|
|
@@ -3902,6 +3911,28 @@ window.__ModuleLoader__.load({
|
|
|
3902
3911
|
"transportMaxRetries",
|
|
3903
3912
|
"offloadSeenImagesForCache"
|
|
3904
3913
|
];
|
|
3914
|
+
const MODELS_FIELDS = [
|
|
3915
|
+
"filterModelsByPlan",
|
|
3916
|
+
"contextWindow",
|
|
3917
|
+
"maxOutputTokens"
|
|
3918
|
+
];
|
|
3919
|
+
/**
|
|
3920
|
+
* Whether anything the collapsed Advanced card owns is blocking the save. The
|
|
3921
|
+
* card is folded on arrival, so this drives the warning badge on its heading.
|
|
3922
|
+
*/
|
|
3923
|
+
function advancedGroupInvalid(state) {
|
|
3924
|
+
return ADVANCED_FIELDS.some((field) => state[field].invalid);
|
|
3925
|
+
}
|
|
3926
|
+
/**
|
|
3927
|
+
* Whether anything the collapsed Models & context group owns is blocking the
|
|
3928
|
+
* save (issue #94). Besides its staged drafts — the plan switch and the two
|
|
3929
|
+
* numbers — that group owns the per-model context rows, whose drafts are
|
|
3930
|
+
* validated one by one: a bad row must surface on the heading just like a bad
|
|
3931
|
+
* number, or Save would sit disabled with nothing on screen explaining why.
|
|
3932
|
+
*/
|
|
3933
|
+
function modelsGroupInvalid(state) {
|
|
3934
|
+
return MODELS_FIELDS.some((field) => state[field].invalid) || state.contextWindowOverrides.some((row) => row.invalid);
|
|
3935
|
+
}
|
|
3905
3936
|
/** The "customized" tag and reset link a staged field shows once it differs from the default. */
|
|
3906
3937
|
function FieldOverride({ label, state, disabled, t, onReset }) {
|
|
3907
3938
|
if (!state.overridden && !state.clear) return null;
|
|
@@ -4453,17 +4484,86 @@ window.__ModuleLoader__.load({
|
|
|
4453
4484
|
});
|
|
4454
4485
|
}
|
|
4455
4486
|
/**
|
|
4487
|
+
* The heading of a foldable group: the whole row is the toggle and the chevron
|
|
4488
|
+
* sits at its trailing edge. Shared by Models & context (issue #94: the
|
|
4489
|
+
* reporter asked for it to fold "like Advanced below") and Advanced itself, so
|
|
4490
|
+
* the two cannot drift apart in either markup or behaviour.
|
|
4491
|
+
*
|
|
4492
|
+
* The title is a `span`, not the `h3` a static group uses, because a heading
|
|
4493
|
+
* element cannot sit inside a button — the same trade-off Advanced has always
|
|
4494
|
+
* made on its own.
|
|
4495
|
+
*/
|
|
4496
|
+
function DisclosureHead({ title, bodyId, expanded, onToggle, badges }) {
|
|
4497
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
4498
|
+
type: "button",
|
|
4499
|
+
className: "cc-groupHead cc-disclosure",
|
|
4500
|
+
"aria-expanded": expanded,
|
|
4501
|
+
"aria-controls": bodyId,
|
|
4502
|
+
onClick: onToggle,
|
|
4503
|
+
children: [
|
|
4504
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4505
|
+
className: "cc-groupTitle",
|
|
4506
|
+
children: title
|
|
4507
|
+
}),
|
|
4508
|
+
badges?.(expanded),
|
|
4509
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "cc-spacer" }),
|
|
4510
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4511
|
+
className: expanded ? "cc-chevron cc-chevronUp" : "cc-chevron",
|
|
4512
|
+
"aria-hidden": "true"
|
|
4513
|
+
})
|
|
4514
|
+
]
|
|
4515
|
+
});
|
|
4516
|
+
}
|
|
4517
|
+
/**
|
|
4518
|
+
* A titled group that folds from its own heading and starts collapsed. The
|
|
4519
|
+
* state is deliberately component-local — not persisted, not lifted into the
|
|
4520
|
+
* controller — so every visit opens at the same, predictable page length, and
|
|
4521
|
+
* folding can never turn into a stored preference the settings document would
|
|
4522
|
+
* have to carry.
|
|
4523
|
+
*/
|
|
4524
|
+
function CollapsibleGroup({ title, bodyId, divided = false, badges, footer, children }) {
|
|
4525
|
+
const [expanded, setExpanded] = (0, react.useState)(false);
|
|
4526
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
4527
|
+
className: divided ? "cc-group cc-groupDivided" : "cc-group",
|
|
4528
|
+
"aria-label": title,
|
|
4529
|
+
children: [
|
|
4530
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DisclosureHead, {
|
|
4531
|
+
title,
|
|
4532
|
+
bodyId,
|
|
4533
|
+
expanded,
|
|
4534
|
+
onToggle: () => setExpanded((value) => !value),
|
|
4535
|
+
badges
|
|
4536
|
+
}),
|
|
4537
|
+
expanded ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4538
|
+
id: bodyId,
|
|
4539
|
+
className: "cc-rows",
|
|
4540
|
+
children
|
|
4541
|
+
}) : null,
|
|
4542
|
+
expanded ? footer : null
|
|
4543
|
+
]
|
|
4544
|
+
});
|
|
4545
|
+
}
|
|
4546
|
+
/**
|
|
4456
4547
|
* Models & context: the plan filter and the allowlist sit together because both
|
|
4457
4548
|
* decide what the model picker lists (the allowlist applies after the plan
|
|
4458
4549
|
* filter), and the context-length fields follow them because they are the same
|
|
4459
4550
|
* subject seen from the other side — the window each listed model advertises.
|
|
4460
4551
|
* Those fields carry no heading or divider of their own: they are rows of this
|
|
4461
|
-
* group, not a section inside it.
|
|
4552
|
+
* group, not a section inside it. The group folds from its heading and starts
|
|
4553
|
+
* collapsed (issue #94, "same as Advanced below"): it is the longest group on
|
|
4554
|
+
* the page and its rows are set-and-forget, so folding keeps Accounts and the
|
|
4555
|
+
* two switches below it reachable without scrolling past the allowlist.
|
|
4462
4556
|
*/
|
|
4463
4557
|
function ModelsCard({ state, disabled, t, onEdit, onReset, onSelect, onClear, onOverrides }) {
|
|
4464
|
-
|
|
4558
|
+
const invalid = modelsGroupInvalid(state);
|
|
4559
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(CollapsibleGroup, {
|
|
4465
4560
|
title: t("modelsTitle"),
|
|
4561
|
+
bodyId: "cc-models-body",
|
|
4466
4562
|
divided: true,
|
|
4563
|
+
badges: (expanded) => !expanded && invalid ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4564
|
+
className: "cc-badge cc-badgeWarn",
|
|
4565
|
+
children: t("modelsInvalid")
|
|
4566
|
+
}) : null,
|
|
4467
4567
|
children: [
|
|
4468
4568
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToggleField, {
|
|
4469
4569
|
id: "cc-filter-models-by-plan",
|
|
@@ -4699,116 +4799,92 @@ window.__ModuleLoader__.load({
|
|
|
4699
4799
|
});
|
|
4700
4800
|
}
|
|
4701
4801
|
/**
|
|
4702
|
-
* The collapsed "Advanced" card: the API base and the network limits.
|
|
4703
|
-
*
|
|
4802
|
+
* The collapsed "Advanced" card: the API base and the network limits. Folds
|
|
4803
|
+
* through the same `CollapsibleGroup` the Models & context group uses, so the
|
|
4804
|
+
* two disclosures stay identical; while collapsed, a badge names the customized
|
|
4704
4805
|
* count and an invalid number (which blocks save) is surfaced on the header.
|
|
4705
4806
|
*/
|
|
4706
4807
|
function AdvancedSection({ state, disabled, t, onEdit, onReset }) {
|
|
4707
|
-
const [expanded, setExpanded] = (0, react.useState)(false);
|
|
4708
4808
|
const overridden = ADVANCED_FIELDS.filter((field) => state[field].overridden).length;
|
|
4709
|
-
const invalid =
|
|
4710
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(
|
|
4711
|
-
|
|
4712
|
-
|
|
4809
|
+
const invalid = advancedGroupInvalid(state);
|
|
4810
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(CollapsibleGroup, {
|
|
4811
|
+
title: t("advancedSettings"),
|
|
4812
|
+
bodyId: "cc-advanced-body",
|
|
4813
|
+
divided: true,
|
|
4814
|
+
badges: (expanded) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [overridden > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4815
|
+
className: "cc-badge",
|
|
4816
|
+
children: overridden === 1 ? t("advancedOverriddenOne") : t("advancedOverriddenMany", { count: overridden })
|
|
4817
|
+
}) : null, !expanded && invalid ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4818
|
+
className: "cc-badge cc-badgeWarn",
|
|
4819
|
+
children: t("advancedInvalid")
|
|
4820
|
+
}) : null] }),
|
|
4821
|
+
footer: invalid ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4822
|
+
className: "cc-rowError",
|
|
4823
|
+
role: "status",
|
|
4824
|
+
children: t("advancedInvalid")
|
|
4825
|
+
}) : null,
|
|
4713
4826
|
children: [
|
|
4714
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
"aria-expanded": expanded,
|
|
4718
|
-
"aria-controls": "cc-advanced-body",
|
|
4719
|
-
onClick: () => setExpanded((value) => !value),
|
|
4720
|
-
children: [
|
|
4721
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4722
|
-
className: "cc-groupTitle",
|
|
4723
|
-
children: t("advancedSettings")
|
|
4724
|
-
}),
|
|
4725
|
-
overridden > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4726
|
-
className: "cc-badge",
|
|
4727
|
-
children: overridden === 1 ? t("advancedOverriddenOne") : t("advancedOverriddenMany", { count: overridden })
|
|
4728
|
-
}) : null,
|
|
4729
|
-
!expanded && invalid ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4730
|
-
className: "cc-badge cc-badgeWarn",
|
|
4731
|
-
children: t("advancedInvalid")
|
|
4732
|
-
}) : null,
|
|
4733
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "cc-spacer" }),
|
|
4734
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4735
|
-
className: expanded ? "cc-chevron cc-chevronUp" : "cc-chevron",
|
|
4736
|
-
"aria-hidden": "true"
|
|
4737
|
-
})
|
|
4738
|
-
]
|
|
4827
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4828
|
+
className: "cc-groupDesc",
|
|
4829
|
+
children: t("advancedSettingsHint")
|
|
4739
4830
|
}),
|
|
4740
|
-
|
|
4741
|
-
id: "cc-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
hint: t("offloadSeenImagesForCacheHint"),
|
|
4798
|
-
state: state.offloadSeenImagesForCache,
|
|
4799
|
-
disabled,
|
|
4800
|
-
defaultChecked: false,
|
|
4801
|
-
onEdit: (text) => onEdit("offloadSeenImagesForCache", text),
|
|
4802
|
-
onReset: () => onReset("offloadSeenImagesForCache"),
|
|
4803
|
-
t
|
|
4804
|
-
})
|
|
4805
|
-
]
|
|
4806
|
-
}) : null,
|
|
4807
|
-
expanded && invalid ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4808
|
-
className: "cc-rowError",
|
|
4809
|
-
role: "status",
|
|
4810
|
-
children: t("advancedInvalid")
|
|
4811
|
-
}) : null
|
|
4831
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Field, {
|
|
4832
|
+
id: "cc-api-base",
|
|
4833
|
+
label: t("apiBase"),
|
|
4834
|
+
hint: t("apiBaseHint"),
|
|
4835
|
+
state: state.apiBase,
|
|
4836
|
+
disabled,
|
|
4837
|
+
wide: true,
|
|
4838
|
+
onEdit: (text) => onEdit("apiBase", text),
|
|
4839
|
+
onReset: () => onReset("apiBase"),
|
|
4840
|
+
t
|
|
4841
|
+
}),
|
|
4842
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Field, {
|
|
4843
|
+
id: "cc-request-timeout",
|
|
4844
|
+
label: t("requestTimeoutMs"),
|
|
4845
|
+
hint: t("requestTimeoutMsHint"),
|
|
4846
|
+
state: state.requestTimeoutMs,
|
|
4847
|
+
disabled,
|
|
4848
|
+
numeric: true,
|
|
4849
|
+
decimal: true,
|
|
4850
|
+
onEdit: (text) => onEdit("requestTimeoutMs", text),
|
|
4851
|
+
onReset: () => onReset("requestTimeoutMs"),
|
|
4852
|
+
t
|
|
4853
|
+
}),
|
|
4854
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Field, {
|
|
4855
|
+
id: "cc-stream-idle-timeout",
|
|
4856
|
+
label: t("streamIdleTimeoutMs"),
|
|
4857
|
+
hint: t("streamIdleTimeoutMsHint"),
|
|
4858
|
+
state: state.streamIdleTimeoutMs,
|
|
4859
|
+
disabled,
|
|
4860
|
+
numeric: true,
|
|
4861
|
+
decimal: true,
|
|
4862
|
+
onEdit: (text) => onEdit("streamIdleTimeoutMs", text),
|
|
4863
|
+
onReset: () => onReset("streamIdleTimeoutMs"),
|
|
4864
|
+
t
|
|
4865
|
+
}),
|
|
4866
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Field, {
|
|
4867
|
+
id: "cc-transport-max-retries",
|
|
4868
|
+
label: t("transportMaxRetries"),
|
|
4869
|
+
hint: t("transportMaxRetriesHint"),
|
|
4870
|
+
state: state.transportMaxRetries,
|
|
4871
|
+
disabled,
|
|
4872
|
+
numeric: true,
|
|
4873
|
+
onEdit: (text) => onEdit("transportMaxRetries", text),
|
|
4874
|
+
onReset: () => onReset("transportMaxRetries"),
|
|
4875
|
+
t
|
|
4876
|
+
}),
|
|
4877
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToggleField, {
|
|
4878
|
+
id: "cc-offload-seen-images-for-cache",
|
|
4879
|
+
label: t("offloadSeenImagesForCache"),
|
|
4880
|
+
hint: t("offloadSeenImagesForCacheHint"),
|
|
4881
|
+
state: state.offloadSeenImagesForCache,
|
|
4882
|
+
disabled,
|
|
4883
|
+
defaultChecked: false,
|
|
4884
|
+
onEdit: (text) => onEdit("offloadSeenImagesForCache", text),
|
|
4885
|
+
onReset: () => onReset("offloadSeenImagesForCache"),
|
|
4886
|
+
t
|
|
4887
|
+
})
|
|
4812
4888
|
]
|
|
4813
4889
|
});
|
|
4814
4890
|
}
|
|
@@ -5478,7 +5554,7 @@ window.__ModuleLoader__.load({
|
|
|
5478
5554
|
* each, with its status and quota inline — so one account's facts no longer
|
|
5479
5555
|
* have to be cross-read across separate surfaces.
|
|
5480
5556
|
*/
|
|
5481
|
-
function AccountsCard({ t, state, usage, login, disabled, actions, onRefresh, createEnrollment }) {
|
|
5557
|
+
function AccountsCard({ t, state, usage, login, disabled, actions, onRefresh, openAnalytics, createEnrollment }) {
|
|
5482
5558
|
const [adding, setAdding] = (0, react.useState)(false);
|
|
5483
5559
|
const [enrollment] = (0, react.useState)(createEnrollment);
|
|
5484
5560
|
const snapshot = (0, react.useSyncExternalStore)(enrollment.store.subscribe, enrollment.store.getSnapshot);
|
|
@@ -5506,6 +5582,12 @@ window.__ModuleLoader__.load({
|
|
|
5506
5582
|
children: t("accountsTitle")
|
|
5507
5583
|
}),
|
|
5508
5584
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "cc-spacer" }),
|
|
5585
|
+
openAnalytics ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
5586
|
+
variant: "ghost",
|
|
5587
|
+
size: "sm",
|
|
5588
|
+
onClick: openAnalytics,
|
|
5589
|
+
children: t("openAnalytics")
|
|
5590
|
+
}) : null,
|
|
5509
5591
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5510
5592
|
type: "button",
|
|
5511
5593
|
className: "cc-linkButton",
|
|
@@ -5853,12 +5935,6 @@ window.__ModuleLoader__.load({
|
|
|
5853
5935
|
className: "cc-intro",
|
|
5854
5936
|
children: t("intro")
|
|
5855
5937
|
}),
|
|
5856
|
-
props.openAnalytics ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
5857
|
-
variant: "ghost",
|
|
5858
|
-
size: "sm",
|
|
5859
|
-
onClick: props.openAnalytics,
|
|
5860
|
-
children: t("openAnalytics")
|
|
5861
|
-
}) : null,
|
|
5862
5938
|
!state.writable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5863
5939
|
className: "cc-readOnly",
|
|
5864
5940
|
role: "status",
|
|
@@ -5872,6 +5948,7 @@ window.__ModuleLoader__.load({
|
|
|
5872
5948
|
disabled,
|
|
5873
5949
|
actions,
|
|
5874
5950
|
onRefresh: props.refreshUsage,
|
|
5951
|
+
openAnalytics: props.openAnalytics,
|
|
5875
5952
|
createEnrollment: props.createEnrollment
|
|
5876
5953
|
}),
|
|
5877
5954
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelsCard, {
|
|
@@ -8300,10 +8377,16 @@ window.__ModuleLoader__.load({
|
|
|
8300
8377
|
* today, so the combination becoming real is visible before it reaches a user.
|
|
8301
8378
|
* This ordering is a latent choice, not a verified upstream rule.
|
|
8302
8379
|
*/
|
|
8303
|
-
function requestRates(price, at, contextTokens, table) {
|
|
8380
|
+
function requestRates(price, at, contextTokens, table, peakHourCache) {
|
|
8304
8381
|
const tier = price.contextTiers?.find((tier) => tier.maxContext === void 0 || contextTokens <= tier.maxContext);
|
|
8305
8382
|
if (tier !== void 0) return tier;
|
|
8306
|
-
|
|
8383
|
+
if (price.peak === void 0 || at === null) return price;
|
|
8384
|
+
let peak = peakHourCache?.get(at);
|
|
8385
|
+
if (peak === void 0) {
|
|
8386
|
+
peak = peakHour(at, table.peakHours);
|
|
8387
|
+
peakHourCache?.set(at, peak);
|
|
8388
|
+
}
|
|
8389
|
+
return peak ? price.peak : price;
|
|
8307
8390
|
}
|
|
8308
8391
|
/** Cache version and wire guard: changing bands/rates must refold historical groups. */
|
|
8309
8392
|
function pricingKey(table) {
|
package/lib/index.d.ts
CHANGED
|
@@ -207,7 +207,13 @@ interface CommandCodeConnectionOptions {
|
|
|
207
207
|
* text-only request never depends on the attachment seam.
|
|
208
208
|
*/
|
|
209
209
|
type ResolveAttachments = () => AttachmentStore | undefined;
|
|
210
|
-
/**
|
|
210
|
+
/**
|
|
211
|
+
* What the rotation hook knows about the request it is rotating within.
|
|
212
|
+
*
|
|
213
|
+
* Not exported: the only consumer is the `rotateApiKey` shape below, so the
|
|
214
|
+
* name never reaches the published `.d.ts` and the package's `exports` map
|
|
215
|
+
* leaves no deep-import path to it.
|
|
216
|
+
*/
|
|
211
217
|
interface AccountRotationContext {
|
|
212
218
|
/** Every API key this request has already used, just-rejected key included. */
|
|
213
219
|
tried: readonly string[];
|
|
@@ -265,13 +271,13 @@ interface CommandCodeAdapterDeps<C extends CommandCodeConnectionOptions = Comman
|
|
|
265
271
|
*/
|
|
266
272
|
imageOffload?: SurfaceImagePolicy;
|
|
267
273
|
}
|
|
268
|
-
/** Account identity from `/alpha/whoami`. */
|
|
274
|
+
/** Account identity from `/alpha/whoami`; reached only through `CommandCodeUsageReport`. */
|
|
269
275
|
interface CommandCodeAccount {
|
|
270
276
|
id: string;
|
|
271
277
|
name: string;
|
|
272
278
|
userName: string;
|
|
273
279
|
}
|
|
274
|
-
/** Usage summary from `/alpha/usage/summary`. */
|
|
280
|
+
/** Usage summary from `/alpha/usage/summary`; reached only through `CommandCodeUsageReport`. */
|
|
275
281
|
interface CommandCodeUsage {
|
|
276
282
|
totalCount: number;
|
|
277
283
|
totalCost: number;
|
|
@@ -326,7 +332,7 @@ interface CommandCodeCredits {
|
|
|
326
332
|
resetAt: number;
|
|
327
333
|
};
|
|
328
334
|
}
|
|
329
|
-
/** Subscription plan state from `/alpha/billing/subscriptions`. */
|
|
335
|
+
/** Subscription plan state from `/alpha/billing/subscriptions`; reached only through `CommandCodeUsageReport`. */
|
|
330
336
|
interface CommandCodePlan {
|
|
331
337
|
/** Raw subscription plan id (e.g. `individual-pro`); empty when unreported. */
|
|
332
338
|
planId: string;
|