# dsh-claude-ux

> 为 DeepSeek Harness web 端复刻 Claude 的区域风控（可反向）与辱骂/有害互动自动结束对话能力，含独立设置页与隐写标记。

## Metadata

- Author: [@eri64](https://github.com/eri64)
- Repo: <https://github.com/eri64/dsh-claude-ux.git>
- GitHub: [eri64/dsh-claude-ux](https://github.com/eri64/dsh-claude-ux)
- Stars: 60
- Language: JavaScript
- License: [MIT](https://spdx.org/licenses/MIT.html)
- Homepage: <https://github.com/eri64/dsh-claude-web>
- Topics: `deepseek-harness`, `dsh`, `dsh-plugin`
- Forks: 1
- Open Issues: 9
- Last push: 2026-08-15T18:18:39.000Z
- Added: 2026-08-20T00:00:00.000Z

## Install

```bash
dsh plugin --profile web add github:eri64/dsh-claude-ux
```

## Wiki

## 一句话定位
复刻 Claude/Anthropic 的两类行为：基于时区、系统语言、代理、域名黑名单、可选公网 IP 等多信号加权识别目标用户（中国/非中国可反向），命中后按"拒绝文案 → 结束会话"阶梯处置；用户持续辱骂或请求严重有害内容时先警告再主动结束对话，并把判定结果通过隐写通道编进系统提示词。

## 核心能力
- 检测目标用户：通过时区、系统/浏览器语言、代理环境、域名黑名单等本机信号打分判定，命中按阶梯惩罚（拒绝文案带尝试计数 → 达到次数结束会话）
- 支持反向风控目标：可选"风控中国用户"（Claude 原版）或"风控非中国用户"
- 自主结束对话：用户持续辱骂先警告再结束；未成年性内容、恐怖主义、大规模暴力等严重有害请求直接结束
- 自伤/他伤风险消息永不触发结束（安全覆盖），与其他结束逻辑独立
- 隐写通道：把区域判定结果通过系统提示词日期格式（2026-06-30 ↔ 2026/06/30）与 Unicode 撇号变体编码，模型自身也能感知
- 提供独立设置页「Claude 风控」（设置页左侧标签栏）与实时检测状态卡片，含消息分类自测工具

## 技术实现
- **语言**: JavaScript (ESM, type: module)
- **关键依赖**: schemastery（设置 schema 校验）、DSH 自身的 settings / llm / sessionProjections / webServer 服务
- **架构模式**: DSH 插件 manifest（`dsh.bundle.patch` 注册条目 + `dsh.client.platform=web` 客户端），主机半面通过 `agent/pre-step` / `llm/stream` / `system-prompt/assemble` / `sessionProjections` 等钩子拦截对话流，浏览器半面通过 `settings.section` 注册独立页面、通过 `conversation.composer` chain 接管输入区
- **入口文件**: lib/index.js（主机，apply 导出）、lib/client.js（浏览器，UMD 模块通过 `window.__ModuleLoader__.load` 装载）

## 适用场景
DSH web profile 用户希望在 AI 对话里复刻 Claude 的两道防线：阻止目标地区用户使用（默认风控中国用户，可反过来只服务国内），并在用户辱骂升级或索取严重有害内容时主动结束会话而非继续回复。隐私敏感用户也能放心使用，因为默认配置（ipCheck 与 webRtcCheck 都关闭）下插件不与任何外部服务通信，全部判定在本机完成。

## 前置依赖与兼容性
| 依赖 | 最低版本 | 说明 |
|---|---|---|
| DSH | 未声明 | 通过 `dsh.bundle.patch` 与 `dsh.client.platform=web` 注册，需运行 DSH web profile |
| Node.js | 未声明 | package.json 未声明 engines |
| 平台 | 跨平台 | 主机端读取 Windows 注册表用 spawnSync('reg')，其他平台读 env 降级；客户端纯 Web 标准 API |
| 原生模块 | 无 | 仅依赖 schemastery，无 node:sqlite / node-pty 等原生模块 |

## 安装方式
```bash
dsh plugin --profile web add github:eri64/dsh-claude-ux
```

## 配置项
| 配置 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| 总开关 | boolean | 启用 Claude 风控与自主性 | `false` |
| 风控目标 | enum(`cn`/`non-cn`) | 选 cn = 检测到中国用户就风控；选 non-cn = 反向风控非中国用户 | `cn` |
| 区域策略 | enum(`block`/`observe`/`off`) | block = 拒绝回复；observe = 只记录+隐写标记；off = 关闭区域检测 | `block` |
| 信号分阈值 | number | 触发目标判定的总分阈值（strong=2 / medium=1 / weak=0.5） | `2` |
| 区域拒绝次数后结束 | number | 拒绝 N 次后结束会话（服务端持续拒绝，重启不失效） | `3` |
| 隐写标记 | boolean | 开启后目标命中时改写系统提示词日期格式与撇号 | `true` |
| 模型级区域指令 | boolean | 目标命中时向系统提示词追加区域限制指令，让模型自己也拒绝 | `true` |
| 公网 IP 归属 | boolean | 联系 ipinfo.io / ip-api.com 查询 IP 归属（关闭则无外部通信） | `false` |
| WebRTC IP 探测 | boolean | 联系 Google STUN 服务器探测本地公网 IP（关闭则无外部通信） | `false` |
| 完全无信号时按目标命中 | boolean | fail-closed 模式：所有信号全失败时按目标命中处理 | `false` |
| 自主性总开关 | boolean | 启用辱骂/有害互动结束对话 | `true` |
| 警告阈值 | number | 辱骂次数达到此值回复警告文案 | `1` |
| 结束阈值 | number | 辱骂次数达到此值结束会话 | `3` |
| 每次辱骂都警告 | boolean | 达到结束阈值前每次辱骂都警告 | `true` |
| 严重有害立即结束 | boolean | 未成年性内容 / 恐怖主义 / 大规模暴力不警告直接结束 | `true` |
| 分类 LLM 模式 | enum(`all`/`fuzzy`/`off`) | all = 全部消息 LLM 语境判定；fuzzy = 仅模糊词调 LLM；off = 纯词表 | `all` |
| 分类模型 provider/model | string | 留空跟随会话主模型（agent-default-model 兜底）；下拉直接选 DSH 已配置模型 | 跟随会话 |
| 分类请求超时（毫秒） | number | LLM 分类调用超时时间 | `5000` |
| 区域拒绝文案 | string | 拒绝回复时使用的文案（留空使用内置中英默认） | 内置默认 |
| 区域结束文案 | string | 拒绝满次数后结束会话的文案 | 内置默认 |
| 警告文案 | string | 辱骂未达结束阈值时的警告文案 | 内置默认 |
| 结束文案（辱骂） | string | 辱骂触发结束的文案 | 内置默认 |
| 有害内容结束文案 | string | 严重有害请求触发的结束文案（与辱骂结束文案区分） | 内置默认 |
| 中国时区表 / 代理中转域名黑名单 / 辱骂词表 / 有害词表 / 自伤词表 | string[] (regex) | 整体替换内置列表，修改需改 patch 后重启 | 内置（默认 ≈60 条黑名单 + 中英双语词表） |

## 常见问题

**Q: 默认是开启还是关闭？**

A: 默认关闭。cordis.patch.yml 中 `enabled: false`，避免自己被风控后无法进设置页改回去。需要进入设置页左侧的「Claude 风控」标签，打开右上总开关并「保存并应用」后才会生效。

**Q: 默认配置下会与外部服务通信吗？**

A: 不会。`ipCheck` 与 `webRtcCheck` 都默认关闭，公网 IP 查询（ipinfo.io / ip-api.com）与 WebRTC STUN 探测（Google stun.l.google.com:19302）都不会触发。除非主动打开这两个开关，否则所有判定（时区、语言、代理、黑名单、浏览器指纹）都在本机完成，不上报任何遥测，详见 docs/PRIVACY.md。

**Q: 自伤/他伤风险的消息会触发结束对话吗？**

A: 不会。源码明确写了"自伤/他伤风险消息永不结束"，这是对齐 Claude 公开限制的安全覆盖——strikes 计数会被清零，会话继续进行，不会被 reject。

**Q: 怎么验证插件已经安装成功？**

A: 重启 dsh web、浏览器硬刷新后，访问 `http://127.0.0.1:3080/_dsh/claude/status`，返回 `{"ok":true,...}` 即主机插件已加载；设置页左侧标签栏出现「Claude 风控」独立标签则说明客户端也生效。

**Q: 分类用的 LLM 模型从哪里选？**

A: 设置页的"分类 LLM"面板会扫描 DSH 已配置的模型目录（settings 的 providers 命名空间），以下拉列出所有可用模型。留空则跟随当前会话主模型；无主模型时回退 agent-default-model。下拉里没有的可以选「自定义…」手填 provider/model。

**Q: 区域风控可以反过来风控非中国用户吗？**

A: 可以。把设置页"区域风控"面板里的"风控目标"切到「非中国用户：检测到不是中国人就风控」（`regionTarget=non-cn`），就变成反向风控——比如想让部署只服务国内用户。其余的拒绝阶梯、隐写标记、模型级指令等行为完全一致。

**Q: 命中区域风控结束会话后，重启 dsh 会失效吗？**

A: 不会。结束状态同时从会话日志推导（最后一条 turn/end 为 blocked、或最后一条 assistant 文本以结束文案前缀开头），重启后依然成立；客户端输入区会被 Chat ended 面板接管，必须开新对话才能继续。

**Q: LLM 分类调用失败会影响判定吗？**

A: 不会。LLM 分类失败会自动降级为词表结果，强词/严重有害/自伤永远以词表为准；只有"模糊词 + LLM 语境消歧"场景下 LLM 不可用才会回退到词表判定。失败的诊断信息每 15 秒最多打一条告警日志，避免刷屏。

## 上手难度
入门 — 默认关闭、安装即用；多数场景无需改任何 patch；想自定义阈值或文案时通过设置页点选即可，不需要写代码。

## 已知问题与限制
- 公网 IP 查询回退链路 `http://ip-api.com/json` 使用明文 HTTP，理论上可被中间人篡改响应，但影响仅限于本机区域判定（不会泄露数据），介意者可保持 `ipCheck: false`
- 状态路由 `GET /_dsh/claude/status` 返回完整判定明细（含公网 IP 与 org，若开启了 IP 查询），无鉴权——任何能访问 3080 端口的人可读取；建议保持 DSH web 仅监听 loopback（默认如此）
- `getNetworkRequests` 中的 `refusalMessage`、`endMessage` 等内置文案为空字符串时灰字显示内置默认；插件据此判断"配置为空时使用默认"，但若用户刻意把文案存成空串，结束文案前缀检测会回退到内置默认前缀（这是设计使然）
- 隐写标记随系统提示词发送给 LLM 提供方；标记本身只含两个 bit（是否命中目标 / 是否命中黑名单），不含账号或消息正文
- 主机端 Windows 注册表读取使用 spawnSync('reg')，其他平台读 env 降级；非 Windows 平台注册表代理信号永远为 0

---

This document is auto-generated by [deepseek-plugin.org](https://deepseek-plugin.org). HTML page: [dsh-claude-ux](https://deepseek-plugin.org/plugins/eri64/dsh-claude-ux)
Wiki generated by AI (model: `MiniMax-M3`)
