@wxip/dsh-sub2api 0.2.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 GodD6366
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,158 @@
1
+ # dsh-sub2api
2
+
3
+ [中文文档](./README.zh.md)
4
+
5
+ Connect your [sub2api](https://github.com/Wei-Shaw/sub2api) gateway to [DeepSeek Harness](https://github.com/deepseek-ai/dsh) as model providers.
6
+
7
+ Sub2API is an AI API gateway that turns subscription quota into OpenAI-compatible endpoints. In its model, **each API key is bound to a group, and the group decides the platform** (OpenAI / Claude / Grok) and the models that key can serve. The three provider routes (`sub2api-openai`, `sub2api-claude`, `sub2api-grok`) are served by the harness's own pi-ai adapter (`dsh-llm-pi-ai`): this plugin translates its `llm-sub2api:` settings into `llm-pi-ai:` provider profiles (all sharing one **bare-host** base URL, no `/v1`), and protocol serialization, streaming, and usage accounting all live in pi-ai. The same gateway serves OpenAI, Claude, and Grok models side by side, and the harness routes each request to the key whose group owns the requested model.
8
+
9
+ ## Features
10
+
11
+ - **Image generation**: select a generation model in settings. `generate_image` saves images to the workspace and returns an inline attachment. The separate image-analysis tool and its model selector have been removed.
12
+
13
+ - **One base URL, three provider routes**: `sub2api-openai`, `sub2api-claude`, `sub2api-grok` — each configured with its own key and at least one model, registered as a live LLM provider as soon as both are set.
14
+ - **Streaming chat (backed by pi-ai)**: SSE streaming, tool calls, reasoning deltas, and token usage are mapped to the harness protocol by `dsh-llm-pi-ai`, which natively handles wire-format details like top-level `function_call` items in the Responses API.
15
+ - **Model discovery**: one-click "fetch models" calls `GET {baseURL}/v1/models` with the key, so each route's catalog matches exactly what the sub2api group serves.
16
+ - **Reasoning effort (thinking mode)**: `reasoning_effort` is passed straight through to the gateway and adjustable right in the chat model selector; the settings page's per-model "reasoning strength" field fills each model's real levels from [models.dev](https://models.dev/) `reasoning_options` (e.g. `gpt-5.6-sol` → none/low/medium/high/xhigh/max, `deepseek-v4-flash` → low/high/max), editable in the settings page; `reasoningEfforts: []` opts a model out.
17
+ - **Usage lookup**: "view usage" calls `GET {baseURL}/v1/usage` and summarizes quota, balance, rate limits, and subscription windows.
18
+ - **Standards-based config**: base URL and model catalogs live in the `llm-sub2api` plugin entry's `config` (`$DSH_HOME/profiles/web/cordis.patch.yml`, written by the web Models page); keys go through the harness credential store.
19
+ - **Provider icons** from [lobehub/lobe-icons](https://lobehub.com/icons), embedded as SVG in the settings page.
20
+
21
+ ## Install
22
+
23
+ Requires DeepSeek Harness **0.2.0-rc.2**. Plugin 0.2.2 uses Loader-owned `Volatile` configuration and the new settings forms API; DSH 0.1.x is outside this release's compatibility range. Settings are persisted in the active profile's `cordis.patch.yml`; the browser UI uses `dsh-client-ui-renderer`.
24
+
25
+ ```bash
26
+ dsh plugin --profile web add @wxip/dsh-sub2api
27
+ ```
28
+
29
+ or, from this repository:
30
+
31
+ ```bash
32
+ dsh plugin --profile web add .
33
+ ```
34
+
35
+ ## Configure
36
+
37
+ Open **Settings → Sub2API 模型** (or edit `$DSH_HOME/profiles/web/cordis.patch.yml` directly):
38
+
39
+ ```yaml
40
+ - id: llm-sub2api
41
+ config:
42
+ baseURL: http://localhost:8080
43
+ providers:
44
+ openai:
45
+ apiKeyEnv: SUB2API_OPENAI_API_KEY
46
+ models:
47
+ - id: gpt-5.6-sol
48
+ claude:
49
+ apiKeyEnv: SUB2API_CLAUDE_API_KEY
50
+ grok:
51
+ apiKeyEnv: SUB2API_GROK_API_KEY
52
+ tools:
53
+ generate:
54
+ provider: openai
55
+ model: gpt-image-1
56
+ ```
57
+
58
+ Store each key through the credentials service (the web Models page writes it, or export `SUB2API_OPENAI_API_KEY=…` etc.). A route activates only when its platform has a key and at least one model; clear the key (or empty the model list) to drop the route again.
59
+
60
+ ### Wire protocol (automatic per group)
61
+
62
+ The gateway serves each platform group upstream through its NATIVE protocol, and pi-ai picks the endpoint automatically from the key's group — no configuration needed. Configure the **bare host** (no `/v1`): OpenAI-style endpoints get `/v1` appended automatically, and the Anthropic SDK appends `/v1/messages` itself:
63
+
64
+ | Group | Protocol used | Endpoint |
65
+ |---|---|---|
66
+ | openai | `openai-responses` | `POST {baseURL}/v1/responses` |
67
+ | claude | `anthropic-messages` | `POST {baseURL}/v1/messages` |
68
+ | grok | `openai-completions` | `POST {baseURL}/v1/chat/completions` |
69
+
70
+ Speaking the native protocol means the gateway never has to convert chat/completions — that conversion is what drops/misaligns tool-call names and ids for parallel calls (`unknown tool ""`, `missing required property …`). To force a different endpoint for a group whose gateway does not serve it natively, declare `api` on the provider in `$DSH_HOME/profiles/web/cordis.patch.yml` (advanced; no settings-page control):
71
+
72
+ ```yaml
73
+ - id: llm-sub2api
74
+ config:
75
+ baseURL: http://localhost:8080
76
+ providers:
77
+ openai:
78
+ apiKeyEnv: SUB2API_OPENAI_API_KEY
79
+ api: openai-completions # optional: openai-completions / openai-responses / anthropic-messages
80
+ models:
81
+ - id: gpt-5.6-sol
82
+ ```
83
+
84
+ `api` accepts `openai-completions` (`/v1/chat/completions`), `openai-responses` (`/v1/responses`), or `anthropic-messages` (`/v1/messages`); omitted means the automatic group default above.
85
+
86
+ ### Relationship to dsh-llm-pi-ai
87
+
88
+ This plugin no longer implements the LLM protocol layer itself: the three `sub2api-*` routes are served by `dsh-llm-pi-ai` (shipped dormant with dsh-base) through the `llm-pi-ai` plugin entry's `providers` configuration. On every `llm-sub2api:` change (and at boot) the plugin translates the bare-host base URL, per-group models, and key references into hand-declared profiles and writes them to the `llm-pi-ai` entry, so routes register/drop live. The settings page, model discovery (`GET /v1/models`), usage lookup (`GET /v1/usage`), the image-generation tool remain this plugin's own.
89
+
90
+ > **Upgrade note**: 0.2.2 no longer patches pi-ai files in the DSH installation at startup. The DSH 0.2.0-rc.2 adapter owns reconstructed message usage. The legacy patch script remains available for manual maintenance of older environments.
91
+
92
+ ### Image input & reasoning effort
93
+
94
+ Attaching an image to the session model requires that model to declare the `image` input modality — otherwise the harness refuses before sending ("model does not support images"). **Both fields are editable in model details**: select image input and enter comma-separated reasoning levels, or disable reasoning. models.dev fills missing values without overriding manual choices:
95
+
96
+ - **Image input**: derived from models.dev `attachment` / `modalities.input` when present (e.g. gpt-5.6-luna → text+image, deepseek-v4-flash → text); otherwise guessed from the model id (`gpt-*`, `claude-*`, `gemini-*`, `grok-*`, `glm-*`, … default to text+image). Pin a model to text-only with `input: [text]` in `$DSH_HOME/profiles/web/cordis.patch.yml`.
97
+ - **Reasoning effort**: derived from models.dev `reasoning_options` when present (e.g. deepseek-v4-flash → high/max); otherwise the default low/medium/high, and models with `reasoning: false` are marked unsupported.
98
+
99
+ When the model accepts images, the request carries the image in the group's native protocol: openai → Responses `input_image`, claude → Messages `image` (base64), grok → chat-completions `image_url`.
100
+
101
+
102
+ ## Development
103
+
104
+ ```bash
105
+ npm install
106
+ npm run build # tsdown → lib/ + client wrapper
107
+ npm run typecheck
108
+ ```
109
+
110
+ ## Publish to npm
111
+
112
+ The package is published as `@wxip/dsh-sub2api` to `https://registry.npmjs.org/`. Sign in with the `wxip` account (or another account with publish access to this package). The account packages page is https://www.npmjs.com/settings/wxip/packages; it is not a registry URL.
113
+
114
+ ```bash
115
+ npm login --registry=https://registry.npmjs.org/
116
+ npm whoami --registry=https://registry.npmjs.org/
117
+ npm run release:npm -- --dry-run
118
+ npm run release:npm
119
+ ```
120
+
121
+ `release:npm` runs typechecking, builds the plugin, runs the tests, and publishes it publicly. `-- --dry-run` performs the same checks and previews the package without uploading it. Publishing uses `--ignore-scripts` because the build has already completed. Each package version can only be published once; update the versions in `package.json` and `package-lock.json` before publishing a new version. For a prerelease, use `npm run release:npm -- --tag next`.
122
+
123
+ This is a manual npm publishing command. The GitHub Release workflow below continues to publish GitHub assets only.
124
+
125
+ ## GitHub Releases
126
+
127
+ Pushing a `v<version>` tag runs `.github/workflows/release.yml`: install locked dependencies, typecheck, build and test, then package the prebuilt plugin and publish a GitHub Release with the `.tgz` and `SHA256SUMS` assets. The tag must match the versions in `package.json` and `package-lock.json`. Versions containing a prerelease identifier, such as `v0.2.3-rc.1`, create prereleases. Reruns update assets on the existing release. The workflow uses GitHub's built-in `GITHUB_TOKEN`; no npm publishing token is required.
128
+
129
+ Commit and push the code and workflow before pushing the tag. This example uses this checkout's `github` remote; substitute the remote for your target repository:
130
+
131
+ ```bash
132
+ git push github HEAD
133
+ git tag v0.2.2
134
+ git push github v0.2.2
135
+ ```
136
+
137
+ To release an existing tag manually, open **Actions → Release → Run workflow** and enter the tag. Manual dispatch requires the workflow on the default branch. The workflow publishes Release assets only, not to npm.
138
+
139
+ Download the `.tgz` from the Release's **Assets**, then install it:
140
+
141
+ ```powershell
142
+ dsh plugin --profile desktop add "C:\Users\admin\Downloads\wxip-dsh-sub2api-0.2.2.tgz"
143
+ ```
144
+
145
+ Replace `desktop` with `web` for the Web profile. The package includes compiled plugin files and does not require permission to run a Git dependency's `prepare` script. GitHub's automatically generated Source code archives are not substitutes for this installation package.
146
+
147
+ To create the same package locally:
148
+
149
+ ```bash
150
+ npm ci --ignore-scripts
151
+ npm run typecheck
152
+ npm test
153
+ npm pack --ignore-scripts
154
+ ```
155
+
156
+ ## License
157
+
158
+ MIT
package/README.zh.md ADDED
@@ -0,0 +1,160 @@
1
+ # dsh-sub2api
2
+
3
+ [English](./README.md)
4
+
5
+ 将你的 [sub2api](https://github.com/Wei-Shaw/sub2api) 网关接入 [DeepSeek Harness](https://github.com/deepseek-ai/dsh),作为模型供应商。
6
+
7
+ sub2api 是一个把订阅配额转成 OpenAI 兼容 API 的网关。它的模型是:**每个 API key 绑定一个分组,分组决定平台**(OpenAI / Claude / Grok)与可用模型。三个供应商路由(`sub2api-openai`、`sub2api-claude`、`sub2api-grok`)由 harness 自带的 pi-ai 适配器(`dsh-llm-pi-ai`)承载:本插件把 `llm-sub2api` 条目的配置翻译成 `llm-pi-ai` 条目的 provider profiles(共享同一个**裸主机** baseURL,不带 `/v1`),协议序列化、流式、用量统计全部由 pi-ai 完成。同一个网关同时提供 OpenAI、Claude、Grok 模型,harness 按 key 所在分组自动路由请求。
8
+
9
+ ## 功能
10
+
11
+ - **一个 baseURL,三个供应商路由**:`sub2api-openai`、`sub2api-claude`、`sub2api-grok`——各自配置独立 key 与至少一个模型,两者就绪后即注册为可用的 LLM 供应商。
12
+ - **流式对话(由 pi-ai 承载)**:SSE 流式、工具调用、reasoning 增量与 token 用量由 `dsh-llm-pi-ai` 映射到 harness 协议,天然正确处理 Responses API 的 `function_call` 顶层条目等 wire format 细节。
13
+ - **模型发现**:一键「获取模型」调用 `GET {baseURL}/v1/models`(携带该 key),每个路由的模型目录与 sub2api 分组实际提供的完全一致。
14
+ - **正式模型参数**:设置页按模型 ID 从 [models.dev](https://models.dev/) 自动补全名称、Context Window 与最大输出长度;匹配不到的字段保持为空,可手动填写。
15
+ - **推理等级(思考模式)**:对话模型选择器可直接调整 `reasoning_effort`(透传网关);设置页「思考强度」字段按 [models.dev](https://models.dev/) 的 `reasoning_options` 逐模型填充真实档位(如 `gpt-5.6-sol` 为 none/low/medium/high/xhigh/max,`deepseek-v4-flash` 为 low/high/max),设置页可编辑展示;可在 cordis.patch.yml 中用 `reasoningEfforts: []` 显式关闭。
16
+ - **用量查询**:「查看用量」调用 `GET {baseURL}/v1/usage`,汇总配额、余额、限流窗口与订阅周期用量。
17
+ - **标准配置**:baseURL 与模型目录存于 `llm-sub2api` 插件条目的 `config`(`$DSH_HOME/profiles/web/cordis.patch.yml`,web 模型页可直接写入);key 走 harness 凭据存储。
18
+ - **供应商图标**来自 [lobehub/lobe-icons](https://lobehub.com/icons),以 SVG 内嵌在设置页中。
19
+
20
+ ## 安装
21
+
22
+ 要求 DeepSeek Harness **0.2.0-rc.2**。插件 0.2.2 使用 Loader 管理的 `Volatile` 配置和新版设置表单接口;0.1.x 不在本版本的兼容范围内。设置保存在当前 profile 的 `cordis.patch.yml`,浏览器界面使用 `dsh-client-ui-renderer` 服务。
23
+
24
+ ```bash
25
+ dsh plugin --profile web add @wxip/dsh-sub2api
26
+ ```
27
+
28
+ 或直接在本仓库目录:
29
+
30
+ ```bash
31
+ dsh plugin --profile web add .
32
+ ```
33
+
34
+ ## 配置
35
+
36
+ 打开 **设置 → Sub2API 模型**(或直接编辑 `$DSH_HOME/profiles/web/cordis.patch.yml`):
37
+
38
+ ```yaml
39
+ - id: llm-sub2api
40
+ config:
41
+ baseURL: http://localhost:8080
42
+ providers:
43
+ openai:
44
+ apiKeyEnv: SUB2API_OPENAI_API_KEY
45
+ models:
46
+ - id: gpt-5.6-sol
47
+ claude:
48
+ apiKeyEnv: SUB2API_CLAUDE_API_KEY
49
+ grok:
50
+ apiKeyEnv: SUB2API_GROK_API_KEY
51
+ tools:
52
+ generate:
53
+ provider: openai
54
+ model: gpt-image-1
55
+ ```
56
+
57
+ 通过凭据服务存储各 key(web 模型页可写入,或导出 `SUB2API_OPENAI_API_KEY=…` 等环境变量)。某平台填了 key 且至少有一个模型后对应路由才激活;清空 key(或清空模型列表)即可移除该路由。
58
+
59
+ ### 网关协议(自动选择)
60
+
61
+ sub2api 网关的每个分组在上游走**原生协议**,pi-ai 按分组自动选择,无需配置。设置里填**裸主机**(不带 `/v1`):OpenAI 风格端点会自动补 `/v1`,Anthropic SDK 会自动补 `/v1/messages`:
62
+
63
+ | 分组 | 自动选择 | 请求端点 |
64
+ |---|---|---|
65
+ | openai | `openai-responses` | `POST {baseURL}/v1/responses` |
66
+ | claude | `anthropic-messages` | `POST {baseURL}/v1/messages` |
67
+ | grok | `openai-completions` | `POST {baseURL}/v1/chat/completions` |
68
+
69
+ 这样网关不需要做 chat/completions ↔ 原生协议转换——并行工具调用正是在这种转换中丢失/错位工具名和 ID,导致 `unknown tool ""`、`missing required property` 报错。如某分组网关实际不走原生协议,可在 cordis.patch.yml 中为该 provider 显式声明 `api`(仅 yaml 层支持,设置页不提供该选项):
70
+
71
+ ```yaml
72
+ - id: llm-sub2api
73
+ config:
74
+ baseURL: http://localhost:8080
75
+ providers:
76
+ openai:
77
+ apiKeyEnv: SUB2API_OPENAI_API_KEY
78
+ api: openai-completions # 可选:openai-completions / openai-responses / anthropic-messages
79
+ models:
80
+ - id: gpt-5.6-sol
81
+ ```
82
+
83
+ `api` 可选值:`openai-completions`(`/v1/chat/completions`)、`openai-responses`(`/v1/responses`)、`anthropic-messages`(`/v1/messages`);省略 = 按上表自动。
84
+
85
+ ### 与 dsh-llm-pi-ai 的关系
86
+
87
+ 本插件不再自己实现 LLM 协议层:三个 `sub2api-*` 路由由 `dsh-llm-pi-ai`(dsh-base 内置、dormant 挂载)通过 `llm-pi-ai` 插件条目的 `providers` 配置承载。插件在每次 `llm-sub2api` 配置变化(及启动)时把裸主机 baseURL、各组模型与 key 引用翻译成 hand-declared profiles 写入 `llm-pi-ai` 条目,路由即时注册 / 撤销。设置页、模型发现(`GET /v1/models`)、用量查询(`GET /v1/usage`)、生图工具仍由本插件提供。
88
+
89
+ > **升级说明**:0.2.2 不再在启动时修改 DSH 安装目录中的 pi-ai 文件。DSH 0.2.0-rc.2 的适配器负责多轮消息的 usage 数据。历史补丁脚本保留用于旧环境的手动维护,不属于新版启动流程。
90
+
91
+ ### 图片输入 / 思考强度
92
+
93
+ 模型详情支持手动选择图片输入和填写思考档位(逗号分隔)。补全数据保留手动设置。独立识图工具及其模型选择项已移除;生图模型仍可配置。
94
+
95
+
96
+ 会话中直接给模型挂图,需要模型声明 `image` 输入模态(否则 harness 在发送前拒绝,提示"当前模型不支持图片")。**这两个字段可以在模型详情里手动设置**;models.dev 仅用于补全未填写的值:
97
+
98
+ - **图片输入**:models.dev 的 `attachment` / `modalities.input` 有数据就自动定(如 gpt-5.6-luna → 文本+图片,deepseek-v4-flash → 仅文本);没数据时按模型 ID 推断(`gpt-*` / `claude-*` / `gemini-*` / `grok-*` / `glm-*` 等默认支持图片),可手动在 cordis.patch.yml 写 `input: [text]` 强制仅文本。
99
+ - **思考强度**:models.dev 的 `reasoning_options` 有数据就自动填真实档位(如 deepseek-v4-flash → high/max);否则默认 low/medium/high,`reasoning: false` 的模型自动标为不支持。
100
+
101
+ 挂图后请求按分组原生协议携带图片:openai → Responses `input_image`,claude → Messages `image`(base64),grok → chat/completions `image_url`。
102
+
103
+
104
+ ## 开发
105
+
106
+ ```bash
107
+ npm install
108
+ npm run build # tsdown → lib/ + client wrapper
109
+ npm run typecheck
110
+ ```
111
+
112
+ ## 发布到 npm
113
+
114
+ 包名为 `@wxip/dsh-sub2api`,发布地址为 `https://registry.npmjs.org/`。使用 `wxip` 账号(或拥有该包发布权限的其他账号)登录。账号包管理页面为 https://www.npmjs.com/settings/wxip/packages,该页面不是 registry 地址。
115
+
116
+ ```bash
117
+ npm login --registry=https://registry.npmjs.org/
118
+ npm whoami --registry=https://registry.npmjs.org/
119
+ npm run release:npm -- --dry-run
120
+ npm run release:npm
121
+ ```
122
+
123
+ `release:npm` 会先执行类型检查、构建插件和运行测试,然后公开发布到 npm。追加 `-- --dry-run` 会执行相同检查并预览安装包,不上传到 npm。发布使用 `--ignore-scripts`,因为构建已经完成。同一包版本只能发布一次;发布新版本前请同步更新 `package.json` 和 `package-lock.json` 中的版本号。预发布版本使用 `npm run release:npm -- --tag next`。
124
+
125
+ 这是手动 npm 发布命令;下面的 GitHub Release 工作流仍只发布 GitHub 附件。
126
+
127
+ ## 发布到 GitHub Release
128
+
129
+ 推送 `v<版本号>` 标签后,`.github/workflows/release.yml` 自动安装锁定依赖、执行类型检查和测试、生成 npm 安装包,再创建 GitHub Release 并上传 `.tgz` 和 `SHA256SUMS`。标签必须与 `package.json` 和 `package-lock.json` 的版本一致;含预发布标识的版本(如 `v0.2.3-rc.1`)自动标记为 prerelease。重复运行时会更新已有 Release 的同名附件。工作流使用 GitHub 自带的 `GITHUB_TOKEN`,无需 npm 发布令牌。
130
+
131
+ 先提交并推送代码及工作流,再推送标签。以下示例发布到本仓库的 `github` remote;发布到其他仓库时替换 remote 名称:
132
+
133
+ ```bash
134
+ git push github HEAD
135
+ git tag v0.2.2
136
+ git push github v0.2.2
137
+ ```
138
+
139
+ 也可以在 GitHub 的 **Actions → Release → Run workflow** 中输入已有标签手动发布;手动触发需要工作流已存在于默认分支。工作流只发布 Release 附件,不发布到 npm。
140
+
141
+ 从 Release 的 **Assets** 下载 `.tgz` 安装包,再执行:
142
+
143
+ ```powershell
144
+ dsh plugin --profile desktop add "C:\Users\admin\Downloads\wxip-dsh-sub2api-0.2.2.tgz"
145
+ ```
146
+
147
+ Web profile 将 `desktop` 替换为 `web`。`.tgz` 包含已构建的插件文件,安装时无需 Git 来源的 `prepare` 构建许可;GitHub 自动生成的 Source code 压缩包不能替代该安装包。
148
+
149
+ 本地生成同样的安装包:
150
+
151
+ ```bash
152
+ npm ci --ignore-scripts
153
+ npm run typecheck
154
+ npm test
155
+ npm pack --ignore-scripts
156
+ ```
157
+
158
+ ## 许可证
159
+
160
+ MIT
@@ -0,0 +1 @@
1
+ <svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Claude</title><path d="M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z"></path></svg>
@@ -0,0 +1 @@
1
+ <svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Grok</title><path d="M9.27 15.29l7.978-5.897c.391-.29.95-.177 1.137.272.98 2.369.542 5.215-1.41 7.169-1.951 1.954-4.667 2.382-7.149 1.406l-2.711 1.257c3.889 2.661 8.611 2.003 11.562-.953 2.341-2.344 3.066-5.539 2.388-8.42l.006.007c-.983-4.232.242-5.924 2.75-9.383.06-.082.12-.164.179-.248l-3.301 3.305v-.01L9.267 15.292M7.623 16.723c-2.792-2.67-2.31-6.801.071-9.184 1.761-1.763 4.647-2.483 7.166-1.425l2.705-1.25a7.808 7.808 0 00-1.829-1A8.975 8.975 0 005.984 5.83c-2.533 2.536-3.33 6.436-1.962 9.764 1.022 2.487-.653 4.246-2.34 6.022-.599.63-1.199 1.259-1.682 1.925l7.62-6.815"></path></svg>
@@ -0,0 +1 @@
1
+ <svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>OpenAI</title><path d="M9.205 8.658v-2.26c0-.19.072-.333.238-.428l4.543-2.616c.619-.357 1.356-.523 2.117-.523 2.854 0 4.662 2.212 4.662 4.566 0 .167 0 .357-.024.547l-4.71-2.759a.797.797 0 00-.856 0l-5.97 3.473zm10.609 8.8V12.06c0-.333-.143-.57-.429-.737l-5.97-3.473 1.95-1.118a.433.433 0 01.476 0l4.543 2.617c1.309.76 2.189 2.378 2.189 3.948 0 1.808-1.07 3.473-2.76 4.163zM7.802 12.703l-1.95-1.142c-.167-.095-.239-.238-.239-.428V5.899c0-2.545 1.95-4.472 4.591-4.472 1 0 1.927.333 2.712.928L8.23 5.067c-.285.166-.428.404-.428.737v6.898zM12 15.128l-2.795-1.57v-3.33L12 8.658l2.795 1.57v3.33L12 15.128zm1.796 7.23c-1 0-1.927-.332-2.712-.927l4.686-2.712c.285-.166.428-.404.428-.737v-6.898l1.974 1.142c.167.095.238.238.238.428v5.233c0 2.545-1.974 4.472-4.614 4.472zm-5.637-5.303l-4.544-2.617c-1.308-.761-2.188-2.378-2.188-3.948A4.482 4.482 0 014.21 6.327v5.423c0 .333.143.571.428.738l5.947 3.449-1.95 1.118a.432.432 0 01-.476 0zm-.262 3.9c-2.688 0-4.662-2.021-4.662-4.519 0-.19.024-.38.047-.57l4.686 2.71c.286.167.571.167.856 0l5.97-3.448v2.26c0 .19-.07.333-.237.428l-4.543 2.616c-.619.357-1.356.523-2.117.523zm5.899 2.83a5.947 5.947 0 005.827-4.756C22.287 18.339 24 15.84 24 13.296c0-1.665-.713-3.282-1.998-4.448.119-.5.19-.999.19-1.498 0-3.401-2.759-5.947-5.946-5.947-.642 0-1.26.095-1.88.31A5.962 5.962 0 0010.205 0a5.947 5.947 0 00-5.827 4.757C1.713 5.447 0 7.945 0 10.49c0 1.666.713 3.283 1.998 4.448-.119.5-.19 1-.19 1.499 0 3.401 2.759 5.946 5.946 5.946.642 0 1.26-.095 1.88-.309a5.96 5.96 0 004.162 1.713z"></path></svg>
@@ -0,0 +1,11 @@
1
+ # Sub2API routes for the harness LLM seam.
2
+ # One base URL, per-key provider routes. Keys are configured through the
3
+ # `llm-sub2api` entry config (the web settings page writes it, or edit
4
+ # the active profile cordis.patch.yml); the adapter registers a route per
5
+ # configured key and drops dormant routes when a key is cleared.
6
+ #
7
+ # Does not override agent-default-model.
8
+
9
+ - insert:
10
+ - id: llm-sub2api
11
+ name: '@wxip/dsh-sub2api'