dsh-zen-remote 2.0.0 → 2.0.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/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/docs/remote-access.md +2 -2
- package/lan-gate.mjs +15 -1
- package/lib/client.js +271 -30
- package/lib/fingerprint.js +4 -2
- package/lib/fingerprint.js.map +1 -1
- package/lib/intercept.js +161 -14
- package/lib/intercept.js.map +1 -1
- package/lib/merge-streams.js +11 -4
- package/lib/merge-streams.js.map +1 -1
- package/lib/relay-access.js.map +1 -1
- package/lib/relay-server.js +32 -11
- package/lib/relay-server.js.map +1 -1
- package/lib/types/client/effects/model-group-side.d.ts +13 -0
- package/lib/types/client/effects/model-group-side.d.ts.map +1 -0
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/styles/compat.css.d.ts +1 -1
- package/lib/types/client/styles/compat.css.d.ts.map +1 -1
- package/lib/types/client/styles/composer.css.d.ts +1 -1
- package/lib/types/client/styles/composer.css.d.ts.map +1 -1
- package/lib/types/client/styles/remote-session.css.d.ts +1 -1
- package/lib/types/client/styles/remote-session.css.d.ts.map +1 -1
- package/lib/types/client-data/model-group-side.d.ts +44 -0
- package/lib/types/client-data/model-group-side.d.ts.map +1 -0
- package/lib/types/fingerprint.d.ts +4 -2
- package/lib/types/fingerprint.d.ts.map +1 -1
- package/lib/types/intercept.d.ts +19 -9
- package/lib/types/intercept.d.ts.map +1 -1
- package/lib/types/merge-streams.d.ts +7 -2
- package/lib/types/merge-streams.d.ts.map +1 -1
- package/lib/types/relay-access.d.ts.map +1 -1
- package/lib/types/relay-server.d.ts.map +1 -1
- package/lib/types/virtual-id.d.ts +14 -0
- package/lib/types/virtual-id.d.ts.map +1 -1
- package/lib/virtual-id.js +14 -0
- package/lib/virtual-id.js.map +1 -1
- package/package.json +48 -49
- package/src/client/effects/model-group-side.ts +132 -0
- package/src/client/index.tsx +7 -0
- package/src/client/styles/compat.css.ts +14 -8
- package/src/client/styles/composer.css.ts +2 -1
- package/src/client/styles/remote-session.css.ts +43 -20
- package/src/client-data/model-group-side.ts +65 -0
- package/src/fingerprint.ts +4 -2
- package/src/intercept.ts +167 -12
- package/src/merge-streams.ts +11 -4
- package/src/relay-access.ts +6 -3
- package/src/relay-server.ts +49 -11
- package/src/virtual-id.ts +15 -0
package/README.md
CHANGED
|
@@ -90,7 +90,7 @@ dsh plugin --profile web add dsh-zen-remote
|
|
|
90
90
|
// ~/.dsh/profiles/desktop/package.json
|
|
91
91
|
{
|
|
92
92
|
"dependencies": {
|
|
93
|
-
"dsh-zen-remote": "^2.0.
|
|
93
|
+
"dsh-zen-remote": "^2.0.2" // for local development: "link:/path/to/dsh-zen-remote"
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
```
|
package/README.zh-CN.md
CHANGED
|
@@ -90,7 +90,7 @@ dsh plugin --profile web add dsh-zen-remote
|
|
|
90
90
|
// ~/.dsh/profiles/desktop/package.json
|
|
91
91
|
{
|
|
92
92
|
"dependencies": {
|
|
93
|
-
"dsh-zen-remote": "^2.0.
|
|
93
|
+
"dsh-zen-remote": "^2.0.2" // 本地开发换成 "link:/path/to/dsh-zen-remote"
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
```
|
package/docs/remote-access.md
CHANGED
|
@@ -325,7 +325,7 @@ sudo cloudflared service install # 通了再装成常驻服务
|
|
|
325
325
|
| `/v1/upload` | POST | 远程会话的**非图片附件**上传:请求体是原始字节流(不是 JSON);查询串按允许清单规范化重建——只保留 `sessionId`(恰好一次、过共享表,未共享 403)与 `name`(至多一次);上限 100 MiB,`Content-Length` 预检加流式计数双保险,超限 413(先回拒绝再排空尾部字节);每设备并发 8(超出 429);随后与 `/v1/http` 一样**进程内**交给宿主 `/api` 共享 handler——上传回执落进的会话与之后 `session/prompt` 解析附件引用的会话是同一个 |
|
|
326
326
|
| `/v1/unshare` | POST | 子客户端主动关闭某会话的远程(只认共享表内的会话) |
|
|
327
327
|
|
|
328
|
-
**允许清单里的方法**(其余一律 `forbidden-method`):会话读写(`session/follow`、`session/page`、`session/prompt`、`session/cancel`、`session/rename`、`session/selectModel`、`session/updateQueue`、`session/attachment`、`session/projections`)、新建与分叉(`session/create`、`session/fork`,结果自动共享)、子智能体(`subagents/prompt`、`subagents/interruptByParent`,按父会话判定)、附件与 @ 引用(`fileUploads/upload`、`fileReferences/list`、`sessionReferenceResolver/candidates`)、面板长尾(`goals/*` 五个、`commands/list|execute`、`agentPresets/select`、`sessionFeedback/record`)、文件树与预览(`workspaceFiles/list|changes|read|readBytes|stat`)、终端(`terminal/*`)、任务(`job/list|follow|kill`)、`skills/list`、消息反馈(`messageFeedback/*`)、`schedule/list`、工作区会话操作(`workspace/pinSession` 等)、以及四个全局读:`session/control` 流、`session/list`、`workspace/follow` 流与 `session/modelCatalog`。前三个不带会话参数,安全靠**输出过滤**:每一帧/每一行结果先按共享表过滤,未共享会话的行到不了客户端;`session/list` 结果行里指向不可访问会话的 `parentSessionId` 字段也会被删掉(行的其余部分照常透传)。`session/modelCatalog` 同样无参数、全局只读——它就是服务端的模型提供方目录,只有分组与模型 id、显示名,不带会话数据;服务端会把结果里的 `failures` 数组清空(宿主的逐组错误文本可能带端点或凭据细节,客户端本来也不展示它)。`sessionReferenceResolver/candidates`(@ 引用候选)的答案带**每一个**服务端会话的标题、目录与现成 mention,同样走行级输出过滤,只放行已共享会话的行。审批/提问事件经 `$zr/events` 订阅转发,逐事件按 `agentId`
|
|
328
|
+
**允许清单里的方法**(其余一律 `forbidden-method`):会话读写(`session/follow`、`session/page`、`session/prompt`、`session/cancel`、`session/rename`、`session/selectModel`、`session/updateQueue`、`session/attachment`、`session/projections`)、新建与分叉(`session/create`、`session/fork`,结果自动共享)、子智能体(`subagents/prompt`、`subagents/interruptByParent`,按父会话判定)、附件与 @ 引用(`fileUploads/upload`、`fileReferences/list`、`sessionReferenceResolver/candidates`)、面板长尾(`goals/*` 五个、`commands/list|execute`、`agentPresets/select`、`sessionFeedback/record`)、文件树与预览(`workspaceFiles/list|changes|read|readBytes|stat`)、终端(`terminal/*`)、任务(`job/list|follow|kill`)、`skills/list`、消息反馈(`messageFeedback/*`)、`schedule/list`、工作区会话操作(`workspace/pinSession` 等)、以及四个全局读:`session/control` 流、`session/list`、`workspace/follow` 流与 `session/modelCatalog`。前三个不带会话参数,安全靠**输出过滤**:每一帧/每一行结果先按共享表过滤,未共享会话的行到不了客户端;`session/list` 结果行里指向不可访问会话的 `parentSessionId` 字段也会被删掉(行的其余部分照常透传)。`session/modelCatalog` 同样无参数、全局只读——它就是服务端的模型提供方目录,只有分组与模型 id、显示名,不带会话数据;服务端会把结果里的 `failures` 数组清空(宿主的逐组错误文本可能带端点或凭据细节,客户端本来也不展示它)。`sessionReferenceResolver/candidates`(@ 引用候选)的答案带**每一个**服务端会话的标题、目录与现成 mention,同样走行级输出过滤,只放行已共享会话的行。审批/提问事件经 `$zr/events` 订阅转发,逐事件按 `agentId` 判定可达性;已共享会话的运行状态事件(`api-session/status` emit)也经同一条订阅转发(T75),按 `args[0]` 里的会话 id 判定可达性——这是唯一一种被放行的 emit。
|
|
329
329
|
|
|
330
330
|
`/v1/http` 那条路由是另一张按**路由名**登记的允许清单(不是方法表的一部分),纪律相同:表外路由一律 404,登记的路由只按声明的会话参数判定;子客户端一侧的对应入口是 `GET /_dsh/zen-remote/client/http/<route>`——浏览器 fetch 包装拦下的 `/api/changes.*` 虚拟 id 请求改道到这里,还原原始 id 后经中继转发,上游 Content-Type 只认 JSON,其余一律降级为 `text/plain` + `nosniff`。
|
|
331
331
|
|
|
@@ -338,7 +338,7 @@ sudo cloudflared service install # 通了再装成常驻服务
|
|
|
338
338
|
- `dsh-session:` 会话引用也会被扫描:DSH 会在**发消息**(`session/prompt` / `subagents/prompt` 的 content 文本块)、**改写排队消息**(`session/updateQueue` 的 edit 内容)与**斜杠命令**(`commands/execute` 参数里的全部字符串——命令处理器会把原始输入拼进下一条用户消息)这三条路径上注入被引用会话的内容,且注入时不再做权限检查,所以引用指向未共享会话的调用在服务端直接 403;@ 引用候选(`sessionReferenceResolver/candidates`)的答案也只放行已共享会话的行;
|
|
339
339
|
- 终端是有意开放的(桌面应用端是可信设备):开的是**服务端**的 PTY,以服务端用户身份运行、不受智能体沙箱与审批限制;关闭会话的远程时终端流一并终止;
|
|
340
340
|
- `workspaceFiles/read` 等文件预览接口不限制在会话目录内(DSH 自身就不限制),服务端进程可读的文件都能读——信任前提与终端相同;
|
|
341
|
-
- 每台设备并发流数有上限(32)、同时在途的 invoke 数也有上限(32,超出 429 `too-many-invokes`);`*/internal` 形状的错误码(`gateway/internal` 等)只回码不带消息——那类消息引用的是服务端内部细节。事件应答按「转发时的订阅 + 设备」核对归属。审批/提问的转发是**先到先得**:服务端自己的界面和子客户端谁先应答谁生效,后答的一方被网关拒绝、同步成「已处理」。中继**不代答**:未共享会话的审批/提问事件不会被转发,服务端界面也不在线时这个审批就一直等待——网关会把仍未应答的事件转交给下一个连上来的订阅,等,而不是替你拒绝(代答会把整批待审批一次性判死,砸掉「推送 → 唤醒 → 审批」链路)。未共享会话的**通知类**事件(EMIT
|
|
341
|
+
- 每台设备并发流数有上限(32)、同时在途的 invoke 数也有上限(32,超出 429 `too-many-invokes`);`*/internal` 形状的错误码(`gateway/internal` 等)只回码不带消息——那类消息引用的是服务端内部细节。事件应答按「转发时的订阅 + 设备」核对归属。审批/提问的转发是**先到先得**:服务端自己的界面和子客户端谁先应答谁生效,后答的一方被网关拒绝、同步成「已处理」。中继**不代答**:未共享会话的审批/提问事件不会被转发,服务端界面也不在线时这个审批就一直等待——网关会把仍未应答的事件转交给下一个连上来的订阅,等,而不是替你拒绝(代答会把整批待审批一次性判死,砸掉「推送 → 唤醒 → 审批」链路)。未共享会话的**通知类**事件(EMIT 帧:会话列表摘要、账号到期之类的服务端全局状态)一律不转发;唯一的例外是已共享会话(含其子会话)的 `api-session/status`——它只描述单个会话的运行/空闲,逐帧按共享表判定,子客户端靠它在主机侧一轮开始或结束时同步运行状态徽标(断线期间的翻转由重连后补拉列表纠正)。
|
|
342
342
|
|
|
343
343
|
---
|
|
344
344
|
|
package/lan-gate.mjs
CHANGED
|
@@ -87,8 +87,22 @@ export function apply(ctx, config) {
|
|
|
87
87
|
// 不传。
|
|
88
88
|
const env = childEnv()
|
|
89
89
|
const targetPort = Number(env.LAN_GATE_TARGET_PORT || 3080)
|
|
90
|
+
// Prefer live webServer bind info (host may be a LAN IP; protocol may be https:).
|
|
91
|
+
const proto = (ctx.webServer && typeof ctx.webServer.protocol === 'string')
|
|
92
|
+
? ctx.webServer.protocol
|
|
93
|
+
: 'http:'
|
|
94
|
+
const rawHost = (ctx.webServer && typeof ctx.webServer.host === 'string' && ctx.webServer.host)
|
|
95
|
+
? ctx.webServer.host
|
|
96
|
+
: '127.0.0.1'
|
|
97
|
+
// URL host: wrap IPv6; wildcard/empty falls back to loopback for the token URL.
|
|
98
|
+
// Inline on purpose — dsh-host-webserver exports isWildcardHost() only from
|
|
99
|
+
// 0.2.x, and the peer range still admits 0.1.7 hosts where importing that
|
|
100
|
+
// named export would throw at load time.
|
|
101
|
+
const hostForUrl = (!rawHost || rawHost === '0.0.0.0' || rawHost === '::' || rawHost === '[::]')
|
|
102
|
+
? '127.0.0.1'
|
|
103
|
+
: (rawHost.includes(':') && !rawHost.startsWith('[') ? `[${rawHost}]` : rawHost)
|
|
90
104
|
const tokenUrl = ctx.connection && typeof ctx.connection.authenticatedUrl === 'function'
|
|
91
|
-
? ctx.connection.authenticatedUrl('
|
|
105
|
+
? ctx.connection.authenticatedUrl(proto + '//' + hostForUrl + ':' + targetPort)
|
|
92
106
|
: undefined
|
|
93
107
|
const nodePath = await ctx.subprocess.resolveExecutable('node')
|
|
94
108
|
if (disposed) return // 行在 await 期间被销毁:不再 spawn
|
package/lib/client.js
CHANGED
|
@@ -8261,14 +8261,20 @@ exports.COMPAT_CSS = ` /* ---------- dsh-web-ui family compatibility ----------
|
|
|
8261
8261
|
cache) is long. It is the single entry the official StatsLine puts in
|
|
8262
8262
|
conversation.composer.dock, so the structural anchor below reaches it
|
|
8263
8263
|
without any DOM marking (S3 deleted the text-matching effect that used
|
|
8264
|
-
to set
|
|
8264
|
+
to set the dock-entry marker). Layout: ONE fixed-height (28px) flex
|
|
8265
8265
|
strip that scrolls horizontally — the full metrics stream stays
|
|
8266
8266
|
reachable by swiping, the row never grows vertically, no ellipsis or
|
|
8267
8267
|
fade, 12px gaps between metric groups, a 2px scrollbar as the swipe
|
|
8268
8268
|
affordance. The phone breakpoint hides the strip outright instead
|
|
8269
8269
|
(styles/composer.css.ts — its data moves into the session info card). */
|
|
8270
8270
|
|
|
8271
|
-
|
|
8271
|
+
/* Marker set is deliberately dual: 0.2.0-rc.2 renders the strip root with
|
|
8272
|
+
data-composer-stats (plural, dsh-client-ui-chat rc.2 lib), 0.2.1-alpha.2
|
|
8273
|
+
dropped the strip wrapper and registers activity/usage as separate dock
|
|
8274
|
+
entries whose pill spans carry data-composer-stat (singular). Keeping
|
|
8275
|
+
both lets this plugin style the strip on a host that has NOT upgraded to
|
|
8276
|
+
alpha.2 — verified against both npm tarballs 2026-10-09. */
|
|
8277
|
+
[data-slot="conversation.composer.dock"] > :is([data-composer-stat], [data-composer-stats]) {
|
|
8272
8278
|
display: flex !important;
|
|
8273
8279
|
flex-flow: row nowrap !important;
|
|
8274
8280
|
align-items: center !important;
|
|
@@ -8290,17 +8296,17 @@ exports.COMPAT_CSS = ` /* ---------- dsh-web-ui family compatibility ----------
|
|
|
8290
8296
|
line-height: 20px !important;
|
|
8291
8297
|
font-size: 12px !important;
|
|
8292
8298
|
}
|
|
8293
|
-
[data-slot="conversation.composer.dock"] > [
|
|
8299
|
+
[data-slot="conversation.composer.dock"] > :is([data-composer-stat], [data-composer-stats])::-webkit-scrollbar {
|
|
8294
8300
|
height: 2px !important;
|
|
8295
8301
|
}
|
|
8296
|
-
[data-slot="conversation.composer.dock"] > [
|
|
8302
|
+
[data-slot="conversation.composer.dock"] > :is([data-composer-stat], [data-composer-stats])::-webkit-scrollbar-thumb {
|
|
8297
8303
|
background: var(--dsw-alias-label-tertiary, rgba(0, 0, 0, .3)) !important;
|
|
8298
8304
|
border-radius: 2px !important;
|
|
8299
8305
|
}
|
|
8300
|
-
[data-slot="conversation.composer.dock"] > [
|
|
8306
|
+
[data-slot="conversation.composer.dock"] > :is([data-composer-stat], [data-composer-stats])::-webkit-scrollbar-track {
|
|
8301
8307
|
background: transparent !important;
|
|
8302
8308
|
}
|
|
8303
|
-
[data-slot="conversation.composer.dock"] > [
|
|
8309
|
+
[data-slot="conversation.composer.dock"] > :is([data-composer-stat], [data-composer-stats]) > * {
|
|
8304
8310
|
display: flex !important;
|
|
8305
8311
|
flex: 0 0 auto !important;
|
|
8306
8312
|
flex-flow: row nowrap !important;
|
|
@@ -8312,10 +8318,10 @@ exports.COMPAT_CSS = ` /* ---------- dsh-web-ui family compatibility ----------
|
|
|
8312
8318
|
margin-right: 12px !important;
|
|
8313
8319
|
padding: 0 !important;
|
|
8314
8320
|
}
|
|
8315
|
-
[data-slot="conversation.composer.dock"] > [
|
|
8321
|
+
[data-slot="conversation.composer.dock"] > :is([data-composer-stat], [data-composer-stats]) > *:last-child {
|
|
8316
8322
|
margin-right: 0 !important;
|
|
8317
8323
|
}
|
|
8318
|
-
[data-slot="conversation.composer.dock"] > [
|
|
8324
|
+
[data-slot="conversation.composer.dock"] > :is([data-composer-stat], [data-composer-stats]) * {
|
|
8319
8325
|
white-space: nowrap !important;
|
|
8320
8326
|
}
|
|
8321
8327
|
|
|
@@ -10889,7 +10895,8 @@ exports.COMPOSER_CSS = `/* ---------- phone composer (< 768px) ---------- */
|
|
|
10889
10895
|
/* --- 8. the official stats strip leaves the composer ---
|
|
10890
10896
|
Its data moves into the session info card (S4). The row is the composer
|
|
10891
10897
|
dock's own \`_root\` entry; the slot itself stays live for later entries. */
|
|
10892
|
-
[data-slot="conversation.composer.dock"] > [class$="_root"]
|
|
10898
|
+
[data-slot="conversation.composer.dock"] > [class$="_root"],
|
|
10899
|
+
[data-slot="conversation.composer.dock"] > [data-composer-stat] {
|
|
10893
10900
|
display: none !important;
|
|
10894
10901
|
}
|
|
10895
10902
|
|
|
@@ -16395,12 +16402,26 @@ __modules["virtual-id.js"] = function (require, module, exports) {
|
|
|
16395
16402
|
* `session-<uuid>` and workspace ids are bare uuids.
|
|
16396
16403
|
*/
|
|
16397
16404
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16398
|
-
exports.VIRTUAL_ID_PREFIX = void 0;
|
|
16405
|
+
exports.VIRTUAL_GROUP_NAME_MARK = exports.VIRTUAL_ID_PREFIX = void 0;
|
|
16399
16406
|
exports.toVirtual = toVirtual;
|
|
16400
16407
|
exports.fromVirtual = fromVirtual;
|
|
16401
16408
|
exports.isVirtual = isVirtual;
|
|
16402
16409
|
/** The fixed prefix every virtual id starts with. */
|
|
16403
16410
|
exports.VIRTUAL_ID_PREFIX = 'zr~';
|
|
16411
|
+
/**
|
|
16412
|
+
* The invisible WORD JOINER (U+2060) every virtual GROUP NAME starts with
|
|
16413
|
+
* (T74). DSH 0.2.0 renders the model menu's provider groups with the
|
|
16414
|
+
* primitives' MenuGroup, whose `aria-labelledby` carries only a useId — the
|
|
16415
|
+
* group id is gone from the markup — so the browser half can no longer tell
|
|
16416
|
+
* a virtual group from a local one by attribute. The merged catalog's group
|
|
16417
|
+
* NAME (merge-streams.ts mergeModelCatalogs) is the one mark that survives
|
|
16418
|
+
* in both 0.1.7 and 0.2.0, and effects/model-group-side.ts classifies each
|
|
16419
|
+
* group container by which headings start with it. Zero-width: headings
|
|
16420
|
+
* read exactly as before. Sidebar workspace TITLES deliberately do NOT
|
|
16421
|
+
* carry it — those groups are told apart by their `zr~` row ids, not by
|
|
16422
|
+
* text.
|
|
16423
|
+
*/
|
|
16424
|
+
exports.VIRTUAL_GROUP_NAME_MARK = '\u2060';
|
|
16404
16425
|
/** The server id half: exactly the 8 lowercase hex chars relay-server.ts
|
|
16405
16426
|
* mints (`randomBytes(4).toString('hex')`). */
|
|
16406
16427
|
const SERVER_ID_PATTERN = /^[0-9a-f]{8}$/;
|
|
@@ -17764,31 +17785,54 @@ html[data-zr-remote-session="1"] [data-sidebar-right-guide-entry="files"]:not([a
|
|
|
17764
17785
|
display: none !important;
|
|
17765
17786
|
}
|
|
17766
17787
|
|
|
17767
|
-
/* ---------- T52: model-menu groups follow the session's side ----------
|
|
17788
|
+
/* ---------- T52/T74: model-menu groups follow the session's side ----------
|
|
17768
17789
|
The model catalog is GLOBAL (one shared load per page), so the merged
|
|
17769
17790
|
catalog shows the server's groups everywhere; but a selection is only
|
|
17770
17791
|
runnable on the side the open session lives on — the interceptor refuses
|
|
17771
|
-
the other side with a clear message. Hide what cannot run
|
|
17772
|
-
|
|
17773
|
-
|
|
17774
|
-
|
|
17775
|
-
|
|
17776
|
-
|
|
17777
|
-
|
|
17778
|
-
|
|
17779
|
-
|
|
17780
|
-
|
|
17781
|
-
-
|
|
17782
|
-
|
|
17783
|
-
|
|
17784
|
-
|
|
17785
|
-
|
|
17786
|
-
|
|
17787
|
-
|
|
17788
|
-
|
|
17792
|
+
the other side with a clear message. Hide what cannot run.
|
|
17793
|
+
|
|
17794
|
+
What changed and why the mechanism is a STAMP now (T74): through 0.1.7
|
|
17795
|
+
each menu group rendered aria-labelledby="<useId>-<group.id>" (RT017
|
|
17796
|
+
dsh-client-ui-model-selection lib/client.js ~824-830) — the group id was
|
|
17797
|
+
IN the attribute, and rules could key on a virtual group's "zr~" prefix
|
|
17798
|
+
directly. 0.2.0 renders the groups with the primitives' MenuGroup
|
|
17799
|
+
instead (RT dsh-client-ui-primitives lib/index.js ~4283-4304): the
|
|
17800
|
+
section's aria-labelledby carries ONLY the useId, the heading is a child
|
|
17801
|
+
div[data-menu-group-heading], and the menu container is a div whose id
|
|
17802
|
+
ends in "-models" with role="menu" (RT dsh-client-ui-model-selection
|
|
17803
|
+
lib/client.js ~974-980). Two consequences killed the old rules: a group
|
|
17804
|
+
section no longer says anywhere in its markup which group it is, and the
|
|
17805
|
+
same MenuGroup renders OTHER menus' groups too — the old
|
|
17806
|
+
[role="menu"] section[role="group"] scope alone was too wide and would
|
|
17807
|
+
have hidden every unmarked group of every menu in a remote session
|
|
17808
|
+
(leaving just the search box), while missing the server's groups in
|
|
17809
|
+
local ones.
|
|
17810
|
+
|
|
17811
|
+
The new keys on what EVERY version actually renders, the heading text:
|
|
17812
|
+
each virtual group's name is prefixed with the invisible WORD JOINER
|
|
17813
|
+
(VIRTUAL_GROUP_NAME_MARK, virtual-id.ts; written by mergeModelCatalogs).
|
|
17814
|
+
The browser effect (effects/model-group-side.ts) reads each group's
|
|
17815
|
+
heading and stamps data-zr-group="remote|local" on the section — but
|
|
17816
|
+
only inside a CONTAINER (the sections' shared parent element) that holds
|
|
17817
|
+
at least one marked heading. That container rule is what scopes these
|
|
17818
|
+
rules to the model menu alone WITHOUT assuming menu structure: an
|
|
17819
|
+
unpaired client's model menu, every other menu, and the whole rest of
|
|
17820
|
+
the page hold no marked heading, receive no stamp, and match neither
|
|
17821
|
+
rule. And since the merged catalog only ever APPENDS virtual groups to
|
|
17822
|
+
the local list, within a decided container the unmarked groups are
|
|
17823
|
+
exactly the local ones — mixed containers (the norm) decide each group
|
|
17824
|
+
separately. The menu is a portal under <body>, but <html> is still its
|
|
17825
|
+
ancestor, so the html-level session attribute scopes both rules. If the
|
|
17826
|
+
effect is not running (uninstalled, or a host-role page that never had
|
|
17827
|
+
it), no stamp exists and both rules go inert — nothing stays hidden.
|
|
17828
|
+
|
|
17829
|
+
KNOWN BOUNDARY (accepted, not fixed): in a remote session, searching the
|
|
17830
|
+
model menu and pressing Enter can commit a HIDDEN local model — the
|
|
17831
|
+
interceptor refuses it with its usual message. */
|
|
17832
|
+
html[data-zr-remote-session="1"] section[role="group"][data-zr-group="local"] {
|
|
17789
17833
|
display: none !important;
|
|
17790
17834
|
}
|
|
17791
|
-
html:not([data-zr-remote-session])
|
|
17835
|
+
html:not([data-zr-remote-session]) section[role="group"][data-zr-group="remote"] {
|
|
17792
17836
|
display: none !important;
|
|
17793
17837
|
}
|
|
17794
17838
|
|
|
@@ -17924,6 +17968,196 @@ function installRemoteSessionGuard(ctx) {
|
|
|
17924
17968
|
}, 'dsh-zen-remote: remote-session attribute');
|
|
17925
17969
|
}
|
|
17926
17970
|
};
|
|
17971
|
+
__modules["client-data/model-group-side.js"] = function (require, module, exports) {
|
|
17972
|
+
"use strict";
|
|
17973
|
+
/**
|
|
17974
|
+
* T74: which side of the pairing a model-menu GROUP belongs to, as pure
|
|
17975
|
+
* functions — the readable core of the browser effect
|
|
17976
|
+
* (src/client/effects/model-group-side.ts).
|
|
17977
|
+
*
|
|
17978
|
+
* WHY: the merged catalog (merge-streams.ts mergeModelCatalogs) appends the
|
|
17979
|
+
* server's provider groups everywhere, but a selection only runs on the side
|
|
17980
|
+
* the open session lives on — the interceptor refuses the other side. Through
|
|
17981
|
+
* DSH 0.1.7 every menu group carried its id in `aria-labelledby`
|
|
17982
|
+
* (`<useId>-<group.id>`), so CSS keyed the hiding on the `zr~` prefix (T52).
|
|
17983
|
+
* DSH 0.2.0 renders the groups with the primitives' MenuGroup, whose
|
|
17984
|
+
* `aria-labelledby` is a bare useId — the id is gone — and the same component
|
|
17985
|
+
* renders OTHER menus' groups too, so attribute scoping misfires in both
|
|
17986
|
+
* directions. Classification therefore moved to the one mark every version
|
|
17987
|
+
* renders: virtual group NAMES start with VIRTUAL_GROUP_NAME_MARK
|
|
17988
|
+
* (virtual-id.ts), read off each group's heading text.
|
|
17989
|
+
*
|
|
17990
|
+
* The container rule is what keeps the effect inert wherever it cannot be
|
|
17991
|
+
* sure: a container with not ONE marked heading — the model menu of a
|
|
17992
|
+
* sub-client with no shared models, every other menu on the page, the whole
|
|
17993
|
+
* rest of the page — classifies as `undefined` for every group, which the
|
|
17994
|
+
* effect reads as "leave the DOM alone". Only a container holding at least
|
|
17995
|
+
* one marked heading is decided, and inside it the unmarked groups are
|
|
17996
|
+
* exactly the LOCAL ones: the merged catalog only ever APPENDS virtual
|
|
17997
|
+
* groups to the local list, never mixes them the other way.
|
|
17998
|
+
*
|
|
17999
|
+
* Defensive like the rest of client-data: an empty or missing heading never
|
|
18000
|
+
* counts as a mark, so it can never decide a container by accident.
|
|
18001
|
+
*/
|
|
18002
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18003
|
+
exports.classifyModelGroups = classifyModelGroups;
|
|
18004
|
+
const virtual_id_ts_1 = require("./virtual-id.js");
|
|
18005
|
+
function classifyModelGroups(groups) {
|
|
18006
|
+
// Per container: did any heading carry the mark? Containers are decided
|
|
18007
|
+
// independently — one mixed model menu must not turn an all-local
|
|
18008
|
+
// container (a second menu elsewhere on the page) into "hide everything
|
|
18009
|
+
// local" there.
|
|
18010
|
+
const marked = new Map();
|
|
18011
|
+
for (const group of groups) {
|
|
18012
|
+
const had = marked.get(group.containerKey) ?? false;
|
|
18013
|
+
marked.set(group.containerKey, had || group.headingText.startsWith(virtual_id_ts_1.VIRTUAL_GROUP_NAME_MARK));
|
|
18014
|
+
}
|
|
18015
|
+
return groups.map((group) => marked.get(group.containerKey)
|
|
18016
|
+
? group.headingText.startsWith(virtual_id_ts_1.VIRTUAL_GROUP_NAME_MARK)
|
|
18017
|
+
? 'remote'
|
|
18018
|
+
: 'local'
|
|
18019
|
+
: undefined);
|
|
18020
|
+
}
|
|
18021
|
+
};
|
|
18022
|
+
__modules["client/effects/model-group-side.js"] = function (require, module, exports) {
|
|
18023
|
+
"use strict";
|
|
18024
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18025
|
+
exports.headingTextOf = headingTextOf;
|
|
18026
|
+
exports.installModelGroupSide = installModelGroupSide;
|
|
18027
|
+
const model_group_side_ts_1 = require("./client-data/model-group-side.js");
|
|
18028
|
+
/**
|
|
18029
|
+
* T74: stamp every model-menu group with the side of the pairing it belongs
|
|
18030
|
+
* to, so remote-session.css.ts can hide the groups the open session cannot
|
|
18031
|
+
* run. The stamps are `data-zr-group="remote|local"` on each
|
|
18032
|
+
* `section[role="group"]`; which sections get one (and which get none) is
|
|
18033
|
+
* the pure classifier's container rule (client-data/model-group-side.ts) —
|
|
18034
|
+
* only a container holding at least one marked (WORD JOINER-prefixed, see
|
|
18035
|
+
* virtual-id.ts) heading is decided at all, so every other menu and the
|
|
18036
|
+
* whole rest of the page is never touched.
|
|
18037
|
+
*
|
|
18038
|
+
* Synchronous in the observer callback, never behind rAF: the callback is a
|
|
18039
|
+
* microtask and runs before this frame paints, so a group that must be
|
|
18040
|
+
* hidden is hidden the first time it is drawn. A rAF would land a frame late
|
|
18041
|
+
* and show one frame of the groups the CSS is about to hide (AGENTS.md's
|
|
18042
|
+
* "晚一帧" rule — the same shape the turn-fold and model-sheet-extras bugs
|
|
18043
|
+
* shared). The cheap batch gate below keeps the full rescan off the hot
|
|
18044
|
+
* path: most mutations (chat streaming, composer typing) touch no group.
|
|
18045
|
+
*/
|
|
18046
|
+
const GROUP_SELECTOR = 'section[role="group"]';
|
|
18047
|
+
/** The stamp this effect writes; remote-session.css.ts hides
|
|
18048
|
+
* `[data-zr-group="local"]` in a remote session and
|
|
18049
|
+
* `[data-zr-group="remote"]` everywhere else. */
|
|
18050
|
+
const STAMP = 'data-zr-group';
|
|
18051
|
+
/**
|
|
18052
|
+
* The heading text a group section renders, across the two DSH layouts:
|
|
18053
|
+
* 0.1.7 points `aria-labelledby` at a heading div (id `<useId>-<group.id>`);
|
|
18054
|
+
* 0.2.0's MenuGroup points it at its own useId heading — which is also the
|
|
18055
|
+
* first `[data-menu-group-heading]` child — and its first child is an
|
|
18056
|
+
* id-less position sentinel span. Falls through in that order, then to the
|
|
18057
|
+
* first id-bearing child (0.1.7's heading, should `aria-labelledby` ever be
|
|
18058
|
+
* dropped), and gives up with `null`.
|
|
18059
|
+
*/
|
|
18060
|
+
function headingTextOf(section, getElementById) {
|
|
18061
|
+
const labelledby = section.getAttribute('aria-labelledby');
|
|
18062
|
+
if (labelledby !== null) {
|
|
18063
|
+
const heading = getElementById(labelledby);
|
|
18064
|
+
if (heading !== null)
|
|
18065
|
+
return heading.textContent;
|
|
18066
|
+
}
|
|
18067
|
+
const own = section.querySelector(':scope > [data-menu-group-heading]');
|
|
18068
|
+
if (own !== null)
|
|
18069
|
+
return own.textContent;
|
|
18070
|
+
for (const child of section.children) {
|
|
18071
|
+
if (child.id !== '')
|
|
18072
|
+
return child.textContent;
|
|
18073
|
+
}
|
|
18074
|
+
return null;
|
|
18075
|
+
}
|
|
18076
|
+
/** Does this mutation involve a group section, inside or as a node? Groups
|
|
18077
|
+
* are rare; everything else (streaming text, composer typing) bails here. */
|
|
18078
|
+
function touchesGroup(mutation) {
|
|
18079
|
+
if (mutation.type === 'childList') {
|
|
18080
|
+
for (const node of mutation.addedNodes)
|
|
18081
|
+
if (isGroupish(node))
|
|
18082
|
+
return true;
|
|
18083
|
+
for (const node of mutation.removedNodes)
|
|
18084
|
+
if (isGroupish(node))
|
|
18085
|
+
return true;
|
|
18086
|
+
}
|
|
18087
|
+
const target = mutation.target;
|
|
18088
|
+
const el = target.nodeType === 1 ? target : target.parentElement;
|
|
18089
|
+
return el !== null && el.closest(GROUP_SELECTOR) !== null;
|
|
18090
|
+
}
|
|
18091
|
+
function isGroupish(node) {
|
|
18092
|
+
if (node.nodeType !== 1)
|
|
18093
|
+
return false;
|
|
18094
|
+
const el = node;
|
|
18095
|
+
return el.matches(GROUP_SELECTOR) || el.querySelector(GROUP_SELECTOR) !== null;
|
|
18096
|
+
}
|
|
18097
|
+
function installModelGroupSide(ctx) {
|
|
18098
|
+
ctx.effect(() => {
|
|
18099
|
+
const applyVerdict = (section, verdict) => {
|
|
18100
|
+
// Write only on change — the observer does not watch attributes (so a
|
|
18101
|
+
// stamp cannot re-trigger it), but a removed section's container may
|
|
18102
|
+
// be re-decided, and an unconditional set would still churn
|
|
18103
|
+
// style/attribute machinery for no effect.
|
|
18104
|
+
if (verdict === undefined) {
|
|
18105
|
+
if (section.hasAttribute(STAMP))
|
|
18106
|
+
section.removeAttribute(STAMP);
|
|
18107
|
+
}
|
|
18108
|
+
else if (section.getAttribute(STAMP) !== verdict) {
|
|
18109
|
+
section.setAttribute(STAMP, verdict);
|
|
18110
|
+
}
|
|
18111
|
+
};
|
|
18112
|
+
const scan = () => {
|
|
18113
|
+
const sections = document.querySelectorAll(GROUP_SELECTOR);
|
|
18114
|
+
// Group by parent element, in document order: querySelectorAll walks
|
|
18115
|
+
// the document, and one parent's children form a contiguous run of it,
|
|
18116
|
+
// so a running number per distinct parent is a stable container key.
|
|
18117
|
+
const containerKeys = new Map();
|
|
18118
|
+
const rows = [];
|
|
18119
|
+
for (const section of sections) {
|
|
18120
|
+
const parent = section.parentElement;
|
|
18121
|
+
if (parent === null)
|
|
18122
|
+
continue;
|
|
18123
|
+
let key = containerKeys.get(parent);
|
|
18124
|
+
if (key === undefined) {
|
|
18125
|
+
key = containerKeys.size;
|
|
18126
|
+
containerKeys.set(parent, key);
|
|
18127
|
+
}
|
|
18128
|
+
const text = headingTextOf(section, (id) => document.getElementById(id));
|
|
18129
|
+
rows.push({ section, containerKey: key, headingText: text ?? '' });
|
|
18130
|
+
}
|
|
18131
|
+
const verdicts = (0, model_group_side_ts_1.classifyModelGroups)(rows);
|
|
18132
|
+
rows.forEach((row, i) => applyVerdict(row.section, verdicts[i]));
|
|
18133
|
+
};
|
|
18134
|
+
// childList + subtree catches mounted/unmounted/re-parented groups,
|
|
18135
|
+
// characterData catches heading texts changing in place. Attributes are
|
|
18136
|
+
// deliberately unwatched: this effect is their only writer.
|
|
18137
|
+
const observer = new MutationObserver((mutations) => {
|
|
18138
|
+
for (const mutation of mutations) {
|
|
18139
|
+
if (touchesGroup(mutation)) {
|
|
18140
|
+
scan();
|
|
18141
|
+
return;
|
|
18142
|
+
}
|
|
18143
|
+
}
|
|
18144
|
+
});
|
|
18145
|
+
observer.observe(document.body, { childList: true, subtree: true, characterData: true });
|
|
18146
|
+
// The initial paint may already hold groups (session restored under an
|
|
18147
|
+
// open menu): stamp them synchronously at install, like every observer
|
|
18148
|
+
// effect here does.
|
|
18149
|
+
scan();
|
|
18150
|
+
return () => {
|
|
18151
|
+
observer.disconnect();
|
|
18152
|
+
// Undo every stamp so the host DOM reads exactly as before the effect
|
|
18153
|
+
// ran — the CSS rules key on the stamp, so this un-hides everything.
|
|
18154
|
+
for (const section of document.querySelectorAll(`${GROUP_SELECTOR}[${STAMP}]`)) {
|
|
18155
|
+
section.removeAttribute(STAMP);
|
|
18156
|
+
}
|
|
18157
|
+
};
|
|
18158
|
+
}, 'dsh-zen-remote: model group side');
|
|
18159
|
+
}
|
|
18160
|
+
};
|
|
17927
18161
|
__modules["client/index.js"] = function (require, module, exports) {
|
|
17928
18162
|
"use strict";
|
|
17929
18163
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -17969,6 +18203,7 @@ const current_session_report_ts_1 = require("./client/current-session-report.js"
|
|
|
17969
18203
|
const remote_group_expansion_ts_1 = require("./client/remote-group-expansion.js");
|
|
17970
18204
|
const remote_fetch_ts_1 = require("./client/remote-fetch.js");
|
|
17971
18205
|
const remote_session_ts_1 = require("./client/effects/remote-session.js");
|
|
18206
|
+
const model_group_side_ts_1 = require("./client/effects/model-group-side.js");
|
|
17972
18207
|
/** Required services (cordis fiber inject — the loader passes all module exports as an object plugin). */
|
|
17973
18208
|
exports.inject = ['slots', 'layout', 'locale', 'sessionLogDownload', 'sessions', 'workspaces'];
|
|
17974
18209
|
/**
|
|
@@ -18050,6 +18285,12 @@ function apply(ctx) {
|
|
|
18050
18285
|
// 逐字节原样放行;标记属性只在虚拟会话打开时出现,卸载时还原。
|
|
18051
18286
|
ctx.effect(() => (0, remote_fetch_ts_1.installRemoteApiFetch)(window), 'dsh-zen-remote: remote api fetch');
|
|
18052
18287
|
(0, remote_session_ts_1.installRemoteSessionGuard)(ctx);
|
|
18288
|
+
// T74 模型选单分组按会话归属显示:0.2.0 的 MenuGroup 的 aria-labelledby 只剩
|
|
18289
|
+
// useId(分组 id 不再出现在标记里),旧的 zr~ 前缀选择器失效——改为 effect 给
|
|
18290
|
+
// 分组打 data-zr-group 标(分类依据是虚拟分组名开头的不可见标记,见
|
|
18291
|
+
// client-data/model-group-side.ts),CSS 按标隐藏。同样必须在桌面门之前挂载:
|
|
18292
|
+
// 桌面端子客户端的模型选单一样要分侧,桌面无手机外壳不影响它。
|
|
18293
|
+
(0, model_group_side_ts_1.installModelGroupSide)(ctx);
|
|
18053
18294
|
// Desktop gate (DSH 0.1.7): the official Electron shell can be dragged
|
|
18054
18295
|
// down to ~520px wide, where every width-based gate would flip the phone
|
|
18055
18296
|
// shell on inside the desktop app. Inside that shell this plugin is a
|
package/lib/fingerprint.js
CHANGED
|
@@ -8,8 +8,10 @@
|
|
|
8
8
|
* definitions, the server puts its map into the handshake, the client
|
|
9
9
|
* compares group by group, and the settings page lists the differing groups.
|
|
10
10
|
* Identical maps mean fully compatible — the DSH version numbers themselves
|
|
11
|
-
* are deliberately NOT compared (docs/spike-relay.md §2.3: 0.1.7 and
|
|
12
|
-
* share byte-identical remote interfaces, so a version gate would
|
|
11
|
+
* are deliberately NOT compared (docs/spike-relay.md §2.3: 0.1.7-rc.2 and
|
|
12
|
+
* 0.2.0-rc.1 share byte-identical remote interfaces, so a version gate would
|
|
13
|
+
* misreject; 0.2.0-rc.2 then changed the session group within one minor —
|
|
14
|
+
* an additive optional field — which a version gate would have missed).
|
|
13
15
|
*
|
|
14
16
|
* What is hashed, per group, in priority order:
|
|
15
17
|
*
|
package/lib/fingerprint.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"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"}
|