dsh-notch 0.3.1 → 0.3.4
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 +58 -47
- package/README.md +60 -55
- package/cordis.patch.yml +3 -0
- package/desktop/README.md +29 -0
- package/desktop/notch-lifecycle.mjs +120 -0
- package/desktop/restart-probe.mjs +61 -0
- package/docs/desktop-017rc2.md +23 -0
- package/docs/elastic-edge-dock.md +127 -0
- package/docs/motion-audit.md +1 -1
- package/docs/releases/v0.3.2.md +38 -0
- package/docs/releases/v0.3.3.md +9 -0
- package/docs/subagent-compatibility.md +51 -0
- package/docs/verification/elastic-algorithm-timing.json +337 -0
- package/docs/verification/elastic-attention.json +44 -0
- package/docs/verification/elastic-frame-timing.json +240 -0
- package/docs/verification/elastic-tension.json +59 -0
- package/docs/verification/elastic-tip-taper.json +181 -0
- package/dshx.yml +2 -0
- package/lib/client.js +112 -0
- package/lib/client.js.map +1 -0
- package/lib/index.mjs +990 -0
- package/lib/index.mjs.map +1 -0
- package/package.json +58 -10
- package/src/board.ts +178 -35
- package/src/client/index.ts +104 -0
- package/src/dsh-notch.ts +19 -2
- package/src/http.ts +17 -2
- package/src/session-state.ts +15 -1
- package/src/store.ts +3 -3
- package/src/types.ts +3 -0
- package/BASELINE.md +0 -13
- package/DESIGN.md +0 -34
- package/cordis.yml +0 -5
- package/macos/Package.swift +0 -17
- package/macos/STATUS-MOTION.md +0 -49
- package/macos/Sources/Client.swift +0 -139
- package/macos/Sources/IdleRobot.swift +0 -423
- package/macos/Sources/NotchMarkdown.swift +0 -266
- package/macos/Sources/Panel.swift +0 -153
- package/macos/Sources/Resources/Idle/balance.json +0 -1
- package/macos/Sources/Resources/Idle/blink.json +0 -1
- package/macos/Sources/Resources/Idle/cube-in.json +0 -1
- package/macos/Sources/Resources/Idle/dance.json +0 -1
- package/macos/Sources/Resources/Idle/hop.json +0 -1
- package/macos/Sources/Resources/Idle/nod.json +0 -1
- package/macos/Sources/Resources/Idle/satellite-in.json +0 -1
- package/macos/Sources/Resources/Idle/satellite-out.json +0 -1
- package/macos/Sources/Resources/Idle/scan.json +0 -1
- package/macos/Sources/Resources/Idle/sleep.json +0 -1
- package/macos/Sources/Resources/Idle/sneeze.json +0 -1
- package/macos/Sources/Resources/Idle/stretch.json +0 -1
- package/macos/Sources/Resources/Idle/tilt.json +0 -1
- package/macos/Sources/ReviewStudio.swift +0 -337
- package/macos/Sources/RootView.swift +0 -1093
- package/macos/Sources/StatusOrbit.swift +0 -642
- package/macos/Sources/main.swift +0 -153
- package/macos/Tests/ExpandedHeightProbe.swift +0 -108
- package/macos/Tests/GeometryProbe.swift +0 -98
- package/macos/Tests/IdleProbe.swift +0 -294
- package/macos/Tests/MotionProbe.swift +0 -106
- package/macos/Tests/OutcomeProbe.swift +0 -133
- package/macos/Tests/ScrollbarProbe.swift +0 -91
- package/macos/Tests/expanded-height.sh +0 -13
- package/macos/Tests/geometry.sh +0 -14
- package/macos/Tests/idle.sh +0 -14
- package/macos/Tests/motion.sh +0 -14
- package/macos/Tests/outcome.sh +0 -14
- package/macos/Tests/scrollbar.sh +0 -13
- package/tests/answer-lifecycle.test.mjs +0 -23
- package/tests/board.test.mjs +0 -7
- package/tests/browse-sync.test.mjs +0 -20
- package/tests/mirror.test.mjs +0 -4
- package/tests/peer-range.test.mjs +0 -21
- package/tests/session-state.test.mjs +0 -54
- package/tests/unread-hold.test.mjs +0 -90
- package/tools/desktop-shell/README.md +0 -56
- package/tools/desktop-shell/child-log.mjs +0 -6
- package/tools/desktop-shell/child-log.test.mjs +0 -14
- package/tools/desktop-shell/package-recovery.py +0 -78
- package/tools/desktop-shell/recovery-probe.cjs +0 -50
- package/tools/desktop-shell/renderer-recovery.mjs +0 -95
- package/tools/desktop-shell/renderer-recovery.test.mjs +0 -24
- package/tools/diagnostics/completion-watch.py +0 -101
- package/tools/diagnostics/completion-watch.test.py +0 -17
- package/tools/diagnostics/renderer-diagnostics.mjs +0 -56
- package/tools/diagnostics/renderer-diagnostics.test.mjs +0 -32
- package/tools/idle/LICENSE.open-bot-motion +0 -21
- package/tools/idle/export.mjs +0 -40
- package/tools/idle/index.html +0 -4
- package/tools/idle/motions.js +0 -83
- package/tools/idle/original.js +0 -1673
- package/tools/idle/renderer.js +0 -1673
- package/tools/recording/Client.swift +0 -76
- package/tools/recording/DemoCatalog.swift +0 -174
- package/tools/recording/README.md +0 -23
- package/tools/recording/build.sh +0 -41
- package/tools/recording/main.swift +0 -100
- package/tools/review/ReviewStudio.swift +0 -236
- package/tools/review/audit.sh +0 -19
- package/tools/review/build.sh +0 -7
- package/tools/review/main.swift +0 -158
- package/tools/review/render-audit.swift +0 -32
package/README.en.md
CHANGED
|
@@ -8,70 +8,57 @@ Installation has two parts: a **Host plugin inside DSH** that supplies session s
|
|
|
8
8
|
|
|
9
9
|
## Installation
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
**DSH Notch 0.3.4 supports official DeepSeek Harness `0.2.0-rc.2`.** Install `dsh-notch@0.3.4` and `dsh-notch-focus@0.1.2` from npm. The native macOS helper remains version 0.3.3 and is included in the release below. This release changes npm packaging and installation instructions; its runtime code matches 0.3.3.
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
- DeepSeek Harness `0.1.7-rc.1`. This package peers `@deepseek-ai/dsh` and the `@deepseek-ai/dsh-*` packages it imports at `>=0.1.7-rc.1 <0.1.8`.
|
|
15
|
-
- A working local DSH Web Host, with `dsh`, `pnpm`, and `git` available in your terminal.
|
|
16
|
-
- Swift 6 or later through Command Line Tools. Check with `swift --version`; use `xcode-select --install` if the developer tools are missing.
|
|
13
|
+
### 1. Download the release
|
|
17
14
|
|
|
18
|
-
|
|
15
|
+
Download from [v0.3.4](https://github.com/aa2246740/dsh-notch/releases/tag/v0.3.4):
|
|
19
16
|
|
|
20
|
-
|
|
17
|
+
| File | Purpose |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| `dsh-notch-0.3.4.tgz` | Host plugin for status, questions, and native connectivity |
|
|
20
|
+
| `dsh-notch-focus-0.1.2.tgz` | Client companion for navigation and reading acknowledgements |
|
|
21
|
+
| `dsh-notch-0.3.3-macos-arm64.tar.gz` | Native executable and robot resources; macOS 14+, Apple Silicon |
|
|
22
|
+
| `SHA256SUMS` | Place beside the downloads and run `shasum -a 256 -c SHA256SUMS` |
|
|
21
23
|
|
|
22
|
-
|
|
23
|
-
git clone https://github.com/aa2246740/dsh-notch.git
|
|
24
|
-
cd dsh-notch
|
|
25
|
-
dsh plugin --profile web add "$PWD"
|
|
26
|
-
```
|
|
24
|
+
Prebuilt packages do not require Swift or DSHX. Other architectures require a source build and are not covered by this binary release.
|
|
27
25
|
|
|
28
|
-
|
|
26
|
+
### 2. Install both plugin packages
|
|
29
27
|
|
|
30
|
-
|
|
28
|
+
**Official Desktop:** enter `dsh-notch@0.3.4` and `dsh-notch-focus@0.1.2` through the app's Plugins page, enable them, follow the app's loading instructions, then reopen the page. The app owns the Desktop profile.
|
|
31
29
|
|
|
32
|
-
|
|
30
|
+
**Web:** use the same `DSH_HOME` as the running Host, then run from your download directory:
|
|
33
31
|
|
|
34
32
|
```sh
|
|
35
|
-
|
|
33
|
+
dsh plugin --profile web add dsh-notch@0.3.4
|
|
34
|
+
dsh plugin --profile web add dsh-notch-focus@0.1.2
|
|
36
35
|
```
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
Append this item to the YAML list in `~/.dsh/profiles/web/cordis.patch.yml`. Create the file if absent. **Keep existing configuration, and add this ID only once.**
|
|
41
|
-
|
|
42
|
-
```yaml
|
|
43
|
-
- insert:
|
|
44
|
-
- id: dsh-notch
|
|
45
|
-
name: dsh-notch
|
|
46
|
-
```
|
|
37
|
+
Both packages declare official `dsh.bundle.patch` entries. Follow the plugin manager's loading guidance and reopen the page. Do not add a second manual insert. Update existing entries when migrating older installations so a Bundle and an old manual patch do not mount the same plugin twice.
|
|
47
38
|
|
|
48
|
-
|
|
39
|
+
A loaded Host writes `$DSH_HOME/dsh-notch/runtime.json`. This is a private connection file managed by the plugin; do not fill it in or share it. Check Host loading errors if it is absent.
|
|
49
40
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
The plugin manages this private connection file automatically. Do not fill it in manually or paste its contents into a chat. If it is absent, resolve YAML, module-resolution, or missing-service errors in the Host before continuing.
|
|
53
|
-
|
|
54
|
-
### 3. Build and start the real Notch
|
|
55
|
-
|
|
56
|
-
From the Notch checkout:
|
|
41
|
+
### 3. Extract and start the native helper
|
|
57
42
|
|
|
58
43
|
```sh
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
44
|
+
tar -xzf dsh-notch-0.3.3-macos-arm64.tar.gz
|
|
45
|
+
cd dsh-notch-0.3.3-macos-arm64
|
|
46
|
+
./dsh-notch --verify-idle-resources
|
|
47
|
+
./dsh-notch
|
|
62
48
|
```
|
|
63
49
|
|
|
64
|
-
The resource check should print `IDLE_RESOURCES=10/10`.
|
|
50
|
+
The resource check should print `IDLE_RESOURCES=10/10`. Keep the terminal open for the first run. If a desktop launcher already manages a Notch helper, update that executable instead. Always keep `dsh-notch` and `DshNotch_DshNotch.bundle` together when moving them. A custom `DSH_HOME` must match the Host's Home.
|
|
65
51
|
|
|
66
|
-
|
|
52
|
+
Optionally set the Host plugin's `helperPath` configuration to the absolute path of the extracted executable and follow the app's plugin loading guidance. The Host then supervises that helper; do not also start another copy manually.
|
|
67
53
|
|
|
68
|
-
### 4. Confirm
|
|
54
|
+
### 4. Confirm synchronization
|
|
69
55
|
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
56
|
+
- Running primary sessions show a blue count; completions, failures, and questions show their corresponding states.
|
|
57
|
+
- Clicking a Notch session opens the matching conversation in DSH.
|
|
58
|
+
- Opening a completed session in foreground DSH clears that result from Notch. Running tasks remain visible.
|
|
59
|
+
- Reading all results returns Notch to the idle robot.
|
|
73
60
|
|
|
74
|
-
|
|
61
|
+
The native helper exits with its Host. Temporary request failures do not close it. Closing only the window keeps it alive if the Host still runs. See [desktop helper ownership](desktop/README.md) for lifecycle integration.
|
|
75
62
|
|
|
76
63
|
## Usage
|
|
77
64
|
|
|
@@ -84,9 +71,17 @@ Use existing sessions for these checks; a new model task is unnecessary. Seeing
|
|
|
84
71
|
| Click an option | Submit that choice; follow the panel for multiple questions or selections |
|
|
85
72
|
| Click the question title | Open the full conversation in DSH |
|
|
86
73
|
| Read all results | Return to the idle robot |
|
|
74
|
+
| Drag and release Notch | Hide it elastically at the screen edge; drag it out again to restore |
|
|
75
|
+
| New completion, failure, or decision while hidden | Bounce back to the normal compact view; repeated polls of the same event do not reveal it again |
|
|
76
|
+
|
|
77
|
+
Ordinary running-state and size updates keep a hidden Notch tucked away. An attention event received during a drag waits until release. Screen work-area changes, including a right-side macOS Dock, do not move the hidden cap away from the physical display edge.
|
|
87
78
|
|
|
88
79
|
The interface uses native AppKit, SwiftUI, and Canvas. Animation itself never calls a model. The panel grows with content, scrolls at the screen-height cap, and respects Reduced Motion.
|
|
89
80
|
|
|
81
|
+
Counts represent user conversations. Workflow workers and nested subagents belong to their owning conversation; they do not add separate running, success, or failure indicators. A background worker keeps its owner running, while result indicators come from the owner's final outcome. Child questions appear on the owner's yellow indicator and answers return to the original requester, with multiple questions handled in order. User-created forks remain independent conversations.
|
|
82
|
+
|
|
83
|
+
External Codex, Claude Code, ACP, and DSH SDK children registered as official background jobs also keep their owner active. Observation never consumes job completion notices. The [dsh-notch-focus companion](companions/dsh-notch-focus/README.md) handles browser navigation and cold-session mirroring; existing installations can keep their current directory. See the [source compatibility audit](docs/subagent-compatibility.md) for entry paths, cancellation, resumption, and verification limits.
|
|
84
|
+
|
|
90
85
|
## Troubleshooting
|
|
91
86
|
|
|
92
87
|
| Symptom | Check |
|
|
@@ -98,16 +93,28 @@ The interface uses native AppKit, SwiftUI, and Canvas. Animation itself never ca
|
|
|
98
93
|
| Two Notches | Check for both a manually started and a desktop-shell-managed copy. |
|
|
99
94
|
| Old behavior after updating source | Rebuild and replace the executable actually running; `git pull` does not replace an existing native process. |
|
|
100
95
|
|
|
101
|
-
The Host plugin requires `sessions`, `webServer`, `approval`, `userQuestions`, and `agents`. It targets a local DSH Web Host on the same Mac. Native foregrounding
|
|
96
|
+
The Host plugin requires `sessions`, `webServer`, `approval`, `userQuestions`, and `agents`. It targets a local DSH Web Host on the same Mac. Native foregrounding prefers official `com.deepseek.dsh` and retains compatibility with `local.dsh.desktop`. Successful package installation alone does not certify multiple Homes, remote Hosts, or every DSH version.
|
|
102
97
|
|
|
103
98
|
## Updates and development
|
|
104
99
|
|
|
105
100
|
After updating source, rebuild the native helper. Native-only changes require updating and relaunching Notch. Changes under `src/` also require the appropriate Host module activation.
|
|
106
101
|
|
|
107
|
-
Maintainers using [dshx](https://github.com/aa2246740/dsh-external-plugin-devkit) can inspect `dshx activation-plan dsh-notch --change artifact` or `--change server`, according to the changed surface.
|
|
102
|
+
Maintainers using [dshx](https://github.com/aa2246740/dsh-external-plugin-devkit) can inspect `dshx activation-plan dsh-notch --change artifact` or `--change server`, according to the changed surface. Package synchronization and live activation are separate checks.
|
|
103
|
+
|
|
104
|
+
Source builds require Node.js 24 and Swift 6 / Command Line Tools:
|
|
105
|
+
|
|
106
|
+
```sh
|
|
107
|
+
npm ci --ignore-scripts --legacy-peer-deps
|
|
108
|
+
npm run build
|
|
109
|
+
npm run build:macos
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
See the [companion README](companions/dsh-notch-focus/README.md) for its DSHX 0.9.2 build against a `dsh-v0.2.0-rc.2` checkout. Release consumers do not need DSHX.
|
|
113
|
+
|
|
114
|
+
Development checks:
|
|
108
115
|
|
|
109
116
|
```sh
|
|
110
|
-
npm ci
|
|
117
|
+
npm ci --ignore-scripts --legacy-peer-deps
|
|
111
118
|
npm test
|
|
112
119
|
npm run test:outcome
|
|
113
120
|
npm run test:motion
|
|
@@ -118,6 +125,8 @@ npm run test:idle
|
|
|
118
125
|
npm run build:macos
|
|
119
126
|
```
|
|
120
127
|
|
|
128
|
+
Try the elastic edge-hiding gesture in the [standalone native preview](tools/elastic-preview/README.md), built with `npm run build:elastic-preview`. It uses local fixtures, makes no model requests, and does not replace an installed Notch.
|
|
129
|
+
|
|
121
130
|
### Optional recording demo
|
|
122
131
|
|
|
123
132
|
For animation review and video recording, separate from plugin installation:
|
|
@@ -129,8 +138,10 @@ open "dist/DSH Notch Demo.app"
|
|
|
129
138
|
|
|
130
139
|
The demo contains 36 bilingual scenes driven by local fixtures. It does not connect to DSH. See the [demo controls](tools/recording/README.md).
|
|
131
140
|
|
|
132
|
-
More: [motion contracts](macos/STATUS-MOTION.md), [design notes](DESIGN.md), [0.3.0 changes](docs/releases/v0.3.0.md), and [optional desktop-shell diagnostics](tools/desktop-shell/README.md).
|
|
141
|
+
More: [motion contracts](macos/STATUS-MOTION.md), [design notes](DESIGN.md), [0.3.3 changes](docs/releases/v0.3.3.md), [0.3.2 changes](docs/releases/v0.3.2.md), [0.3.0 changes](docs/releases/v0.3.0.md), and [optional desktop-shell diagnostics](tools/desktop-shell/README.md).
|
|
133
142
|
|
|
134
143
|
## License
|
|
135
144
|
|
|
136
145
|
[MIT](LICENSE). Robot resources derive from [OpenBotMotion](https://github.com/aa2246740/open-bot-motion); its original [MIT notice](tools/idle/LICENSE.open-bot-motion) is retained. This is a community-maintained DSH plugin.
|
|
146
|
+
|
|
147
|
+
See the [Desktop 0.1.7-rc.2 verification record](docs/desktop-017rc2.md). `DSH_NOTCH_RUNTIME_FILE` selects the connection only. Use explicit `--demo` or `--elastic-preview` modes for offline presentation.
|
package/README.md
CHANGED
|
@@ -8,77 +8,57 @@
|
|
|
8
8
|
|
|
9
9
|
## 安装
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
**DSH Notch 0.3.4 支持官方 DeepSeek Harness `0.2.0-rc.2`。** 从 npm 安装 `dsh-notch@0.3.4` 和 `dsh-notch-focus@0.1.2`。原生 macOS 程序继续使用 0.3.3,包含在下面的发布页中。本次只调整 npm 打包和安装说明,运行代码与 0.3.3 相同。
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
- DeepSeek Harness `0.1.7-rc.1`。本包对 `@deepseek-ai/dsh` 与所用 `@deepseek-ai/dsh-*` 的 peer 是 `>=0.1.7-rc.1 <0.1.8`。
|
|
15
|
-
- 本机已有正常运行的 DSH Web Host;终端能使用 `dsh`、`pnpm` 和 `git`。
|
|
16
|
-
- Swift 6 或更新版本的 Command Line Tools。用 `swift --version` 检查;没有开发工具时先运行 `xcode-select --install`。
|
|
13
|
+
### 1. 下载发布包
|
|
17
14
|
|
|
18
|
-
|
|
15
|
+
从 [v0.3.4 Release](https://github.com/aa2246740/dsh-notch/releases/tag/v0.3.4) 下载:
|
|
19
16
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
```
|
|
17
|
+
| 文件 | 用途 |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| `dsh-notch-0.3.4.tgz` | Host 插件,提供状态、问题和原生程序连接 |
|
|
20
|
+
| `dsh-notch-focus-0.1.2.tgz` | 客户端同步助手,负责双向会话跳转与已读同步 |
|
|
21
|
+
| `dsh-notch-0.3.3-macos-arm64.tar.gz` | macOS 14+、Apple Silicon 原生程序及机器人资源 |
|
|
22
|
+
| `SHA256SUMS` | 下载校验;与上述文件放在同一目录后执行 `shasum -a 256 -c SHA256SUMS` |
|
|
27
23
|
|
|
28
|
-
|
|
24
|
+
预编译包无需 Swift 或 DSHX。其他架构需从源码构建,尚未提供验收过的预编译包。
|
|
29
25
|
|
|
30
|
-
|
|
26
|
+
### 2. 在 DSH 安装两个插件包
|
|
31
27
|
|
|
32
|
-
|
|
33
|
-
<summary>从 Harness 源码运行,没有全局 dsh 命令?</summary>
|
|
28
|
+
**官方 Desktop:** 在应用内插件管理页分别输入 `dsh-notch@0.3.4` 和 `dsh-notch-focus@0.1.2`,确认都已启用,按应用提示完成加载,再重新打开页面。Desktop profile 由应用管理。
|
|
34
29
|
|
|
35
|
-
|
|
30
|
+
**Web:** 对运行中的 Host 使用相同的 `DSH_HOME`,在下载目录执行:
|
|
36
31
|
|
|
37
32
|
```sh
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
然后回到 `dsh-notch` 目录继续下面的步骤。
|
|
42
|
-
|
|
43
|
-
</details>
|
|
44
|
-
|
|
45
|
-
### 2. 在 DSH 中激活插件
|
|
46
|
-
|
|
47
|
-
打开 `~/.dsh/profiles/web/cordis.patch.yml`,在现有 YAML 列表中追加下面这一项。文件不存在时可新建;**保留已有配置,同一个 `id` 只添加一次**。
|
|
48
|
-
|
|
49
|
-
```yaml
|
|
50
|
-
- insert:
|
|
51
|
-
- id: dsh-notch
|
|
52
|
-
name: dsh-notch
|
|
33
|
+
dsh plugin --profile web add dsh-notch@0.3.4
|
|
34
|
+
dsh plugin --profile web add dsh-notch-focus@0.1.2
|
|
53
35
|
```
|
|
54
36
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
标准 Web profile 会监听这份配置并热加载插件。若 DSH 正在运行,保存后等它加载即可;尚未启动 DSH 时,用你原来的启动入口启动它。成功后,Host 日志会出现 `[my-plugins/dsh-notch] loaded`,并生成 `~/.dsh/dsh-notch/runtime.json`。
|
|
58
|
-
|
|
59
|
-
该文件包含 Notch 的本机连接信息,由插件自动管理,不需要手动填写或把内容发给 Agent。如果没有生成,先检查 Host 是否报 YAML、模块解析或缺少服务的错误,再继续第三步。
|
|
37
|
+
两个包都声明了官方 `dsh.bundle.patch`。按插件管理器的提示加载,并重新打开页面;不要再手工追加同名 `insert`。已有安装应更新原条目,避免 Bundle 与旧手动配置重复挂载。
|
|
60
38
|
|
|
61
|
-
|
|
39
|
+
Host 加载后生成 `$DSH_HOME/dsh-notch/runtime.json`。这是插件管理的私有连接文件,不需要填写或分享。找不到它时,先检查 Host 插件的加载错误。
|
|
62
40
|
|
|
63
|
-
|
|
41
|
+
### 3. 解压并启动原生程序
|
|
64
42
|
|
|
65
43
|
```sh
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
44
|
+
tar -xzf dsh-notch-0.3.3-macos-arm64.tar.gz
|
|
45
|
+
cd dsh-notch-0.3.3-macos-arm64
|
|
46
|
+
./dsh-notch --verify-idle-resources
|
|
47
|
+
./dsh-notch
|
|
69
48
|
```
|
|
70
49
|
|
|
71
|
-
资源检查应输出 `IDLE_RESOURCES=10/10
|
|
50
|
+
资源检查应输出 `IDLE_RESOURCES=10/10`。首次运行请保持终端打开;如果已有桌面启动器管理 Notch,更新它使用的那份程序即可。移动时始终把 `dsh-notch` 和 `DshNotch_DshNotch.bundle` 放在一起。使用自定义 `DSH_HOME` 时,原生程序和 Host 必须指向同一 Home。
|
|
72
51
|
|
|
73
|
-
|
|
52
|
+
可在 Host 插件配置中把 `helperPath` 设为已解压的 `dsh-notch` 的绝对路径,让插件随 Host 管理辅助进程;配置后按应用的插件加载提示生效。请勿同时手工启动另一份。
|
|
74
53
|
|
|
75
|
-
### 4.
|
|
54
|
+
### 4. 确认同步正常
|
|
76
55
|
|
|
77
|
-
-
|
|
78
|
-
-
|
|
79
|
-
-
|
|
56
|
+
- 正在运行的主会话显示蓝色计数;完成、失败或等待回答显示对应状态。
|
|
57
|
+
- 点击 Notch 的会话,DSH 打开对应对话。
|
|
58
|
+
- 在 DSH 前台打开已完成的会话,Notch 清除该条未读状态;仍在运行的任务继续保留。
|
|
59
|
+
- 全部结果读完后,Notch 回到机器人待机。
|
|
80
60
|
|
|
81
|
-
|
|
61
|
+
Notch 跟随连接文件中的 Host 进程退出。临时请求失败不会让它退出;只关闭窗口而 Host 仍在后台运行时,它会继续显示任务。[桌面托管说明](desktop/README.md)介绍了辅助程序的退出与快速重启联动。
|
|
82
62
|
|
|
83
63
|
## 使用
|
|
84
64
|
|
|
@@ -91,9 +71,17 @@ macos/.build/release/dsh-notch
|
|
|
91
71
|
| 点击问题选项 | 直接提交该选项;多选或多题按面板提示完成 |
|
|
92
72
|
| 点击问题标题 | 回到 DSH 查看完整上下文 |
|
|
93
73
|
| 全部结果读完 | 回到机器人待机 |
|
|
74
|
+
| 拖动 Notch 后松手 | 弹性收纳到屏幕边缘;再拖出即可恢复 |
|
|
75
|
+
| 隐藏时出现新完成、错误或待审批问题 | 自动弹回正常紧凑状态;同一提醒不会因轮询反复弹出 |
|
|
76
|
+
|
|
77
|
+
隐藏状态下,普通运行和尺寸更新不打扰你。鼠标正在拖动时收到新提醒,会先保持跟手,等松手再恢复。右侧系统 Dock 或显示工作区变化不会改变 Notch 对物理屏幕边缘的定位。
|
|
94
78
|
|
|
95
79
|
Notch 使用原生 AppKit / SwiftUI / Canvas 渲染。动画本身不调用模型。窗口随内容展开,达到屏幕高度上限后滚动;系统开启“减少动态效果”时呈现静态状态。
|
|
96
80
|
|
|
81
|
+
计数以用户的主对话为单位:workflow 和普通子代理(包括嵌套子代理)归到所属主对话,不会各自增加蓝色数字或生成完成、失败灯。后台子代理仍在工作时,主任务继续显示运行中;结果灯以主对话的最终结果为准。子代理需要你回答的问题会显示在主任务的黄色状态下,回答送回原请求,多个问题依次处理。用户手动 fork 出来的对话仍独立计数。
|
|
82
|
+
|
|
83
|
+
外部 Codex、Claude Code、ACP、DSH SDK 子代理转入官方后台任务后,也会归到所属主对话。Notch 只读取状态,不消费后台任务的完成通知。浏览器跳转和未加载会话的同步由 [dsh-notch-focus 助手](companions/dsh-notch-focus/README.md)提供;已有安装保留原目录更新即可。入口、取消与恢复路径的检查范围见[源码兼容性审计](docs/subagent-compatibility.md)。
|
|
84
|
+
|
|
97
85
|
## 常见安装问题
|
|
98
86
|
|
|
99
87
|
| 现象 | 检查位置 |
|
|
@@ -105,28 +93,43 @@ Notch 使用原生 AppKit / SwiftUI / Canvas 渲染。动画本身不调用模
|
|
|
105
93
|
| 屏幕上出现两个 Notch | 检查是否同时启动了手动版本和 App 壳管理的版本,只保留预期的那一份。 |
|
|
106
94
|
| 更新源码后仍是旧效果 | 重新构建,并更新实际运行的可执行文件;只 `git pull` 不会替换已启动的原生进程。 |
|
|
107
95
|
|
|
108
|
-
|
|
96
|
+
若状态灯叠影、点击后才恢复,可按发生时间查看 `~/.dsh/dsh-notch/presentation.jsonl`。日志只记录计数、动画阶段、布局和进程编号,不记录对话正文、标题或认证信息;达到 256 KiB 后轮换,只保留当前和上一份。刷新时会检查过期的转场并补做收尾,菜单交互期间也继续推进状态与布局计时器。
|
|
97
|
+
|
|
98
|
+
当前 Host 插件依赖 `sessions`、`webServer`、`approval`、`userQuestions`、`agents` 服务,面向同一台 Mac 上的 DSH Web Host。原生界面的会话跳转优先唤起官方 `com.deepseek.dsh` 桌面版,并保留旧 `local.dsh.desktop` 壳的兼容。多 Home、远程 Host 和各版本 DSH 的兼容性不能只凭安装成功判断。
|
|
109
99
|
|
|
110
100
|
## 更新与开发
|
|
111
101
|
|
|
112
|
-
更新已安装的源码后,重新构建原生程序。只改原生界面时,更新并重新启动 Notch 即可;若改了 `src/` 下的 Host
|
|
102
|
+
更新已安装的源码后,重新构建原生程序。只改原生界面时,更新并重新启动 Notch 即可;若改了 `src/` 下的 Host 插件代码,先 `npm run build` 更新 `lib/index.mjs`,再做对应的服务端热加载。
|
|
103
|
+
|
|
104
|
+
使用 [dshx](https://github.com/aa2246740/dsh-external-plugin-devkit) 的维护者可先执行 `dshx activation-plan dsh-notch --change artifact` 或 `--change server`,按实际修改范围更新。激活要匹配实际 Host 和挂载方式,不能把复制原生二进制当作 Host 模块热更新。
|
|
105
|
+
|
|
106
|
+
从源码构建 Host 和原生程序需要 Node.js 24、Swift 6 / Command Line Tools:
|
|
113
107
|
|
|
114
|
-
|
|
108
|
+
```sh
|
|
109
|
+
npm ci --ignore-scripts --legacy-peer-deps
|
|
110
|
+
npm run build
|
|
111
|
+
npm run build:macos
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
同步助手的源码构建需要 DSHX 0.9.2 和已备好依赖的 `dsh-v0.2.0-rc.2` Harness checkout;步骤见[助手说明](companions/dsh-notch-focus/README.md)。预编译发布包不需要这些开发工具。
|
|
115
115
|
|
|
116
116
|
开发检查:
|
|
117
117
|
|
|
118
118
|
```sh
|
|
119
|
-
npm ci
|
|
119
|
+
npm ci --ignore-scripts --legacy-peer-deps
|
|
120
120
|
npm test
|
|
121
121
|
npm run test:outcome
|
|
122
122
|
npm run test:motion
|
|
123
123
|
npm run test:geometry
|
|
124
124
|
npm run test:scrollbar
|
|
125
125
|
npm run test:expanded-height
|
|
126
|
+
npm run test:host-lifetime
|
|
126
127
|
npm run test:idle
|
|
127
128
|
npm run build:macos
|
|
128
129
|
```
|
|
129
130
|
|
|
131
|
+
弹性收纳交互可在 [独立原生预览](tools/elastic-preview/README.md) 中试用;运行 `npm run build:elastic-preview` 构建,不连接 DSH、不调用模型,也不替换当前安装。
|
|
132
|
+
|
|
130
133
|
### 录屏 Demo(可选)
|
|
131
134
|
|
|
132
135
|
用于开发、检查动画或录制演示视频,**不属于插件安装步骤**:
|
|
@@ -138,8 +141,10 @@ open "dist/DSH Notch Demo.app"
|
|
|
138
141
|
|
|
139
142
|
Demo 提供 36 个中英双语场景,使用本地假任务,不连接 DSH。录屏控制与快捷键见 [Demo 文档](tools/recording/README.md)。
|
|
140
143
|
|
|
141
|
-
更多:[动效说明](macos/STATUS-MOTION.md) · [设计说明](DESIGN.md) · [0.3.0 更新记录](docs/releases/v0.3.0.md) · [可选 App 壳诊断](tools/desktop-shell/README.md)。
|
|
144
|
+
更多:[动效说明](macos/STATUS-MOTION.md) · [设计说明](DESIGN.md) · [0.3.3 更新记录](docs/releases/v0.3.3.md) · [0.3.2 更新记录](docs/releases/v0.3.2.md) · [0.3.0 更新记录](docs/releases/v0.3.0.md) · [可选 App 壳诊断](tools/desktop-shell/README.md)。
|
|
142
145
|
|
|
143
146
|
## 许可
|
|
144
147
|
|
|
145
148
|
[MIT](LICENSE)。机器人资源基于 [OpenBotMotion](https://github.com/aa2246740/open-bot-motion),保留了原始 [MIT 许可声明](tools/idle/LICENSE.open-bot-motion)。这是社区维护的 DSH 插件。
|
|
149
|
+
|
|
150
|
+
官方桌面版的原生启动适配与验证见 [0.1.7-rc.2 验证记录](docs/desktop-017rc2.md)。`DSH_NOTCH_RUNTIME_FILE` 只指定连接文件,绝不触发演示偏移;演示使用显式的 `--demo` 或 `--elastic-preview` 入口。
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Desktop helper ownership
|
|
2
|
+
|
|
3
|
+
`notch-lifecycle.mjs` is a small Node/Electron integration for desktop shells that launch the native helper. It owns both a helper it spawns and an existing helper adopted from a PID file. It verifies the executable and process start time, retries if the adopted helper exits during startup, and closes the owned helper on application quit.
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
import { superviseNotch } from './notch-lifecycle.mjs'
|
|
7
|
+
|
|
8
|
+
let notch
|
|
9
|
+
app.on('before-quit', () => notch?.stop())
|
|
10
|
+
// After the authenticated Host has finished starting:
|
|
11
|
+
notch = superviseNotch({ bin: absoluteHelperPath, pidPath: helperPIDPath, log })
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Register quit cleanup before awaiting Host startup. If the app quits while startup is pending, cancel/terminate its own starting Host and do not start Notch afterwards. Do not terminate an unrelated Host to manage Notch.
|
|
15
|
+
|
|
16
|
+
An external native updater should create `${pidPath}.updating` before stopping the old helper, replace the binary/resources, start and verify the new helper, publish its PID, then remove the marker in a `finally` block. The marker expires after 60 seconds if an updater crashes. This prevents the shell's recovery from racing the updater.
|
|
17
|
+
|
|
18
|
+
The native helper also watches its Host independently. Actual process exit closes it without a deliberate grace delay; HTTP timeouts do not. A process that has already committed to exiting is replaced by the desktop supervisor rather than treated as a usable helper forever.
|
|
19
|
+
|
|
20
|
+
Validation:
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
npm test
|
|
24
|
+
swift build --package-path macos -c release
|
|
25
|
+
python3 macos/Tests/helper-lifetime.py
|
|
26
|
+
node desktop/restart-probe.mjs
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The native probes use disposable local owner processes and isolated runtime files. They never start DSH or invoke a model.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { spawn, execFileSync } from 'node:child_process'
|
|
2
|
+
import { readFileSync, mkdirSync, writeFileSync, renameSync, unlinkSync, statSync } from 'node:fs'
|
|
3
|
+
import { dirname, resolve } from 'node:path'
|
|
4
|
+
|
|
5
|
+
/** PID alone is not ownership: require both executable and process start time. */
|
|
6
|
+
export function processIdentity(pid) {
|
|
7
|
+
if (!Number.isSafeInteger(pid) || pid <= 1) return { state: 'dead' }
|
|
8
|
+
try {
|
|
9
|
+
const text = execFileSync('/bin/ps', ['-p', String(pid), '-o', 'lstart=', '-o', 'comm='],
|
|
10
|
+
{ encoding: 'utf8', env: { ...process.env, LC_ALL: 'C' }, timeout: 1000 }).trim()
|
|
11
|
+
const match = /^(.{24})\s+(.+)$/.exec(text)
|
|
12
|
+
if (match) return { state: 'alive', stamp: match[1], command: match[2] }
|
|
13
|
+
} catch {}
|
|
14
|
+
try { process.kill(pid, 0) } catch (error) {
|
|
15
|
+
if (error.code === 'ESRCH') return { state: 'dead' }
|
|
16
|
+
}
|
|
17
|
+
return { state: 'unknown' }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function processLiveness(pid) {
|
|
21
|
+
if (!Number.isSafeInteger(pid) || pid <= 1) return 'dead'
|
|
22
|
+
try { process.kill(pid, 0); return 'alive' } catch (error) {
|
|
23
|
+
return error.code === 'ESRCH' ? 'dead' : 'unknown'
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** The desktop owns an adopted helper too. If it exits during adoption, retry. */
|
|
28
|
+
export function superviseNotch({ bin, pidPath, log, interval = 250, env = process.env,
|
|
29
|
+
probe = processIdentity, alive = processLiveness, launch = spawn, signal = process.kill.bind(process) }) {
|
|
30
|
+
let current, pending, timer, stopped = false
|
|
31
|
+
const starts = []
|
|
32
|
+
const note = text => log.write(`[notch] ${text}\n`)
|
|
33
|
+
const storedPID = () => {
|
|
34
|
+
try { return Number(readFileSync(pidPath, 'utf8').trim()) } catch { return 0 }
|
|
35
|
+
}
|
|
36
|
+
const owned = pid => {
|
|
37
|
+
const identity = probe(pid)
|
|
38
|
+
return identity.state === 'alive' && resolve(identity.command) === resolve(bin)
|
|
39
|
+
? { pid, ...identity, checkedAt: Date.now() } : undefined
|
|
40
|
+
}
|
|
41
|
+
const schedule = () => {
|
|
42
|
+
clearTimeout(timer)
|
|
43
|
+
if (!stopped) { timer = setTimeout(reconcile, interval); timer.unref?.() }
|
|
44
|
+
}
|
|
45
|
+
function reconcile() {
|
|
46
|
+
if (stopped) return
|
|
47
|
+
if (pending) { schedule(); return }
|
|
48
|
+
// External installers hold this short lease while replacing executable + PID.
|
|
49
|
+
// A crashed installer cannot disable recovery indefinitely.
|
|
50
|
+
try {
|
|
51
|
+
if (Date.now() - statSync(`${pidPath}.updating`).mtimeMs < 60000) { schedule(); return }
|
|
52
|
+
} catch {}
|
|
53
|
+
if (current) {
|
|
54
|
+
const state = alive(current.pid)
|
|
55
|
+
if (state === 'unknown' || (state === 'alive' && Date.now() - current.checkedAt < 5000)) {
|
|
56
|
+
schedule(); return
|
|
57
|
+
}
|
|
58
|
+
const live = probe(current.pid)
|
|
59
|
+
if (live.state === 'unknown' || (live.state === 'alive' && live.stamp === current.stamp && live.command === current.command)) {
|
|
60
|
+
current.checkedAt = Date.now()
|
|
61
|
+
schedule(); return
|
|
62
|
+
}
|
|
63
|
+
current = undefined
|
|
64
|
+
}
|
|
65
|
+
const pid = storedPID()
|
|
66
|
+
const identity = probe(pid)
|
|
67
|
+
if (identity.state === 'unknown') { schedule(); return }
|
|
68
|
+
current = owned(pid)
|
|
69
|
+
if (current) { note(`adopt ${current.pid}`); schedule(); return }
|
|
70
|
+
while (starts.length && Date.now() - starts[0] > 10000) starts.shift()
|
|
71
|
+
if (starts.length >= 3) { note('helper repeatedly exited; retry paused'); stopped = true; return }
|
|
72
|
+
starts.push(Date.now())
|
|
73
|
+
const child = launch(bin, [], { stdio: ['ignore', 'pipe', 'pipe'], detached: false, env })
|
|
74
|
+
pending = child
|
|
75
|
+
child.stdout?.pipe(log, { end: false })
|
|
76
|
+
child.stderr?.pipe(log, { end: false })
|
|
77
|
+
child.once('spawn', () => {
|
|
78
|
+
if (pending !== child) return
|
|
79
|
+
pending = undefined
|
|
80
|
+
if (stopped) { child.kill('SIGTERM'); return }
|
|
81
|
+
current = owned(child.pid)
|
|
82
|
+
// A successful spawn still must be attributable before touching its PID file.
|
|
83
|
+
if (!current) { child.kill('SIGTERM'); schedule(); return }
|
|
84
|
+
mkdirSync(dirname(pidPath), { recursive: true })
|
|
85
|
+
const stage = `${pidPath}.${process.pid}.tmp`
|
|
86
|
+
writeFileSync(stage, `${child.pid}\n`)
|
|
87
|
+
renameSync(stage, pidPath)
|
|
88
|
+
note(`spawn ${child.pid}`)
|
|
89
|
+
schedule()
|
|
90
|
+
})
|
|
91
|
+
child.once('error', error => { if (pending === child) pending = undefined; note(`spawn error: ${error.message}`); schedule() })
|
|
92
|
+
child.once('exit', () => {
|
|
93
|
+
if (pending === child) pending = undefined
|
|
94
|
+
if (current?.pid === child.pid) current = undefined
|
|
95
|
+
schedule()
|
|
96
|
+
})
|
|
97
|
+
schedule()
|
|
98
|
+
}
|
|
99
|
+
const stop = () => {
|
|
100
|
+
stopped = true
|
|
101
|
+
clearTimeout(timer)
|
|
102
|
+
pending?.kill('SIGTERM')
|
|
103
|
+
// A native hot replacement may have updated the file since the last check.
|
|
104
|
+
const candidates = [current, owned(storedPID())].filter(Boolean)
|
|
105
|
+
const seen = new Set()
|
|
106
|
+
for (const item of candidates) {
|
|
107
|
+
if (seen.has(item.pid)) continue
|
|
108
|
+
seen.add(item.pid)
|
|
109
|
+
const live = owned(item.pid)
|
|
110
|
+
if (!live || live.stamp !== item.stamp) continue
|
|
111
|
+
try { signal(item.pid, 'SIGTERM'); note(`stop ${item.pid}`) } catch (error) {
|
|
112
|
+
if (error.code !== 'ESRCH') note(`stop failed: ${error.message}`)
|
|
113
|
+
}
|
|
114
|
+
if (storedPID() === item.pid) { try { unlinkSync(pidPath) } catch {} }
|
|
115
|
+
}
|
|
116
|
+
current = undefined
|
|
117
|
+
}
|
|
118
|
+
reconcile()
|
|
119
|
+
return { get pid() { return current?.pid ?? pending?.pid }, stop, kill: stop }
|
|
120
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Real native helper + disposable sleep processes; never starts DSH or calls a model.
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
|
+
import { spawn } from 'node:child_process'
|
|
4
|
+
import { once } from 'node:events'
|
|
5
|
+
import { mkdtempSync, writeFileSync, rmSync, readFileSync } from 'node:fs'
|
|
6
|
+
import { tmpdir } from 'node:os'
|
|
7
|
+
import { join } from 'node:path'
|
|
8
|
+
import { fileURLToPath } from 'node:url'
|
|
9
|
+
import { Writable } from 'node:stream'
|
|
10
|
+
import { superviseNotch, processIdentity } from './notch-lifecycle.mjs'
|
|
11
|
+
|
|
12
|
+
const bin = fileURLToPath(new URL('../macos/.build/release/dsh-notch', import.meta.url))
|
|
13
|
+
const delay = ms => new Promise(resolve => setTimeout(resolve, ms))
|
|
14
|
+
const logs = new Writable({ write(_chunk, _encoding, callback) { callback() } })
|
|
15
|
+
const running = child => child.exitCode === null && child.signalCode === null
|
|
16
|
+
async function owner() {
|
|
17
|
+
const child = spawn('/bin/sleep', ['60']); await once(child, 'spawn'); return child
|
|
18
|
+
}
|
|
19
|
+
async function stop(child) {
|
|
20
|
+
if (!child || !running(child)) return
|
|
21
|
+
const exited = once(child, 'exit'); child.kill('SIGTERM'); await exited
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
for (const gap of [0, 50, 1200]) {
|
|
25
|
+
const root = mkdtempSync(join(tmpdir(), 'notch-restart-'))
|
|
26
|
+
const runtime = join(root, 'runtime.json'), pidPath = join(root, 'helper.pid')
|
|
27
|
+
const children = []
|
|
28
|
+
let first, second, manager
|
|
29
|
+
const writeOwner = child => writeFileSync(runtime, JSON.stringify({ pid: child.pid,
|
|
30
|
+
writtenAt: Date.now(), origin: 'http://127.0.0.1:9', token: 'offline-test' }))
|
|
31
|
+
const launch = (file, args, options) => {
|
|
32
|
+
const child = spawn(file, args, { ...options, env: { ...process.env, DSH_NOTCH_RUNTIME_FILE: runtime } })
|
|
33
|
+
children.push(child); return child
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
first = await owner(); writeOwner(first)
|
|
37
|
+
const old = launch(bin, [], { stdio: 'ignore', detached: true }); await once(old, 'spawn')
|
|
38
|
+
writeFileSync(pidPath, String(old.pid))
|
|
39
|
+
await delay(800)
|
|
40
|
+
assert.equal(processIdentity(old.pid).command, bin)
|
|
41
|
+
await stop(first)
|
|
42
|
+
await delay(gap)
|
|
43
|
+
second = await owner(); writeOwner(second)
|
|
44
|
+
manager = superviseNotch({ bin, pidPath, launch, log: logs, interval: 25 })
|
|
45
|
+
await delay(900)
|
|
46
|
+
const live = children.filter(running)
|
|
47
|
+
assert.equal(live.length, 1, `gap ${gap}: exactly one helper expected`)
|
|
48
|
+
assert.equal(manager.pid, live[0].pid)
|
|
49
|
+
assert.equal(Number(readFileSync(pidPath, 'utf8')), live[0].pid)
|
|
50
|
+
const start = performance.now()
|
|
51
|
+
manager.stop()
|
|
52
|
+
while (children.some(running) && performance.now() - start < 1000) await delay(10)
|
|
53
|
+
assert.equal(children.filter(running).length, 0, 'quit must also close an adopted helper')
|
|
54
|
+
console.log(`PASS restart gap=${gap}ms: one live helper; quit ${(performance.now() - start).toFixed(0)}ms`)
|
|
55
|
+
} finally {
|
|
56
|
+
manager?.stop()
|
|
57
|
+
await Promise.all(children.map(stop))
|
|
58
|
+
await stop(first); await stop(second)
|
|
59
|
+
rmSync(root, { recursive: true, force: true })
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# 官方桌面版 0.1.7-rc.2 适配
|
|
2
|
+
|
|
3
|
+
本分支保留 `ff78f13` 的完整弹性拖拽、左端变细、隐藏贴边和关注事件弹回,合入 `e79bbf1` 的 RC2 兼容分支,并保存当前本地桌面部署已经采用的 Home 路径、原生辅助程序托管、后台子任务及桌面唤起适配。
|
|
4
|
+
|
|
5
|
+
## 本次故障
|
|
6
|
+
|
|
7
|
+
正式 Host 给辅助程序传入 `DSH_NOTCH_RUNTIME_FILE`,用于指定连接文件。旧原生入口却用同一个变量判断“演示”,把窗口向内移动 360 pt,并让决策面板忽略自动折叠。现在连接选择与显示行为完全分开:正式入口始终以物理屏幕右边缘为锚点,离线演示只走已有显式入口。
|
|
8
|
+
|
|
9
|
+
## 验证
|
|
10
|
+
|
|
11
|
+
- `npm run test:desktop-launch` 使用真正的 `AppDelegate` 和离线连接文件,检查原生窗口边界:旧入口测得 360 pt 间隙,修复后为 0 pt。测试不连接真实 Host,不调用模型。
|
|
12
|
+
- `npm run test:edge-dock` 通过,覆盖二维拖动、连续形变、原形裁切、回弹打断、重要事件恢复和减少动态效果。
|
|
13
|
+
- `npm test`:61/61 通过,包含 RC2 的 `jobs.list(agent.id)`、`job.owner` 和主任务归属。每个测试进程使用临时 `DSH_HOME`,防止继承真实 Home 写入已读状态。
|
|
14
|
+
- Release 原生构建与 Host 预编译构建通过;`dshx check` 检查源入口通过,热替换文件集合同时声明实际加载的 `lib/index.mjs` 与源码及辅助模块。
|
|
15
|
+
- 原生预览实操完成斜向拖动收纳、运行更新保持隐藏、完成后完整弹回。
|
|
16
|
+
|
|
17
|
+
## 部署边界
|
|
18
|
+
|
|
19
|
+
本次运行中需要改变的只有用户目录里的原生辅助程序。当前 Host 已经加载 RC2 适配的 Host 插件,服务器部分不需要再激活。更新采用辅助程序自己的短更新租约、哈希与进程身份检查、备份和原子替换;由现有托管器拉起唯一新辅助进程。官方应用包、Host 进程、profile 配置及真实任务均不修改。
|
|
20
|
+
|
|
21
|
+
当前 DSHX 外部 CLI 的 desktop `activation-plan` 能分类为 artifact,但离线 profile 合成需要 Creator+ 发出的短时能力,返回 `DESKTOP_PROFILE_BRIDGE_REQUIRED`。本次不绕过此限制、不伪造票据、不执行 Host 插件激活;原生辅助程序的独立更新与运行验证单独记录。以后若改 Host 模块,仍需满足对应激活流程。
|
|
22
|
+
|
|
23
|
+
正式验收区分源代码、构建、安装哈希、唯一进程、Host 快照和 GUI 操作。独立预览不等于向正式会话注入事件,算法测试不等于实屏帧率保证。
|