dsh-vision-router 1.0.0 → 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/README.md CHANGED
@@ -28,7 +28,7 @@
28
28
 
29
29
  Most DSH vision plugins bridge images to DeepSeek as *text descriptions* — lossy, one-shot, and blind to pixels. This plugin keeps the **original pixels on the vision model's side** and DeepSeek on the reasoning side, and makes looking at an image an **ordinary tool call**:
30
30
 
31
- - **One command install.** The package ships its own composition patch (`dsh.bundle.patch`): `dsh plugin add` wires the row, the admission wrapper, the stealth takeover and the attachment limits automatically — zero manual file edits.
31
+ - **One command install, purely additive.** The package ships its own composition patch (`dsh.bundle.patch`): `dsh plugin add` mounts the plugin row and nothing else — no core row is disabled or overridden (issue #34).
32
32
  - **Free by default.** The vision chain starts with a built-in OVHcloud anonymous endpoint (`Qwen2.5-VL-72B-Instruct`, no account, no key, 2 req/min per IP). Paid chains (OpenRouter, Pi-AI providers, direct OpenAI-compatible endpoints) are optional upgrades.
33
33
  - **No Python.** The whole pipeline — downscale, grounding, crop, pixel diff, palette, OCR, SVG trace, cutout, HTML screenshot — runs on sharp / potrace / tesseract / system Chrome.
34
34
  - **Continuous multi-step image work.** An image turn is a text turn that calls tools: `vision_ground` → `vision_crop` → `vision_describe` → `vision_pixel_diff` → fix → screenshot again. The agent keeps iterating until the work is done.
@@ -37,30 +37,29 @@ Most DSH vision plugins bridge images to DeepSeek as *text descriptions* — los
37
37
 
38
38
  ## How it compares
39
39
 
40
- The closest alternative is [@anionex/dsh-vision-toolkit](https://github.com/Anionex/dsh-vision-toolkit) (Anionex), a native DSH bundle of the well-known `agent-vision-toolkit` lineage. Both packages ship a `vision-tools` skill and a family of pixel-level tools; they differ in philosophy — **zero-config paste-and-go** versus **agent-driven visual engineering**:
40
+ Most DSH vision plugins feed DeepSeek a *text description* of the image. This plugin keeps the **original pixels on the vision model's side**, ships a **built-in free chain**, and treats looking at an image as an **ordinary tool call** — paste it and it just works, multi-step until done.
41
41
 
42
- | | dsh-vision-router | @anionex/dsh-vision-toolkit |
43
- |---|---|---|
44
- | Image Q&A out of the box | ✅ Built-in free chain (anonymous OVHcloud endpoint) — no account, no key | Requires your own vision API key (local pixel tools work without one) |
45
- | Runtime | ✅ Node only — no Python | Python 3.11+ managed runtime |
46
- | Getting an image in | ✅ Paste it — the turn auto-routes to the vision chain and auto-mounts the tools | Workspace path + `/vision-tools` command, then explicit tool calls |
47
- | Turn routing | ✅ Image turns switch to vision, text turns switch back to DeepSeek — stealth takeover, the model picker looks stock | Tool-driven; no whole-turn auto-routing |
48
- | Profiles | Web | Web + Headless |
49
- | Playbooks | The pixel loop: ground → crop → diff → fix → screenshot again | Richer case library (long-screenshot OCR, UI restoration, GUI automation) |
50
- | Tests | 86 | 162 |
51
- | Install | One command | One command (npm) |
42
+ | | Manual model switching | Description bridges (dsh-vision-sidecar · dsh-vision-proxy · dsh-vision · dsh-tool-vision) | @anionex/dsh-vision-toolkit | modlens | dsh-vision-router |
43
+ |---|---|---|---|---|---|
44
+ | Works out of the box, no key | ❌ | partial | ❌ remote tools need your own key | ❌ needs your own key | ✅ built-in keyless vision chain |
45
+ | Original-pixel fidelity | ✅ after manual switching | ❌ text description only | ✅ | ✅ structured evidence | ✅ original pixels + pixel tools |
46
+ | No per-turn manual switching | ❌ | ✅ | ✅ | ✅ | ✅ auto tool mounting + stealth routing |
47
+ | Daily model untouched | ❌ session swapped | ✅ | ✅ | ✅ | ✅ DeepSeek stays the brain |
48
+ | Multi-provider fallback with classified errors | ❌ | ❌ | partial | — | ✅ chain + 429 backoff + downscale |
49
+ | No Python runtime | ✅ | ✅ | ❌ Python 3.11+ | ✅ | ✅ Node only |
50
+ | One-command install | — | — | ✅ | ✅ | ✅ bundle patch, zero file edits |
52
51
 
53
- Both are MIT-licensed and one command away. Pick this plugin when you want images to *just work* with zero setup; pick theirs when you need headless profiles or the extended playbook library. (Feature comparison reflects their README as of 2026-08.)
52
+ Want the pixel loop instead? All five routes converge on the same `vision_*` tool family — grounding, crop, pixel diff, colors, OCR, SVG trace, cutout, screenshots — so you can mix and match as you like.
54
53
 
55
54
  ## Quick start
56
55
 
57
56
  ```sh
58
- dsh plugin --profile web add github:ysr666/dsh-vision-router
57
+ dsh plugin --profile web add dsh-vision-router
59
58
  ```
60
59
 
61
60
  Restart `dsh web` — done. Zero configuration:
62
61
 
63
- - the plugin's bundle patch mounts the row, takes over the official DeepSeek route (stealth mode — the model picker looks exactly like stock), and relaxes attachment limits to 20 MB / 100 MP;
62
+ - the plugin's bundle patch mounts the row only: the official DeepSeek route stays untouched, and image turns use the "自动识图" wrapper entry in the picker (or the extra wrappers you configure);
64
63
  - the default vision chain is the built-in free endpoint;
65
64
  - every setting is editable live in **Settings → Plugins → Plugin config → 视觉路由(自动识图)**.
66
65
 
@@ -152,16 +151,15 @@ Failures are classified (region / tos / quota / rate-limit / context / network)
152
151
 
153
152
  ## Stealth mode
154
153
 
155
- A default install takes over the official `deepseek-official` route: the model picker looks exactly like stock (same DeepSeek group, same model names), but each entry is the auto-vision wrapper that declares image input and delegates text turns to a rebuilt native DeepSeek adapter (same `llm-deepseek` settings section and credentials). Old sessions keep working through the hidden `deepseek-vision` alias.
156
-
157
- To keep the stock row instead, override it in your profile patch layer (`~/.dsh/profiles/<profile>/cordis.patch.yml`):
154
+ **Stealth mode is opt-in.** The plugin never disables the official `llm-deepseek` row by itself (issue #34). To take over the official `deepseek-official` route — the model picker looks exactly like stock, but each entry is the auto-vision wrapper that declares image input and delegates text turns to a rebuilt native DeepSeek adapter — add the disable to YOUR profile patch layer:
158
155
 
159
156
  ```yaml
160
157
  - id: llm-deepseek
161
158
  name: '@deepseek-ai/dsh-llm-deepseek'
159
+ disabled: true
162
160
  ```
163
161
 
164
- With the stock row present, the plugin falls back to the visible "DeepSeek + 自动识图" wrapper entry — pick it in the model picker for image turns. Recovery from a broken install is the same one-line override.
162
+ Without the takeover, the plugin registers the visible "DeepSeek + 自动识图" (`deepseek-vision`) wrapper entry — pick it in the model picker for image turns; for third-party text routes, add them to the settings card's **extra vision wrappers**. Recovery from a broken install is the same one-line override (delete the `disabled` line).
165
163
 
166
164
  ## Web settings
167
165
 
@@ -214,7 +212,7 @@ Everything is optional; defaults work out of the box. Edit via the Web card or a
214
212
  ### Install
215
213
 
216
214
  ```sh
217
- dsh plugin --profile web add github:ysr666/dsh-vision-router
215
+ dsh plugin --profile web add dsh-vision-router
218
216
  dsh --profile web --dump-config | grep vision-router # one row, mounted by the bundle patch
219
217
  ```
220
218
 
package/README.zh.md CHANGED
@@ -28,7 +28,7 @@
28
28
 
29
29
  大多数 DSH 视觉插件把图片“翻译”成一段文字描述再喂给 DeepSeek——有损、一次性、看不见像素。本插件把**原图像素留在视觉模型侧**、把推理留在 DeepSeek 侧,并把“看图”变成一次**普通的工具调用**:
30
30
 
31
- - **一条命令安装。** 包自带组合补丁(`dsh.bundle.patch`):`dsh plugin add` 自动完成插件行挂载、准入包装、隐身接管与附件限制放宽——不用手改任何文件。
31
+ - **一条命令安装,纯增量。** 包自带组合补丁(`dsh.bundle.patch`):`dsh plugin add` 只挂载插件行,不禁用、不覆写任何核心行(issue #34)。
32
32
  - **默认免费。** 视觉链内置 OVHcloud 匿名端点(`Qwen2.5-VL-72B-Instruct`,免注册、免 Key,每 IP 2 次/分钟)。付费链路(OpenRouter、Pi-AI 供应商、任意 OpenAI 兼容直连端点)是可选升级。
33
33
  - **无 Python。** 整条管线——缩放、定位、裁剪、像素对比、取色、OCR、SVG 矢量化、抠图、HTML 截图——全部基于 sharp / potrace / tesseract / 系统 Chrome。
34
34
  - **可连续多步看图。** 图片轮 = 调用工具的文本轮:`vision_ground` → `vision_crop` → `vision_describe` → `vision_pixel_diff` → 修复 → 再截图,Agent 可以一直迭代到任务完成。
@@ -37,30 +37,29 @@
37
37
 
38
38
  ## 对比同类插件
39
39
 
40
- 最接近的同类是 [@anionex/dsh-vision-toolkit](https://github.com/Anionex/dsh-vision-toolkit)(Anionex),它是知名 `agent-vision-toolkit` 系列的 DSH 原生版。两者都提供 `vision-tools` 技能和一组像素级工具,区别在理念:**零配置粘贴即用** vs **Agent 主导的视觉工程**:
40
+ 大多数 DSH 视觉插件是把图片转成**文字描述**再喂给 DeepSeek。本插件让视觉模型**直接读原图像素**,内置**免费视觉链**,并把看图变成一次**普通工具调用**——粘贴图片即可用,可连续多步做到完成为止。
41
41
 
42
- | | dsh-vision-router | @anionex/dsh-vision-toolkit |
43
- |---|---|---|
44
- | 开箱图片问答 | ✅ 内置免费视觉链(OVHcloud 匿名端点),免注册免 Key | 远程工具需自备视觉 API Key(本地像素工具免 Key) |
45
- | 运行时 | ✅ 纯 Node,无需 Python | 需要 Python 3.11+ 受管运行时 |
46
- | 图片怎么进来 | ✅ 直接粘贴——轮次自动切视觉链并自动挂载工具 | 工作区路径 + `/vision-tools` 命令,再显式调用工具 |
47
- | 轮次路由 | ✅ 图片轮切视觉、文本轮切回 DeepSeek——隐身接管,模型选择器与官方一致 | 工具驱动,无整轮自动路由 |
48
- | 支持 profile | Web | Web + Headless |
49
- | 玩法库 | 像素循环:定位 → 裁剪 → 对比 → 修复 → 再截图 | 更丰富的案例库(长截图 OCR、UI 还原、GUI 自动化) |
50
- | 测试 | 86 | 162 |
51
- | 安装 | 一条命令 | 一条命令(npm) |
42
+ | | 手动切换模型 | 描述桥(dsh-vision-sidecar · dsh-vision-proxy · dsh-vision · dsh-tool-vision) | @anionex/dsh-vision-toolkit | modlens | dsh-vision-router |
43
+ |---|---|---|---|---|---|
44
+ | 开箱即用、免 Key | ❌ | 部分 | ❌ 远程工具需自备 Key | ❌ 需自备 Key | ✅ 内置免 Key 视觉链 |
45
+ | 原图像素保真 | ✅ 切换后 | ❌ 只有文字描述 | ✅ | ✅ 结构化证据 | ✅ 原图像素 + 像素工具 |
46
+ | 免手动逐轮切换 | ❌ | ✅ | ✅ | ✅ | ✅ 自动挂载工具 + 隐身路由 |
47
+ | 日常模型不受影响 | ❌ 整会话切换 | ✅ | ✅ | ✅ | ✅ DeepSeek 始终是大脑 |
48
+ | 多供应商降级 + 分类报错 | ❌ | ❌ | 部分 | — | ✅ 降级链 + 429 退避 + 自动压缩 |
49
+ | 无需 Python | ✅ | ✅ | ❌ Python 3.11+ | ✅ | ✅ 纯 Node |
50
+ | 一条命令安装 | — | — | ✅ | ✅ | ✅ bundle 补丁零手改 |
52
51
 
53
- 两者都是 MIT 许可、一条命令安装。想要图片**粘贴即用**、零配置就选本插件;需要 Headless 部署或更丰富的案例库,可以看 @anionex/dsh-vision-toolkit。(功能对比以其 README 2026-08 状态为准。)
52
+ 想要像素闭环?五条路线最终都落在同一套 `vision_*` 工具族上——定位、裁剪、像素对比、取色、OCR、矢量化、抠图、截图——按需混用即可。
54
53
 
55
54
  ## 快速开始
56
55
 
57
56
  ```sh
58
- dsh plugin --profile web add github:ysr666/dsh-vision-router
57
+ dsh plugin --profile web add dsh-vision-router
59
58
  ```
60
59
 
61
60
  重启 `dsh web`——完成,零配置:
62
61
 
63
- - 插件的 bundle 补丁自动挂载插件行、接管官方 DeepSeek 路由(隐身模式——模型选择器看起来和原版一模一样)、放宽附件限制到 20MB / 1 亿像素;
62
+ - 插件的 bundle 补丁只挂载插件行:官方 DeepSeek 路由保持原样,图片入口使用选择器里的「自动识图」包装条目(或你在设置里配置的额外包装);
64
63
  - 默认视觉链就是内置免费端点;
65
64
  - 全部配置可在 **设置 → 插件 → 插件配置 → 视觉路由(自动识图)** 实时修改。
66
65
 
@@ -152,16 +151,15 @@ vision_html_screenshot source="page.html" width=1200 height=720
152
151
 
153
152
  ## 隐身模式
154
153
 
155
- 默认安装即接管官方 `deepseek-official` 路由:模型选择器看起来和原版完全一样(同一个 DeepSeek 组、同样的模型名),但每个条目背后都是声明了图片输入的自动识图包装;文字轮交给插件重建的原生 DeepSeek 适配器(读取同一个 `llm-deepseek` 设置段与凭据)。老会话通过隐藏的 `deepseek-vision` 别名继续工作。
156
-
157
- 想保留官方行,在你的 profile 补丁层(`~/.dsh/profiles/<profile>/cordis.patch.yml`)覆写即可:
154
+ **隐身模式改为显式可选。** 插件永远不会自己禁用官方 `llm-deepseek` 行(issue #34)。想接管官方 `deepseek-official` 路由——模型选择器看起来和原版完全一样,但每个条目背后都是声明了图片输入的自动识图包装,文字轮交给插件重建的原生 DeepSeek 适配器——在你自己的 profile 补丁层加上:
158
155
 
159
156
  ```yaml
160
157
  - id: llm-deepseek
161
158
  name: '@deepseek-ai/dsh-llm-deepseek'
159
+ disabled: true
162
160
  ```
163
161
 
164
- 官方行在场时,插件回退为选择器里可见的「DeepSeek + 自动识图」包装入口——发图前选它即可。安装出问题时同样用这一行恢复。
162
+ 不接管时,插件注册选择器里可见的「DeepSeek + 自动识图」(`deepseek-vision`)包装入口——发图前选它即可;第三方文本路由则在设置卡片的「额外识图包装」里添加。安装出问题时删掉 `disabled` 行即可恢复。
165
163
 
166
164
  ## Web 设置
167
165
 
@@ -214,7 +212,7 @@ Web 配置页在 **设置 → 插件 → 插件配置** 下注册「视觉路由
214
212
  ### 安装
215
213
 
216
214
  ```sh
217
- dsh plugin --profile web add github:ysr666/dsh-vision-router
215
+ dsh plugin --profile web add dsh-vision-router
218
216
  dsh --profile web --dump-config | grep vision-router # 一行,由 bundle 补丁挂载
219
217
  ```
220
218
 
@@ -1,41 +1,209 @@
1
1
  <svg xmlns="http://www.w3.org/2000/svg" width="1600" height="640" viewBox="0 0 1600 640">
2
2
  <defs>
3
- <linearGradient id="bg" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#070914"/><stop offset="0.52" stop-color="#0A0D1B"/><stop offset="1" stop-color="#080A13"/></linearGradient>
4
- <radialGradient id="violetGlow" cx="73%" cy="49%" r="42%"><stop offset="0" stop-color="#715CFF" stop-opacity=".23"/><stop offset=".45" stop-color="#604CFF" stop-opacity=".08"/><stop offset="1" stop-color="#604CFF" stop-opacity="0"/></radialGradient>
5
- <radialGradient id="cyanGlow" cx="82%" cy="46%" r="28%"><stop offset="0" stop-color="#46D8FF" stop-opacity=".15"/><stop offset="1" stop-color="#46D8FF" stop-opacity="0"/></radialGradient>
6
- <linearGradient id="iris" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#8D7BFF"/><stop offset=".5" stop-color="#6256FF"/><stop offset="1" stop-color="#36C8FF"/></linearGradient>
7
- <linearGradient id="route" x1="0" y1="0" x2="1" y2="0"><stop offset="0" stop-color="#695BFF"/><stop offset=".55" stop-color="#7B6DFF"/><stop offset="1" stop-color="#42D8FF"/></linearGradient>
8
- <linearGradient id="chip" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#171B2C" stop-opacity=".95"/><stop offset="1" stop-color="#0D1020" stop-opacity=".95"/></linearGradient>
9
- <filter id="glow"><feGaussianBlur stdDeviation="5" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
10
- <filter id="softGlow"><feGaussianBlur stdDeviation="12" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
11
- <pattern id="dots" width="34" height="34" patternUnits="userSpaceOnUse"><circle cx="1.4" cy="1.4" r="1.35" fill="#65708A" opacity=".12"/></pattern>
3
+ <linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
4
+ <stop offset="0" stop-color="#070914"/>
5
+ <stop offset="0.52" stop-color="#0A0D1B"/>
6
+ <stop offset="1" stop-color="#080A13"/>
7
+ </linearGradient>
8
+
9
+ <radialGradient id="violetGlow" cx="73%" cy="49%" r="42%">
10
+ <stop offset="0" stop-color="#715CFF" stop-opacity=".23"/>
11
+ <stop offset=".45" stop-color="#604CFF" stop-opacity=".08"/>
12
+ <stop offset="1" stop-color="#604CFF" stop-opacity="0"/>
13
+ </radialGradient>
14
+
15
+ <radialGradient id="cyanGlow" cx="82%" cy="46%" r="28%">
16
+ <stop offset="0" stop-color="#46D8FF" stop-opacity=".15"/>
17
+ <stop offset="1" stop-color="#46D8FF" stop-opacity="0"/>
18
+ </radialGradient>
19
+
20
+ <linearGradient id="iris" x1="0" y1="0" x2="1" y2="1">
21
+ <stop offset="0" stop-color="#8D7BFF"/>
22
+ <stop offset=".5" stop-color="#6256FF"/>
23
+ <stop offset="1" stop-color="#36C8FF"/>
24
+ </linearGradient>
25
+
26
+ <linearGradient id="route" x1="0" y1="0" x2="1" y2="0">
27
+ <stop offset="0" stop-color="#695BFF"/>
28
+ <stop offset=".55" stop-color="#7B6DFF"/>
29
+ <stop offset="1" stop-color="#42D8FF"/>
30
+ </linearGradient>
31
+
32
+ <linearGradient id="chip" x1="0" y1="0" x2="0" y2="1">
33
+ <stop offset="0" stop-color="#171B2C" stop-opacity=".95"/>
34
+ <stop offset="1" stop-color="#0D1020" stop-opacity=".95"/>
35
+ </linearGradient>
36
+
37
+ <filter id="blur40"><feGaussianBlur stdDeviation="40"/></filter>
38
+ <filter id="glow">
39
+ <feGaussianBlur stdDeviation="5" result="b"/>
40
+ <feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
41
+ </filter>
42
+ <filter id="softGlow">
43
+ <feGaussianBlur stdDeviation="12" result="b"/>
44
+ <feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
45
+ </filter>
46
+
47
+ <pattern id="dots" width="34" height="34" patternUnits="userSpaceOnUse">
48
+ <circle cx="1.4" cy="1.4" r="1.35" fill="#65708A" opacity=".12"/>
49
+ </pattern>
12
50
  </defs>
13
- <rect width="1600" height="640" rx="32" fill="url(#bg)"/><rect width="1600" height="640" rx="32" fill="url(#dots)" opacity=".45"/><rect width="1600" height="640" rx="32" fill="url(#violetGlow)"/><rect width="1600" height="640" rx="32" fill="url(#cyanGlow)"/>
14
- <path d="M790 70 C980 15 1240 42 1515 180" fill="none" stroke="#8D7BFF" stroke-opacity=".08"/><path d="M780 575 C1020 620 1300 585 1510 425" fill="none" stroke="#47CFFF" stroke-opacity=".08"/><path d="M925 36 C1120 160 1380 132 1565 250" fill="none" stroke="#FFFFFF" stroke-opacity=".035"/>
51
+
52
+ <!-- Background -->
53
+ <rect width="1600" height="640" rx="32" fill="url(#bg)"/>
54
+ <rect width="1600" height="640" rx="32" fill="url(#dots)" opacity=".45"/>
55
+ <rect width="1600" height="640" rx="32" fill="url(#violetGlow)"/>
56
+ <rect width="1600" height="640" rx="32" fill="url(#cyanGlow)"/>
57
+
58
+ <!-- ambient curves -->
59
+ <path d="M790 70 C980 15 1240 42 1515 180" fill="none" stroke="#8D7BFF" stroke-opacity=".08" stroke-width="1"/>
60
+ <path d="M780 575 C1020 620 1300 585 1510 425" fill="none" stroke="#47CFFF" stroke-opacity=".08" stroke-width="1"/>
61
+ <path d="M925 36 C1120 160 1380 132 1565 250" fill="none" stroke="#FFFFFF" stroke-opacity=".035" stroke-width="1"/>
62
+
63
+ <!-- LEFT COPY -->
15
64
  <g transform="translate(92,86)">
16
- <g><rect x="0" y="0" width="224" height="34" rx="17" fill="#111528" stroke="#7568FF" stroke-opacity=".42"/><circle cx="19" cy="17" r="4" fill="#6A5BFF" filter="url(#glow)"/><text x="33" y="22" fill="#BFB8FF" font-family="Inter, Arial, sans-serif" font-size="14" font-weight="700" letter-spacing="1.7">DEEPSEEK HARNESS</text></g>
65
+ <g>
66
+ <rect x="0" y="0" width="224" height="34" rx="17" fill="#111528" stroke="#7568FF" stroke-opacity=".42"/>
67
+ <circle cx="19" cy="17" r="4" fill="#6A5BFF" filter="url(#glow)"/>
68
+ <text x="33" y="22" fill="#BFB8FF" font-family="Inter, Arial, sans-serif" font-size="14" font-weight="700" letter-spacing="1.7">DEEPSEEK HARNESS</text>
69
+ </g>
70
+
17
71
  <text x="0" y="101" fill="#F7F8FF" font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif" font-size="68" font-weight="800" letter-spacing="-2.2">DSH 视觉</text>
18
72
  <text x="0" y="176" fill="url(#iris)" font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif" font-size="70" font-weight="800" letter-spacing="-2.2">路由器</text>
19
- <text x="2" y="228" fill="#C7CCDB" font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif" font-size="24">给 DeepSeek 一双眼,而不是换一个大脑。</text>
20
- <text x="2" y="277" fill="#7F889F" font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif" font-size="16.5">内置免费视觉链 · 自动故障切换 · 像素级工具</text>
21
- <text x="2" y="306" fill="#7F889F" font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif" font-size="16.5">一条命令安装 · 无需注册 · 无需 API Key · 无需 Python</text>
22
- <g transform="translate(0,355)" fill="#CFD5E6" font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif" font-size="14" font-weight="650">
23
- <g><rect width="132" height="39" rx="12" fill="#111526" stroke="#252B42"/><circle cx="18" cy="19.5" r="4" fill="#50D890"/><text x="31" y="25">免费链路</text></g>
24
- <g transform="translate(145,0)"><rect width="132" height="39" rx="12" fill="#111526" stroke="#252B42"/><circle cx="18" cy="19.5" r="4" fill="#7B6DFF"/><text x="31" y="25">自动路由</text></g>
25
- <g transform="translate(290,0)"><rect width="132" height="39" rx="12" fill="#111526" stroke="#252B42"/><circle cx="18" cy="19.5" r="4" fill="#4CD5FF"/><text x="31" y="25">像素循环</text></g>
26
- </g>
27
- <g transform="translate(2,438)"><path d="M0 0 H422" stroke="#252A3C"/><text x="0" y="38" fill="#666F85" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" font-size="14">github.com/ysr666/dsh-vision-router</text></g>
73
+
74
+ <text x="2" y="230" fill="#F2F5FF" font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif" font-size="31" font-weight="700">粘贴图片,直接就能用。</text>
75
+
76
+ <text x="2" y="270" fill="#C7CCDB" font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif" font-size="19" font-weight="500">DeepSeek 继续思考,Vision Router 负责看。</text>
77
+
78
+ <text x="2" y="304" fill="#7F889F" font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif" font-size="16.8" font-weight="500">内置免费视觉 · 无需 API Key · 无需 Python · 自动路由</text>
79
+
80
+ <!-- feature chips -->
81
+ <g transform="translate(0,355)">
82
+ <g>
83
+ <rect x="0" y="0" width="116" height="39" rx="12" fill="#111526" stroke="#252B42"/>
84
+ <circle cx="18" cy="19.5" r="4" fill="#50D890"/>
85
+ <text x="31" y="25" fill="#CFD5E6" font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif" font-size="14" font-weight="650">无需 Key</text>
86
+ </g>
87
+ <g transform="translate(129,0)">
88
+ <rect x="0" y="0" width="132" height="39" rx="12" fill="#111526" stroke="#252B42"/>
89
+ <circle cx="18" cy="19.5" r="4" fill="#7B6DFF"/>
90
+ <text x="31" y="25" fill="#CFD5E6" font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif" font-size="14" font-weight="650">自动路由</text>
91
+ </g>
92
+ <g transform="translate(274,0)">
93
+ <rect x="0" y="0" width="132" height="39" rx="12" fill="#111526" stroke="#252B42"/>
94
+ <circle cx="18" cy="19.5" r="4" fill="#4CD5FF"/>
95
+ <text x="31" y="25" fill="#CFD5E6" font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif" font-size="14" font-weight="650">像素循环</text>
96
+ </g>
97
+ </g>
98
+
99
+ <g transform="translate(2,438)">
100
+ <path d="M0 0 H422" stroke="#252A3C"/>
101
+ <text x="0" y="38" fill="#666F85" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" font-size="14">github.com/ysr666/dsh-vision-router</text>
102
+ </g>
28
103
  </g>
104
+
105
+ <!-- RIGHT VISUAL -->
29
106
  <g>
30
- <rect x="760" y="64" width="760" height="510" rx="34" fill="#0C0F1C" fill-opacity=".45" stroke="#252B40" stroke-opacity=".72"/><rect x="780" y="84" width="720" height="470" rx="26" fill="none" stroke="#FFFFFF" stroke-opacity=".035"/>
31
- <g transform="translate(815,248)"><rect width="116" height="142" rx="20" fill="url(#chip)" stroke="#2B3148"/><rect x="16" y="17" width="84" height="82" rx="13" fill="#0A0D17" stroke="#2D3550"/><rect x="28" y="31" width="23" height="23" rx="5" fill="#5C51E8"/><rect x="55" y="31" width="33" height="23" rx="5" fill="#183C58"/><rect x="28" y="58" width="38" height="28" rx="5" fill="#154A63"/><rect x="70" y="58" width="18" height="28" rx="5" fill="#7F6FFF"/><text x="58" y="121" text-anchor="middle" fill="#AEB6CC" font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif" font-size="13" font-weight="700">图像</text></g>
32
- <path d="M931 319 C978 319 995 319 1032 319" fill="none" stroke="url(#route)" stroke-width="2.7" stroke-linecap="round" filter="url(#glow)"/><circle cx="974" cy="319" r="4" fill="#7668FF"/><circle cx="1004" cy="319" r="3" fill="#7668FF" opacity=".65"/>
33
- <g transform="translate(1111,319)"><circle r="102" fill="#0D1020" stroke="#2B314B" stroke-width="1.4"/><circle r="87" fill="none" stroke="#6659FF" stroke-opacity=".18"/><circle r="68" fill="none" stroke="#46D7FF" stroke-opacity=".10"/><path d="M-64 0 C-35 -38 35 -38 64 0 C35 38 -35 38 -64 0Z" fill="#11162A" stroke="url(#iris)" stroke-width="2.5" filter="url(#glow)"/><circle r="28" fill="url(#iris)" opacity=".92" filter="url(#softGlow)"/><circle r="12" fill="#080B14"/><circle cx="7" cy="-8" r="4.5" fill="#DDF8FF"/><circle cx="-91" r="4" fill="#7568FF"/><circle cx="91" cy="-49" r="4" fill="#49D5FF"/><circle cx="101" r="4" fill="#49D5FF"/><circle cx="91" cy="49" r="4" fill="#49D5FF"/><text x="0" y="132" text-anchor="middle" fill="#7A839A" font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif" font-size="13" font-weight="700">视觉路由核心</text></g>
34
- <path d="M1212 270 C1258 270 1260 183 1308 183" fill="none" stroke="url(#route)" stroke-width="2.2"/><path d="M1214 319 C1264 319 1266 319 1308 319" fill="none" stroke="url(#route)" stroke-width="2.2"/><path d="M1212 368 C1258 368 1260 455 1308 455" fill="none" stroke="url(#route)" stroke-width="2.2"/><circle cx="1268" cy="213" r="4" fill="#65D9FF"/><circle cx="1262" cy="319" r="4" fill="#7B6DFF"/><circle cx="1268" cy="425" r="4" fill="#65D9FF"/>
35
- <g transform="translate(1308,137)"><rect width="164" height="92" rx="17" fill="url(#chip)" stroke="#2C334B"/><circle cx="24" cy="26" r="8" fill="#2ED887" fill-opacity=".14" stroke="#4BDB96"/><path d="M20 26 l3 3 l6 -7" fill="none" stroke="#60E6A5" stroke-width="2"/><text x="43" y="31" fill="#E0E5F2" font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif" font-size="14" font-weight="700">免费视觉</text><text x="22" y="61" fill="#737D94" font-family="monospace" font-size="11.5">Qwen2.5-VL</text><text x="22" y="78" fill="#535D74" font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif" font-size="10.5">内置 · 无需 Key</text></g>
36
- <g transform="translate(1308,273)"><rect width="164" height="92" rx="17" fill="url(#chip)" stroke="#403772"/><circle cx="24" cy="26" r="8" fill="#7A6BFF" fill-opacity=".15" stroke="#7A6BFF"/><path d="M20 26 h8 M24 22 v8" stroke="#A79DFF" stroke-width="1.7"/><text x="43" y="31" fill="#E7E4FF" font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif" font-size="14" font-weight="700">故障切换</text><text x="22" y="61" fill="#8E86C9" font-family="monospace" font-size="11.5">provider chain</text><text x="22" y="78" fill="#615B83" font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif" font-size="10.5">配额 · 区域 · 429</text></g>
37
- <g transform="translate(1308,409)"><rect width="164" height="92" rx="17" fill="url(#chip)" stroke="#263D52"/><circle cx="24" cy="26" r="8" fill="#43D6FF" fill-opacity=".13" stroke="#44D6FF"/><path d="M19 26 h10 M24 21 v10" stroke="#7AE3FF" stroke-width="1.7"/><text x="43" y="31" fill="#DDF7FF" font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif" font-size="14" font-weight="700">像素工具</text><text x="22" y="61" fill="#7DB5C6" font-family="monospace" font-size="11.5">crop · diff · OCR</text><text x="22" y="78" fill="#52707D" font-family="monospace" font-size="10.5">ground · trace · color</text></g>
38
- <g transform="translate(982,106)"><rect width="316" height="40" rx="20" fill="#101526" stroke="#2D3450"/><circle cx="21" cy="20" r="4" fill="#A092FF"/><text x="36" y="25" fill="#BAC1D2" font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif" font-size="13" font-weight="650">DEEPSEEK 仍是大脑</text><path d="M239 20 h46" stroke="#343C59" stroke-width="1.5"/><circle cx="291" cy="20" r="4" fill="#4BD5FF"/></g>
107
+ <rect x="760" y="64" width="760" height="510" rx="34" fill="#0C0F1C" fill-opacity=".45" stroke="#252B40" stroke-opacity=".72"/>
108
+ <rect x="780" y="84" width="720" height="470" rx="26" fill="none" stroke="#FFFFFF" stroke-opacity=".035"/>
109
+
110
+ <!-- input tile -->
111
+ <g transform="translate(815,248)">
112
+ <rect x="0" y="0" width="116" height="142" rx="20" fill="url(#chip)" stroke="#2B3148"/>
113
+ <rect x="16" y="17" width="84" height="82" rx="13" fill="#0A0D17" stroke="#2D3550"/>
114
+ <rect x="28" y="31" width="23" height="23" rx="5" fill="#5C51E8"/>
115
+ <rect x="55" y="31" width="33" height="23" rx="5" fill="#183C58"/>
116
+ <rect x="28" y="58" width="38" height="28" rx="5" fill="#154A63"/>
117
+ <rect x="70" y="58" width="18" height="28" rx="5" fill="#7F6FFF"/>
118
+ <text x="58" y="121" text-anchor="middle" fill="#AEB6CC"
119
+ font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif"
120
+ font-size="13" font-weight="700">图像</text>
121
+ </g>
122
+
123
+ <!-- route in -->
124
+ <path d="M931 319 C978 319 995 319 1032 319" fill="none" stroke="url(#route)" stroke-width="2.7" stroke-linecap="round" filter="url(#glow)"/>
125
+ <circle cx="974" cy="319" r="4" fill="#7668FF"/>
126
+ <circle cx="1004" cy="319" r="3" fill="#7668FF" opacity=".65"/>
127
+
128
+ <!-- router eye -->
129
+ <g transform="translate(1111,319)">
130
+ <circle cx="0" cy="0" r="102" fill="#0D1020" stroke="#2B314B" stroke-width="1.4"/>
131
+ <circle cx="0" cy="0" r="87" fill="none" stroke="#6659FF" stroke-opacity=".18"/>
132
+ <circle cx="0" cy="0" r="68" fill="none" stroke="#46D7FF" stroke-opacity=".10"/>
133
+
134
+ <path d="M-64 0 C-35 -38 35 -38 64 0 C35 38 -35 38 -64 0Z" fill="#11162A" stroke="url(#iris)" stroke-width="2.5" filter="url(#glow)"/>
135
+ <circle cx="0" cy="0" r="28" fill="url(#iris)" opacity=".92" filter="url(#softGlow)"/>
136
+ <circle cx="0" cy="0" r="12" fill="#080B14"/>
137
+ <circle cx="7" cy="-8" r="4.5" fill="#DDF8FF" opacity=".9"/>
138
+
139
+ <circle cx="-91" cy="0" r="4" fill="#7568FF"/>
140
+ <circle cx="91" cy="-49" r="4" fill="#49D5FF"/>
141
+ <circle cx="101" cy="0" r="4" fill="#49D5FF"/>
142
+ <circle cx="91" cy="49" r="4" fill="#49D5FF"/>
143
+
144
+ <text x="0" y="132" text-anchor="middle" fill="#7A839A"
145
+ font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif"
146
+ font-size="13" font-weight="700" letter-spacing="1.0">视觉路由核心</text>
147
+ </g>
148
+
149
+ <!-- routes out -->
150
+ <path d="M1212 270 C1258 270 1260 183 1308 183" fill="none" stroke="url(#route)" stroke-width="2.2" stroke-linecap="round"/>
151
+ <path d="M1214 319 C1264 319 1266 319 1308 319" fill="none" stroke="url(#route)" stroke-width="2.2" stroke-linecap="round"/>
152
+ <path d="M1212 368 C1258 368 1260 455 1308 455" fill="none" stroke="url(#route)" stroke-width="2.2" stroke-linecap="round"/>
153
+
154
+ <circle cx="1268" cy="213" r="4" fill="#65D9FF" filter="url(#glow)"/>
155
+ <circle cx="1262" cy="319" r="4" fill="#7B6DFF" filter="url(#glow)"/>
156
+ <circle cx="1268" cy="425" r="4" fill="#65D9FF" filter="url(#glow)"/>
157
+
158
+ <!-- provider cards -->
159
+ <g transform="translate(1308,137)">
160
+ <rect x="0" y="0" width="164" height="92" rx="17" fill="url(#chip)" stroke="#2C334B"/>
161
+ <circle cx="24" cy="26" r="8" fill="#2ED887" fill-opacity=".14" stroke="#4BDB96"/>
162
+ <path d="M20 26 l3 3 l6 -7" fill="none" stroke="#60E6A5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
163
+ <text x="43" y="31" fill="#E0E5F2"
164
+ font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif"
165
+ font-size="14" font-weight="700">免费视觉</text>
166
+ <text x="22" y="61" fill="#737D94" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" font-size="11.5">Qwen2.5-VL</text>
167
+ <text x="22" y="78" fill="#535D74"
168
+ font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif"
169
+ font-size="10.5">内置 · 无需 Key</text>
170
+ </g>
171
+
172
+ <g transform="translate(1308,273)">
173
+ <rect x="0" y="0" width="164" height="92" rx="17" fill="url(#chip)" stroke="#403772"/>
174
+ <circle cx="24" cy="26" r="8" fill="#7A6BFF" fill-opacity=".15" stroke="#7A6BFF"/>
175
+ <path d="M20 26 h8 M24 22 v8" stroke="#A79DFF" stroke-width="1.7" stroke-linecap="round"/>
176
+ <text x="43" y="31" fill="#E7E4FF"
177
+ font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif"
178
+ font-size="14" font-weight="700">故障切换</text>
179
+ <text x="22" y="61" fill="#8E86C9" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" font-size="11.5">provider chain</text>
180
+ <text x="22" y="78" fill="#615B83"
181
+ font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif"
182
+ font-size="10.5">配额 · 区域 · 429</text>
183
+ </g>
184
+
185
+ <g transform="translate(1308,409)">
186
+ <rect x="0" y="0" width="164" height="92" rx="17" fill="url(#chip)" stroke="#263D52"/>
187
+ <circle cx="24" cy="26" r="8" fill="#43D6FF" fill-opacity=".13" stroke="#44D6FF"/>
188
+ <path d="M19 26 h10 M24 21 v10" stroke="#7AE3FF" stroke-width="1.7" stroke-linecap="round"/>
189
+ <text x="43" y="31" fill="#DDF7FF"
190
+ font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif"
191
+ font-size="14" font-weight="700">像素工具</text>
192
+ <text x="22" y="61" fill="#7DB5C6" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" font-size="11.5">crop · diff · OCR</text>
193
+ <text x="22" y="78" fill="#52707D" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" font-size="10.5">ground · trace · color</text>
194
+ </g>
195
+
196
+ <!-- brain stays brain -->
197
+ <g transform="translate(982,106)">
198
+ <rect x="0" y="0" width="316" height="40" rx="20" fill="#101526" stroke="#2D3450"/>
199
+ <circle cx="21" cy="20" r="4" fill="#A092FF"/>
200
+ <text x="36" y="25" fill="#BAC1D2"
201
+ font-family="PingFang SC, Noto Sans CJK SC, Microsoft YaHei, Inter, Arial, sans-serif"
202
+ font-size="13" font-weight="650">DEEPSEEK 仍是大脑</text>
203
+ <path d="M239 20 h46" stroke="#343C59" stroke-width="1.5"/>
204
+ <circle cx="291" cy="20" r="4" fill="#4BD5FF"/>
205
+ </g>
39
206
  </g>
207
+
40
208
  <rect x=".75" y=".75" width="1598.5" height="638.5" rx="31.25" fill="none" stroke="#FFFFFF" stroke-opacity=".08" stroke-width="1.5"/>
41
209
  </svg>
package/assets/hero.svg CHANGED
@@ -49,15 +49,18 @@
49
49
  </pattern>
50
50
  </defs>
51
51
 
52
+ <!-- Background -->
52
53
  <rect width="1600" height="640" rx="32" fill="url(#bg)"/>
53
54
  <rect width="1600" height="640" rx="32" fill="url(#dots)" opacity=".45"/>
54
55
  <rect width="1600" height="640" rx="32" fill="url(#violetGlow)"/>
55
56
  <rect width="1600" height="640" rx="32" fill="url(#cyanGlow)"/>
56
57
 
58
+ <!-- Fine ambient curves -->
57
59
  <path d="M790 70 C980 15 1240 42 1515 180" fill="none" stroke="#8D7BFF" stroke-opacity=".08" stroke-width="1"/>
58
60
  <path d="M780 575 C1020 620 1300 585 1510 425" fill="none" stroke="#47CFFF" stroke-opacity=".08" stroke-width="1"/>
59
61
  <path d="M925 36 C1120 160 1380 132 1565 250" fill="none" stroke="#FFFFFF" stroke-opacity=".035" stroke-width="1"/>
60
62
 
63
+ <!-- LEFT COPY -->
61
64
  <g transform="translate(92,86)">
62
65
  <g>
63
66
  <rect x="0" y="0" width="224" height="34" rx="17" fill="#111528" stroke="#7568FF" stroke-opacity=".42"/>
@@ -68,26 +71,48 @@
68
71
  <text x="0" y="102" fill="#F7F8FF" font-family="Inter, Arial, sans-serif" font-size="74" font-weight="760" letter-spacing="-3.1">DSH VISION</text>
69
72
  <text x="0" y="176" fill="url(#iris)" font-family="Inter, Arial, sans-serif" font-size="74" font-weight="760" letter-spacing="-3.1">ROUTER</text>
70
73
 
71
- <text x="2" y="229" fill="#C7CCDB" font-family="Inter, Arial, sans-serif" font-size="25" font-weight="500">Give DeepSeek eyes, not a new brain.</text>
72
- <text x="2" y="278" fill="#7F889F" font-family="Inter, Arial, sans-serif" font-size="17" font-weight="500">Built-in free vision chain · automatic failover · pixel-level tools</text>
73
- <text x="2" y="306" fill="#7F889F" font-family="Inter, Arial, sans-serif" font-size="17" font-weight="500">One-command install · no signup · no API key · no Python</text>
74
+ <text x="2" y="231" fill="#F2F5FF" font-family="Inter, Arial, sans-serif" font-size="32" font-weight="700" letter-spacing="-.6">Paste an image. It just works.</text>
74
75
 
76
+ <text x="2" y="271" fill="#C7CCDB" font-family="Inter, Arial, sans-serif" font-size="19" font-weight="500">DeepSeek stays the brain. Vision Router adds the eyes.</text>
77
+
78
+ <text x="2" y="305" fill="#7F889F" font-family="Inter, Arial, sans-serif" font-size="17" font-weight="500">Built-in free vision · no API key · no Python · automatic routing</text>
79
+
80
+ <!-- feature chips -->
75
81
  <g transform="translate(0,355)">
76
- <g><rect x="0" y="0" width="132" height="39" rx="12" fill="#111526" stroke="#252B42"/><circle cx="18" cy="19.5" r="4" fill="#50D890"/><text x="31" y="25" fill="#CFD5E6" font-family="Inter, Arial, sans-serif" font-size="14" font-weight="650">FREE CHAIN</text></g>
77
- <g transform="translate(145,0)"><rect x="0" y="0" width="147" height="39" rx="12" fill="#111526" stroke="#252B42"/><circle cx="18" cy="19.5" r="4" fill="#7B6DFF"/><text x="31" y="25" fill="#CFD5E6" font-family="Inter, Arial, sans-serif" font-size="14" font-weight="650">AUTO ROUTING</text></g>
78
- <g transform="translate(305,0)"><rect x="0" y="0" width="139" height="39" rx="12" fill="#111526" stroke="#252B42"/><circle cx="18" cy="19.5" r="4" fill="#4CD5FF"/><text x="31" y="25" fill="#CFD5E6" font-family="Inter, Arial, sans-serif" font-size="14" font-weight="650">PIXEL LOOP</text></g>
82
+ <g>
83
+ <rect x="0" y="0" width="104" height="39" rx="12" fill="#111526" stroke="#252B42"/>
84
+ <circle cx="18" cy="19.5" r="4" fill="#50D890"/>
85
+ <text x="31" y="25" fill="#CFD5E6" font-family="Inter, Arial, sans-serif" font-size="14" font-weight="650">NO KEY</text>
86
+ </g>
87
+ <g transform="translate(117,0)">
88
+ <rect x="0" y="0" width="147" height="39" rx="12" fill="#111526" stroke="#252B42"/>
89
+ <circle cx="18" cy="19.5" r="4" fill="#7B6DFF"/>
90
+ <text x="31" y="25" fill="#CFD5E6" font-family="Inter, Arial, sans-serif" font-size="14" font-weight="650">AUTO ROUTING</text>
91
+ </g>
92
+ <g transform="translate(277,0)">
93
+ <rect x="0" y="0" width="139" height="39" rx="12" fill="#111526" stroke="#252B42"/>
94
+ <circle cx="18" cy="19.5" r="4" fill="#4CD5FF"/>
95
+ <text x="31" y="25" fill="#CFD5E6" font-family="Inter, Arial, sans-serif" font-size="14" font-weight="650">PIXEL LOOP</text>
96
+ </g>
79
97
  </g>
80
98
 
81
- <g transform="translate(2,438)"><path d="M0 0 H422" stroke="#252A3C"/><text x="0" y="38" fill="#666F85" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" font-size="14">github.com/ysr666/dsh-vision-router</text></g>
99
+ <g transform="translate(2,438)">
100
+ <path d="M0 0 H422" stroke="#252A3C"/>
101
+ <text x="0" y="38" fill="#666F85" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" font-size="14">github.com/ysr666/dsh-vision-router</text>
102
+ </g>
82
103
  </g>
83
104
 
105
+ <!-- RIGHT VISUAL: router field -->
84
106
  <g>
107
+ <!-- faint frame -->
85
108
  <rect x="760" y="64" width="760" height="510" rx="34" fill="#0C0F1C" fill-opacity=".45" stroke="#252B40" stroke-opacity=".72"/>
86
109
  <rect x="780" y="84" width="720" height="470" rx="26" fill="none" stroke="#FFFFFF" stroke-opacity=".035"/>
87
110
 
111
+ <!-- image input tile -->
88
112
  <g transform="translate(815,248)">
89
113
  <rect x="0" y="0" width="116" height="142" rx="20" fill="url(#chip)" stroke="#2B3148"/>
90
114
  <rect x="16" y="17" width="84" height="82" rx="13" fill="#0A0D17" stroke="#2D3550"/>
115
+ <!-- abstract image pixels -->
91
116
  <rect x="28" y="31" width="23" height="23" rx="5" fill="#5C51E8"/>
92
117
  <rect x="55" y="31" width="33" height="23" rx="5" fill="#183C58"/>
93
118
  <rect x="28" y="58" width="38" height="28" rx="5" fill="#154A63"/>
@@ -95,28 +120,82 @@
95
120
  <text x="58" y="121" text-anchor="middle" fill="#AEB6CC" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" font-size="12" font-weight="700">IMAGE</text>
96
121
  </g>
97
122
 
123
+ <!-- route line in -->
98
124
  <path d="M931 319 C978 319 995 319 1032 319" fill="none" stroke="url(#route)" stroke-width="2.7" stroke-linecap="round" filter="url(#glow)"/>
99
- <circle cx="974" cy="319" r="4" fill="#7668FF"/><circle cx="1004" cy="319" r="3" fill="#7668FF" opacity=".65"/>
125
+ <circle cx="974" cy="319" r="4" fill="#7668FF"/>
126
+ <circle cx="1004" cy="319" r="3" fill="#7668FF" opacity=".65"/>
100
127
 
128
+ <!-- central router eye -->
101
129
  <g transform="translate(1111,319)">
102
- <circle cx="0" cy="0" r="102" fill="#0D1020" stroke="#2B314B" stroke-width="1.4"/><circle cx="0" cy="0" r="87" fill="none" stroke="#6659FF" stroke-opacity=".18"/><circle cx="0" cy="0" r="68" fill="none" stroke="#46D7FF" stroke-opacity=".10"/>
130
+ <circle cx="0" cy="0" r="102" fill="#0D1020" stroke="#2B314B" stroke-width="1.4"/>
131
+ <circle cx="0" cy="0" r="87" fill="none" stroke="#6659FF" stroke-opacity=".18"/>
132
+ <circle cx="0" cy="0" r="68" fill="none" stroke="#46D7FF" stroke-opacity=".10"/>
133
+
134
+ <!-- eye contour -->
103
135
  <path d="M-64 0 C-35 -38 35 -38 64 0 C35 38 -35 38 -64 0Z" fill="#11162A" stroke="url(#iris)" stroke-width="2.5" filter="url(#glow)"/>
104
- <circle cx="0" cy="0" r="28" fill="url(#iris)" opacity=".92" filter="url(#softGlow)"/><circle cx="0" cy="0" r="12" fill="#080B14"/><circle cx="7" cy="-8" r="4.5" fill="#DDF8FF" opacity=".9"/>
105
- <circle cx="-91" cy="0" r="4" fill="#7568FF"/><circle cx="91" cy="-49" r="4" fill="#49D5FF"/><circle cx="101" cy="0" r="4" fill="#49D5FF"/><circle cx="91" cy="49" r="4" fill="#49D5FF"/>
136
+ <circle cx="0" cy="0" r="28" fill="url(#iris)" opacity=".92" filter="url(#softGlow)"/>
137
+ <circle cx="0" cy="0" r="12" fill="#080B14"/>
138
+ <circle cx="7" cy="-8" r="4.5" fill="#DDF8FF" opacity=".9"/>
139
+
140
+ <!-- routing ticks -->
141
+ <circle cx="-91" cy="0" r="4" fill="#7568FF"/>
142
+ <circle cx="91" cy="-49" r="4" fill="#49D5FF"/>
143
+ <circle cx="101" cy="0" r="4" fill="#49D5FF"/>
144
+ <circle cx="91" cy="49" r="4" fill="#49D5FF"/>
145
+
106
146
  <text x="0" y="132" text-anchor="middle" fill="#7A839A" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" font-size="12" font-weight="700" letter-spacing="1.4">VISION ROUTER CORE</text>
107
147
  </g>
108
148
 
149
+ <!-- routes out -->
109
150
  <path d="M1212 270 C1258 270 1260 183 1308 183" fill="none" stroke="url(#route)" stroke-width="2.2" stroke-linecap="round"/>
110
151
  <path d="M1214 319 C1264 319 1266 319 1308 319" fill="none" stroke="url(#route)" stroke-width="2.2" stroke-linecap="round"/>
111
152
  <path d="M1212 368 C1258 368 1260 455 1308 455" fill="none" stroke="url(#route)" stroke-width="2.2" stroke-linecap="round"/>
112
- <circle cx="1268" cy="213" r="4" fill="#65D9FF" filter="url(#glow)"/><circle cx="1262" cy="319" r="4" fill="#7B6DFF" filter="url(#glow)"/><circle cx="1268" cy="425" r="4" fill="#65D9FF" filter="url(#glow)"/>
113
153
 
114
- <g transform="translate(1308,137)"><rect x="0" y="0" width="164" height="92" rx="17" fill="url(#chip)" stroke="#2C334B"/><circle cx="24" cy="26" r="8" fill="#2ED887" fill-opacity=".14" stroke="#4BDB96"/><path d="M20 26 l3 3 l6 -7" fill="none" stroke="#60E6A5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><text x="43" y="31" fill="#E0E5F2" font-family="Inter, Arial, sans-serif" font-size="14" font-weight="700">FREE VISION</text><text x="22" y="61" fill="#737D94" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" font-size="11.5">Qwen2.5-VL</text><text x="22" y="78" fill="#535D74" font-family="Inter, Arial, sans-serif" font-size="10.5">no key · built in</text></g>
115
- <g transform="translate(1308,273)"><rect x="0" y="0" width="164" height="92" rx="17" fill="url(#chip)" stroke="#403772"/><circle cx="24" cy="26" r="8" fill="#7A6BFF" fill-opacity=".15" stroke="#7A6BFF"/><path d="M20 26 h8 M24 22 v8" stroke="#A79DFF" stroke-width="1.7" stroke-linecap="round"/><text x="43" y="31" fill="#E7E4FF" font-family="Inter, Arial, sans-serif" font-size="14" font-weight="700">FAILOVER</text><text x="22" y="61" fill="#8E86C9" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" font-size="11.5">provider chain</text><text x="22" y="78" fill="#615B83" font-family="Inter, Arial, sans-serif" font-size="10.5">quota · region · 429</text></g>
116
- <g transform="translate(1308,409)"><rect x="0" y="0" width="164" height="92" rx="17" fill="url(#chip)" stroke="#263D52"/><circle cx="24" cy="26" r="8" fill="#43D6FF" fill-opacity=".13" stroke="#44D6FF"/><path d="M19 26 h10 M24 21 v10" stroke="#7AE3FF" stroke-width="1.7" stroke-linecap="round"/><text x="43" y="31" fill="#DDF7FF" font-family="Inter, Arial, sans-serif" font-size="14" font-weight="700">PIXEL TOOLS</text><text x="22" y="61" fill="#7DB5C6" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" font-size="11.5">crop · diff · OCR</text><text x="22" y="78" fill="#52707D" font-family="Inter, Arial, sans-serif" font-size="10.5">ground · trace · color</text></g>
154
+ <!-- moving signal dots -->
155
+ <circle cx="1268" cy="213" r="4" fill="#65D9FF" filter="url(#glow)"/>
156
+ <circle cx="1262" cy="319" r="4" fill="#7B6DFF" filter="url(#glow)"/>
157
+ <circle cx="1268" cy="425" r="4" fill="#65D9FF" filter="url(#glow)"/>
158
+
159
+ <!-- provider cards -->
160
+ <g transform="translate(1308,137)">
161
+ <rect x="0" y="0" width="164" height="92" rx="17" fill="url(#chip)" stroke="#2C334B"/>
162
+ <circle cx="24" cy="26" r="8" fill="#2ED887" fill-opacity=".14" stroke="#4BDB96"/>
163
+ <path d="M20 26 l3 3 l6 -7" fill="none" stroke="#60E6A5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
164
+ <text x="43" y="31" fill="#E0E5F2" font-family="Inter, Arial, sans-serif" font-size="14" font-weight="700">FREE VISION</text>
165
+ <text x="22" y="61" fill="#737D94" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" font-size="11.5">Qwen2.5-VL</text>
166
+ <text x="22" y="78" fill="#535D74" font-family="Inter, Arial, sans-serif" font-size="10.5">no key · built in</text>
167
+ </g>
168
+
169
+ <g transform="translate(1308,273)">
170
+ <rect x="0" y="0" width="164" height="92" rx="17" fill="url(#chip)" stroke="#403772"/>
171
+ <circle cx="24" cy="26" r="8" fill="#7A6BFF" fill-opacity=".15" stroke="#7A6BFF"/>
172
+ <path d="M20 26 h8 M24 22 v8" stroke="#A79DFF" stroke-width="1.7" stroke-linecap="round"/>
173
+ <text x="43" y="31" fill="#E7E4FF" font-family="Inter, Arial, sans-serif" font-size="14" font-weight="700">FAILOVER</text>
174
+ <text x="22" y="61" fill="#8E86C9" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" font-size="11.5">provider chain</text>
175
+ <text x="22" y="78" fill="#615B83" font-family="Inter, Arial, sans-serif" font-size="10.5">quota · region · 429</text>
176
+ </g>
117
177
 
118
- <g transform="translate(988,106)"><rect x="0" y="0" width="307" height="40" rx="20" fill="#101526" stroke="#2D3450"/><circle cx="21" cy="20" r="4" fill="#A092FF"/><text x="36" y="25" fill="#BAC1D2" font-family="Inter, Arial, sans-serif" font-size="12.5" font-weight="650" letter-spacing=".2">DEEPSEEK STAYS THE BRAIN</text><path d="M233 20 h49" stroke="#343C59" stroke-width="1.5"/><circle cx="287" cy="20" r="4" fill="#4BD5FF"/></g>
178
+ <g transform="translate(1308,409)">
179
+ <rect x="0" y="0" width="164" height="92" rx="17" fill="url(#chip)" stroke="#263D52"/>
180
+ <circle cx="24" cy="26" r="8" fill="#43D6FF" fill-opacity=".13" stroke="#44D6FF"/>
181
+ <path d="M19 26 h10 M24 21 v10" stroke="#7AE3FF" stroke-width="1.7" stroke-linecap="round"/>
182
+ <text x="43" y="31" fill="#DDF7FF" font-family="Inter, Arial, sans-serif" font-size="14" font-weight="700">PIXEL TOOLS</text>
183
+ <text x="22" y="61" fill="#7DB5C6" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" font-size="11.5">crop · diff · OCR</text>
184
+ <text x="22" y="78" fill="#52707D" font-family="Inter, Arial, sans-serif" font-size="10.5">ground · trace · color</text>
185
+ </g>
186
+
187
+ <!-- brain stays brain pill -->
188
+ <g transform="translate(988,106)">
189
+ <rect x="0" y="0" width="307" height="40" rx="20" fill="#101526" stroke="#2D3450"/>
190
+ <circle cx="21" cy="20" r="4" fill="#A092FF"/>
191
+ <text x="36" y="25" fill="#BAC1D2" font-family="Inter, Arial, sans-serif" font-size="12.5" font-weight="650" letter-spacing=".2">
192
+ DEEPSEEK STAYS THE BRAIN
193
+ </text>
194
+ <path d="M233 20 h49" stroke="#343C59" stroke-width="1.5"/>
195
+ <circle cx="287" cy="20" r="4" fill="#4BD5FF"/>
196
+ </g>
119
197
  </g>
120
198
 
199
+ <!-- border highlight -->
121
200
  <rect x=".75" y=".75" width="1598.5" height="638.5" rx="31.25" fill="none" stroke="#FFFFFF" stroke-opacity=".08" stroke-width="1.5"/>
122
201
  </svg>
Binary file
Binary file
package/cordis.patch.yml CHANGED
@@ -4,22 +4,13 @@
4
4
  # without any manual cordis.patch.yml edits. Later layers (the profile's own
5
5
  # cordis.patch.yml, --patch overlays) override these rows by id.
6
6
 
7
- # 隐身模式:接管官方 deepseek-official 路由。禁用官方行后插件自己重建原生
8
- # DeepSeek 适配器(读取同一个 llm-deepseek 设置段与凭据),选择器里的
9
- # DeepSeek 条目本身就是「图片自动识图」包装,发图即用。
10
- # 想恢复官方行:在你的 profile cordis.patch.yml 里删掉/覆写本条即可。
11
- - id: llm-deepseek
12
- disabled: true
13
-
14
- # 挂载插件行。配置全部可选(默认即内置免费视觉端点 + 工具优先的图片流程),
15
- # 可在 Web 设置 > 插件 > 插件配置 的「视觉路由」卡片里实时修改。
7
+ # 纯增量安装:只挂载插件行,不改动任何核心行。
8
+ # 官方 llm-deepseek 行保持原样(安装即安全,无隐式接管);
9
+ # 图片入口使用选择器里插件注册的「自动识图」包装条目(deepseek-vision),
10
+ # 或把第三方文本路由写入设置卡片的「额外识图包装」。
11
+ # 想要隐身模式(接管 deepseek-official、选择器看起来和原来一模一样)时,
12
+ # 由用户在自己的 profile cordis.patch.yml 里显式禁用官方行——插件永不
13
+ # 自动替用户禁用核心行(issue #34)。
16
14
  - insert:
17
15
  - id: vision-router
18
16
  name: dsh-vision-router
19
-
20
- # 放宽附件图片限制(部署默认 5MB / 4000 万像素 → 20MB / 1 亿像素),
21
- # 大尺寸设计稿/扫描图可过审。字段可选,不需要可在 profile 补丁层覆写。
22
- - id: attachment-local
23
- config:
24
- maxImageBytes: 20971520
25
- maxImagePixels: 100000000
package/index.js CHANGED
@@ -65,7 +65,9 @@ export const Config = z.object({
65
65
  reverseRouting: z.boolean().default(true),
66
66
  wrapperRoute: z.string().default('deepseek-vision'),
67
67
  chainRoute: z.string().default('vision-chain'),
68
- stealth: z.boolean().default(true),
68
+ // 显式 opt-in(issue #34):默认不尝试接管官方路由;开启后还需在
69
+ // profile 补丁层禁用官方 llm-deepseek 行才真正生效。
70
+ stealth: z.boolean().default(false),
69
71
  textProvider: z
70
72
  .object({
71
73
  provider: z.string().default('deepseek-official'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-vision-router",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Eyes for text-only DeepSeek Harness agents: built-in free vision chain (no key) + pixel-level vision tools (Q&A, grounding, crop, pixel diff, colors, OCR, SVG trace, cutout, screenshots). One-command install, no Python, image turns work like ordinary tool-calling turns.",
5
5
  "license": "MIT",
6
6
  "repository": {