@jaychang1989/dsh-webchat 0.3.0 → 0.4.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/NOTICE +10 -3
- package/README.md +44 -40
- package/README.zh.md +43 -44
- package/cordis.patch.yml +8 -7
- package/lib/client.js +402 -1693
- package/lib/index.js +246 -3884
- package/package.json +3 -35
- package/lib/client.js.map +0 -1
- package/lib/types/client/api.d.ts +0 -74
- package/lib/types/client/controller.d.ts +0 -19
- package/lib/types/client/index.d.ts +0 -30
- package/lib/types/client/locales.d.ts +0 -169
- package/lib/types/client/mount.d.ts +0 -23
- package/lib/types/client/panel/Markdown.d.ts +0 -15
- package/lib/types/client/panel/WebChatPanel.d.ts +0 -28
- package/lib/types/client/sidebar-entry-core.d.ts +0 -60
- package/lib/types/client/sidebar-entry.d.ts +0 -22
- package/lib/types/engine/engine.d.ts +0 -247
- package/lib/types/engine/html-md.d.ts +0 -23
- package/lib/types/index.d.ts +0 -63
- package/lib/types/protocol.d.ts +0 -107
- package/lib/types/routes.d.ts +0 -22
- package/lib/types/store.d.ts +0 -69
- package/lib/types/tools.d.ts +0 -27
- package/lib/types/transfer.d.ts +0 -138
- package/src/client/api.ts +0 -90
- package/src/client/controller.ts +0 -43
- package/src/client/css-modules.d.ts +0 -5
- package/src/client/index.ts +0 -75
- package/src/client/locales.ts +0 -172
- package/src/client/mount.tsx +0 -125
- package/src/client/panel/Markdown.tsx +0 -251
- package/src/client/panel/WebChatPanel.tsx +0 -760
- package/src/client/panel/panel.module.css +0 -936
- package/src/client/sidebar-entry-core.ts +0 -207
- package/src/client/sidebar-entry.ts +0 -49
- package/src/engine/engine.ts +0 -1385
- package/src/engine/html-md.ts +0 -126
- package/src/index.ts +0 -212
- package/src/protocol.ts +0 -116
- package/src/routes.ts +0 -307
- package/src/store.ts +0 -217
- package/src/tools.ts +0 -257
- package/src/transfer.ts +0 -602
package/NOTICE
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
dsh-webchat
|
|
2
2
|
Copyright 2026 jaychang1989
|
|
3
3
|
|
|
4
|
-
This product is a
|
|
4
|
+
This product is a fork of dsh-web-chat
|
|
5
5
|
(https://github.com/xmuwenxiang/dsh-web-chat), Copyright the dsh-web-chat
|
|
6
6
|
authors, licensed under the Apache License, Version 2.0.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
0.3.0 retargeted the plugin at the DeepSeek Harness 0.2.x plugin APIs:
|
|
9
9
|
|
|
10
10
|
* the settings section is no longer registered by the plugin
|
|
11
11
|
(`installSettingsSection` / `settingsNamespace` were removed from
|
|
@@ -15,4 +15,11 @@ The fork retargets the plugin at the DeepSeek Harness 0.2.x plugin APIs:
|
|
|
15
15
|
(`sessionPersistence.open` / `create` + handle `read` / `append` / `flush`)
|
|
16
16
|
instead of the retired service-level `load` / `append` pair.
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
0.4.0 reduced the package to a launcher: it opens the official
|
|
19
|
+
chat.deepseek.com web app in a window instead of driving the page and
|
|
20
|
+
re-rendering the conversation. The custom chat panel, the local transcript
|
|
21
|
+
store, the five `webchat_*` agent tools, the transfer/distillation code and
|
|
22
|
+
thirteen of the fifteen HTTP routes were removed, along with the
|
|
23
|
+
`playwright-core` runtime dependency and the React-based client build.
|
|
24
|
+
|
|
25
|
+
See MAINTAINING.md for the current structure and the constraints behind it.
|
package/README.md
CHANGED
|
@@ -1,78 +1,82 @@
|
|
|
1
1
|
# dsh-webchat
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Opens the official [chat.deepseek.com](https://chat.deepseek.com) web app from inside [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness): one sidebar entry, one button, and the official page itself.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
> See [MAINTAINING.md](./MAINTAINING.md) and [NOTICE](./NOTICE) for the exact difference.
|
|
5
|
+
**It no longer reimplements the chat UI.** The official web app is the client — model picker, deep think, smart search, history and attachments all live there. This plugin opens it and nothing else.
|
|
7
6
|
|
|
8
|
-
##
|
|
7
|
+
## Why a window, and not a pane
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
| --- | --- | --- |
|
|
12
|
-
| Startup | `installSettingsSection` and `settingsNamespace` were removed from `@deepseek-ai/dsh-settings` in dsh 0.1.7, so the host half fails at ESM link time and the whole `webchat` entry reports `failed to import` — the plugin never loads | Uses the Loader-owned settings form (namespace = profile entry id, schema = this package's exported `Config`); the plugin no longer registers a settings section |
|
|
13
|
-
| Transfer to Harness | `sessionPersistence.load(id)` and `persistence.append(id, events)` became a **handle-based** API in dsh 0.2.x, so the call throws | Migrated to the `SessionHandle` returned by `open(id, 'write')` / `create(header)`, using `handle.read` / `append` / `flush` / `close` |
|
|
14
|
-
| Dependency declarations | `devDependencies` pinned at `@deepseek-ai/*: ^0.1.0-rc.7` | Updated to 0.2.x, plus runtime `peerDependencies` and `engines.dsh` |
|
|
9
|
+
Both embedding routes are closed, and that is a measurement rather than a choice:
|
|
15
10
|
|
|
16
|
-
|
|
11
|
+
- `chat.deepseek.com` answers with **`Content-Security-Policy: frame-ancestors 'none'`**, so no iframe can host it;
|
|
12
|
+
- the desktop build runs both windows with **`webviewTag: false`** and blocks `will-attach-webview`, so `<webview>` is unavailable too.
|
|
13
|
+
|
|
14
|
+
A real window is therefore the only faithful way to show the official page.
|
|
15
|
+
|
|
16
|
+
## What opens, in order
|
|
17
|
+
|
|
18
|
+
The button tries these in order and reports which one worked:
|
|
19
|
+
|
|
20
|
+
1. **`app-window`** — a window created by the DSH desktop process itself (the desktop app is Electron). An already-open one is focused instead of duplicated.
|
|
21
|
+
2. **`app-window-shell`** — a chromeless Edge/Chrome window (`--app=`) with its own `--user-data-dir` (`~/.dsh/dsh-webchat/app-window`), so its login stays separate from your everyday browser. Used when the host refuses (1).
|
|
22
|
+
3. **`system-browser`** — handed to the OS default browser, so the button always does something.
|
|
23
|
+
|
|
24
|
+
Sign in once; the window's own profile keeps the session.
|
|
17
25
|
|
|
18
|
-
|
|
26
|
+
## Install
|
|
19
27
|
|
|
20
28
|
```bash
|
|
21
29
|
dsh plugin --profile desktop add @jaychang1989/dsh-webchat
|
|
22
30
|
```
|
|
23
31
|
|
|
24
|
-
Or straight from this repository
|
|
32
|
+
Or straight from this repository:
|
|
25
33
|
|
|
26
34
|
```bash
|
|
27
35
|
dsh plugin --profile desktop add github:jaychang1989/dsh-webchat
|
|
28
36
|
```
|
|
29
37
|
|
|
30
|
-
> The npm package is scoped because the unscoped `dsh-webchat` name belongs to the unmaintained upstream project. The
|
|
31
|
-
|
|
32
|
-
**Switching from upstream:** both packages insert the same `id: webchat` row, and one profile cannot hold the same entry id twice — boot fails on the duplicate. Remove the upstream package first (the Plugin Manager UI, or `dsh plugin --profile desktop remove dsh-webchat`), then add this one.
|
|
33
|
-
|
|
34
|
-
**Restart the DSH desktop app afterwards** — an entry that failed during startup is not hot-reloaded.
|
|
38
|
+
> The npm package is scoped because the unscoped `dsh-webchat` name belongs to the unmaintained upstream project. The scope does not change the plugin's identity: the entry id stays `webchat`.
|
|
35
39
|
|
|
36
|
-
|
|
40
|
+
**Switching from upstream, or from this plugin's 0.3.x:** all of them insert the same `id: webchat` row, and one profile cannot hold the same entry id twice — boot fails on the duplicate. Remove the old package first, then add this one, then restart the desktop app.
|
|
37
41
|
|
|
38
|
-
|
|
39
|
-
2. Click "打开登录窗口" and complete the DeepSeek web login in the window that opens.
|
|
40
|
-
3. The window closes itself once you are logged in; chatting then runs headless.
|
|
42
|
+
## Use
|
|
41
43
|
|
|
42
|
-
|
|
44
|
+
1. Click the "DeepSeek 网页 / DeepSeek Web" entry in the sidebar.
|
|
45
|
+
2. Click "Open chat.deepseek.com" in the panel.
|
|
46
|
+
3. Sign in once in the window it opens; afterwards just use the official web app.
|
|
43
47
|
|
|
44
|
-
|
|
45
|
-
- **Transfer to Harness** — distill the current web conversation into a task brief and open it as a new harness session (first message is the brief), or continue an existing session by appending the brief to it; the transfer can target a registered workspace.
|
|
46
|
-
- **Recover from the web** — pull web-side conversations that are not in the local store yet (panel button / `webchat_recover`).
|
|
47
|
-
- **Import as context** — export a stored web conversation as markdown context.
|
|
48
|
-
- **Agent tools** — `webchat_status`, `webchat_send`, `webchat_recover`, `webchat_import`, `webchat_transfer`, callable by the harness agent directly.
|
|
49
|
-
- **Effortless login** — the login window is visible once, then closes itself; chatting afterwards is headless.
|
|
48
|
+
## Difference from 0.3.x — this release deletes most of the plugin
|
|
50
49
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
| 0.3.x | 0.4.0 |
|
|
51
|
+
| --- | --- |
|
|
52
|
+
| Drove the page with Playwright and re-rendered messages in a custom panel | Does not drive the page; opens it. Custom panel removed |
|
|
53
|
+
| Five agent tools (`webchat_status/send/recover/import/transfer`) | All removed |
|
|
54
|
+
| "Transfer to Harness", "recover from web", "import", "export" | All removed |
|
|
55
|
+
| Local transcript store at `~/.dsh/dsh-webchat/transcripts.json` | Removed (only the window profile directory remains) |
|
|
56
|
+
| Fifteen `/api/dsh-webchat/*` routes | Two: `state` and `open` |
|
|
57
|
+
| Depended on `playwright-core`; the client half needed React and a bundler | **No runtime dependencies**; plain-DOM client, no build step |
|
|
58
|
+
| ~3800 lines of build output | ~700 lines of hand-written JS |
|
|
54
59
|
|
|
55
60
|
## Requirements
|
|
56
61
|
|
|
57
62
|
- DeepSeek Harness **0.2.0-rc.1 or a newer 0.2.x**
|
|
58
63
|
- Node.js >= 22
|
|
59
|
-
-
|
|
60
|
-
- An interactive desktop for the one-time login window
|
|
64
|
+
- Strategy 2 needs Edge or Chrome installed; strategy 1 does not
|
|
61
65
|
|
|
62
66
|
## Limitations
|
|
63
67
|
|
|
64
|
-
- The DeepSeek web front end
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
|
|
68
|
-
## Development
|
|
68
|
+
- The DeepSeek web front end applies its own rate limiting; the plugin hands the page over and does not mediate its login or requests.
|
|
69
|
+
- A strategy-1 window is owned by the DSH process: if you close the DSH main window while it is still open, DSH will not quit (Electron's `window-all-closed`). Close that window too.
|
|
70
|
+
- Reloading the plugin does not close a window that is already open, so a settings change cannot close the conversation you are reading.
|
|
69
71
|
|
|
70
|
-
|
|
72
|
+
## Development and tests
|
|
71
73
|
|
|
72
74
|
```bash
|
|
73
|
-
node --test #
|
|
75
|
+
node --test # 11 cases: host routes, window-strategy selection, and the browser half mounted into a DOM stand-in
|
|
74
76
|
```
|
|
75
77
|
|
|
78
|
+
There is no build step: `lib/index.js` and `lib/client.js` are the hand-written runtime. See [MAINTAINING.md](./MAINTAINING.md).
|
|
79
|
+
|
|
76
80
|
## License
|
|
77
81
|
|
|
78
82
|
[Apache-2.0](./LICENSE). Original copyright belongs to the authors of [xmuwenxiang/dsh-web-chat](https://github.com/xmuwenxiang/dsh-web-chat); see [NOTICE](./NOTICE).
|
package/README.zh.md
CHANGED
|
@@ -1,83 +1,82 @@
|
|
|
1
1
|
# dsh-webchat
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
在 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 里打开 [chat.deepseek.com](https://chat.deepseek.com) 官方网页版:侧边栏一个入口,面板一个按钮,点开就是官方页面。
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
> 差异与原因见 [MAINTAINING.md](./MAINTAINING.md) 与 [NOTICE](./NOTICE)。
|
|
5
|
+
**不再重新实现聊天界面。** 官方网页版本身就是完整的客户端——模型选择、深度思考、智能搜索、历史记录、附件上传都在里面。本插件只负责把它打开,别的一概不管。
|
|
7
6
|
|
|
8
|
-
##
|
|
7
|
+
## 为什么是「开一个窗口」,而不是「嵌在面板里」
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
| --- | --- | --- |
|
|
12
|
-
| 启动 | `installSettingsSection` / `settingsNamespace` 在 dsh 0.1.7 起已从 `@deepseek-ai/dsh-settings` 移除,宿主半区在 ESM 链接期报错,整条 `webchat` entry `failed to import`,插件**完全不加载** | 改为使用 Loader 自带的设置表单(命名空间 = profile entry id,schema = 本包导出的 `Config`),插件不再自行注册设置段 |
|
|
13
|
-
| 转移到 harness | `sessionPersistence.load(id)` / `persistence.append(id, events)` 在 dsh 0.2.x 已改为**句柄式** API,调用即抛错 | 迁到 `open(id, 'write')` / `create(header)` 返回的 `SessionHandle`,用 `handle.read` / `append` / `flush` / `close` |
|
|
14
|
-
| 依赖声明 | `devDependencies` 停留在 `@deepseek-ai/*: ^0.1.0-rc.7` | 更新到 0.2.x,并补上运行时 `peerDependencies` 与 `engines.dsh` |
|
|
9
|
+
两条路都被封死了,这是实测结论而非选择:
|
|
15
10
|
|
|
16
|
-
|
|
11
|
+
- `chat.deepseek.com` 返回 **`Content-Security-Policy: frame-ancestors 'none'`** —— 任何 iframe 嵌入都会被浏览器拒绝;
|
|
12
|
+
- DSH 桌面端两个窗口都是 **`webviewTag: false`**,且 `will-attach-webview` 被显式拦截 —— `<webview>` 也不可用。
|
|
17
13
|
|
|
18
|
-
|
|
14
|
+
所以忠实呈现官方页面的唯一方式就是开一个真实窗口。
|
|
19
15
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
## 打开顺序
|
|
17
|
+
|
|
18
|
+
按钮会按顺序尝试,第一个成功的生效,面板上会显示实际用了哪种:
|
|
19
|
+
|
|
20
|
+
1. **`app-window`** —— 由 DSH 桌面端进程直接创建的窗口(桌面端就是 Electron)。已经开着就聚焦,不会重复开第二个。
|
|
21
|
+
2. **`app-window-shell`** —— 无边框的 Edge/Chrome 窗口(`--app=`),使用独立 `--user-data-dir`(`~/.dsh/dsh-webchat/app-window`),因此登录态与你的日常浏览器互不干扰。用于第 1 种被宿主拒绝的场景。
|
|
22
|
+
3. **`system-browser`** —— 交给操作系统默认浏览器,保证按钮任何时候都有反应。
|
|
23
|
+
|
|
24
|
+
登录一次即可:窗口自己的 profile 会保留登录态。
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
## 安装
|
|
25
27
|
|
|
26
28
|
```bash
|
|
27
|
-
dsh plugin --profile desktop add
|
|
29
|
+
dsh plugin --profile desktop add @jaychang1989/dsh-webchat
|
|
28
30
|
```
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
**从上游切换过来时**:上游包与本包都插入 `id: webchat` 这一行,同一个 profile 里同时存在会因 entry id 重复而在启动时报错。请先移除上游包:
|
|
32
|
+
或直接从仓库安装:
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
|
-
dsh plugin --profile desktop remove dsh-webchat
|
|
36
35
|
dsh plugin --profile desktop add github:jaychang1989/dsh-webchat
|
|
37
36
|
```
|
|
38
37
|
|
|
39
|
-
|
|
38
|
+
> npm 包名带 scope,因为不带 scope 的 `dsh-webchat` 属于已停止维护的上游项目。scope 不影响插件身份:entry id 仍是 `webchat`。
|
|
40
39
|
|
|
41
|
-
|
|
40
|
+
**从上游或本插件 0.3.x 切换过来时**:它们都插入 `id: webchat` 这一行,同一个 profile 里不能并存(entry id 重复会在启动时报错)。先移除旧的再加新的,然后重启桌面端。
|
|
42
41
|
|
|
43
|
-
|
|
44
|
-
2. 点击「打开登录窗口」,在弹出的浏览器中完成 DeepSeek 网页登录。
|
|
45
|
-
3. 登录成功后窗口会自动关闭,之后即可正常聊天 / 转移。
|
|
42
|
+
## 使用
|
|
46
43
|
|
|
47
|
-
|
|
44
|
+
1. 点侧边栏的「DeepSeek 网页」入口;
|
|
45
|
+
2. 点面板里的「打开 chat.deepseek.com」;
|
|
46
|
+
3. 在弹出的窗口里登录一次,之后正常使用官方网页版。
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
- **转移到 Harness**:一键把当前网页对话蒸馏成任务简报(首条消息即简报)并创建新 harness 会话继续开发,或「延续到已有会话」——把简报作为新消息追加进指定会话;转移时可选择目标工作区(未选则归入「未分组」)。
|
|
51
|
-
- **从网页恢复会话**:把网页端已存在但本地未收录的会话拉回本地存储(面板「从网页恢复」按钮 / `webchat_recover`)。
|
|
52
|
-
- **导入为上下文**:把存储的网页对话导出为 markdown 上下文。
|
|
53
|
-
- **Agent 工具**:`webchat_status` / `webchat_send` / `webchat_recover` / `webchat_import` / `webchat_transfer`,harness agent 可直接调用。
|
|
54
|
-
- **无感登录**:首次使用弹出可见浏览器窗口完成登录,登录后窗口自动关闭,后续聊天在无头浏览器中进行。
|
|
48
|
+
## 与 0.3.x 的差异(这是一次大幅删减)
|
|
55
49
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
50
|
+
| 0.3.x | 0.4.0 |
|
|
51
|
+
| --- | --- |
|
|
52
|
+
| 用 Playwright 驱动网页,自研聊天面板重新渲染消息 | 不再驱动网页,直接开官方页面;自研面板删除 |
|
|
53
|
+
| 5 个 agent 工具(`webchat_status/send/recover/import/transfer`) | 全部删除 |
|
|
54
|
+
| 「转移到 harness」「从网页恢复」「导入」「导出」 | 全部删除 |
|
|
55
|
+
| 本地会话存储 `~/.dsh/dsh-webchat/transcripts.json` | 删除(只留窗口 profile 目录) |
|
|
56
|
+
| 15 条 `/api/dsh-webchat/*` 路由 | 只剩 2 条:`state` / `open` |
|
|
57
|
+
| 依赖 `playwright-core`,客户端产物需 React + 构建器 | **零运行时依赖**,客户端为纯 DOM,无构建步骤 |
|
|
58
|
+
| 约 3800 行(构建产物) | 约 700 行(手写 JS) |
|
|
59
59
|
|
|
60
60
|
## 环境要求
|
|
61
61
|
|
|
62
62
|
- DeepSeek Harness **0.2.0-rc.1 或更新的 0.2.x**
|
|
63
63
|
- Node.js >= 22
|
|
64
|
-
-
|
|
65
|
-
- 首次登录需要可交互的图形环境(弹出登录窗口)
|
|
64
|
+
- 第 2 种策略(无边框窗口)需要本机装有 Edge 或 Chrome;第 1 种策略不需要
|
|
66
65
|
|
|
67
66
|
## 限制
|
|
68
67
|
|
|
69
|
-
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
|
|
73
|
-
## 开发
|
|
68
|
+
- 官方网页端受 DeepSeek 官方风控;页面打不开时插件只负责把页面交出去,不介入其登录或请求。
|
|
69
|
+
- 第 1 种策略创建的窗口由 DSH 进程拥有:若你先关掉 DSH 主窗口、而它仍开着,DSH 不会退出(Electron 的 `window-all-closed` 语义)。关掉该窗口即可。
|
|
70
|
+
- 插件被重载时不会主动关闭已经打开的窗口(避免一次设置变更就关掉你正在看的会话)。
|
|
74
71
|
|
|
75
|
-
|
|
72
|
+
## 开发与测试
|
|
76
73
|
|
|
77
74
|
```bash
|
|
78
|
-
node --test #
|
|
75
|
+
node --test # 11 个用例:宿主路由、窗口策略选择、浏览器半区在 DOM 桩里的挂载与按钮行为
|
|
79
76
|
```
|
|
80
77
|
|
|
78
|
+
没有构建步骤:`lib/index.js` 与 `lib/client.js` 就是手写的运行时代码。详见 [MAINTAINING.md](./MAINTAINING.md)。
|
|
79
|
+
|
|
81
80
|
## License
|
|
82
81
|
|
|
83
82
|
[Apache-2.0](./LICENSE) — 原始版权归 [xmuwenxiang/dsh-web-chat](https://github.com/xmuwenxiang/dsh-web-chat) 作者所有,详见 [NOTICE](./NOTICE)。
|
package/cordis.patch.yml
CHANGED
|
@@ -6,13 +6,14 @@
|
|
|
6
6
|
# dsh plugin --profile <name> add github:jaychang1989/dsh-webchat
|
|
7
7
|
#
|
|
8
8
|
# The row is a bare plugin by package name: the node half (exports ".") runs in
|
|
9
|
-
# the host process
|
|
10
|
-
#
|
|
11
|
-
# half (exports "./client", served at /plugins/<id>/client.js) load in
|
|
12
|
-
# GUI. `name` must be this package's
|
|
13
|
-
# included) — dsh-client-modules keys every
|
|
14
|
-
# registers its factory under the same id.
|
|
15
|
-
# 0.1.7 also uses it as the settings form
|
|
9
|
+
# the host process — it registers the two /api/dsh-webchat routes and opens the
|
|
10
|
+
# page in a window — and the `dsh.client` declaration in package.json makes the
|
|
11
|
+
# browser half (exports "./client", served at /plugins/<id>/client.js) load in
|
|
12
|
+
# the web GUI as the sidebar entry and its panel. `name` must be this package's
|
|
13
|
+
# manifest name verbatim (scoped names included) — dsh-client-modules keys every
|
|
14
|
+
# browser row by it, and lib/client.js registers its factory under the same id.
|
|
15
|
+
# `id` is the profile entry id; dsh >= 0.1.7 also uses it as the settings form
|
|
16
|
+
# namespace, so keep it stable.
|
|
16
17
|
#
|
|
17
18
|
# Note: the upstream package xmuwenxiang/dsh-web-chat inserts the same
|
|
18
19
|
# `id: webchat`. Do not keep both installed in one profile — a duplicate entry
|