dsh-zen-remote 1.1.16 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +54 -9
- package/README.md +249 -190
- package/README.zh-CN.md +247 -201
- package/assets/home.png +0 -0
- package/assets/info.png +0 -0
- package/assets/pairing.png +0 -0
- package/assets/session.png +0 -0
- package/assets/sheet.png +0 -0
- package/cordis.patch.yml +12 -11
- package/cordis.patch.yml.example +24 -9
- package/docs/interface.md +57 -2
- package/docs/remote-access.en.md +99 -58
- package/docs/remote-access.md +99 -42
- package/dsh-push.mjs +67 -54
- package/lan-gate.mjs +88 -20
- package/lib/activity.js +168 -0
- package/lib/activity.js.map +1 -0
- package/lib/admin-routes.js +526 -0
- package/lib/admin-routes.js.map +1 -0
- package/lib/client-pairing.js +224 -0
- package/lib/client-pairing.js.map +1 -0
- package/lib/client-routes.js +674 -0
- package/lib/client-routes.js.map +1 -0
- package/lib/client.js +10051 -4777
- package/lib/config.js +346 -0
- package/lib/config.js.map +1 -0
- package/lib/fetch-route-intercept.js +418 -0
- package/lib/fetch-route-intercept.js.map +1 -0
- package/lib/fingerprint.js +363 -0
- package/lib/fingerprint.js.map +1 -0
- package/lib/http.js +69 -0
- package/lib/http.js.map +1 -0
- package/lib/index.js +675 -54
- package/lib/index.js.map +1 -1
- package/lib/intercept-shape.js +81 -0
- package/lib/intercept-shape.js.map +1 -0
- package/lib/intercept.js +3040 -0
- package/lib/intercept.js.map +1 -0
- package/lib/lan-gate-server.cjs +532 -121
- package/lib/merge-streams.js +1165 -0
- package/lib/merge-streams.js.map +1 -0
- package/lib/relay-access.js +496 -0
- package/lib/relay-access.js.map +1 -0
- package/lib/relay-client.js +1303 -0
- package/lib/relay-client.js.map +1 -0
- package/lib/relay-filter.js +282 -0
- package/lib/relay-filter.js.map +1 -0
- package/lib/relay-server.js +1792 -0
- package/lib/relay-server.js.map +1 -0
- package/lib/restart-fields.js +34 -0
- package/lib/restart-fields.js.map +1 -0
- package/lib/restart-watcher.js +106 -0
- package/lib/restart-watcher.js.map +1 -0
- package/lib/session-reference.js +157 -0
- package/lib/session-reference.js.map +1 -0
- package/lib/share-export.js +16 -1
- package/lib/share-export.js.map +1 -1
- package/lib/share-ops.js +86 -0
- package/lib/share-ops.js.map +1 -0
- package/lib/share-store.js +294 -0
- package/lib/share-store.js.map +1 -0
- package/lib/types/activity.d.ts +99 -0
- package/lib/types/activity.d.ts.map +1 -0
- package/lib/types/admin-routes.d.ts +129 -0
- package/lib/types/admin-routes.d.ts.map +1 -0
- package/lib/types/client/MobileDrawerFooter.d.ts.map +1 -1
- package/lib/types/client/MobileHome.d.ts +1 -1
- package/lib/types/client/MobileHome.d.ts.map +1 -1
- package/lib/types/client/MobileHomeChips.d.ts +1 -1
- package/lib/types/client/MobileHomeChips.d.ts.map +1 -1
- package/lib/types/client/MobileSessionHeader.d.ts +13 -2
- package/lib/types/client/MobileSessionHeader.d.ts.map +1 -1
- package/lib/types/client/MobileSessionInfo.d.ts +20 -3
- package/lib/types/client/MobileSessionInfo.d.ts.map +1 -1
- package/lib/types/client/RemoteComposerBanner.d.ts +42 -0
- package/lib/types/client/RemoteComposerBanner.d.ts.map +1 -0
- package/lib/types/client/RemoteHeaderIcon.d.ts +37 -0
- package/lib/types/client/RemoteHeaderIcon.d.ts.map +1 -0
- package/lib/types/client/RemoteShareMenu.d.ts +28 -0
- package/lib/types/client/RemoteShareMenu.d.ts.map +1 -0
- package/lib/types/client/RemoteStatusIcon.d.ts +36 -0
- package/lib/types/client/RemoteStatusIcon.d.ts.map +1 -0
- package/lib/types/client/compat/desktop.d.ts +21 -0
- package/lib/types/client/compat/desktop.d.ts.map +1 -0
- package/lib/types/client/compat/types.d.ts +57 -0
- package/lib/types/client/compat/types.d.ts.map +1 -1
- package/lib/types/client/current-session-report.d.ts +37 -0
- package/lib/types/client/current-session-report.d.ts.map +1 -0
- package/lib/types/client/effects/header-status.d.ts.map +1 -1
- package/lib/types/client/effects/keyboard-guard.d.ts.map +1 -1
- package/lib/types/client/effects/permission-sheet.d.ts +39 -0
- package/lib/types/client/effects/permission-sheet.d.ts.map +1 -0
- package/lib/types/client/effects/remote-session.d.ts +25 -0
- package/lib/types/client/effects/remote-session.d.ts.map +1 -0
- package/lib/types/client/effects/turn-fold.d.ts +9 -0
- package/lib/types/client/effects/turn-fold.d.ts.map +1 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/locales.d.ts +187 -2
- package/lib/types/client/locales.d.ts.map +1 -1
- package/lib/types/client/remote-fetch.d.ts +51 -0
- package/lib/types/client/remote-fetch.d.ts.map +1 -0
- package/lib/types/client/remote-group-expansion.d.ts +41 -0
- package/lib/types/client/remote-group-expansion.d.ts.map +1 -0
- package/lib/types/client/remote-share-css.d.ts +19 -0
- package/lib/types/client/remote-share-css.d.ts.map +1 -0
- package/lib/types/client/remote-share-register.d.ts +113 -0
- package/lib/types/client/remote-share-register.d.ts.map +1 -0
- package/lib/types/client/remote-status-css.d.ts +15 -0
- package/lib/types/client/remote-status-css.d.ts.map +1 -0
- package/lib/types/client/remote-status-register.d.ts +46 -0
- package/lib/types/client/remote-status-register.d.ts.map +1 -0
- package/lib/types/client/settings/SettingsSection.d.ts +46 -0
- package/lib/types/client/settings/SettingsSection.d.ts.map +1 -0
- package/lib/types/client/settings/register-settings.d.ts +58 -0
- package/lib/types/client/settings/register-settings.d.ts.map +1 -0
- package/lib/types/client/settings/settings-css.d.ts +10 -0
- package/lib/types/client/settings/settings-css.d.ts.map +1 -0
- package/lib/types/client/share/share-preview.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/header.css.d.ts +1 -1
- package/lib/types/client/styles/header.css.d.ts.map +1 -1
- package/lib/types/client/styles/info.css.d.ts +1 -1
- package/lib/types/client/styles/info.css.d.ts.map +1 -1
- package/lib/types/client/styles/remote-session.css.d.ts +2 -0
- package/lib/types/client/styles/remote-session.css.d.ts.map +1 -0
- package/lib/types/client-data/current-session.d.ts +41 -0
- package/lib/types/client-data/current-session.d.ts.map +1 -0
- package/lib/types/client-data/remote-group-expansion.d.ts +76 -0
- package/lib/types/client-data/remote-group-expansion.d.ts.map +1 -0
- package/lib/types/client-data/remote-status.d.ts +148 -0
- package/lib/types/client-data/remote-status.d.ts.map +1 -0
- package/lib/types/client-data/settings-form.d.ts +774 -0
- package/lib/types/client-data/settings-form.d.ts.map +1 -0
- package/lib/types/client-data/shares.d.ts +211 -0
- package/lib/types/client-data/shares.d.ts.map +1 -0
- package/lib/types/client-pairing.d.ts +114 -0
- package/lib/types/client-pairing.d.ts.map +1 -0
- package/lib/types/client-routes.d.ts +112 -0
- package/lib/types/client-routes.d.ts.map +1 -0
- package/lib/types/config.d.ts +200 -0
- package/lib/types/config.d.ts.map +1 -0
- package/lib/types/fetch-route-intercept.d.ts +156 -0
- package/lib/types/fetch-route-intercept.d.ts.map +1 -0
- package/lib/types/fingerprint.d.ts +164 -0
- package/lib/types/fingerprint.d.ts.map +1 -0
- package/lib/types/http.d.ts +41 -0
- package/lib/types/http.d.ts.map +1 -0
- package/lib/types/index.d.ts +56 -24
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/intercept-shape.d.ts +32 -0
- package/lib/types/intercept-shape.d.ts.map +1 -0
- package/lib/types/intercept.d.ts +432 -0
- package/lib/types/intercept.d.ts.map +1 -0
- package/lib/types/merge-streams.d.ts +393 -0
- package/lib/types/merge-streams.d.ts.map +1 -0
- package/lib/types/relay-access.d.ts +310 -0
- package/lib/types/relay-access.d.ts.map +1 -0
- package/lib/types/relay-client.d.ts +274 -0
- package/lib/types/relay-client.d.ts.map +1 -0
- package/lib/types/relay-filter.d.ts +103 -0
- package/lib/types/relay-filter.d.ts.map +1 -0
- package/lib/types/relay-server.d.ts +208 -0
- package/lib/types/relay-server.d.ts.map +1 -0
- package/lib/types/restart-fields.d.ts +22 -0
- package/lib/types/restart-fields.d.ts.map +1 -0
- package/lib/types/restart-watcher.d.ts +83 -0
- package/lib/types/restart-watcher.d.ts.map +1 -0
- package/lib/types/session-reference.d.ts +66 -0
- package/lib/types/session-reference.d.ts.map +1 -0
- package/lib/types/share-export.d.ts +14 -1
- package/lib/types/share-export.d.ts.map +1 -1
- package/lib/types/share-ops.d.ts +79 -0
- package/lib/types/share-ops.d.ts.map +1 -0
- package/lib/types/share-store.d.ts +87 -0
- package/lib/types/share-store.d.ts.map +1 -0
- package/lib/types/virtual-id.d.ts +38 -0
- package/lib/types/virtual-id.d.ts.map +1 -0
- package/lib/virtual-id.js +52 -0
- package/lib/virtual-id.js.map +1 -0
- package/llms.txt +17 -14
- package/package.json +60 -50
- package/scripts/build-client.mjs +5 -3
- package/scripts/check-host-shadow.mjs +19 -2
- package/scripts/check-settings-form.mjs +933 -0
- package/scripts/check-shares.mjs +397 -0
- package/scripts/check-upload-endpoint.mjs +59 -3
- package/scripts/sync-doc-version.mjs +8 -15
- package/scripts/verify-fingerprint-live.mjs +111 -0
- package/src/activity.ts +218 -0
- package/src/admin-routes.ts +627 -0
- package/src/client/MobileAttachButton.tsx +2 -2
- package/src/client/MobileAttachChips.tsx +3 -3
- package/src/client/MobileDrawerFooter.tsx +7 -4
- package/src/client/MobileHome.tsx +20 -16
- package/src/client/MobileHomeChips.tsx +16 -16
- package/src/client/MobileNavOverlay.tsx +2 -2
- package/src/client/MobileNavToggle.tsx +3 -3
- package/src/client/MobileSessionHeader.tsx +63 -42
- package/src/client/MobileSessionInfo.tsx +118 -17
- package/src/client/RemoteComposerBanner.tsx +76 -0
- package/src/client/RemoteHeaderIcon.tsx +103 -0
- package/src/client/RemoteShareMenu.tsx +57 -0
- package/src/client/RemoteStatusIcon.tsx +91 -0
- package/src/client/compat/desktop.ts +22 -0
- package/src/client/compat/types.ts +62 -0
- package/src/client/current-session-report.ts +164 -0
- package/src/client/effects/header-status.ts +21 -17
- package/src/client/effects/keyboard-guard.ts +65 -1
- package/src/client/effects/permission-sheet.ts +149 -0
- package/src/client/effects/remote-session.ts +68 -0
- package/src/client/effects/turn-fold.ts +52 -0
- package/src/client/index.tsx +151 -36
- package/src/client/locales.ts +396 -2
- package/src/client/remote-fetch.ts +125 -0
- package/src/client/remote-group-expansion.ts +190 -0
- package/src/client/remote-share-css.ts +54 -0
- package/src/client/remote-share-register.ts +244 -0
- package/src/client/remote-status-css.ts +64 -0
- package/src/client/remote-status-register.ts +107 -0
- package/src/client/settings/SettingsSection.tsx +1229 -0
- package/src/client/settings/register-settings.ts +116 -0
- package/src/client/settings/settings-css.ts +236 -0
- package/src/client/share/share-preview.tsx +6 -3
- package/src/client/share/share-sheet.tsx +3 -3
- package/src/client/styles/composer.css.ts +119 -26
- package/src/client/styles/header.css.ts +7 -7
- package/src/client/styles/info.css.ts +74 -0
- package/src/client/styles/remote-session.css.ts +251 -0
- package/src/client-data/current-session.ts +57 -0
- package/src/client-data/remote-group-expansion.ts +145 -0
- package/src/client-data/remote-status.ts +374 -0
- package/src/client-data/settings-form.ts +1371 -0
- package/src/client-data/shares.ts +467 -0
- package/src/client-pairing.ts +244 -0
- package/src/client-routes.ts +732 -0
- package/src/config.ts +447 -0
- package/src/fetch-route-intercept.ts +510 -0
- package/src/fingerprint.ts +408 -0
- package/src/http.ts +68 -0
- package/src/index.ts +719 -62
- package/src/intercept-shape.ts +87 -0
- package/src/intercept.ts +3362 -0
- package/src/merge-streams.ts +1272 -0
- package/src/relay-access.ts +669 -0
- package/src/relay-client.ts +1514 -0
- package/src/relay-filter.ts +291 -0
- package/src/relay-server.ts +2025 -0
- package/src/restart-fields.ts +36 -0
- package/src/restart-watcher.ts +140 -0
- package/src/session-reference.ts +156 -0
- package/src/share-export.ts +26 -1
- package/src/share-ops.ts +114 -0
- package/src/share-store.ts +373 -0
- package/src/virtual-id.ts +59 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure mergers for the three GLOBAL calls (T23b-2): `workspace/follow` and
|
|
3
|
+
* `session/control` are STREAMS whose frames carry no session-locating
|
|
4
|
+
* argument, and `session/list` is an unscoped invoke — the sidebar reads all
|
|
5
|
+
* three to render its tree, so a sub-client must see the server's shared
|
|
6
|
+
* sessions merged INTO the local answer instead of in place of it.
|
|
7
|
+
*
|
|
8
|
+
* Frame and result shapes are the generated 0.2.0 codecs, field by field:
|
|
9
|
+
* `workspace_follow_result` (baseline / upsert / remove / order / archived /
|
|
10
|
+
* pinned), `session_control_result` (exactly two frame types: `baseline`
|
|
11
|
+
* nesting `value.projections`, and one-key `projection` updates), and
|
|
12
|
+
* `session_list_result` (`{ items }` — no cursor field). The same shapes the
|
|
13
|
+
* server filters by (relay-filter.ts); remote frames arriving here have
|
|
14
|
+
* ALREADY been narrowed to the shared sessions and carry ORIGINAL ids.
|
|
15
|
+
*
|
|
16
|
+
* The rules, mirroring tasks/T23b2.md as corrected by tasks/T23b2-fix.md:
|
|
17
|
+
* - local frames pass through, except that `baseline` / `order` get the
|
|
18
|
+
* remote workspaces APPENDED to their order (remote groups sort after
|
|
19
|
+
* local) and the `archived` / `pinned` lists merge local + remote;
|
|
20
|
+
* - a remote baseline NEVER travels as a second baseline — it would wipe the
|
|
21
|
+
* local data. It becomes one virtualized `upsert` per remote workspace,
|
|
22
|
+
* then the merged `order` / `archived` / `pinned`;
|
|
23
|
+
* - remote frames that arrive before the local baseline are CACHED as state
|
|
24
|
+
* only — the UI has seen nothing yet, so emitting them would order
|
|
25
|
+
* workspaces the local baseline would immediately erase;
|
|
26
|
+
* - a remote stream that died (or a merely offline relay) emits NOTHING and
|
|
27
|
+
* keeps the shown state ({@link WorkspaceMerger.onRemoteDown}): the UI's
|
|
28
|
+
* `ClientWorkspaceModel.remove()` records ids in a never-cleared blacklist
|
|
29
|
+
* and both `upsert` and baseline replacement drop blacklisted ids, so one
|
|
30
|
+
* `remove` for a virtual id would make that group un-revivable on
|
|
31
|
+
* reconnect — while the UI itself keeps the last complete projection
|
|
32
|
+
* visible across carrier loss (its `handleCarrierFailure`);
|
|
33
|
+
* - a NEW remote baseline on the same server is DIFFED against the shown
|
|
34
|
+
* set: still present → fresh `upsert` (content from the new baseline),
|
|
35
|
+
* absent (deleted server-side / no longer shared) → `remove`, then the
|
|
36
|
+
* merged `order` / `archived` / `pinned`;
|
|
37
|
+
* - a server RENAME (same serverId) re-upserts the shown groups under the
|
|
38
|
+
* new title — no removals ({@link WorkspaceMerger.onServerRenamed});
|
|
39
|
+
* - only a serverId CHANGE removes the whole group
|
|
40
|
+
* ({@link WorkspaceMerger.onRemoteGone}): the new prefix is fresh, so it
|
|
41
|
+
* can never collide with the UI's blacklist. The relay entering
|
|
42
|
+
* `unpaired` / `revoked` is NOT this case (T23b2-fix3): the server
|
|
43
|
+
* persists its serverId (relay-server.ts loadServerId), so a re-pair to
|
|
44
|
+
* the same server reuses the prefix and is handled as a remote death
|
|
45
|
+
* ({@link WorkspaceMerger.onRemoteDown}) — the reconnect diff revives
|
|
46
|
+
* the group;
|
|
47
|
+
* - a relay status that is not serving normally (T34: offline, unpaired,
|
|
48
|
+
* revoked, interface mismatch) only ANNOTATES TITLES: setStatus +
|
|
49
|
+
* onStatusChanged re-upsert the shown groups under the annotated titles,
|
|
50
|
+
* and the reconnecting baseline (which always upserts) restores them.
|
|
51
|
+
* - a session the SERVER stopped serving (remote closed / idle-slept / its
|
|
52
|
+
* fork parent closed → the filtered workspace upsert drops it from
|
|
53
|
+
* `sessionIds`) keeps a TOMBSTONE in the group it was last seen in (CP4,
|
|
54
|
+
* reworked by CP4-client-fix2): the merger remembers the workspace each
|
|
55
|
+
* session id was last carried by, and the forwarded record for THAT
|
|
56
|
+
* workspace still lists the id (appended at the end of `sessionIds`). The
|
|
57
|
+
* UI's session store keeps the merged projection/list entry and nothing
|
|
58
|
+
* ever removes it, so without this the sidebar would park the session in
|
|
59
|
+
* 「未分组」 forever — and hiding it in the merged `archived` frame instead
|
|
60
|
+
* (what CP4-client first did) makes the RT navigation guard
|
|
61
|
+
* `clearArchivedCurrent` (dsh-client-ui-workspace `watchNavigation`) kick
|
|
62
|
+
* the OPEN session page back to the home page before its 「远程已关闭」
|
|
63
|
+
* banner can show. A re-share (the id back in some workspace's
|
|
64
|
+
* `sessionIds`) renders it live again and clears the tombstone; the
|
|
65
|
+
* tombstone dies with its workspace (a remove) and with the identity
|
|
66
|
+
* (onRemoteGone).
|
|
67
|
+
* - T58 reworks the tombstone's VISIBILITY, reshaped by T65: a closed-remote
|
|
68
|
+
* session is HIDDEN — moved into the merged `archived` set (the host's
|
|
69
|
+
* `sessionVisible` hides archived ids under the default filter) — while
|
|
70
|
+
* STAYING in its group's forwarded `sessionIds`: under「显示已归档」it
|
|
71
|
+
* renders in place, and it can never resurface as a 「未分组」 stray. The
|
|
72
|
+
* one exception is the session the user currently has OPEN: it is not
|
|
73
|
+
* hidden at all (the page must keep its 「远程已关闭」 banner), and once
|
|
74
|
+
* the caller reports a different current session
|
|
75
|
+
* ({@link WorkspaceMerger.setCurrentSession}) it moves into `archived`
|
|
76
|
+
* too. `archived` is exactly what the host's navigation guard
|
|
77
|
+
* `clearArchivedCurrent` acts on, so the CURRENT session may never enter
|
|
78
|
+
* it — and an unreadable current-session signal falls back to the
|
|
79
|
+
* conservative tombstone behavior (nothing is hidden). Because the
|
|
80
|
+
* browser's report can lag the user's switch by up to a poll interval, a
|
|
81
|
+
* JUST-created tombstone is not hidden for a short grace (T65, injectable
|
|
82
|
+
* clock): the 1s poll re-judges with the fresh report afterwards — the
|
|
83
|
+
* session the user really switched to keeps its tombstone, anything else
|
|
84
|
+
* hides. Re-sharing the session takes it back out of `archived`
|
|
85
|
+
* (live-carried ids never count as hidden). Since hiding moves only the
|
|
86
|
+
* archived set, hide/reveal updates are exactly one merged archived frame
|
|
87
|
+
* — no group content changes, no ordering dance; the current session
|
|
88
|
+
* never enters the set by construction. The hidden ids are sticky: they
|
|
89
|
+
* survive even the death of their home workspace until a re-share or the
|
|
90
|
+
* identity ends.
|
|
91
|
+
* - a workspace with NOTHING to show is not shown at all (T56): the server
|
|
92
|
+
* keeps every workspace and only narrows `sessionIds` (relay-filter.ts),
|
|
93
|
+
* so a workspace where nothing is shared would arrive as an empty group
|
|
94
|
+
* and render as a bare 「服务端名 · 工作区名」 heading. A workspace the UI
|
|
95
|
+
* has never seen is therefore held back — no baseline item, no upsert, no
|
|
96
|
+
* order entry — until its forwarded `sessionIds` (live sessions or
|
|
97
|
+
* tombstones it must carry) first gains content. From that first forward
|
|
98
|
+
* on it counts as SHOWN and stays shown even when the sessions leave
|
|
99
|
+
* again: a `remove` would blacklist the id in the UI's ClientWorkspaceModel
|
|
100
|
+
* and make the group un-revivable, so an emptied group keeps its (empty)
|
|
101
|
+
* display until the page reload rebuilds the model and this rule hides it
|
|
102
|
+
* again. Every removal path — the reconnecting baseline diff, an explicit
|
|
103
|
+
* server remove, {@link WorkspaceMerger.onRemoteGone} — emits a `remove`
|
|
104
|
+
* only for shown workspaces; never-shown ones leave the state silently.
|
|
105
|
+
*
|
|
106
|
+
* Two KNOWN LIMITATIONS, both rooted in the UI's `removedIds` blacklist
|
|
107
|
+
* never clearing during a page's life (a reload rebuilds the model from
|
|
108
|
+
* scratch, which is why a reload fixes both):
|
|
109
|
+
* - switch to a DIFFERENT server and later back to the SAME old one: the
|
|
110
|
+
* switch-away removed the old prefix, so the returning group's upserts
|
|
111
|
+
* are dropped by the blacklist and it stays invisible until the page is
|
|
112
|
+
* reloaded;
|
|
113
|
+
* - the server deletes a workspace and later shares a NEW workspace under
|
|
114
|
+
* the SAME id: the deletion's remove blacklists the id, and the new
|
|
115
|
+
* workspace's upserts are dropped the same way.
|
|
116
|
+
*
|
|
117
|
+
* Everything here is a pure state machine: no DSH imports, no network, no
|
|
118
|
+
* clocks — the virtual-id arithmetic is the one dependency (virtual-id.ts).
|
|
119
|
+
* Shapes are read defensively like relay-filter.ts does: a malformed frame is
|
|
120
|
+
* dropped (diagnosed through the optional hook), never forwarded.
|
|
121
|
+
*
|
|
122
|
+
* T52 adds two RESULT-side pure helpers on the same principles:
|
|
123
|
+
* {@link mergeModelCatalogs} folds the relay's `session/modelCatalog` answer
|
|
124
|
+
* into the local one (the catalog is the model-selection dropdown's data), and
|
|
125
|
+
* {@link virtualizeModelSelectionValue} rewrites a `modelSelection` projection
|
|
126
|
+
* value's provider ids to virtual group ids so the UI can find the current
|
|
127
|
+
* model's display name in the merged catalog.
|
|
128
|
+
*
|
|
129
|
+
* T52-fix2 made that rewrite CONDITIONAL on the server catalog listing the
|
|
130
|
+
* provider; T52-fix3 reverts it to UNCONDITIONAL, and the revert is final:
|
|
131
|
+
* the host's projection store is FIRST-WRITE-WINS per sequence number
|
|
132
|
+
* (dsh-api-session-controller lib/client.js:986-994 —
|
|
133
|
+
* `if (row?.kind === "sequenced" && seq <= row.seq) return`, and the
|
|
134
|
+
* seed / list blocks take the same road). A projection rewritten ORIGINAL
|
|
135
|
+
* while the catalog had not landed yet occupies its seq; when the catalog
|
|
136
|
+
* arrives, the same seq's VIRTUAL value is dropped as stale — the server
|
|
137
|
+
* group never gets its check mark, and resubmitting a reasoning effort
|
|
138
|
+
* echoes the ORIGINAL provider back, which `session/selectModel`'s routing
|
|
139
|
+
* refuses ("请选择「服务端 · …」分组里的模型"). The rewrite of ONE provider
|
|
140
|
+
* must therefore not depend on when the catalog happened to arrive. The
|
|
141
|
+
* accepted cost: a provider absent from the server's OWN catalog renders the
|
|
142
|
+
* `zr~<serverId>~provider/model` fallback string (the pre-fix2 display).
|
|
143
|
+
*/
|
|
144
|
+
/** The (serverId, serverName) pair a merger virtualizes with. A re-handshake
|
|
145
|
+
* with a different server retargets the SAME merger ({@link retarget}) so the
|
|
146
|
+
* locally observed baseline/order state survives the swap. */
|
|
147
|
+
export interface MergerIdentity {
|
|
148
|
+
serverId: string;
|
|
149
|
+
serverName: string;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* The status annotation (T34) appended to every shown remote group's title
|
|
153
|
+
* while the relay is not serving normally. The CALLER (intercept.ts) maps the
|
|
154
|
+
* relay state onto one annotation — `revoked` / `unpaired` outrank `offline`,
|
|
155
|
+
* which outranks `mismatch` — and the merger only renders the suffix it is
|
|
156
|
+
* told to. The suffixes are the CHINESE copy, deliberately hardcoded here:
|
|
157
|
+
* this module is background code with no access to the UI language (the
|
|
158
|
+
* English forms live in src/client/locales.ts, `remoteGroup*` keys).
|
|
159
|
+
*/
|
|
160
|
+
export type MergerAnnotation = 'none' | 'offline' | 'revoked' | 'unpaired' | 'mismatch';
|
|
161
|
+
export interface WorkspaceMergerOptions extends MergerIdentity {
|
|
162
|
+
/** Diagnostics for frames this merger dropped (unknown type or malformed).
|
|
163
|
+
* Optional: without it the drop is silent. */
|
|
164
|
+
onDiagnostic?: (message: string) => void;
|
|
165
|
+
/** T65: the clock the tombstone hide-grace runs on. Default Date.now;
|
|
166
|
+
* tests advance an injectable fake to cross the grace. */
|
|
167
|
+
now?: () => number;
|
|
168
|
+
}
|
|
169
|
+
export interface WorkspaceMerger {
|
|
170
|
+
readonly serverId: string;
|
|
171
|
+
readonly serverName: string;
|
|
172
|
+
/** Feed one frame of the LOCAL workspace/follow stream; returns the frames
|
|
173
|
+
* the UI should see (usually exactly the input, order-merged when remote
|
|
174
|
+
* state exists). */
|
|
175
|
+
onLocal(frame: unknown): unknown[];
|
|
176
|
+
/** Feed one server-filtered frame of the REMOTE stream; returns the frames
|
|
177
|
+
* the UI should see (possibly none — state-only while the local baseline
|
|
178
|
+
* has not passed). A later baseline is DIFFED against what was shown. */
|
|
179
|
+
onRemote(frame: unknown): unknown[];
|
|
180
|
+
/** The remote stream died or the relay went offline (the same server is
|
|
181
|
+
* expected back): emits NOTHING and keeps the shown state — the UI keeps
|
|
182
|
+
* the last projection visible across carrier loss, and a `remove` here
|
|
183
|
+
* would blacklist the virtual ids against revival. */
|
|
184
|
+
onRemoteDown(): unknown[];
|
|
185
|
+
/** The remote side is gone FOR GOOD under THIS identity: a serverId
|
|
186
|
+
* change. (Since T23b2-fix3 an `unpaired` / `revoked` relay is NOT this
|
|
187
|
+
* case — the same serverId comes back on re-pair, so the caller uses
|
|
188
|
+
* {@link onRemoteDown} there.) Removes everything shown from the remote
|
|
189
|
+
* side, resets the remote state. Idempotent — a second call with no
|
|
190
|
+
* remote state returns []. */
|
|
191
|
+
onRemoteGone(): unknown[];
|
|
192
|
+
/** The server was renamed (same serverId — call after {@link retarget}):
|
|
193
|
+
* re-upserts every shown workspace under the new title, nothing else. */
|
|
194
|
+
onServerRenamed(): unknown[];
|
|
195
|
+
/** Record the status annotation (T34) future virtualized titles carry. No
|
|
196
|
+
* frames on its own — pair it with {@link onStatusChanged} to re-upsert the
|
|
197
|
+
* shown groups under the new annotation, or let the next natural upserts
|
|
198
|
+
* (a reconnecting baseline) carry it. */
|
|
199
|
+
setStatus(annotation: MergerAnnotation): void;
|
|
200
|
+
/** Re-upsert every SHOWN workspace under the CURRENT annotation: the whole
|
|
201
|
+
* update when the relay's serving status changed without any remote frame
|
|
202
|
+
* (offline, revoked, unpaired, version mismatch). [] while nothing is
|
|
203
|
+
* shown (no local baseline yet, or no remote state). */
|
|
204
|
+
onStatusChanged(): unknown[];
|
|
205
|
+
/** Record the session id the UI currently has OPEN (T58) — the raw id as
|
|
206
|
+
* the UI knows it (a virtual id for a remote session, a local id
|
|
207
|
+
* otherwise); `undefined` means a READABLE signal says no session is
|
|
208
|
+
* open. An UNREADABLE signal is expressed by not calling this at all —
|
|
209
|
+
* the merger then keeps every tombstone (the conservative fallback).
|
|
210
|
+
* Returns the frames that apply the resulting hide transitions ([] when
|
|
211
|
+
* nothing changed). */
|
|
212
|
+
setCurrentSession(sessionId: string | undefined): unknown[];
|
|
213
|
+
/** Whether some closed-remote session is being kept visible — it is the
|
|
214
|
+
* current session (waiting for the user to navigate away), or the current
|
|
215
|
+
* session was never readable (conservative fallback). While true the
|
|
216
|
+
* caller should keep polling {@link setCurrentSession} at ≥1s intervals. */
|
|
217
|
+
readonly hasPendingHide: boolean;
|
|
218
|
+
/** Point the merger at a (possibly different) server. Local state survives;
|
|
219
|
+
* for a serverId change the remote state must be gone first (onRemoteGone
|
|
220
|
+
* first); for a rename it may stay. */
|
|
221
|
+
retarget(identity: MergerIdentity): void;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* The workspace/follow merger. Remote state is a Map keyed by the ORIGINAL
|
|
225
|
+
* workspace id whose INSERTION ORDER tracks the remote order (baseline sets
|
|
226
|
+
* it, upsert appends new keys, order frames reorder it) — that sequence is
|
|
227
|
+
* what gets appended to every local baseline/order that passes through.
|
|
228
|
+
*/
|
|
229
|
+
export declare function createWorkspaceMerger(options: WorkspaceMergerOptions): WorkspaceMerger;
|
|
230
|
+
export interface ControlMergerOptions {
|
|
231
|
+
serverId: string;
|
|
232
|
+
serverName?: string;
|
|
233
|
+
onDiagnostic?: (message: string) => void;
|
|
234
|
+
}
|
|
235
|
+
export interface ControlMerger {
|
|
236
|
+
readonly serverId: string;
|
|
237
|
+
readonly serverName: string;
|
|
238
|
+
/** Local control frames pass through untouched; the local BASELINE also
|
|
239
|
+
* flushes anything the remote side buffered before it arrived. */
|
|
240
|
+
onLocal(frame: unknown): unknown[];
|
|
241
|
+
/** Remote baseline → per-session per-key `projection` frames; remote
|
|
242
|
+
* projection updates → virtualized. Unknown types are dropped. Frames
|
|
243
|
+
* arriving before the local baseline are buffered (the host's snapshot
|
|
244
|
+
* stream treats an update before the opening snapshot as a protocol
|
|
245
|
+
* violation and kills the stream). */
|
|
246
|
+
onRemote(frame: unknown): unknown[];
|
|
247
|
+
/** Always [] — a control stream has nothing to remove on a temporary
|
|
248
|
+
* remote end (the workspace merger owns the group). */
|
|
249
|
+
onRemoteDown(): unknown[];
|
|
250
|
+
/** Always [] — leftover projection state for vanished virtual sessions is
|
|
251
|
+
* harmless; the workspace merger removes the group. */
|
|
252
|
+
onRemoteGone(): unknown[];
|
|
253
|
+
/** Always [] — projection frames carry no display name. */
|
|
254
|
+
onServerRenamed(): unknown[];
|
|
255
|
+
/** Accepted and ignored: a status annotation is a TITLE concern, and
|
|
256
|
+
* control projections carry no titles. */
|
|
257
|
+
setStatus(annotation: MergerAnnotation): void;
|
|
258
|
+
/** Always [] — nothing shown here could carry an annotation. */
|
|
259
|
+
onStatusChanged(): unknown[];
|
|
260
|
+
/** Accepted and ignored; always answers []. */
|
|
261
|
+
setCurrentSession(sessionId: string | undefined): unknown[];
|
|
262
|
+
/** Always false — the control merger hides nothing. */
|
|
263
|
+
readonly hasPendingHide: boolean;
|
|
264
|
+
retarget(identity: MergerIdentity): void;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* The session/control merger. The control stream is key-value projection
|
|
268
|
+
* traffic with no ordering constraints between sessions, so it needs no
|
|
269
|
+
* state beyond the pre-baseline buffer: local frames pass through, remote
|
|
270
|
+
* frames get their session id virtualized, and a remote baseline is EXPLODED
|
|
271
|
+
* into one `projection` frame per key (never a second baseline).
|
|
272
|
+
*/
|
|
273
|
+
export declare function createControlMerger(options: ControlMergerOptions): ControlMerger;
|
|
274
|
+
/**
|
|
275
|
+
* Merge one `session/list` result pair (first page only — the caller skips
|
|
276
|
+
* paged requests). Local items keep their order and their pagination fields;
|
|
277
|
+
* the remote items are appended with virtualized session ids — `sessionId`
|
|
278
|
+
* AND `parentSessionId` (CP4): the fork link must point at the VIRTUAL parent
|
|
279
|
+
* id the UI knows, or the fork would sort beside a parent id that exists in
|
|
280
|
+
* no list the UI holds — and a T52-fix rewrite of the row's own projections
|
|
281
|
+
* block: a list row carries `{kind:'cached'|'sequenced', asOfSeq, values}`
|
|
282
|
+
* (RT dsh-api-session-controller lib/typert.remote-client.js:381-428) and the
|
|
283
|
+
* client face applies it PER SESSION (lib/client.js:2633 → applyListBlock
|
|
284
|
+
* :2842-2855) — a `sequenced` modelSelection lands under higher-seq-wins
|
|
285
|
+
* (lib/client.js:986-995, `seq <= row.seq` rejects), and the control stream's
|
|
286
|
+
* REWRITTEN frame rides that projection's OWN seq, so an original-provider
|
|
287
|
+
* value left in a row would poison the store forever: the remote session's
|
|
288
|
+
* dropdown would show the raw `provider/model` fallback with no check mark.
|
|
289
|
+
* The rewrite is UNCONDITIONAL (T52-fix3): first-write-wins per seq forbids
|
|
290
|
+
* a catalog gate — a row rewritten while the catalog was missing would
|
|
291
|
+
* occupy the seq forever. A missing or malformed remote result means "remote
|
|
292
|
+
* said nothing" — the local result passes back untouched.
|
|
293
|
+
*/
|
|
294
|
+
export declare function mergeSessionList(localResult: unknown, remoteResult: unknown, serverId: string): unknown;
|
|
295
|
+
/**
|
|
296
|
+
* Fold the relay's `session/modelCatalog` answer into the local one (T52).
|
|
297
|
+
* The result shape is RT dsh-api-session-controller
|
|
298
|
+
* `session_modelCatalog_result$schema` (lib/typert.remote-client.js:489-518):
|
|
299
|
+
* `{default, routableProviders, groups, failures}` — provider group ids and
|
|
300
|
+
* display names only, no session data anywhere, so no output filter guards it
|
|
301
|
+
* server-side and nothing here needs narrowing.
|
|
302
|
+
*
|
|
303
|
+
* - server groups are APPENDED after the local ones (the dropdown sorts
|
|
304
|
+
* `deepseek-account` / `deepseek-official` first and keeps the rest in
|
|
305
|
+
* order, RT dsh-client-ui-model-selection lib/client.js:510 — appended
|
|
306
|
+
* groups render last); each group id becomes the virtual group id
|
|
307
|
+
* `zr~<serverId>~<original>` and its name is prefixed
|
|
308
|
+
* `${serverName} · ${name}` — the same workspace title discipline the
|
|
309
|
+
* merger uses;
|
|
310
|
+
* - `default` and `failures` stay LOCAL untouched: the default drives what a
|
|
311
|
+
* blank LOCAL session would run (a remote session's current model comes
|
|
312
|
+
* from its projection instead), and the UI renders every failure as a
|
|
313
|
+
* prominent warning row whose Retry reloads the WHOLE catalog
|
|
314
|
+
* (lib/client.js:816-827) — a server-side group failure is not retryable
|
|
315
|
+
* from here and would put a permanent alarm on every dropdown, so it does
|
|
316
|
+
* not travel (dsh-vision-router's settings read the same result and shows
|
|
317
|
+
* an error state exactly when groups are empty AND failures exist,
|
|
318
|
+
* lib/client.js:635-647 — dropping remote failures keeps that honest).
|
|
319
|
+
* KNOWN BOUNDARY (pre-T52 behavior, unchanged): a NEW server session's
|
|
320
|
+
* projection `next` is null until its first selection or turn, so the UI
|
|
321
|
+
* shows `catalog.value.default` — the LOCAL default — as that session's
|
|
322
|
+
* current model (RT dsh-client-ui-model-selection lib/client.js:316,
|
|
323
|
+
* `projected?.next ?? catalog.value?.default`), which may differ from what
|
|
324
|
+
* the server would actually run until its first selection lands.
|
|
325
|
+
* - `routableProviders` mirrors the group ids by construction host-side
|
|
326
|
+
* (RT dsh-api-session-controller lib/index.js:544 — literally
|
|
327
|
+
* `groups.map(g => g.id)`); no client UI reads it (the dropdown's
|
|
328
|
+
* routable verdict comes from the groups themselves, lib/client.js:334),
|
|
329
|
+
* so appending the virtual ids is a consistency move: the merged catalog
|
|
330
|
+
* keeps the invariant the Host maintains, whatever reads it next.
|
|
331
|
+
*
|
|
332
|
+
* A malformed local or remote value means "one side said nothing" — the
|
|
333
|
+
* local result passes back untouched, like {@link mergeSessionList}.
|
|
334
|
+
*/
|
|
335
|
+
export declare function mergeModelCatalogs(localValue: unknown, remoteValue: unknown, identity: MergerIdentity): unknown;
|
|
336
|
+
/**
|
|
337
|
+
* Virtualize the provider ids inside one `modelSelection` projection value —
|
|
338
|
+
* `{lastUsed: {provider, model, reasoningEffort?} | null, next: …}` (RT
|
|
339
|
+
* dsh-api-session-controller lib/types/model-selection-projection.js:12-15,
|
|
340
|
+
* wire shapes at lib/typert.remote-client.js:83-94). The UI resolves the
|
|
341
|
+
* current model's display name by matching `(provider, model)` against the
|
|
342
|
+
* catalog groups (dsh-client-ui-model-selection lib/client.js:334, 520); for
|
|
343
|
+
* a remote session the provider is a SERVER group id, so it must become the
|
|
344
|
+
* virtual group id to be found in the merged catalog — and while the relay
|
|
345
|
+
* serves, the merged catalog always carries it, so the composer trigger
|
|
346
|
+
* shows the model NAME instead of the raw `provider/model` fallback string
|
|
347
|
+
* (lib/client.js:700).
|
|
348
|
+
*
|
|
349
|
+
* UNCONDITIONAL by decision (T52-fix3, reverting T52-fix2's catalog gate):
|
|
350
|
+
* the host's projection store is first-write-wins per sequence number
|
|
351
|
+
* (lib/client.js:986-994), so whether a value is rewritten may not depend on
|
|
352
|
+
* WHEN the catalog happened to arrive — an original written pre-catalog
|
|
353
|
+
* occupies the seq and the later virtual value is dropped, leaving the
|
|
354
|
+
* server group unchecked and the next reasoning-effort submit refused.
|
|
355
|
+
* Accepted cost: a provider the server's own catalog does not list renders
|
|
356
|
+
* the `zr~<serverId>~provider/model` fallback string. Nulls and malformed
|
|
357
|
+
* entries pass through untouched; `model` and `reasoningEffort` are
|
|
358
|
+
* group-agnostic ids and stay as they are.
|
|
359
|
+
*/
|
|
360
|
+
export declare function virtualizeModelSelectionValue(value: unknown, serverId: string): unknown;
|
|
361
|
+
/**
|
|
362
|
+
* T63: the virtual session ids a set of FORWARDED workspace frames carries —
|
|
363
|
+
* the `sessionIds` of `upsert` records and of baseline `value.items`. The
|
|
364
|
+
* workspace route feeds these to the summary sync, which announces list rows
|
|
365
|
+
* for ids the UI has no summary for yet (the sidebar drops a group member
|
|
366
|
+
* without one — RT dsh-client-ui-workspace orderByRecency / groupByWorkspace).
|
|
367
|
+
* Reading the FORWARDED output (not the merger's raw state) is the point:
|
|
368
|
+
* T56 already withheld empty groups and T58 already dropped hidden sessions,
|
|
369
|
+
* so a hidden closed-remote session never reaches here and is never
|
|
370
|
+
* announced. Only virtual ids count — local baseline content rides these
|
|
371
|
+
* frames verbatim and its rows already have summaries.
|
|
372
|
+
*/
|
|
373
|
+
export declare function virtualSessionIdsInWorkspaceFrames(frames: readonly unknown[]): string[];
|
|
374
|
+
/**
|
|
375
|
+
* T63: the synthesized `api-session/added` emit frames for one relay
|
|
376
|
+
* `session/list` answer — one `{type:'emit', event:'api-session/added',
|
|
377
|
+
* args:[row]}` frame per row. This is the host's own mechanism for adding a
|
|
378
|
+
* list row without a re-pull (RT dsh-api-session-controller: the client face
|
|
379
|
+
* subscribes `api-session/added` → handleSessionAdded → mergeSummary →
|
|
380
|
+
* applyMutation's upsert, which ADDS an unknown row and fills an existing
|
|
381
|
+
* one — idempotent), and the emit frame shape is the client face's
|
|
382
|
+
* exact-keys `{type, event, args}` with args a JSON array
|
|
383
|
+
* (dsh-api-gateway lib/client.js parseRemoteEventFrame) — the same shape the
|
|
384
|
+
* T52 catalog-refresh frame uses. The rows are virtualized by
|
|
385
|
+
* {@link mergeSessionList} itself, so a synthesized row carries exactly what
|
|
386
|
+
* the merged `session/list` route would have answered: the session id AND
|
|
387
|
+
* the fork parent virtualized, and the projections' modelSelection providers
|
|
388
|
+
* rewritten (a row's `sequenced` block must not poison the projection store
|
|
389
|
+
* against the control stream's rewritten frames — T52-fix3). A malformed
|
|
390
|
+
* remote result means "the server said nothing" — no frames.
|
|
391
|
+
*/
|
|
392
|
+
export declare function sessionSummaryAddedFrames(remoteResult: unknown, serverId: string): unknown[];
|
|
393
|
+
//# sourceMappingURL=merge-streams.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-streams.d.ts","sourceRoot":"","sources":["../../src/merge-streams.ts"],"names":[],"mappings":"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"}
|