dsh-model-flatmap 0.0.0-stage → 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 dsh-model-flatmap contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,120 @@
1
- # Temporary Holding Version
1
+ # dsh-model-flatmap
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ > A flat, two-level-free model picker for the DeepSeek Harness (DSH) composer:
4
+ > every model and reasoning level on one surface, no second-level menus.
5
+
6
+ [简体中文](./README.zh.md)
7
+
8
+ ## What it is
9
+
10
+ `dsh-model-flatmap` is a **client-side** DSH plugin that runs in both the **Web GUI and the
11
+ Desktop app**. It replaces the composer's `conversation.input.model` seat with a single flat
12
+ panel rendered in the client UI.
13
+ Instead of nested popovers, the whole catalogue is one searchable grid where the
14
+ model grid, the current model's reasoning levels, and the agent-teamwork switch
15
+ are all visible at once.
16
+
17
+ The plugin reads and writes through **public Client APIs only** — the per-Session
18
+ model directory, the teamwork setting, and the host's locale. The host half
19
+ (`index.js`) contributes no service, tool, or event; the UI lives in `client.js`,
20
+ which registers with a negative priority so it shadows the shipped `ModelSelect`
21
+ while active. Disabling the plugin restores the native control with no residue.
22
+
23
+ ## Screenshot
24
+
25
+ The panel in action — a flat grid of models, the current model's reasoning
26
+ levels, and the agent-teamwork switch on one surface:
27
+
28
+ ![Flat model picker panel](./docs/model-picker.jpeg)
29
+
30
+ ## Features
31
+
32
+ - **One surface.** The trigger opens one panel capped at 320 px. The header, the
33
+ reasoning row, and the teamwork row stay fixed; only the model grid scrolls.
34
+ - **Global search.** Filters across every provider and every family. Groups that
35
+ end up empty are dropped, so no stray headings remain. Prefix matches rank
36
+ first, then substring matches, then ordered character matches.
37
+ - **Word-wise search.** Whitespace splits the query into tokens, and every token
38
+ must land somewhere in the name. A hit ranks by its weakest token.
39
+ - **Provider-wide search.** A query that matches a *provider* (its id, catalog
40
+ name, or section label) keeps that provider's entire catalogue in the grid.
41
+ - **Two grouping modes.** A segment control switches the grid between
42
+ *By provider* and *By family*. Grouping and search are independent.
43
+ - **Model families.** A built-in dictionary recognises DeepSeek, Grok, Opus,
44
+ Haiku, Sonnet, Claude, Qwen, GLM, Kimi, GPT, Gemini, Llama, Mistral and others.
45
+ Unrecognised models are inferred from their id; anything unjudgeable falls into
46
+ *Others* (always sorts last). Families stay flat — no nesting.
47
+ - **Generations are kept apart.** A registered brand splits by generation:
48
+ `hy3` → `HY3`, `hy4free` / `hy4std` / `hy4-preview` → `HY4`, and a bare `hy`
49
+ → `HY`. Unregistered brands still collapse their version tail; dictionary
50
+ families (GPT, Qwen…) are never split.
51
+ - **Rows are provider-primary.** Under *By family* the heading already says what
52
+ the models are, so the family name is not repeated in a row: the primary text
53
+ is the provider name. Only when one provider offers several models in the same
54
+ family does a short id-derived suffix differentiate them. The full model name
55
+ and description stay in the tooltip.
56
+ - **Reasoning effort.** The current model's reasoning levels render as an
57
+ exclusive, keyboard-operable group ("推理等级" / "Reasoning effort") driven by
58
+ radio semantics.
59
+ - **Adaptive footer.** The reasoning group and the agent-teamwork switch share
60
+ one line when both fit with a 30 px gap, and fall back to one row each when
61
+ they do not — the break is CSS flex wrapping, not a measured pixel threshold.
62
+ - **Out-of-balance models are struck through — everywhere.** A model whose last
63
+ call failed on insufficient balance, credit, or quota keeps a `line-through`
64
+ on its row text until a later call for that same model returns anything else.
65
+ The strike follows the model the failing request actually used, and covers the
66
+ Host's `QUOTA` / `ACCOUNT_QUOTA` codes, a provider `402`, and a `429` whose
67
+ body reports an empty balance — a plain rate limit never strikes. Because a
68
+ balance is a property of the model route and its account, **not of one
69
+ conversation**, the marks are global: a failure seen in any Session strikes
70
+ the model in every Session and workspace, and the state is persisted to
71
+ `localStorage` so it survives a reload. Observations are ordered by event
72
+ time, so the newest one wins and replaying older history cannot resurrect a
73
+ strike that a later call already cleared.
74
+ - **Theme-aware.** Styled with host theme tokens only; looks correct in both
75
+ light and dark themes.
76
+
77
+ See [`docs/DETAIL.md`](./docs/DETAIL.md) for the full behaviour spec and
78
+ [`DECISIONS.md`](./DECISIONS.md) for the decision log behind the design.
79
+
80
+ ## Installation
81
+
82
+ This package is a DSH **bundle**. Install it from your DSH profile (the plugin
83
+ manager), or drop it into the profile's bundle directory so the `dsh` loader
84
+ picks up `cordis.patch.yml`.
85
+
86
+ ```bash
87
+ # Example: install the bundle into a running profile (paths vary by install)
88
+ cp -r . "<profile>/bundles/dsh-model-flatmap"
89
+ ```
90
+
91
+ Enable or disable the plugin from the profile's plugin list — no native control
92
+ is touched when the bundle is off.
93
+
94
+ ## Project layout
95
+
96
+ | Path | Purpose |
97
+ | -------------------- | -------------------------------------------------------- |
98
+ | `index.js` | Host half — bundle entry, contributes nothing at runtime. |
99
+ | `client.js` | Browser half — the entire flat picker UI. |
100
+ | `cordis.patch.yml` | Cordis patch applied by the `dsh` bundle loader. |
101
+ | `locale/en.json` | English copy and metadata. |
102
+ | `locale/zh.json` | Simplified-Chinese copy and metadata. |
103
+ | `docs/DETAIL.md` | Detailed behaviour specification. |
104
+ | `test/` | Render-path tests driven through a minimal hook runtime. |
105
+
106
+ ## Development
107
+
108
+ The plugin is plain ES modules with no build step.
109
+
110
+ ```bash
111
+ # Run the render-path tests (no browser required)
112
+ node --test test/
113
+ ```
114
+
115
+ Tests read `client.js` directly and drive the real component through a minimal
116
+ hook runtime to catch crashes, missing sections, and wrong column counts.
117
+
118
+ ## License
119
+
120
+ Released under the [MIT License](./LICENSE).
package/README.zh.md ADDED
@@ -0,0 +1,102 @@
1
+ # dsh-model-flatmap
2
+
3
+ > 一个平铺、无二级菜单的 DeepSeek Harness(DSH)模型选择器:所有模型与推理等级
4
+ > 都在同一平面上,没有层层弹层。
5
+
6
+ [English](./README.md)
7
+
8
+ ## 这是什么
9
+
10
+ `dsh-model-flatmap` 是一个**客户端** DSH 插件,在 **Web GUI 与桌面端** 均生效。它把会话输入框中的
11
+ `conversation.input.model` 控件替换成一个平铺面板,渲染在客户端界面中。面板没有
12
+ 嵌套的二级菜单:模型网格、当前模型的推理等级,以及智能体协作开关,全部同时可见。
13
+
14
+ 插件**只通过公开的 Client API 读写数据**——每个会话的模型目录、协作设置、以及宿主
15
+ 的语言文案。宿主部分(`index.js`)不提供任何服务、工具或事件;UI 全部在
16
+ `client.js` 中,注册时使用负优先级以在启用期间覆盖原生的 `ModelSelect`。关闭插件
17
+ 即可无残留地恢复原生控件。
18
+
19
+ ## 截图
20
+
21
+ 运行中的面板——模型平铺网格、当前模型的推理等级,以及智能体协作开关,
22
+ 全部位于同一平面上:
23
+
24
+ ![平铺模型选择器面板](./docs/model-picker.jpeg)
25
+
26
+ ## 功能
27
+
28
+ - **一块平面。** 触发器打开一个高度上限 320 px 的面板。头部、推理等级行与协作行
29
+ 固定常驻,只有模型网格可滚动。
30
+ - **全局搜索。** 跨所有 provider 与 family 过滤。过滤后为空的组会被丢弃,不会留下
31
+ 空标题。命中排序:前缀优先,其次子串,最后有序字符匹配。
32
+ - **分词搜索。** 空白把查询拆成多个 token,每个 token 都要在名称中命中;一次命中的
33
+ 排序取决于最弱的那一个 token。
34
+ - **按 provider 整体搜索。** 命中某个 *provider*(其 id、目录名或分组标签)时,该
35
+ provider 的整个目录都会保留在网格中。
36
+ - **两种分组模式。** 分段控件在 *按 provider* 与 *按 family* 之间切换。分组与搜索彼此
37
+ 独立。
38
+ - **模型家族。** 内置词典识别 DeepSeek、Grok、Opus、Haiku、Sonnet、Claude、Qwen、
39
+ GLM、Kimi、GPT、Gemini、Llama、Mistral 等。未覆盖的模型按 id 推断;无法判断的归入
40
+ *Others*(永远排在最后)。家族保持平铺,不嵌套。
41
+ - **generation 要区分开。** 已注册品牌按 generation 分节:`hy3` 归 `HY3`、`hy4free` /
42
+ `hy4std` / `hy4-preview` 归 `HY4`,裸 `hy` 仍是 `HY`;未注册品牌仍折叠版本后缀。
43
+ 词典家族(GPT、Qwen…)不拆 generation。
44
+ - **row content 以 provider 为主。** *按 family* 下标题已经说明模型是什么,所以行里
45
+ 不再重复家族名,主文本改为 provider name;仅当同一 provider 在同一家族下有多个
46
+ 模型时,才补一个由 id 推出的短后缀区分。完整模型名/描述保留在 tooltip。
47
+ - **推理等级。** 当前模型的推理等级渲染为一个互斥、可键盘操作的分组("推理等级",
48
+ 基于 radio 语义)。
49
+ - **自适应底栏。** 推理等级组与智能体协作开关在放得下(中间至少 30 px)时共用一行,
50
+ 放不下时各自占一行回到原来的两行布局——换行由 CSS flex 换行决定,不靠 JS 量像素。
51
+ - **额度不足的模型加删除线,且全局生效。** 某个模型的调用因额度/余额/信用不足而失败后,
52
+ 该模型的行文字会带 `line-through` 删除线,直到同一个模型的下一次调用返回非额度不足的
53
+ 结果才去掉。标记跟随失败那次请求实际使用的模型;覆盖宿主的 `QUOTA` / `ACCOUNT_QUOTA`
54
+ 代码、provider 的 `402`,以及**正文说明余额不足的 `429`**——纯限流的 429 不会划线。
55
+ 因为「还有没有额度」是模型路由(及其账号)的属性、**与单个会话无关**,所以标记是全局的:
56
+ 在任意会话里观察到的失败,会在所有会话与工作区里同样划线;状态持久化在 `localStorage`
57
+ 中,重载后仍然保留。观察按事件时间排序,最新的一条说了算,因此回放更早的历史不会让一条
58
+ 已被后续调用清除的划线复活。
59
+ - **跟随主题。** 仅使用宿主主题令牌着色,在浅色与深色主题下都正确。
60
+
61
+ 完整行为规格见 [`docs/DETAIL.md`](./docs/DETAIL.md),设计决策见
62
+ [`DECISIONS.md`](./DECISIONS.md)。
63
+
64
+ ## 安装
65
+
66
+ 本包是一个 DSH **bundle**。从 DSH 配置文件的插件管理器安装,或将其放入配置文件的
67
+ bundle 目录,由 `dsh` 加载器读取 `cordis.patch.yml`。
68
+
69
+ ```bash
70
+ # 示例:把 bundle 装到某个运行中的 profile(路径因安装而异)
71
+ cp -r . "<profile>/bundles/dsh-model-flatmap"
72
+ ```
73
+
74
+ 在配置文件的插件列表中启用或停用本插件即可——关闭 bundle 不会触碰任何原生控件。
75
+
76
+ ## 目录结构
77
+
78
+ | 路径 | 用途 |
79
+ | -------------------- | ------------------------------------------------ |
80
+ | `index.js` | 宿主部分——bundle 入口,运行时不提供任何能力。 |
81
+ | `client.js` | 浏览器部分——完整的平铺选择器 UI。 |
82
+ | `cordis.patch.yml` | 由 `dsh` bundle 加载器应用的 Cordis 补丁。 |
83
+ | `locale/en.json` | 英文文案与元数据。 |
84
+ | `locale/zh.json` | 简体中文文案与元数据。 |
85
+ | `docs/DETAIL.md` | 详细行为规格。 |
86
+ | `test/` | 通过最小化 hook 运行时驱动的渲染路径测试。 |
87
+
88
+ ## 开发
89
+
90
+ 插件是纯 ES 模块,无需构建步骤。
91
+
92
+ ```bash
93
+ # 运行渲染路径测试(无需浏览器)
94
+ node --test test/
95
+ ```
96
+
97
+ 测试直接读取 `client.js`,并通过最小化 hook 运行时驱动真实组件,以捕获崩溃、缺失
98
+ 区块和错误的列数。
99
+
100
+ ## 许可证
101
+
102
+ 基于 [MIT 许可证](./LICENSE) 发布。