dsh-bingo-ren 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.en.md +89 -0
- package/README.md +38 -38
- package/README.zh.md +1 -1
- package/client/bingo-client.js +1 -1
- package/cordis.patch.yml +7 -7
- package/icon.svg +16 -16
- package/lib/index.js +1497 -1497
- package/lib/restart-helper.cjs +609 -609
- package/package.json +7 -3
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Bingo Contributors
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bingo Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.en.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
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
|
+
## Configuration
|
|
52
|
+
|
|
53
|
+
Configure the plugin row in the profile's `cordis.patch.yml`:
|
|
54
|
+
|
|
55
|
+
```yaml
|
|
56
|
+
- id: dsh-bingo-ren
|
|
57
|
+
config:
|
|
58
|
+
enabled: true
|
|
59
|
+
pollMs: 4000 # 1500–60000 milliseconds
|
|
60
|
+
allowRestart: true
|
|
61
|
+
position: bottom-left # or bottom-right
|
|
62
|
+
debug: false
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`confirm` is reserved; the current client always opens the panel first.
|
|
66
|
+
|
|
67
|
+
## Uninstall
|
|
68
|
+
|
|
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:
|
|
70
|
+
|
|
71
|
+
```powershell
|
|
72
|
+
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/install-local-desktop.ps1 -Uninstall
|
|
73
|
+
```
|
|
74
|
+
|
|
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.
|
|
76
|
+
|
|
77
|
+
## Privacy and compatibility
|
|
78
|
+
|
|
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.
|
|
80
|
+
|
|
81
|
+
Requires Node.js 20+ and DeepSeek Harness 0.2.0-rc.1+. Uses public Cordis APIs without modifying DSH core.
|
|
82
|
+
|
|
83
|
+
## Troubleshooting
|
|
84
|
+
|
|
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.
|
|
88
|
+
|
|
89
|
+
[MIT License](LICENSE)
|
package/README.md
CHANGED
|
@@ -1,89 +1,89 @@
|
|
|
1
|
-
# Bingo —
|
|
1
|
+
# Bingo — DeepSeek Harness 一键重启插件
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
在 DeepSeek Harness 中添加一个可拖动的 Bingo 按钮,支持整应用重启和新插件安装提醒。
|
|
4
4
|
|
|
5
|
-
[
|
|
5
|
+
[English](README.en.md) · [版本与下载](https://github.com/kongkongya367-glitch/dsh-bingo-ren/releases)
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## 功能
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
9
|
+
- 点击按钮打开面板,再点「Bingo 一下」重启桌面应用。
|
|
10
|
+
- 运行期间检测到新插件时弹窗提醒;「稍后」只确认当前这组插件。
|
|
11
|
+
- 按钮支持拖动、靠近边缘时吸附,并记住位置。
|
|
12
|
+
- `Ctrl+Alt+B` 打开面板,macOS 使用 `Cmd+Alt+B`。
|
|
13
|
+
- 适配深浅色主题,零运行时依赖,无遥测。
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## 预览
|
|
16
16
|
|
|
17
|
-
|
|
|
17
|
+
| 按钮 | 面板 | 新插件提醒 |
|
|
18
18
|
| --- | --- | --- |
|
|
19
|
-
| <img src="assets/screenshot-button.png" width="280" alt="Bingo
|
|
19
|
+
| <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
20
|
|
|
21
|
-
|
|
21
|
+
图片使用模拟数据。按钮、面板和弹窗是设计渲染;[拖动示例](assets/screenshot-dragged.png) 是模拟预览页的浏览器截图。
|
|
22
22
|
|
|
23
|
-
##
|
|
23
|
+
## 安装
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
在 **设置 → 插件 → 添加插件** 中输入:
|
|
26
26
|
|
|
27
27
|
```text
|
|
28
28
|
dsh-bingo-ren
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
也可使用 [GitHub 仓库地址](https://github.com/kongkongya367-glitch/dsh-bingo-ren) 安装。安装完成后,手动退出并重新打开 DeepSeek Harness 一次,让 Bingo 加载。
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
运行中的桌面 profile 应通过应用内插件页管理。CLI 仅用于独立的 Web 或测试 profile:
|
|
34
34
|
|
|
35
35
|
```sh
|
|
36
36
|
dsh plugin --profile bingo-selftest add dsh-bingo-ren
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
源码的本地安装方法见 [开发说明](https://github.com/kongkongya367-glitch/dsh-bingo-ren/blob/main/SPEC.md)。
|
|
40
40
|
|
|
41
|
-
##
|
|
41
|
+
## 使用与限制
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
点击 Bingo 打开面板,再点「Bingo 一下」即可重启;面板本身就是确认步骤。
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
**重启会中断正在执行的任务。** 保存工作后再操作。若重启失败,面板会恢复并允许重试;诊断日志位于 `~/.dsh/bingo/restart.log`。
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
检测到新插件时,可以立即重启,也可以点「稍后」、按 `Esc` 或点击遮罩。应用关闭期间安装的插件会在下次启动时成为基线,不重复提醒。提醒表示插件清单发生新增;是否必须重启取决于插件和宿主的加载方式。
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
完整重启仅支持官方 Electron 桌面端。在 Web 模式中重启不可用,面板提供刷新页面。
|
|
50
50
|
|
|
51
|
-
##
|
|
51
|
+
## 配置
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
在 profile 的 `cordis.patch.yml` 中配置:
|
|
54
54
|
|
|
55
55
|
```yaml
|
|
56
56
|
- id: dsh-bingo-ren
|
|
57
57
|
config:
|
|
58
58
|
enabled: true
|
|
59
|
-
pollMs: 4000 # 1500–60000
|
|
59
|
+
pollMs: 4000 # 检测间隔,1500–60000 毫秒
|
|
60
60
|
allowRestart: true
|
|
61
|
-
position: bottom-left #
|
|
61
|
+
position: bottom-left # 或 bottom-right
|
|
62
62
|
debug: false
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
`confirm`
|
|
65
|
+
`confirm` 为保留选项;当前版本始终先显示面板。
|
|
66
66
|
|
|
67
|
-
##
|
|
67
|
+
## 卸载
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
在 **设置 → 插件** 中移除 Bingo,再重启一次应用。若使用源码中的本地安装脚本,请先退出应用,再执行:
|
|
70
70
|
|
|
71
71
|
```powershell
|
|
72
72
|
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/install-local-desktop.ps1 -Uninstall
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
本地卸载只移除 Bingo 的依赖、bundle 条目和包目录,保留其他插件配置。可选删除 `~/.dsh/bingo/` 清理检测状态与日志。
|
|
76
76
|
|
|
77
|
-
##
|
|
77
|
+
## 隐私与兼容性
|
|
78
78
|
|
|
79
|
-
Bingo
|
|
79
|
+
Bingo 只读取本地 profile 清单,并访问同源 `/bingo/*` 接口;不发送遥测,不加载第三方资源。状态与日志保存在本机。
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
需要 Node.js 20+、DeepSeek Harness 0.2.0-rc.1+。使用公开 Cordis 接口,不修改 DSH 核心。
|
|
82
82
|
|
|
83
|
-
##
|
|
83
|
+
## 排查
|
|
84
84
|
|
|
85
|
-
-
|
|
86
|
-
-
|
|
87
|
-
-
|
|
85
|
+
- 没有按钮:首次安装后手动重启,确认插件已启用。
|
|
86
|
+
- 重启不可用:确认是桌面端,且 `allowRestart` 未关闭。
|
|
87
|
+
- 重启失败:查看 `~/.dsh/bingo/restart.log`,排除可执行文件或权限问题后重试。
|
|
88
88
|
|
|
89
89
|
[MIT License](LICENSE)
|
package/README.zh.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
在 DeepSeek Harness 中添加一个可拖动的 Bingo 按钮,支持整应用重启和新插件安装提醒。
|
|
4
4
|
|
|
5
|
-
[English](README.md) · [
|
|
5
|
+
[English](README.en.md) · [版本与下载](https://github.com/kongkongya367-glitch/dsh-bingo-ren/releases)
|
|
6
6
|
|
|
7
7
|
## 功能
|
|
8
8
|
|
package/client/bingo-client.js
CHANGED
|
@@ -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.1.3';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});})();
|
package/cordis.patch.yml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# Bingo: a bottom-left restart button for DeepSeek Harness.
|
|
2
|
-
# Inserted as one host plugin row; the package itself has no client module.
|
|
3
|
-
- insert:
|
|
4
|
-
- id: dsh-bingo-ren
|
|
5
|
-
name: dsh-bingo-ren
|
|
6
|
-
config:
|
|
7
|
-
enabled: true
|
|
1
|
+
# Bingo: a bottom-left restart button for DeepSeek Harness.
|
|
2
|
+
# Inserted as one host plugin row; the package itself has no client module.
|
|
3
|
+
- insert:
|
|
4
|
+
- id: dsh-bingo-ren
|
|
5
|
+
name: dsh-bingo-ren
|
|
6
|
+
config:
|
|
7
|
+
enabled: true
|
package/icon.svg
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 64 64" role="img" aria-label="Bingo">
|
|
2
|
-
<defs>
|
|
3
|
-
<linearGradient id="bingo-plate" x1="6" y1="4" x2="58" y2="60" gradientUnits="userSpaceOnUse">
|
|
4
|
-
<stop stop-color="#191C23"/>
|
|
5
|
-
<stop offset="1" stop-color="#0B0D11"/>
|
|
6
|
-
</linearGradient>
|
|
7
|
-
<linearGradient id="bingo-spark" x1="45" y1="13" x2="51" y2="21" gradientUnits="userSpaceOnUse">
|
|
8
|
-
<stop stop-color="#9DCBFF"/>
|
|
9
|
-
<stop offset="1" stop-color="#4F7FF0"/>
|
|
10
|
-
</linearGradient>
|
|
11
|
-
</defs>
|
|
12
|
-
<rect x="2" y="2" width="60" height="60" rx="16" fill="url(#bingo-plate)"/>
|
|
13
|
-
<rect x="2.5" y="2.5" width="59" height="59" rx="15.5" fill="none" stroke="#FFFFFF" stroke-opacity="0.12"/>
|
|
14
|
-
<path d="M32 11 C34.4 24.2 39.8 29.6 53 32 C39.8 34.4 34.4 39.8 32 53 C29.6 39.8 24.2 34.4 11 32 C24.2 29.6 29.6 24.2 32 11 Z" fill="#F8F9FB"/>
|
|
15
|
-
<circle cx="47.5" cy="16.5" r="2.8" fill="url(#bingo-spark)"/>
|
|
16
|
-
</svg>
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 64 64" role="img" aria-label="Bingo">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="bingo-plate" x1="6" y1="4" x2="58" y2="60" gradientUnits="userSpaceOnUse">
|
|
4
|
+
<stop stop-color="#191C23"/>
|
|
5
|
+
<stop offset="1" stop-color="#0B0D11"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
<linearGradient id="bingo-spark" x1="45" y1="13" x2="51" y2="21" gradientUnits="userSpaceOnUse">
|
|
8
|
+
<stop stop-color="#9DCBFF"/>
|
|
9
|
+
<stop offset="1" stop-color="#4F7FF0"/>
|
|
10
|
+
</linearGradient>
|
|
11
|
+
</defs>
|
|
12
|
+
<rect x="2" y="2" width="60" height="60" rx="16" fill="url(#bingo-plate)"/>
|
|
13
|
+
<rect x="2.5" y="2.5" width="59" height="59" rx="15.5" fill="none" stroke="#FFFFFF" stroke-opacity="0.12"/>
|
|
14
|
+
<path d="M32 11 C34.4 24.2 39.8 29.6 53 32 C39.8 34.4 34.4 39.8 32 53 C29.6 39.8 24.2 34.4 11 32 C24.2 29.6 29.6 24.2 32 11 Z" fill="#F8F9FB"/>
|
|
15
|
+
<circle cx="47.5" cy="16.5" r="2.8" fill="url(#bingo-spark)"/>
|
|
16
|
+
</svg>
|