dsh-bingo-ren 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md ADDED
@@ -0,0 +1,99 @@
1
+ # Bingo — one-click restart for DeepSeek Harness
2
+
3
+ A draggable Bingo button that restarts the desktop app and prompts when new plugins are installed.
4
+
5
+ [中文说明](README.md) · [GitHub Releases](https://github.com/kongkongya367-glitch/dsh-bingo-ren/releases)
6
+
7
+ ## Features
8
+
9
+ - Open the panel and click **Bingo 一下** to restart the entire desktop app.
10
+ - Detect new plugins while the app runs; **稍后** (Later) acknowledges the current set.
11
+ - Drag the button, snap it near an edge, and remember its position.
12
+ - Open with `Ctrl+Alt+B` (`Cmd+Alt+B` on macOS).
13
+ - Light/dark themes, zero runtime dependencies, no telemetry.
14
+
15
+ ## Preview
16
+
17
+ | Button | Panel | New plugin |
18
+ | --- | --- | --- |
19
+ | <img src="assets/screenshot-button.png" width="280" alt="Bingo button"> | <img src="assets/screenshot-panel.png" width="280" alt="Bingo panel"> | <img src="assets/screenshot-new-plugin.png" width="280" alt="New plugin dialog"> |
20
+
21
+ Images use mock data. The button, panel and dialog images are design renders; the [drag example](assets/screenshot-dragged.png) is a browser capture of the mock preview page.
22
+
23
+ ## Install
24
+
25
+ In **Settings → Plugins → Add plugin**, enter:
26
+
27
+ ```text
28
+ dsh-bingo-ren
29
+ ```
30
+
31
+ You can also install using the [GitHub repository URL](https://github.com/kongkongya367-glitch/dsh-bingo-ren). Quit and reopen DeepSeek Harness once after installation so Bingo can load.
32
+
33
+ Manage the running desktop profile through the app. The CLI is for separate web or test profiles:
34
+
35
+ ```sh
36
+ dsh plugin --profile bingo-selftest add dsh-bingo-ren
37
+ ```
38
+
39
+ For a local source install, see the [development notes](https://github.com/kongkongya367-glitch/dsh-bingo-ren/blob/main/SPEC.md).
40
+
41
+ ## Use and limitations
42
+
43
+ Click **Bingo**, then **Bingo 一下**. The panel is the confirmation step.
44
+
45
+ **Restart interrupts running tasks.** Save your work first. If a restart fails, the panel recovers and allows another attempt. Diagnostics are in `~/.dsh/bingo/restart.log`.
46
+
47
+ The new-plugin dialog offers **立即 Bingo** (Restart now) and **稍后** (Later). Escape and clicking the backdrop also dismiss it. Plugins installed while the app is closed become the next startup baseline. A prompt indicates a new manifest entry; whether a restart is necessary depends on the plugin and host loading behavior.
48
+
49
+ Full restart requires the official Electron desktop app. Web mode disables restart and offers a page refresh. The interface currently uses Chinese labels.
50
+
51
+ ## Plugin management
52
+
53
+ Open **插件记录 · 试用 · 验收** in the Bingo panel.
54
+
55
+ - **History:** records observed additions, declared-version changes, removals and trial decisions per profile. Keeps 200 entries locally and shows the newest 100. The first run establishes a baseline; unchanged manifest ranges with changed lockfile resolutions are not detected.
56
+ - **Trials:** mark an installed plugin, or mark newly added plugins from the prompt. On the next app boot, choose Keep, Ask next boot, or Remove. Removal needs explicit confirmation and uses the native host manager. Changed version declarations require re-marking first; Bingo cannot trial-remove itself. Trials do not isolate permissions or automatically uninstall packages.
57
+ - **Acceptance:** shows up to 30 recently changed plugins, or current plugins when no changes exist. Reads native bundle and live-entry state: active, failed, disabled, pending or unknown. Active means host entries are running; it does not independently verify business behavior or the loaded code version. Missing host information and client-only bundles are not treated as success.
58
+
59
+ History and trial state remain on this machine and do not include conversations. A confirmed removal delegates package operations to the host, which may use its configured registry. Protected or in-use plugins may require removal through the native plugin page.
60
+
61
+ ## Configuration
62
+
63
+ Configure the plugin row in the profile's `cordis.patch.yml`:
64
+
65
+ ```yaml
66
+ - id: dsh-bingo-ren
67
+ config:
68
+ enabled: true
69
+ pollMs: 4000 # 1500–60000 milliseconds
70
+ allowRestart: true
71
+ position: bottom-left # or bottom-right
72
+ debug: false
73
+ ```
74
+
75
+ `confirm` is reserved; the current client always opens the panel first.
76
+
77
+ ## Uninstall
78
+
79
+ Remove Bingo in **Settings → Plugins**, then restart the app once. For a source install made with the local script, quit the app first and run:
80
+
81
+ ```powershell
82
+ powershell -NoProfile -ExecutionPolicy Bypass -File scripts/install-local-desktop.ps1 -Uninstall
83
+ ```
84
+
85
+ The local uninstaller removes only Bingo's dependency, bundle entry and package directory, preserving other plugin configuration. Optionally remove `~/.dsh/bingo/` to clear detection state and logs.
86
+
87
+ ## Privacy and compatibility
88
+
89
+ Bingo reads the local profile manifest and uses same-origin `/bingo/*` routes. It sends no telemetry, loads no third-party assets, and stores state and logs locally.
90
+
91
+ Requires Node.js 20+ and DeepSeek Harness 0.2.0-rc.1+. Uses public Cordis APIs without modifying DSH core.
92
+
93
+ ## Troubleshooting
94
+
95
+ - No button: restart once after installation and confirm the plugin is enabled.
96
+ - Restart disabled: use the desktop app and check `allowRestart`.
97
+ - Restart failed: inspect `~/.dsh/bingo/restart.log`, resolve executable or permission problems, and retry.
98
+
99
+ [MIT License](LICENSE)
package/README.md CHANGED
@@ -1,89 +1,122 @@
1
- # Bingo — one-click restart for DeepSeek Harness
1
+ # Bingo — DeepSeek Harness 插件管家
2
2
 
3
- A draggable Bingo button that restarts the desktop app and prompts when new plugins are installed.
3
+ 一个可拖动的 Bingo 按钮,集中处理重启提醒、插件变更记录、临时试用和运行状态验收。
4
4
 
5
- [中文说明](README.zh.md) · [GitHub Releases](https://github.com/kongkongya367-glitch/dsh-bingo-ren/releases)
5
+ [English](README.en.md) · [版本与下载](https://github.com/kongkongya367-glitch/dsh-bingo-ren/releases)
6
6
 
7
- ## Features
7
+ ## 功能
8
8
 
9
- - Open the panel and click **Bingo 一下** to restart the entire desktop app.
10
- - Detect new plugins while the app runs; **稍后** (Later) acknowledges the current set.
11
- - Drag the button, snap it near an edge, and remember its position.
12
- - Open with `Ctrl+Alt+B` (`Cmd+Alt+B` on macOS).
13
- - Light/dark themes, zero runtime dependencies, no telemetry.
9
+ - 点击按钮打开面板,再点「Bingo 一下」重启桌面应用。
10
+ - 运行期间检测到新插件时弹窗提醒;「稍后」只确认当前这组插件。
11
+ - 按钮支持拖动、靠近边缘时吸附,并记住位置。
12
+ - `Ctrl+Alt+B` 打开面板,macOS 使用 `Cmd+Alt+B`。
13
+ - 插件变更记录跨重启保留,支持安装后标记临时试用。
14
+ - 验收清单读取宿主报告的运行状态,帮助排查加载问题。
15
+ - 适配深浅色主题,零运行时依赖,无遥测。
14
16
 
15
- ## Preview
17
+ ## 预览
16
18
 
17
- | Button | Panel | New plugin |
19
+ | 按钮 | 面板 | 新插件提醒 |
18
20
  | --- | --- | --- |
19
- | <img src="assets/screenshot-button.png" width="280" alt="Bingo button"> | <img src="assets/screenshot-panel.png" width="280" alt="Bingo panel"> | <img src="assets/screenshot-new-plugin.png" width="280" alt="New plugin dialog"> |
21
+ | <img src="assets/screenshot-button.png" width="280" alt="Bingo 按钮"> | <img src="assets/screenshot-panel.png" width="280" alt="Bingo 面板"> | <img src="assets/screenshot-new-plugin.png" width="280" alt="新插件提醒"> |
20
22
 
21
- Images use mock data. The button, panel and dialog images are design renders; the [drag example](assets/screenshot-dragged.png) is a browser capture of the mock preview page.
23
+ 图片使用模拟数据。按钮、面板和弹窗是设计渲染;[拖动示例](assets/screenshot-dragged.png) 是模拟预览页的浏览器截图。
22
24
 
23
- ## Install
25
+ ## 安装
24
26
 
25
- In **Settings → Plugins → Add plugin**, enter:
27
+ 在 **设置 → 插件 → 添加插件** 中输入:
26
28
 
27
29
  ```text
28
30
  dsh-bingo-ren
29
31
  ```
30
32
 
31
- You can also install using the [GitHub repository URL](https://github.com/kongkongya367-glitch/dsh-bingo-ren). Quit and reopen DeepSeek Harness once after installation so Bingo can load.
33
+ 也可使用 [GitHub 仓库地址](https://github.com/kongkongya367-glitch/dsh-bingo-ren) 安装。安装完成后,手动退出并重新打开 DeepSeek Harness 一次,让 Bingo 加载。
32
34
 
33
- Manage the running desktop profile through the app. The CLI is for separate web or test profiles:
35
+ 运行中的桌面 profile 应通过应用内插件页管理。CLI 仅用于独立的 Web 或测试 profile:
34
36
 
35
37
  ```sh
36
38
  dsh plugin --profile bingo-selftest add dsh-bingo-ren
37
39
  ```
38
40
 
39
- For a local source install, see the [development notes](https://github.com/kongkongya367-glitch/dsh-bingo-ren/blob/main/SPEC.md).
41
+ 源码的本地安装方法见 [开发说明](https://github.com/kongkongya367-glitch/dsh-bingo-ren/blob/main/SPEC.md)。
40
42
 
41
- ## Use and limitations
43
+ ## 使用与限制
42
44
 
43
- Click **Bingo**, then **Bingo 一下**. The panel is the confirmation step.
45
+ 点击 Bingo 打开面板,再点「Bingo 一下」即可重启;面板本身就是确认步骤。
44
46
 
45
- **Restart interrupts running tasks.** Save your work first. If a restart fails, the panel recovers and allows another attempt. Diagnostics are in `~/.dsh/bingo/restart.log`.
47
+ **重启会中断正在执行的任务。** 保存工作后再操作。若重启失败,面板会恢复并允许重试;诊断日志位于 `~/.dsh/bingo/restart.log`。
46
48
 
47
- The new-plugin dialog offers **立即 Bingo** (Restart now) and **稍后** (Later). Escape and clicking the backdrop also dismiss it. Plugins installed while the app is closed become the next startup baseline. A prompt indicates a new manifest entry; whether a restart is necessary depends on the plugin and host loading behavior.
49
+ 检测到新插件时,可以立即重启,也可以点「稍后」、按 `Esc` 或点击遮罩。应用关闭期间安装的插件会在下次启动时成为基线,不重复提醒。提醒表示插件清单发生新增;是否必须重启取决于插件和宿主的加载方式。
48
50
 
49
- Full restart requires the official Electron desktop app. Web mode disables restart and offers a page refresh. The interface currently uses Chinese labels.
51
+ 完整重启仅支持官方 Electron 桌面端。在 Web 模式中重启不可用,面板提供刷新页面。
50
52
 
51
- ## Configuration
53
+ ## 插件管家
52
54
 
53
- Configure the plugin row in the profile's `cordis.patch.yml`:
55
+ 点击 Bingo 面板中的「插件记录 · 试用 · 验收」打开插件管家。
56
+
57
+ | 变更记录 | 临时试用 | 验收清单 |
58
+ | --- | --- | --- |
59
+ | <img src="assets/screenshot-history.png" width="260" alt="插件变更记录"> | <img src="assets/screenshot-trials.png" width="260" alt="临时试用与保留、移除操作"> | <img src="assets/screenshot-checks.png" width="260" alt="插件运行状态验收"> |
60
+
61
+ 以上为真实浏览器中的模拟场景,不包含真实账号或插件数据。
62
+
63
+ ### 变更记录
64
+
65
+ 记录安装、清单版本变更和移除,以及试用开始与保留等操作。记录按当前 profile 分开保存在本机,重启后保留;最多保存 200 条,界面展示最近 100 条。首次启用只建立基线,不追溯此前的历史。
66
+
67
+ 版本变更比较的是清单声明,无法发现版本范围不变但锁文件实际解析版本变化的更新。应用关闭期间发生的变化会在下次启动时比较并标记为「启动时发现」。
68
+
69
+ ### 临时试用
70
+
71
+ - 在「临时试用」中选择已安装插件并标记,或在新插件弹窗点击「本次新增设为试用」。
72
+ - 下次启动时提醒选择「保留」「下次启动再问」或「移除」。
73
+ - 「保留」只结束试用提醒;「移除」需要再次确认,并交由 Harness 原生插件管理器处理。
74
+ - 安装声明变更后必须重新标记,避免误删替换后的版本。Bingo 本身不支持试用移除。
75
+
76
+ 试用不隔离插件权限,也不会自动删除插件。宿主不支持移除、插件受到保护或仍被占用时,请到 Harness 插件页处理。依赖清理由宿主管理器负责,插件产生的数据是否清理由该插件决定。
77
+
78
+ ### 验收清单
79
+
80
+ 展示最近变更的插件,最多 30 个;无变更时检查当前插件。根据宿主插件管理接口显示:运行中、加载失败、已禁用、等待启动或无法确认。
81
+
82
+ 「运行中」仅说明对应的宿主条目已启动,不代表业务功能或运行代码版本已独立测试。仅有安装文件、仅客户端插件或宿主未提供足够信息时,不会误报为通过。点击「刷新」重新读取当前状态。
83
+
84
+ ## 配置
85
+
86
+ 在 profile 的 `cordis.patch.yml` 中配置:
54
87
 
55
88
  ```yaml
56
89
  - id: dsh-bingo-ren
57
90
  config:
58
91
  enabled: true
59
- pollMs: 4000 # 1500–60000 milliseconds
92
+ pollMs: 4000 # 检测间隔,1500–60000 毫秒
60
93
  allowRestart: true
61
- position: bottom-left # or bottom-right
94
+ position: bottom-left # 或 bottom-right
62
95
  debug: false
63
96
  ```
64
97
 
65
- `confirm` is reserved; the current client always opens the panel first.
98
+ `confirm` 为保留选项;当前版本始终先显示面板。
66
99
 
67
- ## Uninstall
100
+ ## 卸载
68
101
 
69
- Remove Bingo in **Settings → Plugins**, then restart the app once. For a source install made with the local script, quit the app first and run:
102
+ 在 **设置 → 插件** 中移除 Bingo,再重启一次应用。若使用源码中的本地安装脚本,请先退出应用,再执行:
70
103
 
71
104
  ```powershell
72
105
  powershell -NoProfile -ExecutionPolicy Bypass -File scripts/install-local-desktop.ps1 -Uninstall
73
106
  ```
74
107
 
75
- The local uninstaller removes only Bingo's dependency, bundle entry and package directory, preserving other plugin configuration. Optionally remove `~/.dsh/bingo/` to clear detection state and logs.
108
+ 本地卸载只移除 Bingo 的依赖、bundle 条目和包目录,保留其他插件配置。可选删除 `~/.dsh/bingo/` 清理检测状态与日志。
76
109
 
77
- ## Privacy and compatibility
110
+ ## 隐私与兼容性
78
111
 
79
- Bingo reads the local profile manifest and uses same-origin `/bingo/*` routes. It sends no telemetry, loads no third-party assets, and stores state and logs locally.
112
+ Bingo 读取本地 profile 清单及宿主插件状态,界面访问同源 `/bingo/*` 接口。变更记录、试用状态与日志仅保存在本机,不记录聊天,不发送遥测。用户确认移除时,由宿主管理器执行包管理操作,可能涉及其配置的注册表。
80
113
 
81
- Requires Node.js 20+ and DeepSeek Harness 0.2.0-rc.1+. Uses public Cordis APIs without modifying DSH core.
114
+ 需要 Node.js 20+、DeepSeek Harness 0.2.0-rc.1+。使用公开 Cordis 接口,不修改 DSH 核心。
82
115
 
83
- ## Troubleshooting
116
+ ## 排查
84
117
 
85
- - No button: restart once after installation and confirm the plugin is enabled.
86
- - Restart disabled: use the desktop app and check `allowRestart`.
87
- - Restart failed: inspect `~/.dsh/bingo/restart.log`, resolve executable or permission problems, and retry.
118
+ - 没有按钮:首次安装后手动重启,确认插件已启用。
119
+ - 重启不可用:确认是桌面端,且 `allowRestart` 未关闭。
120
+ - 重启失败:查看 `~/.dsh/bingo/restart.log`,排除可执行文件或权限问题后重试。
88
121
 
89
122
  [MIT License](LICENSE)
package/README.zh.md CHANGED
@@ -1,8 +1,8 @@
1
- # Bingo — DeepSeek Harness 一键重启插件
1
+ # Bingo — DeepSeek Harness 插件管家
2
2
 
3
- 在 DeepSeek Harness 中添加一个可拖动的 Bingo 按钮,支持整应用重启和新插件安装提醒。
3
+ 一个可拖动的 Bingo 按钮,集中处理重启提醒、插件变更记录、临时试用和运行状态验收。
4
4
 
5
- [English](README.md) · [GitHub Releases](https://github.com/kongkongya367-glitch/dsh-bingo-ren/releases)
5
+ [English](README.en.md) · [版本与下载](https://github.com/kongkongya367-glitch/dsh-bingo-ren/releases)
6
6
 
7
7
  ## 功能
8
8
 
@@ -10,6 +10,8 @@
10
10
  - 运行期间检测到新插件时弹窗提醒;「稍后」只确认当前这组插件。
11
11
  - 按钮支持拖动、靠近边缘时吸附,并记住位置。
12
12
  - `Ctrl+Alt+B` 打开面板,macOS 使用 `Cmd+Alt+B`。
13
+ - 插件变更记录跨重启保留,支持安装后标记临时试用。
14
+ - 验收清单读取宿主报告的运行状态,帮助排查加载问题。
13
15
  - 适配深浅色主题,零运行时依赖,无遥测。
14
16
 
15
17
  ## 预览
@@ -48,6 +50,37 @@ dsh plugin --profile bingo-selftest add dsh-bingo-ren
48
50
 
49
51
  完整重启仅支持官方 Electron 桌面端。在 Web 模式中重启不可用,面板提供刷新页面。
50
52
 
53
+ ## 插件管家
54
+
55
+ 点击 Bingo 面板中的「插件记录 · 试用 · 验收」打开插件管家。
56
+
57
+ | 变更记录 | 临时试用 | 验收清单 |
58
+ | --- | --- | --- |
59
+ | <img src="assets/screenshot-history.png" width="260" alt="插件变更记录"> | <img src="assets/screenshot-trials.png" width="260" alt="临时试用与保留、移除操作"> | <img src="assets/screenshot-checks.png" width="260" alt="插件运行状态验收"> |
60
+
61
+ 以上为真实浏览器中的模拟场景,不包含真实账号或插件数据。
62
+
63
+ ### 变更记录
64
+
65
+ 记录安装、清单版本变更和移除,以及试用开始与保留等操作。记录按当前 profile 分开保存在本机,重启后保留;最多保存 200 条,界面展示最近 100 条。首次启用只建立基线,不追溯此前的历史。
66
+
67
+ 版本变更比较的是清单声明,无法发现版本范围不变但锁文件实际解析版本变化的更新。应用关闭期间发生的变化会在下次启动时比较并标记为「启动时发现」。
68
+
69
+ ### 临时试用
70
+
71
+ - 在「临时试用」中选择已安装插件并标记,或在新插件弹窗点击「本次新增设为试用」。
72
+ - 下次启动时提醒选择「保留」「下次启动再问」或「移除」。
73
+ - 「保留」只结束试用提醒;「移除」需要再次确认,并交由 Harness 原生插件管理器处理。
74
+ - 安装声明变更后必须重新标记,避免误删替换后的版本。Bingo 本身不支持试用移除。
75
+
76
+ 试用不隔离插件权限,也不会自动删除插件。宿主不支持移除、插件受到保护或仍被占用时,请到 Harness 插件页处理。依赖清理由宿主管理器负责,插件产生的数据是否清理由该插件决定。
77
+
78
+ ### 验收清单
79
+
80
+ 展示最近变更的插件,最多 30 个;无变更时检查当前插件。根据宿主插件管理接口显示:运行中、加载失败、已禁用、等待启动或无法确认。
81
+
82
+ 「运行中」仅说明对应的宿主条目已启动,不代表业务功能或运行代码版本已独立测试。仅有安装文件、仅客户端插件或宿主未提供足够信息时,不会误报为通过。点击「刷新」重新读取当前状态。
83
+
51
84
  ## 配置
52
85
 
53
86
  在 profile 的 `cordis.patch.yml` 中配置:
@@ -76,7 +109,7 @@ powershell -NoProfile -ExecutionPolicy Bypass -File scripts/install-local-deskto
76
109
 
77
110
  ## 隐私与兼容性
78
111
 
79
- Bingo 只读取本地 profile 清单,并访问同源 `/bingo/*` 接口;不发送遥测,不加载第三方资源。状态与日志保存在本机。
112
+ Bingo 读取本地 profile 清单及宿主插件状态,界面访问同源 `/bingo/*` 接口。变更记录、试用状态与日志仅保存在本机,不记录聊天,不发送遥测。用户确认移除时,由宿主管理器执行包管理操作,可能涉及其配置的注册表。
80
113
 
81
114
  需要 Node.js 20+、DeepSeek Harness 0.2.0-rc.1+。使用公开 Cordis 接口,不修改 DSH 核心。
82
115
 
Binary file
Binary file
Binary file
@@ -1,2 +1,2 @@
1
1
  /*! dsh-bingo-ren | preview/src */
2
- :host{position:fixed !important;left:18px;bottom:64px;right:auto;top:auto;width:0 !important;height:0 !important;margin:0 !important;padding:0 !important;border:0 !important;display:block !important;overflow:visible !important;pointer-events:none !important;z-index:2147483000 !important;-webkit-app-region:no-drag}:host(.is-snapping){transition:left .18s cubic-bezier(.2,.8,.2,1),top .18s cubic-bezier(.2,.8,.2,1)}.r{--f:-apple-system,BlinkMacSystemFont,"Segoe UI Variable Text","Segoe UI","PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;--m:ui-monospace,"Cascadia Mono","SFMono-Regular",Consolas,"Liberation Mono",monospace;--i:#0f1115;--i2:#5d636a;--i3:#8b9198;--ih:#22262b;--oi:#fff;--s:#fff;--s2:#f5f6f7;--bd:rgba(15,17,21,.09);--bs:rgba(15,17,21,.16);--hv:rgba(15,17,21,.055);--a:#4d6bfe;--ok:#1f9d62;--w:#9a6412;--wb:#fdf8ed;--wbd:rgba(154,100,18,.2);--dg:#b42318;--dgb:rgba(180,35,24,.07);--sc:rgba(16,18,22,.3);--rs-scrim:rgba(249,250,251,.76);--shp:0 1px 2px rgba(16,18,22,.07),0 10px 26px -14px rgba(16,18,22,.42);--shph:0 2px 4px rgba(16,18,22,.07),0 16px 34px -16px rgba(16,18,22,.5);--shn:0 2px 6px rgba(16,18,22,.06),0 28px 64px -26px rgba(16,18,22,.42);--shd:0 4px 12px rgba(16,18,22,.08),0 44px 110px -32px rgba(16,18,22,.52);position:absolute;left:0;bottom:0;width:0;height:0;pointer-events:none;color-scheme:light;font-family:var(--f);color:var(--i);-webkit-font-smoothing:antialiased}.r *,.r *::before,.r *::after{box-sizing:border-box}.r svg{display:block;flex:none}.r [hidden]{display:none !important}.r[data-visible="false"]{display:none !important}.r[data-theme="dark"]{color-scheme:dark}.r[data-theme="dark"]{--i:#f2f4f6;--i2:#a8aeb5;--i3:#8f959d;--ih:#e2e5e8;--oi:#111315;--s:#1c1f23;--s2:#24282d;--bd:rgba(255,255,255,.1);--bs:rgba(255,255,255,.19);--hv:rgba(255,255,255,.06);--a:#7f95ff;--ok:#3ecf8e;--w:#e9b96b;--wb:rgba(233,185,107,.075);--wbd:rgba(233,185,107,.22);--dg:#ff9d95;--dgb:rgba(255,122,112,.09);--sc:rgba(5,6,8,.5);--rs-scrim:rgba(10,11,13,.6);--shp:0 1px 2px rgba(0,0,0,.4),0 12px 28px -14px rgba(0,0,0,.7);--shph:0 2px 4px rgba(0,0,0,.45),0 18px 38px -16px rgba(0,0,0,.8);--shn:0 2px 8px rgba(0,0,0,.35),0 30px 70px -24px rgba(0,0,0,.85);--shd:0 4px 14px rgba(0,0,0,.4),0 50px 120px -30px rgba(0,0,0,.9)}@media (prefers-color-scheme:dark){.r:not([data-theme="light"]){color-scheme:dark}}.p{position:absolute;left:0;top:0;display:inline-flex;align-items:center;gap:9px;height:44px;padding:0 16px 0 10px;border:1px solid var(--bd);border-radius:999px;background:var(--s);color:var(--i);font:500 13px/1 var(--f);letter-spacing:.005em;white-space:nowrap;cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none;pointer-events:auto;box-shadow:var(--shp);transition:transform .15s ease,box-shadow .18s ease,border-color .18s ease,background .18s ease}:host(.is-dragging) .p{cursor:grabbing;transition:none;transform:none}.p:hover{transform:translateY(-1px);border-color:var(--bs);box-shadow:var(--shph)}.p:active{transform:translateY(0) scale(.985)}.p:focus-visible{outline:2px solid var(--a);outline-offset:3px}.p[disabled]{opacity:.6;cursor:default;transform:none}.pl{font-weight:600;letter-spacing:.012em}.pd{display:none;width:6px;height:6px;margin-left:1px;border-radius:50%;background:#e3a03c;box-shadow:0 0 0 3px rgba(227,160,60,.16)}.p[data-pending="true"] .pd{display:block}.mk{display:grid;place-items:center;width:24px;height:24px;border-radius:8px;background:var(--i);color:var(--oi);transition:background .18s ease}.mk svg{width:13px;height:13px}.mks{width:22px;height:22px;border-radius:7px}.mks svg{width:12px;height:12px}.ps{display:none;width:12px;height:12px;border-radius:50%;border:1.5px solid currentColor;border-right-color:transparent;animation:bingo-spin .8s linear infinite}.p[data-loading="true"] .mk svg{display:none}.p[data-loading="true"] .ps{display:block}.pn{position:absolute;left:0;bottom:54px;width:312px;max-width:calc(100vw - 36px);padding:14px;border:1px solid var(--bd);border-radius:16px;background:var(--s);box-shadow:var(--shn);transform-origin:bottom left;pointer-events:auto;animation:pn-in .18s cubic-bezier(.2,.8,.2,1)}.hd{display:flex;align-items:center;gap:7px;min-height:22px}.ht{font-size:13.5px;font-weight:650;letter-spacing:-.005em}.vr{padding:1px 5px;border:1px solid var(--bd);border-radius:5px;background:var(--s2);color:var(--i3);font-size:10px;font-weight:500;line-height:1.5;font-variant-numeric:tabular-nums}.ib{display:grid;place-items:center;width:26px;height:26px;margin-left:auto;padding:0;border:0;border-radius:8px;background:transparent;color:var(--i3);cursor:pointer;transition:background .15s ease,color .15s ease}.ib:hover{background:var(--hv);color:var(--i)}.ib:focus-visible{outline:2px solid var(--a);outline-offset:-1px}.st{display:flex;align-items:center;gap:7px;min-height:18px;margin-top:12px;color:var(--i2);font-size:12px;line-height:1.45}.dt{width:6px;height:6px;flex:none;border-radius:50%;background:var(--i3)}.dt[data-tone="ok"]{background:var(--ok)}.dt[data-tone="warn"]{background:var(--w)}.pg{margin-top:12px;padding:10px 10px 8px;border:1px solid var(--wbd);border-radius:12px;background:var(--wb);animation:bingo-fade-in .2s ease-out}.pgh{display:flex;align-items:center;gap:6px;margin-bottom:6px}.pgt{color:var(--w);font-size:11.5px;font-weight:650;letter-spacing:.01em}.cnt{margin-left:auto;color:var(--w);font-size:10px;font-weight:500;opacity:.72;font-variant-numeric:tabular-nums}.pks{display:grid;gap:3px;margin:0;padding:0;list-style:none}.pk{display:flex;align-items:baseline;gap:8px;min-width:0;font-size:11.5px;line-height:1.55}.pkn{min-width:0;overflow:hidden;color:var(--i);font-family:var(--m);font-size:10.8px;text-overflow:ellipsis;white-space:nowrap}.pkv{flex:none;margin-left:auto;color:var(--i3);font-size:10.5px;font-variant-numeric:tabular-nums}.mo{margin-top:5px;color:var(--i3);font-size:10.5px;line-height:1.4}.ac{display:grid;gap:6px;margin-top:13px}.bt{position:relative;display:inline-flex;align-items:center;justify-content:center;gap:7px;width:100%;height:36px;padding:0 12px;border:1px solid transparent;border-radius:10px;font:600 12.5px/1 var(--f);letter-spacing:.005em;cursor:pointer;transition:background .15s ease,border-color .15s ease,opacity .15s ease,transform .1s ease}.bt:active:not(:disabled){transform:scale(.995)}.bt:focus-visible{outline:2px solid var(--a);outline-offset:2px}.bt:disabled{opacity:.42;cursor:default}.btp{background:var(--i);color:var(--oi);box-shadow:0 1px 2px rgba(16,18,22,.12)}.btp:hover:not(:disabled){background:var(--ih)}.btg{border-color:var(--bd);background:transparent;color:var(--i);font-weight:550}.btg:hover:not(:disabled){border-color:var(--bs);background:var(--hv)}.bts{display:none;width:12px;height:12px;border-radius:50%;border:1.5px solid currentColor;border-right-color:transparent;animation:bingo-spin .8s linear infinite}.bt[data-loading="true"] .bts{display:block}.nt{margin:9px 2px 0;color:var(--i3);font-size:10.8px;line-height:1.5;text-align:center}.er{margin:9px 0 0;padding:6px 8px;border-radius:8px;background:var(--dgb);color:var(--dg);font-size:11px;line-height:1.45}.mt{display:flex;align-items:center;gap:5px;margin-top:10px;color:var(--i3);font-size:10.8px;line-height:1.4}.mt svg{width:11px;height:11px;opacity:.75}.mt[data-failed="true"]{color:var(--w)}.ft{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:11px;padding-top:9px;border-top:1px solid var(--bd);color:var(--i3);font-size:10.5px;line-height:1.4}.kb{padding:1px 5px;border:1px solid var(--bd);border-radius:5px;background:var(--s2);color:var(--i2);font-family:var(--m);font-size:9.8px;letter-spacing:.01em;white-space:nowrap}.ly{position:fixed;inset:0;z-index:2;display:grid;place-items:center;padding:24px;pointer-events:auto}.lyd{background:var(--sc);-webkit-backdrop-filter:blur(6px) saturate(1.05);backdrop-filter:blur(6px) saturate(1.05);animation:bingo-fade-in .18s ease-out}.dlg{width:360px;max-width:100%;padding:20px;border:1px solid var(--bd);border-radius:18px;background:var(--s);box-shadow:var(--shd);outline:none;animation:dlg-in .22s cubic-bezier(.2,.8,.2,1)}.dli{display:grid;place-items:center;width:38px;height:38px;margin-bottom:13px;border:1px solid var(--wbd);border-radius:12px;background:var(--wb);color:var(--w)}.dli svg{width:18px;height:18px}.dlt2{margin:0;color:var(--i);font-size:15px;font-weight:650;line-height:1.35;letter-spacing:-.01em}.dld2{margin:5px 0 0;color:var(--i2);font-size:12.5px;line-height:1.55}.pksd{max-height:214px;margin-top:13px;padding:3px 0;overflow:auto;border:1px solid var(--bd);border-radius:11px;background:var(--s2)}.pksd .pk{padding:6px 10px;font-size:12px}.pksd .pk + .pk{border-top:1px solid var(--bd)}.pksd .pkn{font-size:11.5px}.mod{margin-top:7px;color:var(--i3);font-size:11px;line-height:1.4;text-align:center}.dla{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:16px}.dlh{margin:10px 0 0;color:var(--i3);font-size:10.8px;line-height:1.45;text-align:center}.lyr{z-index:3;background:var(--rs-scrim);-webkit-backdrop-filter:blur(10px) saturate(.9);backdrop-filter:blur(10px) saturate(.9);animation:bingo-fade-in .2s ease-out}.rs{display:grid;justify-items:center;gap:8px;width:300px;max-width:100%;padding:26px 30px;border:1px solid var(--bd);border-radius:16px;background:var(--s);box-shadow:var(--shd);text-align:center}.sp{width:26px;height:26px;margin-bottom:4px;border:2px solid var(--bs);border-top-color:var(--i);border-radius:50%;animation:bingo-spin .85s linear infinite}.rst{color:var(--i);font-size:13.5px;font-weight:650;line-height:1.4}.rsh{color:var(--i2);font-size:11.5px;line-height:1.5}.rsm{margin-top:2px;color:var(--i3);font-size:11px;line-height:1.55}.sr{position:absolute !important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}@keyframes pn-in{from{opacity:0;transform:translateY(6px) scale(.985)}to{opacity:1;transform:none}}@keyframes dlg-in{from{opacity:0;transform:translateY(8px) scale(.975)}to{opacity:1;transform:none}}@keyframes bingo-fade-in{from{opacity:0}to{opacity:1}}@keyframes bingo-spin{to{transform:rotate(360deg)}}@media (max-width:480px){:host{left:12px;bottom:64px}:host([data-position="bottom-right"]){left:auto;right:12px}.pn{width:calc(100vw - 24px);max-width:calc(100vw - 24px);bottom:54px}.dlg{padding:18px}.dla{grid-template-columns:1fr}}@media (max-height:560px){.pn{max-height:calc(100vh - 190px);overflow:auto;overscroll-behavior:contain}}@media (prefers-reduced-motion:reduce){:host(.is-snapping){transition-duration:.001ms !important}.r *,.r *::before,.r *::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;transition-duration:.001ms !important}}
2
+ :host{position:fixed !important;left:18px;bottom:64px;right:auto;top:auto;width:0 !important;height:0 !important;margin:0 !important;padding:0 !important;border:0 !important;display:block !important;overflow:visible !important;pointer-events:none !important;z-index:2147483000 !important;-webkit-app-region:no-drag}:host(.is-snapping){transition:left .18s cubic-bezier(.2,.8,.2,1),top .18s cubic-bezier(.2,.8,.2,1)}.r{--f:-apple-system,BlinkMacSystemFont,"Segoe UI Variable Text","Segoe UI","PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;--m:ui-monospace,"Cascadia Mono","SFMono-Regular",Consolas,"Liberation Mono",monospace;--i:#0f1115;--i2:#5d636a;--i3:#8b9198;--ih:#22262b;--oi:#fff;--s:#fff;--s2:#f5f6f7;--bd:rgba(15,17,21,.09);--bs:rgba(15,17,21,.16);--hv:rgba(15,17,21,.055);--a:#4d6bfe;--ok:#1f9d62;--w:#9a6412;--wb:#fdf8ed;--wbd:rgba(154,100,18,.2);--dg:#b42318;--dgb:rgba(180,35,24,.07);--sc:rgba(16,18,22,.3);--rs-scrim:rgba(249,250,251,.76);--shp:0 1px 2px rgba(16,18,22,.07),0 10px 26px -14px rgba(16,18,22,.42);--shph:0 2px 4px rgba(16,18,22,.07),0 16px 34px -16px rgba(16,18,22,.5);--shn:0 2px 6px rgba(16,18,22,.06),0 28px 64px -26px rgba(16,18,22,.42);--shd:0 4px 12px rgba(16,18,22,.08),0 44px 110px -32px rgba(16,18,22,.52);position:absolute;left:0;bottom:0;width:0;height:0;pointer-events:none;color-scheme:light;font-family:var(--f);color:var(--i);-webkit-font-smoothing:antialiased}.r *,.r *::before,.r *::after{box-sizing:border-box}.r svg{display:block;flex:none}.r [hidden]{display:none !important}.r[data-visible="false"]{display:none !important}.r[data-theme="dark"]{color-scheme:dark}.r[data-theme="dark"]{--i:#f2f4f6;--i2:#a8aeb5;--i3:#8f959d;--ih:#e2e5e8;--oi:#111315;--s:#1c1f23;--s2:#24282d;--bd:rgba(255,255,255,.1);--bs:rgba(255,255,255,.19);--hv:rgba(255,255,255,.06);--a:#7f95ff;--ok:#3ecf8e;--w:#e9b96b;--wb:rgba(233,185,107,.075);--wbd:rgba(233,185,107,.22);--dg:#ff9d95;--dgb:rgba(255,122,112,.09);--sc:rgba(5,6,8,.5);--rs-scrim:rgba(10,11,13,.6);--shp:0 1px 2px rgba(0,0,0,.4),0 12px 28px -14px rgba(0,0,0,.7);--shph:0 2px 4px rgba(0,0,0,.45),0 18px 38px -16px rgba(0,0,0,.8);--shn:0 2px 8px rgba(0,0,0,.35),0 30px 70px -24px rgba(0,0,0,.85);--shd:0 4px 14px rgba(0,0,0,.4),0 50px 120px -30px rgba(0,0,0,.9)}@media (prefers-color-scheme:dark){.r:not([data-theme="light"]){color-scheme:dark}}.p{position:absolute;left:0;top:0;display:inline-flex;align-items:center;gap:9px;height:44px;padding:0 16px 0 10px;border:1px solid var(--bd);border-radius:999px;background:var(--s);color:var(--i);font:500 13px/1 var(--f);letter-spacing:.005em;white-space:nowrap;cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none;pointer-events:auto;box-shadow:var(--shp);transition:transform .15s ease,box-shadow .18s ease,border-color .18s ease,background .18s ease}:host(.is-dragging) .p{cursor:grabbing;transition:none;transform:none}.p:hover{transform:translateY(-1px);border-color:var(--bs);box-shadow:var(--shph)}.p:active{transform:translateY(0) scale(.985)}.p:focus-visible{outline:2px solid var(--a);outline-offset:3px}.p[disabled]{opacity:.6;cursor:default;transform:none}.pl{font-weight:600;letter-spacing:.012em}.pd{display:none;width:6px;height:6px;margin-left:1px;border-radius:50%;background:#e3a03c;box-shadow:0 0 0 3px rgba(227,160,60,.16)}.p[data-pending="true"] .pd{display:block}.mk{display:grid;place-items:center;width:24px;height:24px;border-radius:8px;background:var(--i);color:var(--oi);transition:background .18s ease}.mk svg{width:13px;height:13px}.mks{width:22px;height:22px;border-radius:7px}.mks svg{width:12px;height:12px}.ps{display:none;width:12px;height:12px;border-radius:50%;border:1.5px solid currentColor;border-right-color:transparent;animation:bingo-spin .8s linear infinite}.p[data-loading="true"] .mk svg{display:none}.p[data-loading="true"] .ps{display:block}.pn{position:absolute;left:0;bottom:54px;width:312px;max-width:calc(100vw - 36px);padding:14px;border:1px solid var(--bd);border-radius:16px;background:var(--s);box-shadow:var(--shn);transform-origin:bottom left;pointer-events:auto;animation:pn-in .18s cubic-bezier(.2,.8,.2,1)}.bingo-manage{width:100%;margin-top:10px}.bingo-desk{width:min(680px,calc(100vw - 48px));max-height:calc(100vh - 48px);overflow:auto;padding:18px;border:1px solid var(--bd);border-radius:18px;background:var(--s);box-shadow:var(--shn);color:var(--i);pointer-events:auto}.bingo-tabs{display:flex;gap:6px;margin:16px 0 12px}.bingo-tabs button{flex:1;border:1px solid var(--bd);border-radius:9px;padding:9px 6px;color:var(--i2);background:var(--s2);cursor:pointer}.bingo-tabs button[aria-pressed="true"]{color:var(--oi);background:var(--i)}.bingo-tabs button:focus-visible,.bingo-select:focus-visible{outline:2px solid var(--a);outline-offset:2px}.bingo-desk-toolbar{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:12px;color:var(--i2)}.bingo-desk-toolbar .bt{width:auto;min-height:30px;flex:none;padding:5px 12px}.bingo-desk-content{margin-top:12px}.bingo-muted{font-size:12px;line-height:1.6;color:var(--i2);overflow-wrap:anywhere;margin:6px 0 10px}.bingo-record{padding:12px 0;border-bottom:1px solid var(--bd);font-size:13px;overflow-wrap:anywhere}.bingo-record strong{display:block;font-weight:600}.bingo-record-actions,.bingo-trial-controls{display:flex;gap:8px;flex-wrap:wrap;margin-top:8px}.bingo-record-actions .bt,.bingo-trial-controls .bt{width:auto;flex:none;min-height:32px;padding:5px 12px}.bingo-select{flex:1;min-width:120px;max-width:100%;border:1px solid var(--bd);border-radius:8px;color:var(--i);background:var(--s);padding:7px}.bingo-check-state{display:inline-block;padding:3px 8px;border-radius:6px;background:var(--s2);color:var(--i2);font-size:12px}.bingo-check-state[data-state="active"]{color:var(--ok)}.bingo-check-state[data-state="failed"]{color:var(--dg)}.bingo-check-state[data-state="pending"]{color:var(--w)}.hd{display:flex;align-items:center;gap:7px;min-height:22px}.ht{font-size:13.5px;font-weight:650;letter-spacing:-.005em}.vr{padding:1px 5px;border:1px solid var(--bd);border-radius:5px;background:var(--s2);color:var(--i3);font-size:10px;font-weight:500;line-height:1.5;font-variant-numeric:tabular-nums}.ib{display:grid;place-items:center;width:26px;height:26px;margin-left:auto;padding:0;border:0;border-radius:8px;background:transparent;color:var(--i3);cursor:pointer;transition:background .15s ease,color .15s ease}.ib:hover{background:var(--hv);color:var(--i)}.ib:focus-visible{outline:2px solid var(--a);outline-offset:-1px}.st{display:flex;align-items:center;gap:7px;min-height:18px;margin-top:12px;color:var(--i2);font-size:12px;line-height:1.45}.dt{width:6px;height:6px;flex:none;border-radius:50%;background:var(--i3)}.dt[data-tone="ok"]{background:var(--ok)}.dt[data-tone="warn"]{background:var(--w)}.pg{margin-top:12px;padding:10px 10px 8px;border:1px solid var(--wbd);border-radius:12px;background:var(--wb);animation:bingo-fade-in .2s ease-out}.pgh{display:flex;align-items:center;gap:6px;margin-bottom:6px}.pgt{color:var(--w);font-size:11.5px;font-weight:650;letter-spacing:.01em}.cnt{margin-left:auto;color:var(--w);font-size:10px;font-weight:500;opacity:.72;font-variant-numeric:tabular-nums}.pks{display:grid;gap:3px;margin:0;padding:0;list-style:none}.pk{display:flex;align-items:baseline;gap:8px;min-width:0;font-size:11.5px;line-height:1.55}.pkn{min-width:0;overflow:hidden;color:var(--i);font-family:var(--m);font-size:10.8px;text-overflow:ellipsis;white-space:nowrap}.pkv{flex:none;margin-left:auto;color:var(--i3);font-size:10.5px;font-variant-numeric:tabular-nums}.mo{margin-top:5px;color:var(--i3);font-size:10.5px;line-height:1.4}.ac{display:grid;gap:6px;margin-top:13px}.bt{position:relative;display:inline-flex;align-items:center;justify-content:center;gap:7px;width:100%;height:36px;padding:0 12px;border:1px solid transparent;border-radius:10px;font:600 12.5px/1 var(--f);letter-spacing:.005em;cursor:pointer;transition:background .15s ease,border-color .15s ease,opacity .15s ease,transform .1s ease}.bt:active:not(:disabled){transform:scale(.995)}.bt:focus-visible{outline:2px solid var(--a);outline-offset:2px}.bt:disabled{opacity:.42;cursor:default}.btp{background:var(--i);color:var(--oi);box-shadow:0 1px 2px rgba(16,18,22,.12)}.btp:hover:not(:disabled){background:var(--ih)}.btg{border-color:var(--bd);background:transparent;color:var(--i);font-weight:550}.btg:hover:not(:disabled){border-color:var(--bs);background:var(--hv)}.bts{display:none;width:12px;height:12px;border-radius:50%;border:1.5px solid currentColor;border-right-color:transparent;animation:bingo-spin .8s linear infinite}.bt[data-loading="true"] .bts{display:block}.nt{margin:9px 2px 0;color:var(--i3);font-size:10.8px;line-height:1.5;text-align:center}.er{margin:9px 0 0;padding:6px 8px;border-radius:8px;background:var(--dgb);color:var(--dg);font-size:11px;line-height:1.45}.mt{display:flex;align-items:center;gap:5px;margin-top:10px;color:var(--i3);font-size:10.8px;line-height:1.4}.mt svg{width:11px;height:11px;opacity:.75}.mt[data-failed="true"]{color:var(--w)}.ft{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:11px;padding-top:9px;border-top:1px solid var(--bd);color:var(--i3);font-size:10.5px;line-height:1.4}.kb{padding:1px 5px;border:1px solid var(--bd);border-radius:5px;background:var(--s2);color:var(--i2);font-family:var(--m);font-size:9.8px;letter-spacing:.01em;white-space:nowrap}.ly{position:fixed;inset:0;z-index:2;display:grid;place-items:center;padding:24px;pointer-events:auto}.lyd{background:var(--sc);-webkit-backdrop-filter:blur(6px) saturate(1.05);backdrop-filter:blur(6px) saturate(1.05);animation:bingo-fade-in .18s ease-out}.dlg{width:360px;max-width:100%;padding:20px;border:1px solid var(--bd);border-radius:18px;background:var(--s);box-shadow:var(--shd);outline:none;animation:dlg-in .22s cubic-bezier(.2,.8,.2,1)}.dli{display:grid;place-items:center;width:38px;height:38px;margin-bottom:13px;border:1px solid var(--wbd);border-radius:12px;background:var(--wb);color:var(--w)}.dli svg{width:18px;height:18px}.dlt2{margin:0;color:var(--i);font-size:15px;font-weight:650;line-height:1.35;letter-spacing:-.01em}.dld2{margin:5px 0 0;color:var(--i2);font-size:12.5px;line-height:1.55}.pksd{max-height:214px;margin-top:13px;padding:3px 0;overflow:auto;border:1px solid var(--bd);border-radius:11px;background:var(--s2)}.pksd .pk{padding:6px 10px;font-size:12px}.pksd .pk + .pk{border-top:1px solid var(--bd)}.pksd .pkn{font-size:11.5px}.mod{margin-top:7px;color:var(--i3);font-size:11px;line-height:1.4;text-align:center}.dla{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:16px}.dlh{margin:10px 0 0;color:var(--i3);font-size:10.8px;line-height:1.45;text-align:center}.lyr{z-index:3;background:var(--rs-scrim);-webkit-backdrop-filter:blur(10px) saturate(.9);backdrop-filter:blur(10px) saturate(.9);animation:bingo-fade-in .2s ease-out}.rs{display:grid;justify-items:center;gap:8px;width:300px;max-width:100%;padding:26px 30px;border:1px solid var(--bd);border-radius:16px;background:var(--s);box-shadow:var(--shd);text-align:center}.sp{width:26px;height:26px;margin-bottom:4px;border:2px solid var(--bs);border-top-color:var(--i);border-radius:50%;animation:bingo-spin .85s linear infinite}.rst{color:var(--i);font-size:13.5px;font-weight:650;line-height:1.4}.rsh{color:var(--i2);font-size:11.5px;line-height:1.5}.rsm{margin-top:2px;color:var(--i3);font-size:11px;line-height:1.55}.sr{position:absolute !important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}@keyframes pn-in{from{opacity:0;transform:translateY(6px) scale(.985)}to{opacity:1;transform:none}}@keyframes dlg-in{from{opacity:0;transform:translateY(8px) scale(.975)}to{opacity:1;transform:none}}@keyframes bingo-fade-in{from{opacity:0}to{opacity:1}}@keyframes bingo-spin{to{transform:rotate(360deg)}}@media (max-width:480px){:host{left:12px;bottom:64px}:host([data-position="bottom-right"]){left:auto;right:12px}.pn{width:calc(100vw - 24px);max-width:calc(100vw - 24px);bottom:54px}.dlg{padding:18px}.dla{grid-template-columns:1fr}}@media (max-height:560px){.pn{max-height:calc(100vh - 190px);overflow:auto;overscroll-behavior:contain}}@media (prefers-reduced-motion:reduce){:host(.is-snapping){transition-duration:.001ms !important}.r *,.r *::before,.r *::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;transition-duration:.001ms !important}}
@@ -1,2 +1,2 @@
1
1
  /*! dsh-bingo-ren | preview/src */
2
- (function(){'use strict';if(window.__DSH_BINGO_LOADED__)return;window.__DSH_BINGO_LOADED__=true;var VERSION=typeof window.__DSH_BINGO_VERSION__==='string'&&window.__DSH_BINGO_VERSION__?window.__DSH_BINGO_VERSION__:'0.1.2';var API='/bingo';var CSS_URL=typeof window.__DSH_BINGO_CLIENT_CSS__==='string'&&window.__DSH_BINGO_CLIENT_CSS__?window.__DSH_BINGO_CLIENT_CSS__:API+'/client.css?v='+encodeURIComponent(VERSION);var INITIAL_POSITION=window.__DSH_BINGO_POSITION__==='bottom-right'?'bottom-right':'bottom-left';var AUTO_DIALOG=window.__DSH_BINGO_NO_AUTO_DIALOG__!==true;var DEFAULT_POLL=4000;var MAX_RETRY=30000;var REQUEST_TIMEOUT=5000;var MANUAL_HINT_AFTER=12000;var PANEL_PENDING_LIMIT=4;var DIALOG_PENDING_LIMIT=6;var POS_KEY='dsh-bingo.position.v1';var SNAP_MARGIN=16;var SNAP_THRESHOLD=64;var DRAG_SLOP=4;var ICON_SPARK='<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 2.4c.47 4.74 3.86 8.13 8.6 8.6-4.74.47-8.13 3.86-8.6 8.6-.47-4.74-3.86-8.13-8.6-8.6 4.74-.47 8.13-3.86 8.6-8.6Z"/></svg>';var ICON_CLOSE='<svg viewBox="0 0 16 16" width="12" height="12" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" aria-hidden="true"><path d="M4 4l8 8M12 4l-8 8"/></svg>';var ICON_CLOCK='<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" aria-hidden="true"><circle cx="8" cy="8" r="5.6"/><path d="M8 5.2V8l1.9 1.3"/></svg>';var TEMPLATE=['<button class="p" data-el="pill" type="button" aria-label="Bingo:重启 DeepSeek Harness" aria-haspopup="dialog" aria-expanded="false">','<span class="mk" aria-hidden="true">'+ICON_SPARK+'<span class="ps"></span></span>','<span class="pl">Bingo</span>','<span class="pd" aria-hidden="true"></span>','</button>','<section class="pn" data-el="panel" role="dialog" aria-modal="false" aria-labelledby="ti" hidden>','<header class="hd">','<span class="mk mks" aria-hidden="true">'+ICON_SPARK+'</span>','<span class="ht" id="ti">Bingo</span>','<span class="vr" data-el="version">v'+VERSION+'</span>','<button class="ib" data-el="close" type="button" aria-label="关闭面板">'+ICON_CLOSE+'</button>','</header>','<div class="st"><span class="dt" data-el="statusDot" aria-hidden="true"></span><span data-el="status">正在读取 Bingo 状态…</span></div>','<div class="pg" data-el="pending" hidden>','<div class="pgh"><span class="pgt">检测到新插件</span><span class="cnt" data-el="pendingCount"></span></div>','<ul class="pks" data-el="pendingList"></ul>','<div class="mo" data-el="pendingMore" hidden></div>','</div>','<div class="ac">','<button class="bt btp" data-el="primary" type="button"><span class="bts" aria-hidden="true"></span><span data-el="primaryLabel">Bingo 一下</span></button>','<button class="bt btg" data-el="later" type="button">稍后</button>','<button class="bt btg" data-el="refresh" type="button" hidden>刷新页面</button>','</div>','<p class="nt" data-el="note">会中断正在进行的任务,约 3 秒恢复</p>','<p class="er" data-el="error" role="alert" hidden></p>','<div class="mt" data-el="meta" data-failed="false" hidden>'+ICON_CLOCK+'<span data-el="metaText"></span></div>','<footer class="ft"><span>快捷键</span><span class="kb" data-el="kbd">Ctrl + Alt + B</span></footer>','<p class="sr" data-el="live" role="status" aria-live="polite"></p>','</section>','<div class="ly lyd" data-el="dialogLayer" hidden>','<div class="dlg" data-el="dialog" role="alertdialog" aria-modal="true" aria-labelledby="dlt" aria-describedby="dld" tabindex="-1">','<div class="dli" aria-hidden="true">'+ICON_SPARK+'</div>','<h2 class="dlt2" id="dlt">检测到新插件</h2>','<p class="dld2" id="dld">是否要 Bingo 一下?重启 Harness 后新插件才会生效。</p>','<ul class="pks pksd" data-el="dialogList"></ul>','<div class="mo mod" data-el="dialogMore" hidden></div>','<div class="dla">','<button class="bt btp" data-el="dialogPrimary" type="button">立即 Bingo</button>','<button class="bt btg" data-el="dialogLater" type="button">稍后</button>','</div>','<p class="dlh">稍后可从左下角的 Bingo 面板随时处理</p>','</div>','</div>','<div class="ly lyr" data-el="restartLayer" hidden>','<div class="rs" data-el="restartCard" role="status" aria-live="assertive" tabindex="-1">','<span class="sp" aria-hidden="true"></span>','<div class="rst">正在重启 Harness</div>','<div class="rsh">页面会自动恢复,请稍候</div>','<div class="rsm" data-el="manualHint" hidden>如果长时间未恢复,请手动启动 DeepSeek Harness。</div>','</div>','</div>'].join('');var S={st:null,pd:null,v:VERSION,f:0,sh:false,pn:false,dl:false,dg:'',rs:false,restartCycle:0,bs:false,em:false,fl:false,tm:0,mt:0,pm:DEFAULT_POLL,sn:Object.create(null),pos:null,edge:null,posUser:false,drag:null,suppressClick:false,};var host=null;var shadow=null;var root=null;var link=null;var els={};var lastFocus=null;function el(tag,cls,text){var node=document.createElement(tag);if(cls)node.className=cls;if(text!=null)node.textContent=text;return node;}function clamp(value,min,max){return Math.min(max,Math.max(min,value));}function live(text){if(!els.live)return;els.live.textContent=text||'';}function detectTheme(){var forced=window.__DSH_BINGO_FORCE_THEME__;if(forced==='dark'||forced==='light')return forced;var html=document.documentElement;var body=document.body;var explicit=html.getAttribute('data-theme')||html.getAttribute('data-ds-theme-source');if(explicit!=='dark'&&explicit!=='light'&&body){explicit=body.getAttribute('data-theme')||body.getAttribute('data-ds-theme-source');}if(explicit==='dark'||explicit==='light')return explicit;if(html.classList.contains('dark')||(body&&body.classList.contains('dark')))return'dark';if(html.classList.contains('light'))return'light';if(body&&body.hasAttribute('data-ds-dark-theme'))return'dark';try{return window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light';}catch(err){return'light';}}function applyTheme(){if(!root)return;root.setAttribute('data-theme',detectTheme());}function viewportSize(){return{w:Math.max(0,window.innerWidth||(document.documentElement&&document.documentElement.clientWidth)||0),h:Math.max(0,window.innerHeight||(document.documentElement&&document.documentElement.clientHeight)||0)};}function pillSize(){var rect=els.pill?els.pill.getBoundingClientRect():null;return{w:(rect&&rect.width)||120,h:(rect&&rect.height)||44};}function edgeMargin(){return viewportSize().w<=480?12:SNAP_MARGIN;}function readSavedPosition(){try{var raw=window.localStorage&&window.localStorage.getItem(POS_KEY);if(!raw)return null;var value=JSON.parse(raw);if(!value||typeof value.x!=='number'||typeof value.y!=='number')return null;var edge=value.edge&&typeof value.edge==='object'?{h:value.edge.h==='left'||value.edge.h==='right'?value.edge.h:null,v:value.edge.v==='top'||value.edge.v==='bottom'?value.edge.v:null}:null;return{x:value.x,y:value.y,edge:edge};}catch(err){}return null;}function savePosition(pos){try{if(window.localStorage)window.localStorage.setItem(POS_KEY,JSON.stringify(pos));}catch(err){}}function currentEdge(x,y,size,vp,margin){var edge='free';if(x<=margin+SNAP_THRESHOLD)edge='left';else if(vp.w-(x+size.w)<=margin+SNAP_THRESHOLD)edge='right';if(y<=margin+SNAP_THRESHOLD)edge=edge==='free'?'top':edge+'-top';else if(vp.h-(y+size.h)<=margin+SNAP_THRESHOLD)edge=edge==='free'?'bottom':edge+'-bottom';return edge;}function setPosition(x,y,persist,edge){if(edge!==undefined)S.edge=edge;var vp=viewportSize();var size=pillSize();var margin=edgeMargin();var maxX=Math.max(margin,vp.w-size.w-margin);var maxY=Math.max(margin,vp.h-size.h-margin);var nx=Math.min(maxX,Math.max(margin,x));var ny=Math.min(maxY,Math.max(margin,y));S.pos={x:nx,y:ny};if(!host)return;host.style.left=nx+'px';host.style.top=ny+'px';host.style.right='auto';host.style.bottom='auto';host.setAttribute('data-edge',currentEdge(nx,ny,size,vp,margin));if(persist)savePosition({x:nx,y:ny,edge:S.edge||null});if(S.pn)positionPanel();}function applySaved(saved){var vp=viewportSize();var size=pillSize();var margin=edgeMargin();var x=saved.x;var y=saved.y;var edge=saved.edge||null;if(edge&&edge.h==='left')x=margin;else if(edge&&edge.h==='right')x=vp.w-size.w-margin;if(edge&&edge.v==='top')y=margin;else if(edge&&edge.v==='bottom')y=vp.h-size.h-margin;setPosition(x,y,false,edge);}function reapplySaved(){if(S.drag)return;var saved=readSavedPosition();if(saved)applySaved(saved);}function scheduleReapply(){try{if(document.fonts&&document.fonts.ready&&typeof document.fonts.ready.then==='function'){document.fonts.ready.then(reapplySaved).catch(function(){});}}catch(err){}window.setTimeout(reapplySaved,300);}function initPosition(){var saved=readSavedPosition();if(saved){S.posUser=true;applySaved(saved);scheduleReapply();return;}var vp=viewportSize();var size=pillSize();var x=INITIAL_POSITION==='bottom-right'?vp.w-18-size.w:18;setPosition(x,vp.h-64-size.h,false);}function snapToEdges(){if(!S.pos)return;var vp=viewportSize();var size=pillSize();var margin=edgeMargin();var x=S.pos.x;var y=S.pos.y;var dLeft=x-margin;var dRight=vp.w-(x+size.w)-margin;var dTop=y-margin;var dBottom=vp.h-(y+size.h)-margin;var nx=x;var ny=y;var hEdge=null;var vEdge=null;if(dLeft<=SNAP_THRESHOLD&&dLeft<=dRight){nx=margin;hEdge='left';}else if(dRight<=SNAP_THRESHOLD){nx=vp.w-size.w-margin;hEdge='right';}if(dTop<=SNAP_THRESHOLD&&dTop<=dBottom){ny=margin;vEdge='top';}else if(dBottom<=SNAP_THRESHOLD){ny=vp.h-size.h-margin;vEdge='bottom';}S.edge={h:hEdge,v:vEdge};if(host)host.classList.add('is-snapping');setPosition(nx,ny,true,S.edge);window.setTimeout(function(){if(host)host.classList.remove('is-snapping');},220);}function positionPanel(){if(!S.pn||!els.panel||els.panel.hidden)return;var button=els.pill.getBoundingClientRect();var panel=els.panel.getBoundingClientRect();var vp=viewportSize();var gap=10;var pad=8;var width=panel.width||312;var height=panel.height||200;var top=button.top-height-gap;if(top<pad)top=button.bottom+gap;var left=button.left;if(left+width>vp.w-pad)left=button.right-width;left=Math.max(pad,Math.min(left,Math.max(pad,vp.w-width-pad)));top=Math.max(pad,Math.min(top,Math.max(pad,vp.h-height-pad)));els.panel.style.position='fixed';els.panel.style.left=left+'px';els.panel.style.top=top+'px';els.panel.style.right='auto';els.panel.style.bottom='auto';els.panel.style.maxHeight=Math.max(160,vp.h-pad*2)+'px';els.panel.style.overflow='auto';els.panel.style.transformOrigin=(top<button.top?'bottom':'top')+' '+(left<button.left?'right':'left');}function onResize(){if(!S.pos)return;var vp=viewportSize();var size=pillSize();var margin=edgeMargin();var x=S.pos.x;var y=S.pos.y;if(S.edge&&S.edge.h==='left')x=margin;else if(S.edge&&S.edge.h==='right')x=vp.w-size.w-margin;else if(x<=margin+2)x=margin;else if(x+size.w>=vp.w-margin-2)x=vp.w-size.w-margin;if(S.edge&&S.edge.v==='top')y=margin;else if(S.edge&&S.edge.v==='bottom')y=vp.h-size.h-margin;else if(y<=margin+2)y=margin;else if(y+size.h>=vp.h-margin-2)y=vp.h-size.h-margin;setPosition(x,y,true,S.edge);if(S.pn)positionPanel();}function watchTheme(){try{if(typeof MutationObserver==='undefined')return;var observer=new MutationObserver(applyTheme);observer.observe(document.documentElement,{attributes:true,attributeFilter:['class','data-theme','data-ds-theme-source']});if(document.body){observer.observe(document.body,{attributes:true,attributeFilter:['class','data-theme','data-ds-dark-theme','data-ds-theme-source']});}}catch(err){}try{var mq=window.matchMedia('(prefers-color-scheme: dark)');if(mq.addEventListener)mq.addEventListener('change',applyTheme);else if(mq.addListener)mq.addListener(applyTheme);}catch(err){}}function request(path,init){var ctrl=null;var timer=0;try{if(typeof AbortController!=='undefined')ctrl=new AbortController();}catch(err){}var options={method:(init&&init.method)||'GET',cache:'no-store'};if(init&&init.body!=null){options.body=init.body;options.headers={'Content-Type':'application/json'};}if(ctrl){options.signal=ctrl.signal;timer=window.setTimeout(function(){try{ctrl.abort();}catch(err){}},REQUEST_TIMEOUT);}return fetch(path,options).then(function(res){if(timer)window.clearTimeout(timer);return res.json().catch(function(){return null;}).then(function(data){if(!res.ok){var error=new Error('HTTP '+res.status);error.status=res.status;error.data=data;throw error;}return data;});},function(error){if(timer)window.clearTimeout(timer);throw error;});}function nextRetry(){return Math.min(MAX_RETRY,2000*Math.pow(2,Math.max(0,S.f-1)));}function schedule(ms){if(S.tm)window.clearTimeout(S.tm);S.tm=0;if(document.hidden)return;S.tm=window.setTimeout(function(){S.tm=0;pollOnce(false);},Math.max(0,ms||0));}function pollOnce(force){if(S.fl)return;if(!force&&document.hidden)return;S.fl=true;var restartCycle=S.restartCycle;request(API+'/status').then(function(data){if(!data||data.ok===false)throw new Error('Bad status');S.f=0;S.st=data;S.pd=data.pending||null;if(typeof data.pollMs==='number')S.pm=clamp(data.pollMs,1500,60000);applyVersion(data.version);render();reveal();if(data.restarting)enterRestarting(true);else if(S.rs&&restartCycle===S.restartCycle)leaveRestarting();handlePending();if(!S.em){S.em=true;try{window.dispatchEvent(new CustomEvent('dsh-bingo:ready',{detail:{status:data}}));}catch(err){}}schedule(S.rs?1200:S.pm);}).catch(function(){S.f+=1;if(S.f>=3&&!S.rs)conceal();render();schedule(nextRetry());}).then(function(){S.fl=false;});}function applyVersion(version){if(!version||typeof version!=='string'||version===S.v)return;S.v=version;if(els.version)els.version.textContent='v'+version;}function reveal(){if(!root||S.sh)return;S.sh=true;root.setAttribute('data-visible','true');initPosition();}function conceal(){if(S.pn)closePanel(false);if(S.dl)closeDialog(false);S.sh=false;if(root)root.setAttribute('data-visible','false');}function handlePending(){var pending=S.pd;var signature=pending&&pending.signature?String(pending.signature):'';if(!pending){if(S.dl)closeDialog(false);return;}if(signature&&signature!==S.dg&&!S.sn[signature]&&AUTO_DIALOG&&!S.rs){S.sn[signature]=true;openDialog();return;}if(S.dl&&signature!==S.dg){S.dg=signature;render();}}function statusText(){var status=S.st;if(S.rs||(status&&status.restarting))return'正在重启 Harness…';if(!status)return S.f?'暂时无法连接服务':'正在读取 Bingo 状态…';if(!status.desktop)return'当前为 Web 运行方式';if(status.canRestart===false)return'重启已被禁用';return'Harness 桌面端 · 可重启';}function noteText(){var status=S.st;if(!status)return'会中断正在进行的任务,约 3 秒恢复';if(!status.desktop)return'Web 运行方式不支持整应用重启,可刷新页面';if(status.canRestart===false)return'重启已被禁用,可在插件配置中开启';return'会中断正在进行的任务,约 3 秒恢复';}function formatTime(iso){if(!iso)return'';try{var date=new Date(iso);if(isNaN(date.getTime()))return'';return new Intl.DateTimeFormat('zh-CN',{month:'numeric',day:'numeric',hour:'2-digit',minute:'2-digit',hour12:false}).format(date);}catch(err){return'';}}function formatVersion(version){if(version==null||version==='')return'';var text=String(version);return text.charAt(0)==='v'?text:'v'+text;}function fillPackages(list,more,packages,limit){if(!list)return;while(list.firstChild)list.removeChild(list.firstChild);var items=Array.isArray(packages)?packages:[];items.slice(0,limit).forEach(function(pkg){var name=pkg&&pkg.name?String(pkg.name):'未知插件';var version=formatVersion(pkg&&pkg.version);var row=el('li','pk');row.appendChild(el('span','pkn',name));row.appendChild(el('span','pkv',version));list.appendChild(row);});var extra=items.length-limit;if(!more)return;more.hidden=extra<=0;if(extra>0)more.textContent='还有 '+extra+' 个插件';}function render(){if(!root)return;var status=S.st;var pending=S.pd;var restarting=!!(S.rs||(status&&status.restarting));var canRestart=!!(status&&status.canRestart&&!restarting&&!S.bs);els.version.textContent='v'+(S.v||VERSION);els.status.textContent=statusText();els.statusDot.hidden=!status;els.statusDot.setAttribute('data-tone',restarting?'warn':(!status||!status.desktop||status.canRestart===false?'warn':'ok'));els.pill.dataset.pending=pending?'true':'false';els.pill.dataset.loading=restarting?'true':'false';els.pill.disabled=restarting;els.pill.setAttribute('aria-busy',restarting?'true':'false');els.pending.hidden=!pending;if(pending){var packages=Array.isArray(pending.packages)?pending.packages:[];fillPackages(els.pendingList,els.pendingMore,packages,PANEL_PENDING_LIMIT);els.pendingCount.textContent=packages.length+' 个';}els.primary.disabled=!canRestart;els.primary.dataset.loading=restarting||S.bs?'true':'false';els.primaryLabel.textContent=restarting?'正在 Bingo…':(S.bs?'正在请求…':'Bingo 一下');els.later.textContent='稍后';els.refresh.hidden=!(status&&status.desktop===false);els.note.textContent=noteText();els.meta.hidden=!(status&&status.lastRestart);if(status&&status.lastRestart){var last=status.lastRestart;var ok=last.ok!==false;els.meta.setAttribute('data-failed',ok?'false':'true');els.metaText.textContent='上次重启 · '+(formatTime(last.at)||'时间未知')+' · '+(ok?'成功':'未确认');}if(S.dl&&pending){fillPackages(els.dialogList,els.dialogMore,pending.packages,DIALOG_PENDING_LIMIT);els.dialogPrimary.disabled=!canRestart;}if(S.pn)positionPanel();}function showError(message){if(!els.error)return;els.error.textContent=message;els.error.hidden=false;}function clearError(){if(!els.error)return;els.error.hidden=true;els.error.textContent='';}function focusPill(){try{els.pill.focus({preventScroll:true});}catch(err){try{els.pill.focus();}catch(err2){}}}function activeElement(){try{return shadow&&shadow.activeElement;}catch(err){return null;}}function rememberFocus(){var node=activeElement();if(node&&els.panel.contains(node))node=null;if(!node){node=document.activeElement;if(node===document.body||(host&&host.contains(node)))node=null;}lastFocus=node||null;}function restoreFocus(){var node=lastFocus;lastFocus=null;if(node&&node.isConnected){try{node.focus({preventScroll:true});return;}catch(err){}}focusPill();}function openPanel(){if(S.pn||S.rs)return;S.pn=true;els.panel.hidden=false;els.pill.setAttribute('aria-expanded','true');render();positionPanel();window.setTimeout(function(){if(!S.pn)return;positionPanel();try{els.close.focus({preventScroll:true});}catch(err){}},40);}function closePanel(returnFocus){if(!S.pn)return;S.pn=false;els.panel.hidden=true;els.pill.setAttribute('aria-expanded','false');if(returnFocus!==false)focusPill();}function togglePanel(){if(S.dl)return;if(S.pn)closePanel();else openPanel();}function openDialog(){if(!S.pd||S.rs)return;rememberFocus();S.dl=true;S.dg=S.pd.signature?String(S.pd.signature):'';closePanel(false);render();els.dialogLayer.hidden=false;root.setAttribute('data-dialog','true');live('检测到新插件,是否要 Bingo 一下?');window.setTimeout(function(){if(!S.dl)return;try{els.dialogPrimary.focus({preventScroll:true});}catch(err){}},40);}function closeDialog(returnFocus){if(!S.dl)return;S.dl=false;S.dg='';els.dialogLayer.hidden=true;root.removeAttribute('data-dialog');if(returnFocus!==false&&!S.rs)restoreFocus();}function dismissPending(source){var pending=S.pd;var signature=pending&&pending.signature?String(pending.signature):'';if(!signature){if(S.dl)closeDialog();else closePanel();return;}S.sn[signature]=true;S.pd=null;if(S.st)S.st.pending=null;render();closeDialog();live('已稍后处理');request(API+'/dismiss',{method:'POST',body:JSON.stringify({signature:signature})}).catch(function(){});}function handleRestartError(error){var code=error&&error.data&&error.data.code;if(code==='restarting'){enterRestarting(true);return;}var message;if(code==='unsupported')message='当前运行方式不支持整应用重启。';else if(code==='spawn-failed')message='重启进程启动失败,请查看 bingo/restart.log。';else if(error&&error.status===403)message='请求被宿主拒绝,请刷新页面后重试。';else message='重启请求失败,请稍后再试。';if(S.dl){closeDialog(false);openPanel();}showError(message);live(message);}function triggerRestart(trigger){if(!S.st||!S.st.canRestart||S.rs||S.bs)return;clearError();S.bs=true;render();request(API+'/restart',{method:'POST',body:JSON.stringify({trigger:trigger})}).then(function(data){if(!data||data.ok===false){var error=new Error('Restart rejected');error.data=data;throw error;}S.bs=false;enterRestarting(false);}).catch(function(error){S.bs=false;render();handleRestartError(error);});}function enterRestarting(){if(S.rs)return;S.rs=true;S.restartCycle+=1;S.bs=false;closePanel(false);closeDialog(false);els.restartLayer.hidden=false;render();live('正在重启 Harness,页面会自动恢复');try{els.restartCard.focus({preventScroll:true});}catch(err){}if(S.mt)window.clearTimeout(S.mt);S.mt=window.setTimeout(function(){if(!S.rs)return;els.manualHint.hidden=false;},MANUAL_HINT_AFTER);schedule(1200);}function leaveRestarting(){S.rs=false;if(S.mt)window.clearTimeout(S.mt);S.mt=0;els.restartLayer.hidden=true;render();openPanel();if(S.st&&S.st.lastRestart&&S.st.lastRestart.ok===false){showError('重启未完成,请查看日志后重试。');live('重启失败,可以重试');}}function trapTab(event){var nodes=els.dialog.querySelectorAll('button:not([disabled])');if(!nodes.length)return;var first=nodes[0];var last=nodes[nodes.length-1];var active=activeElement();if(event.shiftKey&&(active===first||!els.dialog.contains(active))){event.preventDefault();last.focus();}else if(!event.shiftKey&&(active===last||!els.dialog.contains(active))){event.preventDefault();first.focus();}}function onKeyDown(event){var key=event.key||'';if((event.ctrlKey||event.metaKey)&&event.altKey&&(key==='b'||key==='B'||event.code==='KeyB')){if(S.rs)return;event.preventDefault();togglePanel();return;}if(key==='Escape'||key==='Esc'){if(S.dl){event.preventDefault();event.stopPropagation();dismissPending('esc');return;}if(S.pn){event.preventDefault();closePanel();return;}}if(key==='Tab'&&S.dl)trapTab(event);}function onPointerDown(event){if(!S.pn)return;var path=event.composedPath?event.composedPath():[];var inside=false;for(var i=0;i<path.length;i+=1){if(path[i]===els.panel||path[i]===els.pill){inside=true;break;}}if(!inside)closePanel();}function onVisibility(){if(document.hidden){if(S.tm)window.clearTimeout(S.tm);S.tm=0;return;}pollOnce(true);}function onPillPointerDown(event){if(S.rs||S.bs)return;if(event.button!==undefined&&event.button!==0)return;var rect=els.pill.getBoundingClientRect();S.drag={id:event.pointerId,startX:event.clientX,startY:event.clientY,originX:rect.left,originY:rect.top,moved:false};try{els.pill.setPointerCapture(event.pointerId);}catch(err){}}function onPillPointerMove(event){if(!S.drag||event.pointerId!==S.drag.id)return;var dx=event.clientX-S.drag.startX;var dy=event.clientY-S.drag.startY;if(!S.drag.moved&&Math.abs(dx)+Math.abs(dy)>DRAG_SLOP){S.drag.moved=true;if(host)host.classList.add('is-dragging');closePanel(false);}if(!S.drag.moved)return;S.edge=null;setPosition(S.drag.originX+dx,S.drag.originY+dy,false);if(event.cancelable)event.preventDefault();}function finishDrag(event,cancel){var drag=S.drag;if(!drag||(event&&event.pointerId!==drag.id))return;S.drag=null;try{els.pill.releasePointerCapture(drag.id);}catch(err){}if(host)host.classList.remove('is-dragging');if(!drag.moved)return;S.posUser=true;S.suppressClick=true;window.setTimeout(function(){S.suppressClick=false;},60);if(cancel){if(S.pos)setPosition(S.pos.x,S.pos.y,true);return;}snapToEdges();}function bind(){els.pill.addEventListener('click',function(event){if(S.suppressClick){event.preventDefault();event.stopPropagation();return;}togglePanel();});els.pill.addEventListener('pointerdown',onPillPointerDown);els.pill.addEventListener('pointermove',onPillPointerMove);els.pill.addEventListener('pointerup',function(event){finishDrag(event,false);});els.pill.addEventListener('pointercancel',function(event){finishDrag(event,true);});els.pill.addEventListener('dragstart',function(event){event.preventDefault();});window.addEventListener('resize',onResize);els.close.addEventListener('click',function(){closePanel();});els.primary.addEventListener('click',function(){if(!S.st||!S.st.canRestart)return;triggerRestart('button');});els.later.addEventListener('click',function(){if(S.pd)dismissPending('panel');else closePanel();});els.refresh.addEventListener('click',function(){try{window.location.reload();}catch(err){}});els.dialogPrimary.addEventListener('click',function(){if(!S.st||!S.st.canRestart)return;triggerRestart('new-plugin');});els.dialogLater.addEventListener('click',function(){dismissPending('dialog');});els.dialogLayer.addEventListener('pointerdown',function(event){if(event.target===els.dialogLayer)dismissPending('overlay');});window.addEventListener('keydown',onKeyDown,true);document.addEventListener('pointerdown',onPointerDown,true);document.addEventListener('visibilitychange',onVisibility);}function expose(){window.__DSH_BINGO__={openPanel:openPanel};}function mount(){if(document.getElementById('dsh-bingo-host'))return;host=document.createElement('div');host.id='dsh-bingo-host';host.setAttribute('data-dsh-bingo','');host.hidden=true;shadow=host.attachShadow({mode:'open'});root=document.createElement('div');root.className='r';root.setAttribute('data-visible','false');root.setAttribute('data-theme',detectTheme());root.innerHTML=TEMPLATE;shadow.appendChild(root);var names=root.querySelectorAll('[data-el]');for(var i=0;i<names.length;i+=1){els[names[i].getAttribute('data-el')]=names[i];}els.kbd.textContent=/Mac|iPhone|iPad/.test(navigator.platform||'')?'⌘ + Alt + B':'Ctrl + Alt + B';bind();expose();applyTheme();watchTheme();link=document.createElement('link');link.rel='stylesheet';link.href=CSS_URL;link.addEventListener('load',function(){host.hidden=false;initPosition();pollOnce(true);window.setTimeout(function(){if(S.drag)return;var saved=readSavedPosition();if(saved)setPosition(saved.x,saved.y,false);else initPosition();},60);});link.addEventListener('error',function(){if(host&&host.parentNode)host.parentNode.removeChild(host);});shadow.appendChild(link);document.body.appendChild(host);}function boot(){if(!document.body){window.setTimeout(boot,40);return;}try{mount();}catch(err){if(host&&host.parentNode)host.parentNode.removeChild(host);}}if(document.body)boot();else document.addEventListener('DOMContentLoaded',boot,{once:true});})();
2
+ (function(){'use strict';if(window.__DSH_BINGO_LOADED__)return;window.__DSH_BINGO_LOADED__=true;var VERSION=typeof window.__DSH_BINGO_VERSION__==='string'&&window.__DSH_BINGO_VERSION__?window.__DSH_BINGO_VERSION__:'0.2.0';var API='/bingo';var CSS_URL=typeof window.__DSH_BINGO_CLIENT_CSS__==='string'&&window.__DSH_BINGO_CLIENT_CSS__?window.__DSH_BINGO_CLIENT_CSS__:API+'/client.css?v='+encodeURIComponent(VERSION);var INITIAL_POSITION=window.__DSH_BINGO_POSITION__==='bottom-right'?'bottom-right':'bottom-left';var AUTO_DIALOG=window.__DSH_BINGO_NO_AUTO_DIALOG__!==true;var DEFAULT_POLL=4000;var MAX_RETRY=30000;var REQUEST_TIMEOUT=5000;var MANUAL_HINT_AFTER=12000;var PANEL_PENDING_LIMIT=4;var DIALOG_PENDING_LIMIT=6;var POS_KEY='dsh-bingo.position.v1';var SNAP_MARGIN=16;var SNAP_THRESHOLD=64;var DRAG_SLOP=4;var ICON_SPARK='<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 2.4c.47 4.74 3.86 8.13 8.6 8.6-4.74.47-8.13 3.86-8.6 8.6-.47-4.74-3.86-8.13-8.6-8.6 4.74-.47 8.13-3.86 8.6-8.6Z"/></svg>';var ICON_CLOSE='<svg viewBox="0 0 16 16" width="12" height="12" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" aria-hidden="true"><path d="M4 4l8 8M12 4l-8 8"/></svg>';var ICON_CLOCK='<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" aria-hidden="true"><circle cx="8" cy="8" r="5.6"/><path d="M8 5.2V8l1.9 1.3"/></svg>';var TEMPLATE=['<button class="p" data-el="pill" type="button" aria-label="Bingo:重启 DeepSeek Harness" aria-haspopup="dialog" aria-expanded="false">','<span class="mk" aria-hidden="true">'+ICON_SPARK+'<span class="ps"></span></span>','<span class="pl">Bingo</span>','<span class="pd" aria-hidden="true"></span>','</button>','<section class="pn" data-el="panel" role="dialog" aria-modal="false" aria-labelledby="ti" hidden>','<header class="hd">','<span class="mk mks" aria-hidden="true">'+ICON_SPARK+'</span>','<span class="ht" id="ti">Bingo</span>','<span class="vr" data-el="version">v'+VERSION+'</span>','<button class="ib" data-el="close" type="button" aria-label="关闭面板">'+ICON_CLOSE+'</button>','</header>','<div class="st"><span class="dt" data-el="statusDot" aria-hidden="true"></span><span data-el="status">正在读取 Bingo 状态…</span></div>','<div class="pg" data-el="pending" hidden>','<div class="pgh"><span class="pgt">检测到新插件</span><span class="cnt" data-el="pendingCount"></span></div>','<ul class="pks" data-el="pendingList"></ul>','<div class="mo" data-el="pendingMore" hidden></div>','</div>','<div class="ac">','<button class="bt btp" data-el="primary" type="button"><span class="bts" aria-hidden="true"></span><span data-el="primaryLabel">Bingo 一下</span></button>','<button class="bt btg" data-el="later" type="button">稍后</button>','<button class="bt btg" data-el="refresh" type="button" hidden>刷新页面</button>','</div>','<p class="nt" data-el="note">会中断正在进行的任务,约 3 秒恢复</p>','<p class="er" data-el="error" role="alert" hidden></p>','<div class="mt" data-el="meta" data-failed="false" hidden>'+ICON_CLOCK+'<span data-el="metaText"></span></div>','<button class="bt btg bingo-manage" data-el="manage" type="button">插件记录 · 试用 · 验收</button>','<footer class="ft"><span>快捷键</span><span class="kb" data-el="kbd">Ctrl + Alt + B</span></footer>','<p class="sr" data-el="live" role="status" aria-live="polite"></p>','</section>','<div class="ly lyd" data-el="dialogLayer" hidden>','<div class="dlg" data-el="dialog" role="alertdialog" aria-modal="true" aria-labelledby="dlt" aria-describedby="dld" tabindex="-1">','<div class="dli" aria-hidden="true">'+ICON_SPARK+'</div>','<h2 class="dlt2" id="dlt">检测到新插件</h2>','<p class="dld2" id="dld">是否要 Bingo 一下?部分插件需要重启后生效。</p>','<ul class="pks pksd" data-el="dialogList"></ul>','<div class="mo mod" data-el="dialogMore" hidden></div>','<div class="dla">','<button class="bt btp" data-el="dialogPrimary" type="button">立即 Bingo</button>','<button class="bt btg" data-el="dialogLater" type="button">稍后</button>','</div>','<button class="bt btg bingo-manage" data-el="tryGroup" type="button">本次新增设为试用</button>','<p class="dlh">稍后可从左下角的 Bingo 面板随时处理</p>','</div>','</div>','<div class="ly lyd" data-el="deskLayer" hidden>','<section class="bingo-desk" data-el="desk" role="dialog" aria-modal="true" aria-labelledby="bingo-desk-title" tabindex="-1">','<header class="hd"><strong id="bingo-desk-title">Bingo 插件管家</strong><button class="ib" data-el="deskClose" type="button" aria-label="关闭插件管家">'+ICON_CLOSE+'</button></header>','<nav class="bingo-tabs" aria-label="插件管理"><button data-el="historyTab" type="button">变更记录</button><button data-el="trialsTab" type="button">临时试用</button><button data-el="checksTab" type="button">验收清单</button></nav>','<div class="bingo-desk-toolbar"><span data-el="deskMessage" role="status" aria-live="polite"></span><button class="bt btg" data-el="deskRefresh" type="button">刷新</button></div>','<div class="bingo-desk-content" data-el="deskContent"></div>','</section></div>','<div class="ly lyr" data-el="restartLayer" hidden>','<div class="rs" data-el="restartCard" role="status" aria-live="assertive" tabindex="-1">','<span class="sp" aria-hidden="true"></span>','<div class="rst">正在重启 Harness</div>','<div class="rsh">页面会自动恢复,请稍候</div>','<div class="rsm" data-el="manualHint" hidden>如果长时间未恢复,请手动启动 DeepSeek Harness。</div>','</div>','</div>'].join('');var S={st:null,pd:null,v:VERSION,f:0,sh:false,pn:false,dl:false,dg:'',rs:false,restartCycle:0,bs:false,em:false,fl:false,tm:0,mt:0,pm:DEFAULT_POLL,sn:Object.create(null),pos:null,edge:null,posUser:false,drag:null,suppressClick:false,desk:false,deskTab:'history',activity:null,activityBusy:false,activityLoading:false,removeConfirm:'',reviewSeen:Object.create(null),};var host=null;var shadow=null;var root=null;var link=null;var els={};var lastFocus=null;function el(tag,cls,text){var node=document.createElement(tag);if(cls)node.className=cls;if(text!=null)node.textContent=text;return node;}function clamp(value,min,max){return Math.min(max,Math.max(min,value));}function live(text){if(!els.live)return;els.live.textContent=text||'';}function detectTheme(){var forced=window.__DSH_BINGO_FORCE_THEME__;if(forced==='dark'||forced==='light')return forced;var html=document.documentElement;var body=document.body;var explicit=html.getAttribute('data-theme')||html.getAttribute('data-ds-theme-source');if(explicit!=='dark'&&explicit!=='light'&&body){explicit=body.getAttribute('data-theme')||body.getAttribute('data-ds-theme-source');}if(explicit==='dark'||explicit==='light')return explicit;if(html.classList.contains('dark')||(body&&body.classList.contains('dark')))return'dark';if(html.classList.contains('light'))return'light';if(body&&body.hasAttribute('data-ds-dark-theme'))return'dark';try{return window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light';}catch(err){return'light';}}function applyTheme(){if(!root)return;root.setAttribute('data-theme',detectTheme());}function viewportSize(){return{w:Math.max(0,window.innerWidth||(document.documentElement&&document.documentElement.clientWidth)||0),h:Math.max(0,window.innerHeight||(document.documentElement&&document.documentElement.clientHeight)||0)};}function pillSize(){var rect=els.pill?els.pill.getBoundingClientRect():null;return{w:(rect&&rect.width)||120,h:(rect&&rect.height)||44};}function edgeMargin(){return viewportSize().w<=480?12:SNAP_MARGIN;}function readSavedPosition(){try{var raw=window.localStorage&&window.localStorage.getItem(POS_KEY);if(!raw)return null;var value=JSON.parse(raw);if(!value||typeof value.x!=='number'||typeof value.y!=='number')return null;var edge=value.edge&&typeof value.edge==='object'?{h:value.edge.h==='left'||value.edge.h==='right'?value.edge.h:null,v:value.edge.v==='top'||value.edge.v==='bottom'?value.edge.v:null}:null;return{x:value.x,y:value.y,edge:edge};}catch(err){}return null;}function savePosition(pos){try{if(window.localStorage)window.localStorage.setItem(POS_KEY,JSON.stringify(pos));}catch(err){}}function currentEdge(x,y,size,vp,margin){var edge='free';if(x<=margin+SNAP_THRESHOLD)edge='left';else if(vp.w-(x+size.w)<=margin+SNAP_THRESHOLD)edge='right';if(y<=margin+SNAP_THRESHOLD)edge=edge==='free'?'top':edge+'-top';else if(vp.h-(y+size.h)<=margin+SNAP_THRESHOLD)edge=edge==='free'?'bottom':edge+'-bottom';return edge;}function setPosition(x,y,persist,edge){if(edge!==undefined)S.edge=edge;var vp=viewportSize();var size=pillSize();var margin=edgeMargin();var maxX=Math.max(margin,vp.w-size.w-margin);var maxY=Math.max(margin,vp.h-size.h-margin);var nx=Math.min(maxX,Math.max(margin,x));var ny=Math.min(maxY,Math.max(margin,y));S.pos={x:nx,y:ny};if(!host)return;host.style.left=nx+'px';host.style.top=ny+'px';host.style.right='auto';host.style.bottom='auto';host.setAttribute('data-edge',currentEdge(nx,ny,size,vp,margin));if(persist)savePosition({x:nx,y:ny,edge:S.edge||null});if(S.pn)positionPanel();}function applySaved(saved){var vp=viewportSize();var size=pillSize();var margin=edgeMargin();var x=saved.x;var y=saved.y;var edge=saved.edge||null;if(edge&&edge.h==='left')x=margin;else if(edge&&edge.h==='right')x=vp.w-size.w-margin;if(edge&&edge.v==='top')y=margin;else if(edge&&edge.v==='bottom')y=vp.h-size.h-margin;setPosition(x,y,false,edge);}function reapplySaved(){if(S.drag)return;var saved=readSavedPosition();if(saved)applySaved(saved);}function scheduleReapply(){try{if(document.fonts&&document.fonts.ready&&typeof document.fonts.ready.then==='function'){document.fonts.ready.then(reapplySaved).catch(function(){});}}catch(err){}window.setTimeout(reapplySaved,300);}function initPosition(){var saved=readSavedPosition();if(saved){S.posUser=true;applySaved(saved);scheduleReapply();return;}var vp=viewportSize();var size=pillSize();var x=INITIAL_POSITION==='bottom-right'?vp.w-18-size.w:18;setPosition(x,vp.h-64-size.h,false);}function snapToEdges(){if(!S.pos)return;var vp=viewportSize();var size=pillSize();var margin=edgeMargin();var x=S.pos.x;var y=S.pos.y;var dLeft=x-margin;var dRight=vp.w-(x+size.w)-margin;var dTop=y-margin;var dBottom=vp.h-(y+size.h)-margin;var nx=x;var ny=y;var hEdge=null;var vEdge=null;if(dLeft<=SNAP_THRESHOLD&&dLeft<=dRight){nx=margin;hEdge='left';}else if(dRight<=SNAP_THRESHOLD){nx=vp.w-size.w-margin;hEdge='right';}if(dTop<=SNAP_THRESHOLD&&dTop<=dBottom){ny=margin;vEdge='top';}else if(dBottom<=SNAP_THRESHOLD){ny=vp.h-size.h-margin;vEdge='bottom';}S.edge={h:hEdge,v:vEdge};if(host)host.classList.add('is-snapping');setPosition(nx,ny,true,S.edge);window.setTimeout(function(){if(host)host.classList.remove('is-snapping');},220);}function positionPanel(){if(!S.pn||!els.panel||els.panel.hidden)return;var button=els.pill.getBoundingClientRect();var panel=els.panel.getBoundingClientRect();var vp=viewportSize();var gap=10;var pad=8;var width=panel.width||312;var height=panel.height||200;var top=button.top-height-gap;if(top<pad)top=button.bottom+gap;var left=button.left;if(left+width>vp.w-pad)left=button.right-width;left=Math.max(pad,Math.min(left,Math.max(pad,vp.w-width-pad)));top=Math.max(pad,Math.min(top,Math.max(pad,vp.h-height-pad)));els.panel.style.position='fixed';els.panel.style.left=left+'px';els.panel.style.top=top+'px';els.panel.style.right='auto';els.panel.style.bottom='auto';els.panel.style.maxHeight=Math.max(160,vp.h-pad*2)+'px';els.panel.style.overflow='auto';els.panel.style.transformOrigin=(top<button.top?'bottom':'top')+' '+(left<button.left?'right':'left');}function onResize(){if(!S.pos)return;var vp=viewportSize();var size=pillSize();var margin=edgeMargin();var x=S.pos.x;var y=S.pos.y;if(S.edge&&S.edge.h==='left')x=margin;else if(S.edge&&S.edge.h==='right')x=vp.w-size.w-margin;else if(x<=margin+2)x=margin;else if(x+size.w>=vp.w-margin-2)x=vp.w-size.w-margin;if(S.edge&&S.edge.v==='top')y=margin;else if(S.edge&&S.edge.v==='bottom')y=vp.h-size.h-margin;else if(y<=margin+2)y=margin;else if(y+size.h>=vp.h-margin-2)y=vp.h-size.h-margin;setPosition(x,y,true,S.edge);if(S.pn)positionPanel();}function watchTheme(){try{if(typeof MutationObserver==='undefined')return;var observer=new MutationObserver(applyTheme);observer.observe(document.documentElement,{attributes:true,attributeFilter:['class','data-theme','data-ds-theme-source']});if(document.body){observer.observe(document.body,{attributes:true,attributeFilter:['class','data-theme','data-ds-dark-theme','data-ds-theme-source']});}}catch(err){}try{var mq=window.matchMedia('(prefers-color-scheme: dark)');if(mq.addEventListener)mq.addEventListener('change',applyTheme);else if(mq.addListener)mq.addListener(applyTheme);}catch(err){}}function request(path,init){var ctrl=null;var timer=0;try{if(typeof AbortController!=='undefined')ctrl=new AbortController();}catch(err){}var options={method:(init&&init.method)||'GET',cache:'no-store'};if(init&&init.body!=null){options.body=init.body;options.headers={'Content-Type':'application/json'};}if(ctrl){options.signal=ctrl.signal;timer=window.setTimeout(function(){try{ctrl.abort();}catch(err){}},(init&&init.timeout)||REQUEST_TIMEOUT);}return fetch(path,options).then(function(res){if(timer)window.clearTimeout(timer);return res.json().catch(function(){return null;}).then(function(data){if(!res.ok){var error=new Error('HTTP '+res.status);error.status=res.status;error.data=data;throw error;}return data;});},function(error){if(timer)window.clearTimeout(timer);throw error;});}function nextRetry(){return Math.min(MAX_RETRY,2000*Math.pow(2,Math.max(0,S.f-1)));}function schedule(ms){if(S.tm)window.clearTimeout(S.tm);S.tm=0;if(document.hidden)return;S.tm=window.setTimeout(function(){S.tm=0;pollOnce(false);},Math.max(0,ms||0));}function pollOnce(force){if(S.fl)return;if(!force&&document.hidden)return;S.fl=true;var restartCycle=S.restartCycle;request(API+'/status').then(function(data){if(!data||data.ok===false)throw new Error('Bad status');S.f=0;S.st=data;S.pd=data.pending||null;if(typeof data.pollMs==='number')S.pm=clamp(data.pollMs,1500,60000);applyVersion(data.version);render();reveal();if(data.restarting)enterRestarting(true);else if(S.rs&&restartCycle===S.restartCycle)leaveRestarting();handlePending();var review=data.activity;if(review&&review.reviewCount>0&&review.reviewSignature&&!S.reviewSeen[review.reviewSignature]&&!S.rs&&!S.dl&&!S.pn&&!S.desk){S.reviewSeen[review.reviewSignature]=true;openDesk('trials');}if(!S.em){S.em=true;try{window.dispatchEvent(new CustomEvent('dsh-bingo:ready',{detail:{status:data}}));}catch(err){}}schedule(S.rs?1200:S.pm);}).catch(function(){S.f+=1;if(S.f>=3&&!S.rs)conceal();render();schedule(nextRetry());}).then(function(){S.fl=false;});}function applyVersion(version){if(!version||typeof version!=='string'||version===S.v)return;S.v=version;if(els.version)els.version.textContent='v'+version;}function reveal(){if(!root||S.sh)return;S.sh=true;root.setAttribute('data-visible','true');initPosition();}function conceal(){if(S.pn)closePanel(false);if(S.dl)closeDialog(false);S.sh=false;if(root)root.setAttribute('data-visible','false');}function handlePending(){var pending=S.pd;var signature=pending&&pending.signature?String(pending.signature):'';if(!pending){if(S.dl)closeDialog(false);return;}if(signature&&signature!==S.dg&&!S.sn[signature]&&AUTO_DIALOG&&!S.rs&&!S.desk){S.sn[signature]=true;openDialog();return;}if(S.dl&&signature!==S.dg){S.dg=signature;render();}}function statusText(){var status=S.st;if(S.rs||(status&&status.restarting))return'正在重启 Harness…';if(!status)return S.f?'暂时无法连接服务':'正在读取 Bingo 状态…';if(!status.desktop)return'当前为 Web 运行方式';if(status.canRestart===false)return'重启已被禁用';return'Harness 桌面端 · 可重启';}function noteText(){var status=S.st;if(!status)return'会中断正在进行的任务,约 3 秒恢复';if(!status.desktop)return'Web 运行方式不支持整应用重启,可刷新页面';if(status.canRestart===false)return'重启已被禁用,可在插件配置中开启';return'会中断正在进行的任务,约 3 秒恢复';}function formatTime(iso){if(!iso)return'';try{var date=new Date(iso);if(isNaN(date.getTime()))return'';return new Intl.DateTimeFormat('zh-CN',{month:'numeric',day:'numeric',hour:'2-digit',minute:'2-digit',hour12:false}).format(date);}catch(err){return'';}}function formatVersion(version){if(version==null||version==='')return'';var text=String(version);return text.charAt(0)==='v'?text:'v'+text;}function fillPackages(list,more,packages,limit){if(!list)return;while(list.firstChild)list.removeChild(list.firstChild);var items=Array.isArray(packages)?packages:[];items.slice(0,limit).forEach(function(pkg){var name=pkg&&pkg.name?String(pkg.name):'未知插件';var version=formatVersion(pkg&&pkg.version);var row=el('li','pk');row.appendChild(el('span','pkn',name));row.appendChild(el('span','pkv',version));list.appendChild(row);});var extra=items.length-limit;if(!more)return;more.hidden=extra<=0;if(extra>0)more.textContent='还有 '+extra+' 个插件';}function render(){if(!root)return;var status=S.st;var pending=S.pd;var restarting=!!(S.rs||(status&&status.restarting));var canRestart=!!(status&&status.canRestart&&!restarting&&!S.bs);els.version.textContent='v'+(S.v||VERSION);els.status.textContent=statusText();els.statusDot.hidden=!status;els.statusDot.setAttribute('data-tone',restarting?'warn':(!status||!status.desktop||status.canRestart===false?'warn':'ok'));els.pill.dataset.pending=pending?'true':'false';els.pill.dataset.loading=restarting?'true':'false';els.pill.disabled=restarting;els.pill.setAttribute('aria-busy',restarting?'true':'false');els.pending.hidden=!pending;if(pending){var packages=Array.isArray(pending.packages)?pending.packages:[];fillPackages(els.pendingList,els.pendingMore,packages,PANEL_PENDING_LIMIT);els.pendingCount.textContent=packages.length+' 个';}els.primary.disabled=!canRestart;els.primary.dataset.loading=restarting||S.bs?'true':'false';els.primaryLabel.textContent=restarting?'正在 Bingo…':(S.bs?'正在请求…':'Bingo 一下');els.later.textContent='稍后';els.refresh.hidden=!(status&&status.desktop===false);els.note.textContent=noteText();if(els.manage){var reviews=status&&status.activity&&status.activity.reviewCount||0;els.manage.textContent=reviews?'插件管家 · '+reviews+' 个试用待决定':'插件记录 · 试用 · 验收';}if(els.tryGroup)els.tryGroup.disabled=S.bs||restarting;els.meta.hidden=!(status&&status.lastRestart);if(status&&status.lastRestart){var last=status.lastRestart;var ok=last.ok!==false;els.meta.setAttribute('data-failed',ok?'false':'true');els.metaText.textContent='上次重启 · '+(formatTime(last.at)||'时间未知')+' · '+(ok?'成功':'未确认');}if(S.dl&&pending){fillPackages(els.dialogList,els.dialogMore,pending.packages,DIALOG_PENDING_LIMIT);els.dialogPrimary.disabled=!canRestart;}if(S.pn)positionPanel();}function showError(message){if(!els.error)return;els.error.textContent=message;els.error.hidden=false;}function clearError(){if(!els.error)return;els.error.hidden=true;els.error.textContent='';}function focusPill(){try{els.pill.focus({preventScroll:true});}catch(err){try{els.pill.focus();}catch(err2){}}}function activeElement(){try{return shadow&&shadow.activeElement;}catch(err){return null;}}function rememberFocus(){var node=activeElement();if(node&&els.panel.contains(node))node=null;if(!node){node=document.activeElement;if(node===document.body||(host&&host.contains(node)))node=null;}lastFocus=node||null;}function restoreFocus(){var node=lastFocus;lastFocus=null;if(node&&node.isConnected){try{node.focus({preventScroll:true});return;}catch(err){}}focusPill();}function openPanel(){if(S.pn||S.rs)return;S.pn=true;els.panel.hidden=false;els.pill.setAttribute('aria-expanded','true');render();positionPanel();window.setTimeout(function(){if(!S.pn)return;positionPanel();try{els.close.focus({preventScroll:true});}catch(err){}},40);}function closePanel(returnFocus){if(!S.pn)return;S.pn=false;els.panel.hidden=true;els.pill.setAttribute('aria-expanded','false');if(returnFocus!==false)focusPill();}function togglePanel(){if(S.dl)return;if(S.pn)closePanel();else openPanel();}function openDialog(){if(!S.pd||S.rs)return;rememberFocus();S.dl=true;S.dg=S.pd.signature?String(S.pd.signature):'';closePanel(false);render();els.dialogLayer.hidden=false;root.setAttribute('data-dialog','true');live('检测到新插件,是否要 Bingo 一下?');window.setTimeout(function(){if(!S.dl)return;try{els.dialogPrimary.focus({preventScroll:true});}catch(err){}},40);}function closeDialog(returnFocus){if(!S.dl)return;S.dl=false;S.dg='';els.dialogLayer.hidden=true;root.removeAttribute('data-dialog');if(returnFocus!==false&&!S.rs)restoreFocus();}function dismissPending(source){var pending=S.pd;var signature=pending&&pending.signature?String(pending.signature):'';if(!signature){if(S.dl)closeDialog();else closePanel();return;}S.sn[signature]=true;S.pd=null;if(S.st)S.st.pending=null;render();closeDialog();live('已稍后处理');request(API+'/dismiss',{method:'POST',body:JSON.stringify({signature:signature})}).catch(function(){});}function handleRestartError(error){var code=error&&error.data&&error.data.code;if(code==='restarting'){enterRestarting(true);return;}var message;if(code==='unsupported')message='当前运行方式不支持整应用重启。';else if(code==='spawn-failed')message='重启进程启动失败,请查看 bingo/restart.log。';else if(error&&error.status===403)message='请求被宿主拒绝,请刷新页面后重试。';else message='重启请求失败,请稍后再试。';if(S.dl){closeDialog(false);openPanel();}showError(message);live(message);}function triggerRestart(trigger){if(!S.st||!S.st.canRestart||S.rs||S.bs)return;clearError();S.bs=true;render();request(API+'/restart',{method:'POST',body:JSON.stringify({trigger:trigger})}).then(function(data){if(!data||data.ok===false){var error=new Error('Restart rejected');error.data=data;throw error;}S.bs=false;enterRestarting(false);}).catch(function(error){S.bs=false;render();handleRestartError(error);});}function enterRestarting(){if(S.rs)return;S.rs=true;S.restartCycle+=1;S.bs=false;closePanel(false);closeDialog(false);if(S.desk)closeDesk(false);els.restartLayer.hidden=false;render();live('正在重启 Harness,页面会自动恢复');try{els.restartCard.focus({preventScroll:true});}catch(err){}if(S.mt)window.clearTimeout(S.mt);S.mt=window.setTimeout(function(){if(!S.rs)return;els.manualHint.hidden=false;},MANUAL_HINT_AFTER);schedule(1200);}function leaveRestarting(){S.rs=false;if(S.mt)window.clearTimeout(S.mt);S.mt=0;els.restartLayer.hidden=true;render();openPanel();if(S.st&&S.st.lastRestart&&S.st.lastRestart.ok===false){showError('重启未完成,请查看日志后重试。');live('重启失败,可以重试');}}function activityError(error){var code=error&&error.data&&error.data.code;var messages={'version-changed':'插件版本已变化,请刷新后重新标记试用。','trial-changed':'试用记录已变化,请刷新后重试。','not-trialable':'该插件无法标记试用,Bingo 本身不支持试用移除。','not-removable':'宿主不允许移除此插件,请到 Harness 插件页查看。','manager-unavailable':'宿主移除接口暂不可用,请到 Harness 插件页操作。','native-remove-refused':'宿主未完成移除,请到 Harness 插件页查看原因;可能需要先退出应用。','removal-incomplete':'插件清单仍包含该插件,请到 Harness 插件页确认移除结果。','operation-busy':'有操作正在进行,请稍候。','state-unwritable':'记录无法保存,请检查本机状态目录权限。','trial-limit':'试用列表已满,请先保留或移除部分试用插件。'};return messages[code]||'操作未完成,请刷新查看当前状态后重试。';}function deskButton(label,handler,disabled){var button=el('button','bt btg',label);button.type='button';button.disabled=!!(disabled||S.activityBusy);button.addEventListener('click',handler);return button;}function renderDesk(){if(!S.desk||!els.deskContent)return;var content=els.deskContent;while(content.firstChild)content.removeChild(content.firstChild);['history','trials','checks'].forEach(function(tab){els[tab+'Tab'].setAttribute('aria-pressed',S.deskTab===tab?'true':'false');});els.deskClose.disabled=S.activityBusy;els.deskRefresh.disabled=S.activityBusy||S.activityLoading;var data=S.activity;if(!data){content.appendChild(el('p','bingo-muted','正在读取插件信息…'));return;}var note=function(text){content.appendChild(el('p','bingo-muted',text));};var card=function(title,detail){var row=el('article','bingo-record');row.appendChild(el('strong','',title));if(detail)row.appendChild(el('p','bingo-muted',detail));content.appendChild(row);return row;};if(S.deskTab==='history'){note('记录启用 Bingo 后观察到的变化,最近显示 100 条。版本以插件清单声明为准;不记录聊天内容。');var kinds={added:'新增',updated:'版本变更',removed:'移除','trial-started':'开始试用','trial-kept':'保留试用插件','trial-removed':'移除试用插件'};if(!data.history.length)note('还没有变更记录。下次安装、更新或移除插件后会出现在这里。');data.history.forEach(function(item){var detail=formatTime(item.at)+(item.source==='startup'?' · 启动时发现':'');if(item.kind==='updated')detail+=' · '+(item.from||'未声明')+' → '+(item.to||'未声明');else if(item.to||item.from)detail+=' · '+(item.to||item.from);card((kinds[item.kind]||'变更')+' · '+item.name,detail);});}else if(S.deskTab==='trials'){note('安装后标记试用,下次启动提醒你决定。试用不隔离插件权限,也不会自动卸载;“保留”只结束提醒。');var controls=el('div','bingo-trial-controls');var select=el('select','bingo-select');select.setAttribute('aria-label','选择要试用的已安装插件');data.packages.forEach(function(pkg){var option=el('option','',pkg.name);option.value=pkg.name;select.appendChild(option);});select.disabled=S.activityBusy;controls.appendChild(select);controls.appendChild(deskButton('标记试用',function(){var pkg=data.packages.filter(function(p){return p.name===select.value;})[0];if(pkg)performTrial('start',pkg);},!data.packages.length));content.appendChild(controls);if(!data.trials.length)note('暂无试用插件。也可以在新插件提醒中选择“本次新增设为试用”。');data.trials.forEach(function(trial){var row=card(trial.name,(trial.reviewDue?'待决定':'试用中')+' · '+(trial.version||'未声明版本')+' · '+formatTime(trial.createdAt));var actions=el('div','bingo-record-actions');actions.appendChild(deskButton('保留',function(){performTrial('keep',trial);}));actions.appendChild(deskButton('下次启动再问',function(){performTrial('snooze',trial);},!trial.reviewDue));if(trial.versionChanged){row.appendChild(el('p','bingo-muted','安装声明已变化。重新标记后才能移除,避免误删替换后的版本。'));actions.appendChild(deskButton('重新标记',function(){var pkg=data.packages.filter(function(p){return p.name===trial.name;})[0];if(pkg)performTrial('start',pkg);}));}actions.appendChild(deskButton(S.removeConfirm===trial.id?'确认移除':'移除',function(){if(S.removeConfirm!==trial.id){S.removeConfirm=trial.id;els.deskMessage.textContent='确认移除 '+trial.name+'?由宿主管理器执行,相关功能将停止,其他会话也会受影响。';renderDesk();}else performTrial('remove',trial);},!trial.removable||!data.canRemove));if(S.removeConfirm===trial.id)actions.appendChild(deskButton('取消',function(){S.removeConfirm='';renderDesk();}));row.appendChild(actions);if(!trial.removable&&!trial.versionChanged)row.appendChild(el('p','bingo-muted','当前不能在 Bingo 中移除,请在 Harness 插件页查看。'));});}else{note('宿主连接正常。检查最近变更的插件,最多 30 个;无变更时显示当前插件。');note('“运行中”表示宿主条目已启动,不代表插件业务功能或运行代码版本已独立测试。仅有安装文件时不会判定通过。');var states={active:'运行中',failed:'加载失败',disabled:'已禁用',pending:'等待启动',unknown:'无法确认'};if(!data.acceptance.length)note('当前没有可验收的插件。');data.acceptance.forEach(function(item){var row=card(item.name,'安装版本:'+(item.installedVersion||'未知')+' · 声明:'+(item.version||'未声明'));var badge=el('span','bingo-check-state',states[item.state]||'无法确认');badge.setAttribute('data-state',item.state);row.appendChild(badge);});}}function loadActivity(){if(S.activityLoading)return Promise.resolve();S.activityLoading=true;els.deskMessage.textContent='正在读取…';els.deskRefresh.disabled=true;return request(API+'/activity',{timeout:15000}).then(function(data){if(!data||data.ok===false)throw new Error('Bad activity');S.activity=data;els.deskMessage.textContent=data.warning||'记录仅保存在本机';}).catch(function(error){els.deskMessage.textContent=activityError(error);}).then(function(){S.activityLoading=false;renderDesk();});}function openDesk(tab){if(S.rs)return;if(!S.desk)rememberFocus();closePanel(false);S.desk=true;S.deskTab=tab||'history';S.removeConfirm='';els.deskLayer.hidden=false;renderDesk();loadActivity();try{els.desk.focus({preventScroll:true});}catch(err){}}function closeDesk(returnFocus){if(S.activityBusy&&returnFocus!==false)return;S.desk=false;S.removeConfirm='';els.deskLayer.hidden=true;if(returnFocus!==false)restoreFocus();}function performTrial(action,item){if(S.activityBusy||S.activityLoading)return;S.activityBusy=true;renderDesk();els.deskMessage.textContent=action==='remove'?'正在由宿主管理器移除,请稍候…':'正在保存…';var result;request(API+'/trials',{method:'POST',timeout:120000,body:JSON.stringify({action:action,name:item.name,id:item.id,version:item.version,confirmed:action==='remove'})}).then(function(data){result=data;S.removeConfirm='';return loadActivity();}).then(function(){els.deskMessage.textContent=result&&result.restartRequired?'已移除,宿主提示需要重启。':'操作完成';}).catch(function(error){els.deskMessage.textContent=activityError(error);}).then(function(){S.activityBusy=false;renderDesk();pollOnce(true);});}function trialPendingGroup(){if(!S.pd||S.bs)return;var packages=(S.pd.packages||[]).filter(function(p){return p.name!=='dsh-bingo-ren';});if(!packages.length)return;var signature=S.pd.signature;S.bs=true;render();var sequence=Promise.resolve();packages.forEach(function(pkg){sequence=sequence.then(function(){return request(API+'/trials',{method:'POST',body:JSON.stringify({action:'start',name:pkg.name,version:pkg.version})});});});sequence.then(function(){S.bs=false;if(S.pd&&S.pd.signature===signature){dismissPending('trial');openDesk('trials');}else{render();live('原有插件已标记试用,另有新的插件待处理');}}).catch(function(error){S.bs=false;closeDialog(false);openPanel();showError(activityError(error));render();});}function trapTab(event){var container=S.desk?els.desk:els.dialog;var nodes=container.querySelectorAll('button:not([disabled]), select:not([disabled])');if(!nodes.length)return;var first=nodes[0];var last=nodes[nodes.length-1];var active=activeElement();if(event.shiftKey&&(active===first||!container.contains(active))){event.preventDefault();last.focus();}else if(!event.shiftKey&&(active===last||!container.contains(active))){event.preventDefault();first.focus();}}function onKeyDown(event){var key=event.key||'';if((event.ctrlKey||event.metaKey)&&event.altKey&&(key==='b'||key==='B'||event.code==='KeyB')){if(S.rs)return;event.preventDefault();if(S.desk){closeDesk();return;}togglePanel();return;}if(key==='Escape'||key==='Esc'){if(S.desk){event.preventDefault();closeDesk();return;}if(S.dl){event.preventDefault();event.stopPropagation();dismissPending('esc');return;}if(S.pn){event.preventDefault();closePanel();return;}}if(key==='Tab'&&(S.dl||S.desk))trapTab(event);}function onPointerDown(event){if(!S.pn)return;var path=event.composedPath?event.composedPath():[];var inside=false;for(var i=0;i<path.length;i+=1){if(path[i]===els.panel||path[i]===els.pill){inside=true;break;}}if(!inside)closePanel();}function onVisibility(){if(document.hidden){if(S.tm)window.clearTimeout(S.tm);S.tm=0;return;}pollOnce(true);}function onPillPointerDown(event){if(S.rs||S.bs)return;if(event.button!==undefined&&event.button!==0)return;var rect=els.pill.getBoundingClientRect();S.drag={id:event.pointerId,startX:event.clientX,startY:event.clientY,originX:rect.left,originY:rect.top,moved:false};try{els.pill.setPointerCapture(event.pointerId);}catch(err){}}function onPillPointerMove(event){if(!S.drag||event.pointerId!==S.drag.id)return;var dx=event.clientX-S.drag.startX;var dy=event.clientY-S.drag.startY;if(!S.drag.moved&&Math.abs(dx)+Math.abs(dy)>DRAG_SLOP){S.drag.moved=true;if(host)host.classList.add('is-dragging');closePanel(false);}if(!S.drag.moved)return;S.edge=null;setPosition(S.drag.originX+dx,S.drag.originY+dy,false);if(event.cancelable)event.preventDefault();}function finishDrag(event,cancel){var drag=S.drag;if(!drag||(event&&event.pointerId!==drag.id))return;S.drag=null;try{els.pill.releasePointerCapture(drag.id);}catch(err){}if(host)host.classList.remove('is-dragging');if(!drag.moved)return;S.posUser=true;S.suppressClick=true;window.setTimeout(function(){S.suppressClick=false;},60);if(cancel){if(S.pos)setPosition(S.pos.x,S.pos.y,true);return;}snapToEdges();}function bind(){els.manage.addEventListener('click',function(){openDesk('history');});els.tryGroup.addEventListener('click',trialPendingGroup);els.deskClose.addEventListener('click',function(){closeDesk();});els.deskRefresh.addEventListener('click',loadActivity);els.deskLayer.addEventListener('pointerdown',function(event){if(event.target===els.deskLayer)closeDesk();});['history','trials','checks'].forEach(function(tab){els[tab+'Tab'].addEventListener('click',function(){if(S.activityBusy)return;S.deskTab=tab;S.removeConfirm='';renderDesk();});});els.pill.addEventListener('click',function(event){if(S.suppressClick){event.preventDefault();event.stopPropagation();return;}togglePanel();});els.pill.addEventListener('pointerdown',onPillPointerDown);els.pill.addEventListener('pointermove',onPillPointerMove);els.pill.addEventListener('pointerup',function(event){finishDrag(event,false);});els.pill.addEventListener('pointercancel',function(event){finishDrag(event,true);});els.pill.addEventListener('dragstart',function(event){event.preventDefault();});window.addEventListener('resize',onResize);els.close.addEventListener('click',function(){closePanel();});els.primary.addEventListener('click',function(){if(!S.st||!S.st.canRestart)return;triggerRestart('button');});els.later.addEventListener('click',function(){if(S.pd)dismissPending('panel');else closePanel();});els.refresh.addEventListener('click',function(){try{window.location.reload();}catch(err){}});els.dialogPrimary.addEventListener('click',function(){if(!S.st||!S.st.canRestart)return;triggerRestart('new-plugin');});els.dialogLater.addEventListener('click',function(){dismissPending('dialog');});els.dialogLayer.addEventListener('pointerdown',function(event){if(event.target===els.dialogLayer)dismissPending('overlay');});window.addEventListener('keydown',onKeyDown,true);document.addEventListener('pointerdown',onPointerDown,true);document.addEventListener('visibilitychange',onVisibility);}function expose(){window.__DSH_BINGO__={openPanel:openPanel,openManager:openDesk};}function mount(){if(document.getElementById('dsh-bingo-host'))return;host=document.createElement('div');host.id='dsh-bingo-host';host.setAttribute('data-dsh-bingo','');host.hidden=true;shadow=host.attachShadow({mode:'open'});root=document.createElement('div');root.className='r';root.setAttribute('data-visible','false');root.setAttribute('data-theme',detectTheme());root.innerHTML=TEMPLATE;shadow.appendChild(root);var names=root.querySelectorAll('[data-el]');for(var i=0;i<names.length;i+=1){els[names[i].getAttribute('data-el')]=names[i];}els.kbd.textContent=/Mac|iPhone|iPad/.test(navigator.platform||'')?'⌘ + Alt + B':'Ctrl + Alt + B';bind();expose();applyTheme();watchTheme();link=document.createElement('link');link.rel='stylesheet';link.href=CSS_URL;link.addEventListener('load',function(){host.hidden=false;initPosition();pollOnce(true);window.setTimeout(function(){if(S.drag)return;var saved=readSavedPosition();if(saved)setPosition(saved.x,saved.y,false);else initPosition();},60);});link.addEventListener('error',function(){if(host&&host.parentNode)host.parentNode.removeChild(host);});shadow.appendChild(link);document.body.appendChild(host);}function boot(){if(!document.body){window.setTimeout(boot,40);return;}try{mount();}catch(err){if(host&&host.parentNode)host.parentNode.removeChild(host);}}if(document.body)boot();else document.addEventListener('DOMContentLoaded',boot,{once:true});})();