dsh-magpie-connect 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 dsh-magpie-connect 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 ADDED
@@ -0,0 +1,133 @@
1
+ # dsh-magpie-connect
2
+
3
+ **Magpie LAN gateway models, natively inside DSH (DeepSeek Harness).**
4
+
5
+ No extra process. Points at your configured gateway origin and serves
6
+ every model from the gateway's `GET …/models` in the DSH model picker as provider
7
+ `dsh-magpie-connect` (picker label `magpie`).
8
+
9
+ > The gateway is **not** configured out of the box: set the API URL **and**
10
+ > API key on the Settings → Magpie page (or via `cordis.patch.yml`). Both
11
+ > are required — until then the picker stays empty and calls fail fast with
12
+ > a "not configured" error.
13
+
14
+ - **双接口** — `/v1/chat/completions` 与 `/v1/responses` 按模型 `native_endpoints`
15
+ 自动分流(Muse Spark / Codex / Grok 走 responses,其余走 completions)
16
+ - **图片识别** — 声明 `modalities.input: image` 的模型开放图片输入,经 harness
17
+ 附件服务取字节后以 OpenAI `image_url` / `input_image` 上行
18
+ - **思考级别选择** — 网关 `supported_reasoning_levels` 原样进 picker(含 `none` /
19
+ `ultra` 扩展档),直通网关不截断;过期档位按就近原则收敛,不会 400
20
+
21
+ ## Install
22
+
23
+ ```sh
24
+ dsh plugin --profile web add dsh-magpie-connect
25
+ ```
26
+
27
+ Restart `dsh web` after installing. Requires DSH with a web profile;
28
+ Node.js ≥ 20; LAN route to `http://api.lan`.
29
+
30
+ ## Settings page
31
+
32
+ Settings → Magpie 网关 (sidebar): edit the API URL and API key, test the
33
+ connection (reports how many models the endpoint serves), and choose which
34
+ models appear in the model picker. Everything saves to
35
+ `~/.dsh-magpie-connect/settings.json` and applies immediately — no restart.
36
+
37
+ **两种提交时机**:地址与 Key 需要点「保存」(凭证不适合静默写入);**模型列表的
38
+ 增删会自动保存**,不需要、也没有保存按钮。因为模型卡片在连接卡片下方,一个管全部
39
+ 的保存按钮会让"删了一行"看起来已经生效——它其实没有。自动保存通过队列串行化,
40
+ 连点多次删除不会因为响应乱序而把旧集合写回磁盘。
41
+
42
+ **API 地址是带版本号的完整前缀**,例如 `http://api.lan/v1`:插件只往后拼资源名
43
+ (`/models`、`/chat/completions`、`/responses`),**绝不自己补版本号**。网关以后
44
+ 上 `/v2`、`/v3` 时,只改这一个字符串即可,不会拼成 `/v2/v1/models`。尾斜杠会被
45
+ 去掉,路径原样保留。
46
+
47
+ **获取可用模型** 打开候选弹窗:它问的是**表单当前显示的地址与 Key**(包括还没
48
+ 保存的),所以填一个新网关是一趟而不是"保存—返回—再看"。弹窗里可搜索、可全选/
49
+ 取消全选、逐个勾选,**应用选择**把勾选结果换算成隐藏集合。列表只显示已启用的模型,
50
+ 隐藏的只在弹窗里;行尾的「删除」即隐藏,重新加回也在弹窗。保存时会清掉网关已经
51
+ 不再提供的陈旧 id。查不通不会卡死——失败信息就显示在列表下方,行仍然可以手改。
52
+
53
+ Precedence per field: settings page > `cordis.patch.yml` config > defaults.
54
+ Hidden models only come from the page; an empty list shows everything.
55
+
56
+ Toggling visibility, changing the origin, or a refresh that added/dropped
57
+ models publishes `llm/adapters-updated`, the one event DSH's picker listens
58
+ to — the browser caches one catalog read per Host generation, so without it
59
+ the picker keeps the stale list until `dsh web` restarts.
60
+
61
+ ## Configuration
62
+
63
+ Set the gateway URL first — either on the Settings → Magpie page (recommended,
64
+ applies instantly) or via the profile's `cordis.patch.yml`:
65
+
66
+ ```yaml
67
+ - id: dsh-magpie-connect
68
+ name: 'dsh-magpie-connect'
69
+ config:
70
+ providerId: dsh-magpie-connect
71
+ displayName: magpie
72
+ baseUrl: http://api.lan/v1 # versioned API root — include the version
73
+ apiKey: not-needed # LAN gateway needs none
74
+ refreshSeconds: 300
75
+ maxRetries: 2
76
+ timeoutMs: 300000
77
+ firstEventTimeoutMs: 90000
78
+ idleTimeoutMs: 60000
79
+ ```
80
+
81
+ | Option | Default | Description |
82
+ | --- | --- | --- |
83
+ | `providerId` | `dsh-magpie-connect` | Provider name shown in DSH. |
84
+ | `displayName` | `magpie` | Picker grouping label. |
85
+ | `baseUrl` | `''` (not configured) | Versioned API root, e.g. `http://api.lan/v1`. The version is part of the value, not appended — a gateway on `/v2` is reached by changing this string. Required. |
86
+ | `apiKey` | `''` (not configured) | Bearer key. Required, even if `/models` answers without one. |
87
+ | `dataDir` | `~/.dsh-magpie-connect` | State dir (status, settings file, cache). |
88
+ | `refreshSeconds` | `300` | Live catalog refresh interval. |
89
+ | `maxRetries` | `2` | Connection-setup retries on 429/5xx. |
90
+ | `timeoutMs` | `300000` | Overall upstream request cap in ms. |
91
+ | `firstEventTimeoutMs` | `90000` | Stall watchdog: max wait for first event. |
92
+ | `idleTimeoutMs` | `60000` | Stall watchdog: max silence between events. |
93
+
94
+ ## How it works
95
+
96
+ ```
97
+ DSH session
98
+ │ harness chunks (block-start / text-delta / usage / finish …)
99
+ ▼
100
+ MagpieAdapter (registered LlmAdapter)
101
+ │ pi-ai openai-completions stream (default) /
102
+ │ openai-responses stream (responses-only lane)
103
+ ▼
104
+ http://api.lan/v1 ← chat/completions or responses per native_endpoints
105
+ ```
106
+
107
+ - **Catalog** — `GET {baseUrl}/models` 全量接入,无付费过滤;磁盘缓存 + 编译期静态
108
+ 快照兜底,网关宕机时 picker 仍可用。任何暴露集合的变化(隐藏/显示、换网关
109
+ 地址、刷新后模型增删)都会 `emit('llm/adapters-updated')`,让浏览器那份
110
+ catalog 缓存立即重读——否则 picker 会一直显示旧列表到下次重启。
111
+ - **思考档** — `reasoning=true` 且有 ladder 的模型出 picker;无 ladder 但可思考
112
+ 的模型保持 wire 可思考(显式档位直通);`none` 显式关闭思考,`ultra` 直通
113
+ 网关,不在 pi-ai 内截断。
114
+ - **图片** — 有图的请求经 `ctx.get('attachments')` 取 request 版本字节;
115
+ 文本模型误收图时直接失败(harness 按 inputModalities 已做门控)。
116
+ - **韧性** — 启动即注册,目录后台预热(失败按短间隔重试);stall 看门狗让静默
117
+ 挂起快速失败为 `TIMEOUT`;`length` 截断如实上抛,不做自动续写。
118
+
119
+ Health snapshot: `~/.dsh-magpie-connect/adapter-status.json`.
120
+
121
+ ## Development
122
+
123
+ ```sh
124
+ pnpm install
125
+ pnpm run check
126
+ ```
127
+
128
+ The check ladder is typecheck + tests + build; `lib/` is committed, so profile
129
+ installs run without a build.
130
+
131
+ ## License
132
+
133
+ [MIT](./LICENSE)
@@ -0,0 +1,23 @@
1
+ # dsh-magpie-connect DSH plugin — bundle patch: insert the plugin row (deployment-global).
2
+ #
3
+ # The gateway is NOT configured out of the box: set baseUrl on the Settings
4
+ # sidebar page ("Magpie") or via the config object below (see src/config.ts).
5
+ # Until an API root is set the picker stays empty and calls fail fast.
6
+ #
7
+ # The Settings sidebar page can override baseUrl/apiKey at runtime
8
+ # (saved to <dataDir>/settings.json, applied without restart) and hides models
9
+ # from the picker. Page values win per-field; the patch config below stays as
10
+ # fallback (e.g. headless compositions without the settings page).
11
+ #
12
+ # - baseUrl: versioned API root, e.g. http://api.lan/v1 (required). Include the
13
+ # version segment: the plugin appends only the resource (/models, /responses),
14
+ # so a gateway on /v2 or /v3 is reached by changing this one string.
15
+ # - apiKey: gateway credential (required, even if /models needs none).
16
+ # - dataDir: plugin state dir (status snapshot, settings file, catalog cache).
17
+ # - displayName: cosmetic label in the model picker (route id stays providerId).
18
+ # - providerId: RENAME the route id itself (existing sessions pointing at the
19
+ # old id will orphan — prefer displayName for a cosmetic rename).
20
+ - insert:
21
+ - id: dsh-magpie-connect
22
+ name: 'dsh-magpie-connect'
23
+ config: {}
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "dsh-magpie-connect",
3
+ "description": "Magpie LAN gateway models for the DeepSeek Harness web GUI",
4
+ "version": "0.2.0",
5
+ "entry": {
6
+ "name": "dsh-magpie-connect",
7
+ "inject": ["llm"]
8
+ }
9
+ }