dsh-sidecard-ask 1.3.0 → 1.3.2
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/CHANGELOG.md +40 -0
- package/README.md +49 -1
- package/client.js +40 -2
- package/index.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.3.2
|
|
4
|
+
|
|
5
|
+
**主题:核对并适配 DSH 桌面版(Electron,0.2.0-rc.2)。**
|
|
6
|
+
|
|
7
|
+
核对结论(实测,详见 README §5.3):
|
|
8
|
+
|
|
9
|
+
- 桌面版是**独立运行形态**:Electron-as-Node 跑 `app.asar\dsh\...\dsh-desktop-host`,框架包全在 `app.asar` 内,
|
|
10
|
+
自带 node 24.18.1 + pnpm 11.7.0;`DSH_PROFILE=desktop`,与 web 版的 `profiles\web` **各自独立**;
|
|
11
|
+
- 本插件在桌面 profile 中已登记(`link:D:/Users/34332/AI/dsh-sidecard-ask` + `dsh.profile.bundles`),
|
|
12
|
+
**无需改动即加载**:宿主半 `v1.3.1` 正常,客户端自检上报显示三个槽位落点正常、两个适配器均可用,
|
|
13
|
+
真机 `start→reasoning×106→delta×46→status→done`(1.89 s)通过;
|
|
14
|
+
- 桌面版用的 dsh-better-sidebar 是 **0.24.1**:与 0.22.1 的消费端契约差异**纯增量**
|
|
15
|
+
(`target` 增加 `'side'`、新增可选 `preferNewPane`),本插件不传这两项 → 不受影响。
|
|
16
|
+
|
|
17
|
+
**桌面特有修改:窗口拖拽区防御。** 桌面外壳把顶层元素标记为窗口拖拽区(`-webkit-app-region: drag`),
|
|
18
|
+
落在其中的点击会变成拖动窗口;同生态的 dsh-better-sidebar 为此专门带了一条防御,而本插件的浮层此前没有。
|
|
19
|
+
现在样式表为每个自有根节点声明 `-webkit-app-region:no-drag`(`.dsa-layer/.dsa-trigger/.dsa-pop/.dsa-stack/
|
|
20
|
+
.dsa-card/.dsa-toast/.dsa-settings`),并有回归测试锁定该规则(含"该规则是真实规则而非只出现在注释里"的断言)。
|
|
21
|
+
该属性在浏览器中无效,web 版不受影响。
|
|
22
|
+
|
|
23
|
+
**确认无需改动的部分**:`styles.insert` / `host.call` 只属于**动态**客户端半(本插件是静态形态,官方等价做法
|
|
24
|
+
就是手工插 `<style>`,宿主通信走自有 HTTP 路由);名为 `shortcuts` 与 `conversation` 的客户端服务在运行实例中
|
|
25
|
+
**都不存在**(inspection 报 `no catalogued Service`),因此快捷键与 composer 草稿保持既有实现与占位降级。
|
|
26
|
+
|
|
27
|
+
自测 327 → **336 项**(verify 53 / contract 149 / smoke 134)。
|
|
28
|
+
|
|
29
|
+
## 1.3.1
|
|
30
|
+
|
|
31
|
+
**主题:让"两半代际不一致"成为一个被处理的状态,而不是噪声。**
|
|
32
|
+
|
|
33
|
+
这个插件的宿主半只在**重启 DSH** 时更新,客户端半在**页面加载**时更新,所以"新客户端 + 旧宿主"是结构性常态
|
|
34
|
+
(当前本机就是这个状态:页面已跑到 1.3.x,宿主仍是重启前的 1.2.0)。
|
|
35
|
+
|
|
36
|
+
- 客户端在自检上报被宿主以 `not-found`(该路由还不存在,旧宿主)、`bad-response`(SPA 兜底返回 HTML)
|
|
37
|
+
或 `unreachable` 拒绝时,**记住"此宿主不支持自检"并停止重试**,只打一条 info 说明"重启 DSH 后生效";
|
|
38
|
+
其它错误(例如配置类真实错误)仍按 warning 记录,不会错误地关闭通道。
|
|
39
|
+
- 新增纯函数 `isDiagnosticsUnsupported(error)` 并纳入契约测试(5 条断言覆盖各错误码)。
|
|
40
|
+
|
|
41
|
+
自测 322 → **327 项**(verify 53 / contract 140 / smoke 134)。
|
|
42
|
+
|
|
3
43
|
## 1.3.0
|
|
4
44
|
|
|
5
45
|
**主题:把"客户端半的状态"变成宿主可读——补上导致前两次缺陷排查困难的观测盲点。**
|
package/README.md
CHANGED
|
@@ -221,6 +221,50 @@ better-sidebar 会把收到的每个 tab 描述符**镜像注册进同一个原
|
|
|
221
221
|
|
|
222
222
|
两者共存、均 `active: true` —— 即"同 kind 冲突"已被消除,`auto` 默认走原生右侧栏,强制 `sideSurface: better-sidebar` 仍可用。
|
|
223
223
|
|
|
224
|
+
### 5.3 与 DSH 桌面版(Electron)的适配核对(2026-09-30)
|
|
225
|
+
|
|
226
|
+
桌面版与命令行/web 版**不是同一套运行形态**,核对结论如下。
|
|
227
|
+
|
|
228
|
+
| 维度 | 事实(实测) |
|
|
229
|
+
|---|---|
|
|
230
|
+
| 桌面 App | `DeepSeek Harness.exe` **0.2.0-rc.2**(`resources\app-update.yml` 更新通道 `nightly`,源 `download.deepseek.com/dsh-desk/feeds/win-x64/`) |
|
|
231
|
+
| 运行形态 | Electron-as-Node 跑 `app.asar\dsh\node_modules\@deepseek-ai\dsh-desktop-host\lib\index.js`;**框架包全部打包在 `app.asar` 内**(121 MB 归档,普通 shell/glob/grep 读不到,只能靠运行实例的 inspection 查) |
|
|
232
|
+
| 自带运行时 | `resources\runtime\versions.json`:node **24.18.1** + pnpm **11.7.0**(装插件用的是它自带的 pnpm) |
|
|
233
|
+
| profile | **`DSH_PROFILE=desktop` → `C:\Users\34332\.dsh\profiles\desktop`**,与 web 版的 `profiles\web` **互相独立**:两者各有自己的 `package.json`/`node_modules`/`dsh.profile.bundles`,插件必须分别安装 |
|
|
234
|
+
| 本插件安装状态 | 桌面 profile 的 `package.json` 中为 `"dsh-sidecard-ask": "link:D:/Users/34332/AI/dsh-sidecard-ask"`,且已在 `dsh.profile.bundles` 内 → **无需改动即加载** |
|
|
235
|
+
| 宿主半 | `GET http://127.0.0.1:19387/sidecard-ask/api/state` → `dsh-sidecard-ask v1.3.1`、`sideEngine=true`(provider `spawn,fork`)、`capabilities.parent` 正常、配置落点 `~/.dsh/sidecard-ask/config.json` |
|
|
236
|
+
| 客户端半 | 由本插件自己的自检上报读出:`version=1.3.1`、`slots={overlay: shell.overlay, settings: settings.section, sessionProbe: conversation.input.right}`、`native.available=true`、`better.available=true` 且 `better.version=0.24.1` |
|
|
237
|
+
| 端到端 | 真机 `start→reasoning×106→delta×46→status→done`,1.89 s,`done.text` 是真实答案(子代理 + 流式帧 + 只读工具白名单全部正常) |
|
|
238
|
+
| 客户端服务目录 | 与 web 版**完全一致**(layout / locale / sessions / slots / theme / timer / uiWorkspace / workspaces),无桌面专属差异 |
|
|
239
|
+
|
|
240
|
+
**桌面版用到的 dsh-better-sidebar 是 0.24.1**(比上轮核对的 0.22.1 新):0.22.1 → 0.24.1 的
|
|
241
|
+
`lib/types/client/service.d.ts` 差异是**纯增量**——`target?: 'right' | 'bottom'` 增加 `'side'`(右侧栏第二窗格),
|
|
242
|
+
并新增可选 `preferNewPane?: boolean`;`SIDEBAR_FEATURES` 仍含 `tabMeta`,`dsh.client.inject` 未变。
|
|
243
|
+
本插件不传这两个字段 → **不受影响**(默认落点行为未变)。
|
|
244
|
+
|
|
245
|
+
**桌面版特有的适配修改(1.3.2):窗口拖拽区。** 桌面外壳会把顶层元素标记为窗口拖拽区
|
|
246
|
+
(`-webkit-app-region: drag`),落在拖拽区内的点击会**变成拖动窗口**而不是点中 UI。同生态的
|
|
247
|
+
dsh-better-sidebar 为此专门带了一条防御(`html[data-platform] body>[data-dsh-better-sidebar]{-webkit-app-region:initial}`
|
|
248
|
+
+ `[data-dsh-panel-host]>*{-webkit-app-region:no-drag}`)。本插件的浮层此前**没有这条防御**,现已在样式表里为
|
|
249
|
+
每个自有根节点声明 `-webkit-app-region:no-drag`
|
|
250
|
+
(`.dsa-layer/.dsa-trigger/.dsa-pop/.dsa-stack/.dsa-card/.dsa-toast/.dsa-settings`),并加回归测试锁定该规则。
|
|
251
|
+
该属性在浏览器里无效,不影响 web 版。
|
|
252
|
+
|
|
253
|
+
**桌面形态下确认「不需要改」的两点**:
|
|
254
|
+
|
|
255
|
+
- `styles.insert` / `host.call` 属于**动态运行时**的插件能力(inspection 的 `Builtin` 定义就是
|
|
256
|
+
"Plain-JavaScript symbols available to a **dynamic** Client half")。本插件是**静态**客户端半
|
|
257
|
+
(`__ModuleLoader__.load` + `require('react')`),官方形态就是手工插入 `<style>`——同为静态形态的
|
|
258
|
+
`uiskin-theme` 在源码里注明 "the static twin of the dynamic runner's `styles.insert`";宿主通信走自有的
|
|
259
|
+
`/sidecard-ask/api` 路由;
|
|
260
|
+
- 名为 `shortcuts` 与 `conversation` 的客户端服务**都不在运行实例的服务目录里**(inspection 明确报
|
|
261
|
+
`no catalogued Service named ...`)。所以"并入宿主快捷键注册表"与"使用 composer 草稿服务"两条路都不存在:
|
|
262
|
+
本插件继续自带 keydown 监听(快捷键可配置)与 `PLACEHOLDER: composer-draft` 降级路径。
|
|
263
|
+
|
|
264
|
+
**仍未验证的部分(如实记录)**:桌面窗口内的**视觉与点击行为**(本工作区无 GUI 自动化,无法点按验证);
|
|
265
|
+
`Alt+Q` 是否会撞上桌面 App 的菜单加速键(Electron 的菜单加速键由菜单先处理,页面的 keydown 可能收不到;
|
|
266
|
+
若冲突,在设置页改成 `Ctrl+Alt+Q` 之类即可);Electron 下 `navigator.clipboard` 的写入权限(已有"选中文本"降级兜底)。
|
|
267
|
+
|
|
224
268
|
---
|
|
225
269
|
|
|
226
270
|
## 六、未知 DSH API:占位接口与替换方式
|
|
@@ -396,7 +440,7 @@ node test/smoke-test.mjs # 端到端:流式/截断/取消/持久化/失
|
|
|
396
440
|
```
|
|
397
441
|
|
|
398
442
|
三个脚本都以 `process.exitCode` 反映结果,失败会列出具体条目;测试会把 `DSH_HOME` 指向临时目录,不会污染真实配置。
|
|
399
|
-
当前规模:verify 53 项 + contract
|
|
443
|
+
当前规模:verify 53 项 + contract 149 项 + smoke 134 项 = **336 项全部通过**。
|
|
400
444
|
|
|
401
445
|
### 10.2 版本能力探测(§7 矩阵的来源)
|
|
402
446
|
|
|
@@ -447,6 +491,10 @@ $tmp = Join-Path $env:TEMP 'probe.json'
|
|
|
447
491
|
`native.reason` / `better.reason` 会写明**为什么**某个承载面不可用(例如 `no-tab-meta` 或注册表的报错原文)——
|
|
448
492
|
1.2.1 修掉的那个 tab kind 冲突正是靠这类信息才定位到的。
|
|
449
493
|
|
|
494
|
+
> **两半代际不一致是常态**:宿主半只在重启 DSH 时更新,客户端半在页面加载时更新。
|
|
495
|
+
> 所以"新客户端 + 旧宿主"很常见——此时 `/diagnose` 还不存在,客户端会**识别这一点、只提示一次并停止重试**
|
|
496
|
+
> (`not-found` / SPA 兜底 HTML / 不可达三类失败),不会每次加载都刷警告。
|
|
497
|
+
|
|
450
498
|
**2026-09-28 在 DSH 0.1.7-rc.2 上的实测结果**(`provider=spawn`、`sideTools=readonly`):
|
|
451
499
|
`start x1 → reasoning x181 → delta x90 → status x1 → done x1`,耗时 2.6 s,`done.text` 为真实模型答案。
|
|
452
500
|
这条记录同时说明:子代理启动、只读工具白名单(与真实工具表求交后)、流式帧桥接、SSE 线协议、运行结束后的 `dispose()` 都是**在真实宿主上跑通的**,
|
package/client.js
CHANGED
|
@@ -47,7 +47,7 @@ window.__ModuleLoader__.load({
|
|
|
47
47
|
* the Host and the module's `api.version` both read it, so a report can
|
|
48
48
|
* never claim a generation the browser is not actually running.
|
|
49
49
|
*/
|
|
50
|
-
const CLIENT_VERSION = '1.3.
|
|
50
|
+
const CLIENT_VERSION = '1.3.2'
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
53
|
* Tab kind served by the DSH native right rail (also its implementation id).
|
|
@@ -948,6 +948,23 @@ window.__ModuleLoader__.load({
|
|
|
948
948
|
*/
|
|
949
949
|
let capturedComposerActions = null
|
|
950
950
|
|
|
951
|
+
/**
|
|
952
|
+
* Whether `POST /diagnose` is worth calling on this host generation.
|
|
953
|
+
*
|
|
954
|
+
* The two halves update independently — the Host half only on a DSH
|
|
955
|
+
* restart, the Client half on a page load — so a page can easily run a
|
|
956
|
+
* NEWER Client against an older Host that has no `/diagnose` route. The
|
|
957
|
+
* first refusal turns the channel off for this page instead of retrying
|
|
958
|
+
* (and warning) on every report.
|
|
959
|
+
*
|
|
960
|
+
* @param {unknown} error - the thrown wire error.
|
|
961
|
+
* @returns {boolean} true when the failure means "this host lacks the route".
|
|
962
|
+
*/
|
|
963
|
+
function isDiagnosticsUnsupported(error) {
|
|
964
|
+
const code = error?.code
|
|
965
|
+
return code === 'not-found' || code === 'bad-response' || code === 'unreachable'
|
|
966
|
+
}
|
|
967
|
+
|
|
951
968
|
/**
|
|
952
969
|
* What this Client half wants the Host to know about its own state.
|
|
953
970
|
*
|
|
@@ -1015,6 +1032,17 @@ window.__ModuleLoader__.load({
|
|
|
1015
1032
|
|
|
1016
1033
|
/** Theme-token-only stylesheet. Every class is prefixed `dsa-`. */
|
|
1017
1034
|
const CSS_TEXT = `
|
|
1035
|
+
/* Desktop (Electron) window-drag guard.
|
|
1036
|
+
The DSH desktop shell marks top-level elements as window-drag regions
|
|
1037
|
+
(\`-webkit-app-region: drag\`), and a click landing inside such a region MOVES
|
|
1038
|
+
THE WINDOW instead of reaching the UI — which would make the floating trigger,
|
|
1039
|
+
the question popover and the cards unclickable in the desktop app. A
|
|
1040
|
+
descendant of a drag region must opt out explicitly; dsh-better-sidebar ships
|
|
1041
|
+
exactly this guard for its own host
|
|
1042
|
+
(\`html[data-platform] body>[data-dsh-better-sidebar]{-webkit-app-region:initial}\`
|
|
1043
|
+
plus \`[data-dsh-panel-host]>*{-webkit-app-region:no-drag}\`).
|
|
1044
|
+
Every surface we draw declares it. The property is inert in a browser. */
|
|
1045
|
+
.dsa-layer,.dsa-trigger,.dsa-pop,.dsa-stack,.dsa-card,.dsa-toast,.dsa-settings{-webkit-app-region:no-drag}
|
|
1018
1046
|
.dsa-layer{pointer-events:none;position:relative;z-index:60}
|
|
1019
1047
|
.dsa-trigger{pointer-events:auto;position:fixed;display:flex;align-items:center;gap:4px;
|
|
1020
1048
|
padding:4px 8px;border-radius:8px;border:1px solid var(--dsw-alias-border-l2, rgba(127,127,127,.35));
|
|
@@ -2164,14 +2192,23 @@ window.__ModuleLoader__.load({
|
|
|
2164
2192
|
|
|
2165
2193
|
/**
|
|
2166
2194
|
* Debounced self-report to the Host. Diagnostics are best-effort: a
|
|
2167
|
-
* failure is logged and never surfaces as a user-visible error
|
|
2195
|
+
* failure is logged and never surfaces as a user-visible error, and a
|
|
2196
|
+
* host too old to have the route is remembered so the channel is not
|
|
2197
|
+
* retried for the rest of the page's life.
|
|
2168
2198
|
*/
|
|
2169
2199
|
let reportTimer = null
|
|
2200
|
+
let diagnosticsSupported = true
|
|
2170
2201
|
const scheduleReport = (delay = 600) => {
|
|
2202
|
+
if (!diagnosticsSupported) return
|
|
2171
2203
|
if (reportTimer !== null) clearTimeout(reportTimer)
|
|
2172
2204
|
reportTimer = setTimeout(() => {
|
|
2173
2205
|
reportTimer = null
|
|
2174
2206
|
void postJson('diagnose', buildClientReport(store.state)).catch((error) => {
|
|
2207
|
+
if (isDiagnosticsUnsupported(error)) {
|
|
2208
|
+
diagnosticsSupported = false
|
|
2209
|
+
console.info(`[${PLUGIN_ID}] 宿主半尚不支持自检上报(宿主半比客户端旧,重启 DSH 后生效)`)
|
|
2210
|
+
return
|
|
2211
|
+
}
|
|
2175
2212
|
console.warn(`[${PLUGIN_ID}] 自检上报失败(不影响功能):`, error?.message ?? error)
|
|
2176
2213
|
})
|
|
2177
2214
|
}, delay)
|
|
@@ -2456,6 +2493,7 @@ window.__ModuleLoader__.load({
|
|
|
2456
2493
|
composeMainPrompt,
|
|
2457
2494
|
askInMainConversation,
|
|
2458
2495
|
buildClientReport,
|
|
2496
|
+
isDiagnosticsUnsupported,
|
|
2459
2497
|
renderRichText,
|
|
2460
2498
|
pickSurface,
|
|
2461
2499
|
dict: DICT,
|
package/index.js
CHANGED
|
@@ -42,7 +42,7 @@ export const name = 'dsh-sidecard-ask'
|
|
|
42
42
|
export const inject = ['webServer']
|
|
43
43
|
|
|
44
44
|
/** Version of this plugin (kept in step with package.json by test/verify.mjs). */
|
|
45
|
-
export const PLUGIN_VERSION = '1.3.
|
|
45
|
+
export const PLUGIN_VERSION = '1.3.2'
|
|
46
46
|
|
|
47
47
|
/** Route prefix of the plugin's own API. */
|
|
48
48
|
export const ROUTE_PREFIX = '/sidecard-ask/api'
|