dsh-zen-remote 2.3.11 → 2.4.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/CHANGELOG.md +39 -78
- package/README.md +94 -84
- package/README.zh-CN.md +90 -81
- package/bin/zen-remote.mjs +5 -0
- package/docs/interface.md +6 -6
- package/docs/remote-access.en.md +6 -4
- package/docs/remote-access.md +6 -4
- package/dsh-push.mjs +96 -10
- package/lib/adapters/dsh-better-sidebar/index.js +7 -3
- package/lib/adapters/dsh-better-sidebar/index.js.map +1 -1
- package/lib/admin-routes.js +10 -2
- package/lib/admin-routes.js.map +1 -1
- package/lib/cli/args.js +251 -0
- package/lib/cli/args.js.map +1 -0
- package/lib/cli/bootstrap.js +449 -0
- package/lib/cli/bootstrap.js.map +1 -0
- package/lib/cli/command-setup.js +484 -0
- package/lib/cli/command-setup.js.map +1 -0
- package/lib/cli/commands-client.js +359 -0
- package/lib/cli/commands-client.js.map +1 -0
- package/lib/cli/commands-host.js +1108 -0
- package/lib/cli/commands-host.js.map +1 -0
- package/lib/cli/commands-status.js +279 -0
- package/lib/cli/commands-status.js.map +1 -0
- package/lib/cli/config-writer.js +334 -0
- package/lib/cli/config-writer.js.map +1 -0
- package/lib/cli/context.js +10 -0
- package/lib/cli/context.js.map +1 -0
- package/lib/cli/i18n.js +620 -0
- package/lib/cli/i18n.js.map +1 -0
- package/lib/cli/ipc-client.js +160 -0
- package/lib/cli/ipc-client.js.map +1 -0
- package/lib/cli/ipc-server.js +464 -0
- package/lib/cli/ipc-server.js.map +1 -0
- package/lib/cli/main.js +245 -0
- package/lib/cli/main.js.map +1 -0
- package/lib/cli/qr-terminal.js +48 -0
- package/lib/cli/qr-terminal.js.map +1 -0
- package/lib/client-data/qr.js +286 -0
- package/lib/client-data/qr.js.map +1 -0
- package/lib/client-routes.js +308 -25
- package/lib/client-routes.js.map +1 -1
- package/lib/client.js +1013 -229
- package/lib/config.js +50 -12
- package/lib/config.js.map +1 -1
- package/lib/debug-report.js +28 -1
- package/lib/debug-report.js.map +1 -1
- package/lib/fetch-route-intercept.js +334 -26
- package/lib/fetch-route-intercept.js.map +1 -1
- package/lib/index.js +564 -363
- package/lib/index.js.map +1 -1
- package/lib/intercept.js +1833 -280
- package/lib/intercept.js.map +1 -1
- package/lib/lan-gate-server.cjs +36 -10
- package/lib/merge-streams.js +103 -11
- package/lib/merge-streams.js.map +1 -1
- package/lib/plugin-route-intercept.js +93 -63
- package/lib/plugin-route-intercept.js.map +1 -1
- package/lib/relay-access.js +8 -1
- package/lib/relay-access.js.map +1 -1
- package/lib/relay-client.js +133 -4
- package/lib/relay-client.js.map +1 -1
- package/lib/relay-pool.js +275 -0
- package/lib/relay-pool.js.map +1 -0
- package/lib/relay-server.js +269 -17
- package/lib/relay-server.js.map +1 -1
- package/lib/restart-fields.js +6 -4
- package/lib/restart-fields.js.map +1 -1
- package/lib/share-store.js +65 -27
- package/lib/share-store.js.map +1 -1
- package/lib/state-store.js +400 -0
- package/lib/state-store.js.map +1 -0
- package/lib/types/adapters/dsh-better-sidebar/index.d.ts +3 -2
- package/lib/types/adapters/dsh-better-sidebar/index.d.ts.map +1 -1
- package/lib/types/admin-routes.d.ts.map +1 -1
- package/lib/types/cli/args.d.ts +78 -0
- package/lib/types/cli/args.d.ts.map +1 -0
- package/lib/types/cli/bootstrap.d.ts +170 -0
- package/lib/types/cli/bootstrap.d.ts.map +1 -0
- package/lib/types/cli/command-setup.d.ts +72 -0
- package/lib/types/cli/command-setup.d.ts.map +1 -0
- package/lib/types/cli/commands-client.d.ts +36 -0
- package/lib/types/cli/commands-client.d.ts.map +1 -0
- package/lib/types/cli/commands-host.d.ts +82 -0
- package/lib/types/cli/commands-host.d.ts.map +1 -0
- package/lib/types/cli/commands-status.d.ts +46 -0
- package/lib/types/cli/commands-status.d.ts.map +1 -0
- package/lib/types/cli/config-writer.d.ts +92 -0
- package/lib/types/cli/config-writer.d.ts.map +1 -0
- package/lib/types/cli/context.d.ts +39 -0
- package/lib/types/cli/context.d.ts.map +1 -0
- package/lib/types/cli/i18n.d.ts +32 -0
- package/lib/types/cli/i18n.d.ts.map +1 -0
- package/lib/types/cli/ipc-client.d.ts +83 -0
- package/lib/types/cli/ipc-client.d.ts.map +1 -0
- package/lib/types/cli/ipc-server.d.ts +113 -0
- package/lib/types/cli/ipc-server.d.ts.map +1 -0
- package/lib/types/cli/main.d.ts +57 -0
- package/lib/types/cli/main.d.ts.map +1 -0
- package/lib/types/cli/qr-terminal.d.ts +17 -0
- package/lib/types/cli/qr-terminal.d.ts.map +1 -0
- package/lib/types/client/RemoteStatusIcon.d.ts.map +1 -1
- package/lib/types/client/current-session-report.d.ts +4 -0
- package/lib/types/client/current-session-report.d.ts.map +1 -1
- package/lib/types/client/effects/model-group-side.d.ts.map +1 -1
- package/lib/types/client/effects/remote-session.d.ts.map +1 -1
- package/lib/types/client/locales.d.ts +47 -3
- package/lib/types/client/locales.d.ts.map +1 -1
- package/lib/types/client/settings/SettingsSection.d.ts.map +1 -1
- package/lib/types/client/settings/settings-css.d.ts +1 -1
- package/lib/types/client/settings/settings-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/wizard/GatewayWizard.d.ts.map +1 -1
- package/lib/types/client/wizard/cards/ProxyCard.d.ts.map +1 -1
- package/lib/types/client/wizard/wizard-css.d.ts +1 -1
- package/lib/types/client/wizard/wizard-css.d.ts.map +1 -1
- package/lib/types/client-data/model-group-side.d.ts +23 -2
- package/lib/types/client-data/model-group-side.d.ts.map +1 -1
- package/lib/types/client-data/remote-status.d.ts +47 -1
- package/lib/types/client-data/remote-status.d.ts.map +1 -1
- package/lib/types/client-data/settings-form.d.ts +85 -1
- package/lib/types/client-data/settings-form.d.ts.map +1 -1
- package/lib/types/client-data/wizard.d.ts +56 -1
- package/lib/types/client-data/wizard.d.ts.map +1 -1
- package/lib/types/client-routes.d.ts +25 -1
- package/lib/types/client-routes.d.ts.map +1 -1
- package/lib/types/config.d.ts +40 -14
- package/lib/types/config.d.ts.map +1 -1
- package/lib/types/debug-report.d.ts.map +1 -1
- package/lib/types/fetch-route-intercept.d.ts +66 -8
- package/lib/types/fetch-route-intercept.d.ts.map +1 -1
- package/lib/types/index.d.ts +9 -2
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/intercept.d.ts +72 -10
- package/lib/types/intercept.d.ts.map +1 -1
- package/lib/types/merge-streams.d.ts +79 -1
- package/lib/types/merge-streams.d.ts.map +1 -1
- package/lib/types/plugin-route-intercept.d.ts +25 -9
- package/lib/types/plugin-route-intercept.d.ts.map +1 -1
- package/lib/types/relay-access.d.ts +3 -1
- package/lib/types/relay-access.d.ts.map +1 -1
- package/lib/types/relay-client.d.ts +23 -2
- package/lib/types/relay-client.d.ts.map +1 -1
- package/lib/types/relay-pool.d.ts +148 -0
- package/lib/types/relay-pool.d.ts.map +1 -0
- package/lib/types/relay-server.d.ts +30 -3
- package/lib/types/relay-server.d.ts.map +1 -1
- package/lib/types/restart-fields.d.ts +5 -5
- package/lib/types/restart-fields.d.ts.map +1 -1
- package/lib/types/share-store.d.ts.map +1 -1
- package/lib/types/state-store.d.ts +179 -0
- package/lib/types/state-store.d.ts.map +1 -0
- package/lib/types/upload-limits.d.ts +15 -0
- package/lib/types/upload-limits.d.ts.map +1 -1
- package/lib/types/virtual-id.d.ts +21 -0
- package/lib/types/virtual-id.d.ts.map +1 -1
- package/lib/types/wizard/probe.d.ts.map +1 -1
- package/lib/types/wizard/proxy-snippets.d.ts +3 -0
- package/lib/types/wizard/proxy-snippets.d.ts.map +1 -1
- package/lib/types/wizard/routes.d.ts +1 -0
- package/lib/types/wizard/routes.d.ts.map +1 -1
- package/lib/types/wizard/status.d.ts +9 -0
- package/lib/types/wizard/status.d.ts.map +1 -1
- package/lib/types/wizard/verify.d.ts +3 -0
- package/lib/types/wizard/verify.d.ts.map +1 -1
- package/lib/upload-limits.js +15 -0
- package/lib/upload-limits.js.map +1 -1
- package/lib/virtual-id.js +60 -0
- package/lib/virtual-id.js.map +1 -1
- package/lib/wizard/probe.js +46 -1
- package/lib/wizard/probe.js.map +1 -1
- package/lib/wizard/proxy-snippets.js +14 -1
- package/lib/wizard/proxy-snippets.js.map +1 -1
- package/lib/wizard/routes.js +23 -4
- package/lib/wizard/routes.js.map +1 -1
- package/lib/wizard/status.js +21 -0
- package/lib/wizard/status.js.map +1 -1
- package/lib/wizard/verify.js +31 -8
- package/lib/wizard/verify.js.map +1 -1
- package/package.json +8 -4
- package/pwa/icons/badge-96.png +0 -0
- package/pwa/icons/badge.svg +1 -0
- package/pwa/manifest.json +2 -1
- package/pwa/sw.js +3 -1
- package/scripts/check-debug-report.mjs +41 -1
- package/scripts/check-settings-form.mjs +14 -3
- package/scripts/check-settings-view.mjs +247 -0
- package/scripts/check-wizard-ui.mjs +37 -0
- package/src/adapters/dsh-better-sidebar/index.ts +7 -3
- package/src/admin-routes.ts +10 -2
- package/src/cli/args.ts +289 -0
- package/src/cli/bootstrap.ts +569 -0
- package/src/cli/command-setup.ts +540 -0
- package/src/cli/commands-client.ts +369 -0
- package/src/cli/commands-host.ts +1127 -0
- package/src/cli/commands-status.ts +296 -0
- package/src/cli/config-writer.ts +354 -0
- package/src/cli/context.ts +38 -0
- package/src/cli/i18n.ts +645 -0
- package/src/cli/ipc-client.ts +216 -0
- package/src/cli/ipc-server.ts +531 -0
- package/src/cli/main.ts +285 -0
- package/src/cli/qr-terminal.ts +49 -0
- package/src/client/RemoteStatusIcon.tsx +4 -1
- package/src/client/current-session-report.ts +28 -4
- package/src/client/effects/model-group-side.ts +19 -5
- package/src/client/effects/remote-session.ts +26 -6
- package/src/client/locales.ts +96 -6
- package/src/client/settings/SettingsSection.tsx +287 -92
- package/src/client/settings/settings-css.ts +18 -0
- package/src/client/styles/remote-session.css.ts +15 -1
- package/src/client/wizard/GatewayWizard.tsx +470 -109
- package/src/client/wizard/cards/ProxyCard.tsx +2 -1
- package/src/client/wizard/wizard-css.ts +23 -0
- package/src/client-data/model-group-side.ts +37 -10
- package/src/client-data/remote-status.ts +112 -17
- package/src/client-data/settings-form.ts +164 -8
- package/src/client-data/wizard.ts +112 -2
- package/src/client-routes.ts +334 -26
- package/src/config.ts +62 -16
- package/src/debug-report.ts +27 -1
- package/src/fetch-route-intercept.ts +381 -32
- package/src/index.ts +566 -367
- package/src/intercept.ts +1866 -286
- package/src/merge-streams.ts +155 -10
- package/src/plugin-route-intercept.ts +120 -71
- package/src/relay-access.ts +14 -3
- package/src/relay-client.ts +163 -5
- package/src/relay-pool.ts +387 -0
- package/src/relay-server.ts +312 -16
- package/src/restart-fields.ts +6 -4
- package/src/share-store.ts +59 -26
- package/src/state-store.ts +428 -0
- package/src/upload-limits.ts +16 -0
- package/src/virtual-id.ts +57 -0
- package/src/wizard/probe.ts +54 -2
- package/src/wizard/proxy-snippets.ts +17 -2
- package/src/wizard/routes.ts +24 -5
- package/src/wizard/status.ts +28 -0
- package/src/wizard/verify.ts +33 -11
- package/AGENTS.md +0 -185
- package/docs/adr/0001-plugin-bridge-forwards-plugin-routes.md +0 -15
- package/docs/adr/0002-relay-emulates-websocket.md +0 -8
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI-2 IPC client: the CLI half of the local control channel that
|
|
3
|
+
* `src/cli/ipc-server.ts` serves inside the DSH plugin process. Discovery
|
|
4
|
+
* walks the same candidate socket paths the server binds (or a single
|
|
5
|
+
* explicit `--socket` path), pings each existing one with a short 200ms
|
|
6
|
+
* budget, and sorts the answers into three buckets the command layer can
|
|
7
|
+
* speak about: LIVE instances whose `cliProtocolVersion` matches, sockets
|
|
8
|
+
* speaking a DIFFERENT protocol version (the upgrade-prompt case), and paths
|
|
9
|
+
* that refused us with EACCES / EPERM (the "DSH runs as another user, try
|
|
10
|
+
* `sudo -E`" case).
|
|
11
|
+
*
|
|
12
|
+
* The request helper is a thin http-over-Unix-socket (Windows: named pipe)
|
|
13
|
+
* round trip. Transport errors REJECT — a dead socket is a real failure the
|
|
14
|
+
* caller must see — while HTTP error statuses resolve normally: the IPC
|
|
15
|
+
* protocol answers every failure as JSON (`{ ok: false, error: … }`), so a
|
|
16
|
+
* 409 wrong-role or 409 env-shadowed is data, not an exception.
|
|
17
|
+
*/
|
|
18
|
+
import type { IncomingHttpHeaders } from 'node:http';
|
|
19
|
+
/** What a live plugin instance answers `GET /ping` with. Mirrors the body
|
|
20
|
+
* `src/cli/ipc-server.ts` builds (minus `ok`). */
|
|
21
|
+
export interface CliPingResponse {
|
|
22
|
+
ok: true;
|
|
23
|
+
cliProtocolVersion: number;
|
|
24
|
+
pluginVersion: string;
|
|
25
|
+
pid: number;
|
|
26
|
+
role: 'host' | 'client' | 'peer';
|
|
27
|
+
serves: boolean;
|
|
28
|
+
connects: boolean;
|
|
29
|
+
serverName: string;
|
|
30
|
+
profileName?: string;
|
|
31
|
+
}
|
|
32
|
+
export type DiscoveredLive = CliPingResponse & {
|
|
33
|
+
socketPath: string;
|
|
34
|
+
};
|
|
35
|
+
export interface DiscoveredSockets {
|
|
36
|
+
/** Version-matching live instances, one entry per answering socket. */
|
|
37
|
+
live: DiscoveredLive[];
|
|
38
|
+
/** Sockets that answered but speak another `cliProtocolVersion`. */
|
|
39
|
+
versionMismatch: {
|
|
40
|
+
socketPath: string;
|
|
41
|
+
cliProtocolVersion: number | undefined;
|
|
42
|
+
}[];
|
|
43
|
+
/** Paths that refused the probe (or even the stat) with EACCES / EPERM —
|
|
44
|
+
* the cross-user DSH case. */
|
|
45
|
+
permissionDenied: string[];
|
|
46
|
+
}
|
|
47
|
+
export interface DiscoverCliSocketsOptions {
|
|
48
|
+
dshHome: string;
|
|
49
|
+
/** Probe ONLY this path instead of the candidate walk. */
|
|
50
|
+
explicitSocket?: string;
|
|
51
|
+
/** Bind-shape override (tests pin both platforms). */
|
|
52
|
+
platform?: NodeJS.Platform;
|
|
53
|
+
}
|
|
54
|
+
export interface CliIpcRequestResult {
|
|
55
|
+
status: number;
|
|
56
|
+
body: unknown;
|
|
57
|
+
headers: IncomingHttpHeaders;
|
|
58
|
+
}
|
|
59
|
+
export interface CliIpcClient {
|
|
60
|
+
readonly socketPath: string;
|
|
61
|
+
ping(): Promise<CliPingResponse>;
|
|
62
|
+
getStatus(): Promise<unknown>;
|
|
63
|
+
getDebugReport(): Promise<unknown>;
|
|
64
|
+
writeConfig(input: {
|
|
65
|
+
set?: Record<string, unknown>;
|
|
66
|
+
unset?: readonly string[];
|
|
67
|
+
}): Promise<CliIpcRequestResult>;
|
|
68
|
+
request(method: string, path: string, body?: unknown, timeoutMs?: number): Promise<CliIpcRequestResult>;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Walk the CLI socket candidates under `dshHome` (or only `explicitSocket`)
|
|
72
|
+
* and classify every answering socket. Absent candidates are skipped without
|
|
73
|
+
* a probe; a dead file that merely squats a candidate name simply answers
|
|
74
|
+
* nothing and lands nowhere.
|
|
75
|
+
*/
|
|
76
|
+
export declare function discoverCliSockets(options: DiscoverCliSocketsOptions): Promise<DiscoveredSockets>;
|
|
77
|
+
/**
|
|
78
|
+
* A client bound to one socket path. `request` is the generic escape hatch
|
|
79
|
+
* for routes added in later CLI phases; the named methods cover the routes
|
|
80
|
+
* this phase already drives.
|
|
81
|
+
*/
|
|
82
|
+
export declare function createCliIpcClient(socketPath: string): CliIpcClient;
|
|
83
|
+
//# sourceMappingURL=ipc-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ipc-client.d.ts","sourceRoot":"","sources":["../../../src/cli/ipc-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAA;AAKpD;kDACkD;AAClD,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,IAAI,CAAA;IACR,kBAAkB,EAAE,MAAM,CAAA;IAC1B,aAAa,EAAE,MAAM,CAAA;IACrB,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAA;IAChC,MAAM,EAAE,OAAO,CAAA;IACf,QAAQ,EAAE,OAAO,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,MAAM,cAAc,GAAG,eAAe,GAAG;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,CAAA;AAErE,MAAM,WAAW,iBAAiB;IAChC,uEAAuE;IACvE,IAAI,EAAE,cAAc,EAAE,CAAA;IACtB,oEAAoE;IACpE,eAAe,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,EAAE,CAAA;IACjF;kCAC8B;IAC9B,gBAAgB,EAAE,MAAM,EAAE,CAAA;CAC3B;AAED,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,MAAM,CAAA;IACf,0DAA0D;IAC1D,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,EAAE,mBAAmB,CAAA;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,IAAI,IAAI,OAAO,CAAC,eAAe,CAAC,CAAA;IAChC,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;IAC7B,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;IAClC,WAAW,CAAC,KAAK,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAC9G,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAA;CACxG;AA4FD;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAYvG;AAUD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,CAmBnE"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The CLI's local IPC control server (CLI-1): a small HTTP server over a
|
|
3
|
+
* 0600 Unix domain socket (`<dshHome>/zen-remote-cli.sock`, Windows: a named
|
|
4
|
+
* pipe), owned by the DSH plugin process. Every DSH `webServer` route sits
|
|
5
|
+
* behind signed-cookie auth, and the pieces the CLI must drive (the relay
|
|
6
|
+
* pool, the managed Caddy / cloudflared children, the wizard state) follow
|
|
7
|
+
* the plugin's single-in-process-owner discipline — so the CLI talks to THIS
|
|
8
|
+
* process over THIS socket instead of a second entry point. Same user, same
|
|
9
|
+
* machine: the 0600 socket IS the authentication.
|
|
10
|
+
*
|
|
11
|
+
* Lifecycle: the server is module-level (one per process, per dshHome). A
|
|
12
|
+
* plugin row reload — including the role flips `restart-watcher` triggers —
|
|
13
|
+
* re-acquires it and swaps the request DELEGATE in place; the underlying
|
|
14
|
+
* socket never unbinds, so a CLI session survives every reload. When the
|
|
15
|
+
* last owning row released it and a short grace period passes without a new
|
|
16
|
+
* acquire, the server closes and the socket file is removed (the grace
|
|
17
|
+
* covers the cordis dispose order, where the OLD row's disposer runs after
|
|
18
|
+
* the NEW row's apply — a plain refcount would tear down between them).
|
|
19
|
+
*
|
|
20
|
+
* The wiring side (src/index.ts) folds the acquire/release into the existing
|
|
21
|
+
* `'dsh-zen-remote: restart watcher'` effect on purpose: test/
|
|
22
|
+
* role-wiring.test.cjs pins the exact number of top-level `ctx.effect`
|
|
23
|
+
* registrations per role, so the IPC lifecycle may not add one.
|
|
24
|
+
*/
|
|
25
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
26
|
+
import type { ZenRemoteConfig } from '../config.js';
|
|
27
|
+
/** The CLI protocol's major version. A client asking for a different one is
|
|
28
|
+
* talking to a build it cannot drive (SPEC: refuse and tell the user to
|
|
29
|
+
* upgrade the plugin). */
|
|
30
|
+
export declare const CLI_PROTOCOL_VERSION = 1;
|
|
31
|
+
/** The protocol handshake route. */
|
|
32
|
+
export declare const CLI_PING_ROUTE = "/_dsh/zen-remote/cli/ping";
|
|
33
|
+
/** The config-write route (POST `{set, unset}` → the anti-shadowing writer). */
|
|
34
|
+
export declare const CLI_CONFIG_ROUTE = "/_dsh/zen-remote/cli/config";
|
|
35
|
+
/** Socket file / pipe basename: `zen-remote-cli.sock`, `-2.sock`, … */
|
|
36
|
+
export declare const CLI_SOCKET_BASENAME = "zen-remote-cli";
|
|
37
|
+
/** How long a fully-released IPC server waits for a re-acquire (the hot
|
|
38
|
+
* reload window: cordis runs the OLD row's disposer AFTER the new apply, so
|
|
39
|
+
* refcount 0 is momentary during every reload). Exported for tests. */
|
|
40
|
+
export declare const CLI_CLOSE_GRACE_MS = 250;
|
|
41
|
+
/**
|
|
42
|
+
* The bind candidates, in backoff order: `<dshHome>/zen-remote-cli.sock`,
|
|
43
|
+
* then `-2.sock` … `-8.sock` (two DSH instances on one machine — a web
|
|
44
|
+
* profile and a headless one — each get their own channel). Windows has no
|
|
45
|
+
* filesystem sockets: named pipes under the package's pipe name
|
|
46
|
+
* `dsh-zen-remote-cli` with the same numbering.
|
|
47
|
+
*/
|
|
48
|
+
export declare function candidateSocketPaths(dshHome: string, platform?: NodeJS.Platform): string[];
|
|
49
|
+
/** One role-gated handler set the IPC server forwards to — the row-scoped
|
|
50
|
+
* closures src/index.ts builds per apply (per role branch). */
|
|
51
|
+
export interface CliIpcDelegate {
|
|
52
|
+
/** The CURRENT effective role, re-read per request (a volatile row field). */
|
|
53
|
+
role(): 'host' | 'client' | 'peer';
|
|
54
|
+
/** The row's display name (this device's name on a client). */
|
|
55
|
+
serverName(): string;
|
|
56
|
+
/** The profile context's name, when the composition has one. */
|
|
57
|
+
profileName(): string | undefined;
|
|
58
|
+
/** This package's version, for the handshake header and ping body. */
|
|
59
|
+
pluginVersion(): string;
|
|
60
|
+
/** The anti-shadowing config write (src/cli/config-writer.ts, wired with
|
|
61
|
+
* the row object and the restart watcher's checkNow). */
|
|
62
|
+
writeConfig(input: {
|
|
63
|
+
set?: Record<string, unknown>;
|
|
64
|
+
unset?: readonly string[];
|
|
65
|
+
}): {
|
|
66
|
+
ok: true;
|
|
67
|
+
values: ZenRemoteConfig;
|
|
68
|
+
} | {
|
|
69
|
+
ok: false;
|
|
70
|
+
code: 'env-shadowed';
|
|
71
|
+
field: string;
|
|
72
|
+
envVar: string;
|
|
73
|
+
};
|
|
74
|
+
/** Host-role handler sets; absent means the composition never built them
|
|
75
|
+
* (the wrong-role gate answers before any consumer reaches here). */
|
|
76
|
+
wizardHandler?: CliRouteHandler | undefined;
|
|
77
|
+
adminHandler?: CliRouteHandler | undefined;
|
|
78
|
+
/** Both roles mount a client handler (remote-status / debug-report are
|
|
79
|
+
* role-agnostic); the wrong-role gate covers the pairing routes. */
|
|
80
|
+
clientHandler?: CliRouteHandler | undefined;
|
|
81
|
+
}
|
|
82
|
+
export type CliRouteHandler = (req: IncomingMessage, res: ServerResponse) => void | Promise<void>;
|
|
83
|
+
export interface CliIpcServerOptions {
|
|
84
|
+
dshHome: string;
|
|
85
|
+
delegate: CliIpcDelegate;
|
|
86
|
+
/** Bind-shape override (tests pin both platforms' candidate lists). */
|
|
87
|
+
platform?: NodeJS.Platform;
|
|
88
|
+
}
|
|
89
|
+
export interface CliIpcServer {
|
|
90
|
+
/** The candidate path this instance actually bound. */
|
|
91
|
+
readonly socketPath: string;
|
|
92
|
+
/** Hot reload: replace the delegate without touching the socket. */
|
|
93
|
+
swapDelegate(delegate: CliIpcDelegate): void;
|
|
94
|
+
/** Close the server, clean the socket file, and answer once drained. */
|
|
95
|
+
close(): Promise<void>;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Bind one CLI IPC server: walk the candidate paths, probing occupied files
|
|
99
|
+
* for a live owner (skip those), cleaning stale ones, and answering with the
|
|
100
|
+
* bound handle. Throws when every candidate is taken by a live instance.
|
|
101
|
+
*/
|
|
102
|
+
export declare function createCliIpcServer(options: CliIpcServerOptions): Promise<CliIpcServer>;
|
|
103
|
+
/**
|
|
104
|
+
* Acquire (or hot-swap into) this process's IPC server for `dshHome`.
|
|
105
|
+
* Synchronous on purpose: apply() runs inside cordis and cannot await. The
|
|
106
|
+
* returned handle's `release()` is the row disposer; a release that hits
|
|
107
|
+
* refcount 0 closes the server after {@link CLI_CLOSE_GRACE_MS} unless a new
|
|
108
|
+
* row acquires first.
|
|
109
|
+
*/
|
|
110
|
+
export declare function acquireCliIpcServer(dshHome: string, delegate: CliIpcDelegate): {
|
|
111
|
+
release(): void;
|
|
112
|
+
};
|
|
113
|
+
//# sourceMappingURL=ipc-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ipc-server.d.ts","sourceRoot":"","sources":["../../../src/cli/ipc-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,KAAK,EAAE,eAAe,EAA2B,cAAc,EAAE,MAAM,WAAW,CAAA;AAIzF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAMnD;;0BAE0B;AAC1B,eAAO,MAAM,oBAAoB,IAAI,CAAA;AAErC,oCAAoC;AACpC,eAAO,MAAM,cAAc,8BAA8B,CAAA;AAEzD,gFAAgF;AAChF,eAAO,MAAM,gBAAgB,gCAAgC,CAAA;AAE7D,uEAAuE;AACvE,eAAO,MAAM,mBAAmB,mBAAmB,CAAA;AAEnD;;uEAEuE;AACvE,eAAO,MAAM,kBAAkB,MAAM,CAAA;AAqBrC;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,MAAM,EAAE,CAU5G;AAED;+DAC+D;AAC/D,MAAM,WAAW,cAAc;IAC7B,8EAA8E;IAC9E,IAAI,IAAI,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAA;IAClC,+DAA+D;IAC/D,UAAU,IAAI,MAAM,CAAA;IACpB,gEAAgE;IAChE,WAAW,IAAI,MAAM,GAAG,SAAS,CAAA;IACjC,sEAAsE;IACtE,aAAa,IAAI,MAAM,CAAA;IACvB;6DACyD;IACzD,WAAW,CAAC,KAAK,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,GAC3E;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,MAAM,EAAE,eAAe,CAAA;KAAE,GACrC;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,cAAc,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IACtE;yEACqE;IACrE,aAAa,CAAC,EAAE,eAAe,GAAG,SAAS,CAAA;IAC3C,YAAY,CAAC,EAAE,eAAe,GAAG,SAAS,CAAA;IAC1C;wEACoE;IACpE,aAAa,CAAC,EAAE,eAAe,GAAG,SAAS,CAAA;CAC5C;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAEjG,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,cAAc,CAAA;IACxB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,uDAAuD;IACvD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,oEAAoE;IACpE,YAAY,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAA;IAC5C,wEAAwE;IACxE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AA8DD;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC,CAqF5F;AAuLD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG;IAAE,OAAO,IAAI,IAAI,CAAA;CAAE,CAsDlG"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI-5: the process entry point behind `bin/zen-remote.mjs`. `runCli` turns
|
|
3
|
+
* a parsed argv into exactly one verdict: static answers (help, version,
|
|
4
|
+
* the SPEC's `--role peer` refusal, unknown commands) render here; every
|
|
5
|
+
* plugin-driving command first comes alive through `ensureDshRunning` and
|
|
6
|
+
* then dispatches into the CLI-3/CLI-4 command functions over the discovered
|
|
7
|
+
* IPC socket; `setup` owns its preflight (install + launch) and runs the
|
|
8
|
+
* three-step wizard.
|
|
9
|
+
*
|
|
10
|
+
* Two things belong ONLY here: the interactivity verdict for the whole run
|
|
11
|
+
* (TTY && !`--yes`, with the default readline prompter created lazily and —
|
|
12
|
+
* importantly — closed in the end, or an unanswered stdin handle would keep
|
|
13
|
+
* the process alive after the answer printed), and the structured error
|
|
14
|
+
* boundary that turns a MissingRequiredOptionError into one precise
|
|
15
|
+
* bilingual line instead of a stack trace. All dependencies are injectable
|
|
16
|
+
* so the tests drive the real entry function with fakes (SPEC's test seam
|
|
17
|
+
* three).
|
|
18
|
+
*/
|
|
19
|
+
import type { CliPrompter, ExecProbe } from './bootstrap.js';
|
|
20
|
+
import { discoverCliSockets } from './ipc-client.js';
|
|
21
|
+
export interface CliRuntimeDeps {
|
|
22
|
+
/** Environment for the language resolution and the `DSH_HOME` fallback. */
|
|
23
|
+
env?: NodeJS.ProcessEnv;
|
|
24
|
+
/** The DSH home the sockets / profiles live under. Default
|
|
25
|
+
* `<env.DSH_HOME ?? ~/.dsh>` — the same resolution config.ts uses. */
|
|
26
|
+
dshHome?: string;
|
|
27
|
+
/** Whether this run can prompt. Default `process.stdin.isTTY === true`. */
|
|
28
|
+
isTty?: boolean;
|
|
29
|
+
stdout?: {
|
|
30
|
+
write(text: string): void;
|
|
31
|
+
};
|
|
32
|
+
/** The ask-everything funnel; the default readline prompter is built
|
|
33
|
+
* lazily (and closed at the end) when a run may actually prompt. */
|
|
34
|
+
prompter?: CliPrompter;
|
|
35
|
+
/** `--version`'s answer; default the package.json version next to lib/. */
|
|
36
|
+
packageVersion?: string;
|
|
37
|
+
/** Bind-shape override (tests pin every platform branch). */
|
|
38
|
+
platform?: NodeJS.Platform;
|
|
39
|
+
/** uid for the launchd `gui/<uid>/…` target. */
|
|
40
|
+
uid?: number;
|
|
41
|
+
macosAppPath?: string;
|
|
42
|
+
systemUnitDir?: string;
|
|
43
|
+
/** Test seams, forwarded into the preflight / bootstrap. */
|
|
44
|
+
discover?: typeof discoverCliSockets;
|
|
45
|
+
spawnCommand?: (command: string, args: readonly string[]) => Promise<number>;
|
|
46
|
+
execProbe?: ExecProbe;
|
|
47
|
+
now?: () => Date;
|
|
48
|
+
cwd?: string;
|
|
49
|
+
pollIntervalMs?: number;
|
|
50
|
+
abortSignal?: AbortSignal;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Run one CLI invocation (argv WITHOUT the node binary and script path) and
|
|
54
|
+
* answer its exit code. The bin entry assigns it to `process.exitCode`.
|
|
55
|
+
*/
|
|
56
|
+
export declare function runCli(argv: readonly string[], deps?: CliRuntimeDeps): Promise<number>;
|
|
57
|
+
//# sourceMappingURL=main.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../src/cli/main.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AASH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAkBpD,MAAM,WAAW,cAAc;IAC7B,2EAA2E;IAC3E,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IACvB;0EACsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;IACtC;wEACoE;IACpE,QAAQ,CAAC,EAAE,WAAW,CAAA;IACtB,2EAA2E;IAC3E,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;IAC1B,gDAAgD;IAChD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,OAAO,kBAAkB,CAAA;IACpC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAC5E,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAA;IAChB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B;AAqED;;;GAGG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA0I5F"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI-2 terminal QR rendering, zero dependencies: reuse the repo's own
|
|
3
|
+
* minimal encoder (`src/client-data/qr.ts`) and draw the module matrix with
|
|
4
|
+
* Unicode half-block characters — two module ROWS per terminal line, so the
|
|
5
|
+
* symbol stays square on screen (terminal cells are roughly twice as tall as
|
|
6
|
+
* they are wide):
|
|
7
|
+
*
|
|
8
|
+
* dark top + dark bottom → `█` dark top + light bottom → `▀`
|
|
9
|
+
* light top + dark bottom → `▄` light top + light bottom → ` `
|
|
10
|
+
*
|
|
11
|
+
* A 2-module quiet zone of light modules surrounds the symbol on every side
|
|
12
|
+
* (ISO 18004 recommendance) — without it many scanners refuse to lock on.
|
|
13
|
+
* Text too long for the encoder (over 106 UTF-8 bytes, its version-5-L
|
|
14
|
+
* capacity) returns `null`; the caller shows the plain URL instead.
|
|
15
|
+
*/
|
|
16
|
+
export declare function renderTerminalQr(text: string): string | null;
|
|
17
|
+
//# sourceMappingURL=qr-terminal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qr-terminal.d.ts","sourceRoot":"","sources":["../../../src/cli/qr-terminal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA4B5D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RemoteStatusIcon.d.ts","sourceRoot":"","sources":["../../../src/client/RemoteStatusIcon.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAEjF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AAExE,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAA;AAEjC,MAAM,WAAW,qBAAsB,SAAQ,YAAY,CAAC,qCAAqC,CAAC,EAAE,WAAW,CAAC,OAAO,EAAE,CAAC;IACxH;eACW;IACX,MAAM,EAAE,iBAAiB,CAAA;CAC1B;AAED,wBAAgB,gBAAgB,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,qBAAqB,
|
|
1
|
+
{"version":3,"file":"RemoteStatusIcon.d.ts","sourceRoot":"","sources":["../../../src/client/RemoteStatusIcon.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAEjF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AAExE,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAA;AAEjC,MAAM,WAAW,qBAAsB,SAAQ,YAAY,CAAC,qCAAqC,CAAC,EAAE,WAAW,CAAC,OAAO,EAAE,CAAC;IACxH;eACW;IACX,MAAM,EAAE,iBAAiB,CAAA;CAC1B;AAED,wBAAgB,gBAAgB,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,qBAAqB,sCAoD/E"}
|
|
@@ -18,6 +18,10 @@ export interface CurrentSessionReporterOptions {
|
|
|
18
18
|
intervalMs?: number;
|
|
19
19
|
/** The unconditional re-send window (T66); default 30000ms. */
|
|
20
20
|
resendIntervalMs?: number;
|
|
21
|
+
/** Optional UI language reader (`'zh'` | `'en'`); when present (or when
|
|
22
|
+
* `<html lang>` is set in the browser), the value rides the POST body as
|
|
23
|
+
* `lang` so the backend merger can localize sidebar group suffixes. */
|
|
24
|
+
getLang?: () => 'zh' | 'en' | undefined;
|
|
21
25
|
}
|
|
22
26
|
/**
|
|
23
27
|
* Start the reporter loop. Returns the disposer (listeners + interval) the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"current-session-report.d.ts","sourceRoot":"","sources":["../../../src/client/current-session-report.ts"],"names":[],"mappings":"AA6CA;;oBAEoB;AACpB,UAAU,WAAW;IACnB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;CACpC;AAED,MAAM,WAAW,6BAA6B;IAC5C;+EAC2E;IAC3E,OAAO,CAAC,EAAE,WAAW,CAAA;IACrB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAChE,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC,CAAA;IACxD,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,+DAA+D;IAC/D,gBAAgB,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"current-session-report.d.ts","sourceRoot":"","sources":["../../../src/client/current-session-report.ts"],"names":[],"mappings":"AA6CA;;oBAEoB;AACpB,UAAU,WAAW;IACnB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;CACpC;AAED,MAAM,WAAW,6BAA6B;IAC5C;+EAC2E;IAC3E,OAAO,CAAC,EAAE,WAAW,CAAA;IACrB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAChE,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC,CAAA;IACxD,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,+DAA+D;IAC/D,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;2EAEuE;IACvE,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,IAAI,GAAG,SAAS,CAAA;CACxC;AAKD;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,GAAE,6BAAkC,GAAG,MAAM,IAAI,CAkGnG;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE;IAAE,MAAM,CAAC,EAAE,EAAE,MAAM,MAAM,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EAAE,OAAO,GAAE,6BAAkC,GAAG,IAAI,CAExJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-group-side.d.ts","sourceRoot":"","sources":["../../../../src/client/effects/model-group-side.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"model-group-side.d.ts","sourceRoot":"","sources":["../../../../src/client/effects/model-group-side.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAmCvD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAY7G;AAoBD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAqE9D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-session.d.ts","sourceRoot":"","sources":["../../../../src/client/effects/remote-session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAoB,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"remote-session.d.ts","sourceRoot":"","sources":["../../../../src/client/effects/remote-session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAoB,MAAM,oBAAoB,CAAA;AA2DzE,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAoGlE"}
|
|
@@ -110,6 +110,10 @@ export declare const zh: {
|
|
|
110
110
|
readonly 'settings.invalidPort': "需要 1–65535 的整数";
|
|
111
111
|
readonly 'settings.invalidPositiveInt': "需要正整数";
|
|
112
112
|
readonly 'settings.pushTitle': "推送";
|
|
113
|
+
readonly 'settings.fieldPushEnabled': "启用会话通知";
|
|
114
|
+
readonly 'settings.fieldPushEnabledHint': "总开关:关闭后停止所有自动推送,且不注册 push_notify 工具与系统提示词。";
|
|
115
|
+
readonly 'settings.fieldPushSessionName': "推送来源会话名";
|
|
116
|
+
readonly 'settings.fieldPushSessionNameHint': "在推送正文第一行显示「来源会话:<会话名>」。";
|
|
113
117
|
readonly 'settings.fieldPushSummary': "推送内容摘要";
|
|
114
118
|
readonly 'settings.fieldPushSummaryHint': "在推送正文中包含回合的最终文本或待回答的问题。";
|
|
115
119
|
readonly 'settings.fieldPushTurnEnd': "回合结束推送";
|
|
@@ -186,7 +190,7 @@ export declare const zh: {
|
|
|
186
190
|
readonly 'settings.statusUnknown': "无法读取插件状态";
|
|
187
191
|
readonly 'settings.refreshFailed': "状态刷新失败,当前显示的是上一次成功的数据";
|
|
188
192
|
readonly 'settings.resetPreview': "保存后恢复为下一层的值";
|
|
189
|
-
readonly 'settings.client.connectTitle': "
|
|
193
|
+
readonly 'settings.client.connectTitle': "连接主服务端";
|
|
190
194
|
readonly 'settings.client.serverUrl': "服务端地址";
|
|
191
195
|
readonly 'settings.client.serverUrlHint': "服务端网关地址,例如 http://192.168.1.10:3088 或 https://dsh.example.com。";
|
|
192
196
|
readonly 'settings.client.deviceNameDefault': "桌面应用端";
|
|
@@ -202,7 +206,26 @@ export declare const zh: {
|
|
|
202
206
|
readonly 'settings.client.failUnreachable': "无法连接服务端";
|
|
203
207
|
readonly 'settings.client.failRoleMismatch': "该配对码不适用于桌面应用端";
|
|
204
208
|
readonly 'settings.client.failUnexpected': "服务端回应无法识别,请确认服务端已安装 dsh-zen-remote 2.0.0";
|
|
205
|
-
readonly 'settings.client.
|
|
209
|
+
readonly 'settings.client.failLimitReached': "已达主服务端数量上限:请先移除旧服务端,或输入已配对服务端的地址覆盖重配";
|
|
210
|
+
readonly 'settings.client.poolCount': "已配对 {count} / {max} 台";
|
|
211
|
+
readonly 'settings.client.poolCapNote': "最多可同时连接 {max} 台主服务端。";
|
|
212
|
+
readonly 'settings.client.limitReached': "已配满 {count} / {max} 台主服务端(已达上限)。如需添加新服务端,请先移除旧服务端;输入已配对服务端的地址仍可覆盖重配。";
|
|
213
|
+
readonly 'settings.client.serversTitle': "已配对主服务端";
|
|
214
|
+
readonly 'settings.client.serversEmpty': "尚未配对任何主服务端(最多可同时连接 {max} 台)";
|
|
215
|
+
readonly 'settings.client.repair': "重新配对";
|
|
216
|
+
readonly 'settings.client.serverRemove': "移除";
|
|
217
|
+
readonly 'settings.client.unpairServerConfirm': "将从本机移除该主服务端的配对(服务端上的数据与设备记录不受影响)。确定移除?";
|
|
218
|
+
readonly 'settings.client.unpairAllServers': "全部移除";
|
|
219
|
+
readonly 'settings.client.unpairAllServersConfirm': "将从本机移除全部已配对的主服务端(服务端上的数据与设备记录不受影响)。确定移除?";
|
|
220
|
+
readonly 'settings.client.serverStateConnected': "已连接";
|
|
221
|
+
readonly 'settings.client.serverStateRetry': "离线,{seconds} 秒后重试";
|
|
222
|
+
readonly 'settings.client.serverStateRetrySoon': "离线,即将重试";
|
|
223
|
+
readonly 'settings.client.serverStateOffline': "离线";
|
|
224
|
+
readonly 'settings.client.serverStateRevoked': "令牌已吊销";
|
|
225
|
+
readonly 'settings.client.serverStateIncompatible': "不兼容";
|
|
226
|
+
readonly 'settings.client.serverStateInvalidUrl': "地址无效";
|
|
227
|
+
readonly 'settings.client.serverStateUnpaired': "未连接";
|
|
228
|
+
readonly 'settings.client.serverDiagTitle': "各主服务端诊断";
|
|
206
229
|
readonly 'settings.client.statusTitle': "连接状态";
|
|
207
230
|
readonly 'settings.client.statusUnpaired': "未配对";
|
|
208
231
|
readonly 'settings.client.statusConnected': "已连接到 {serverUrl}";
|
|
@@ -364,6 +387,7 @@ export declare const zh: {
|
|
|
364
387
|
readonly 'wizard.desktop.generate': "生成桌面客户端配对码";
|
|
365
388
|
readonly 'wizard.desktop.regenerate': "重新生成配对码";
|
|
366
389
|
readonly 'wizard.desktop.copyInfo': "复制地址与配对码";
|
|
390
|
+
readonly 'wizard.desktop.copiedText': "服务端地址:{address}\n桌面客户端配对码:{code}";
|
|
367
391
|
readonly 'wizard.desktop.guide': "在另一台电脑打开本插件详情页,第 1 步选「作为桌面客户端」,第 2 步填入上方服务端地址与 8 位配对码即可完成连接。";
|
|
368
392
|
readonly 'wizard.desktop.pairedTitle': "已连接的桌面客户端({count})";
|
|
369
393
|
readonly 'wizard.desktop.pairedEmpty': "暂未配对桌面客户端";
|
|
@@ -478,7 +502,7 @@ export declare const zh: {
|
|
|
478
502
|
readonly 'wizard.overview.devicesSummary': "手机/网页 {web} 台 · 桌面客户端 {desktop} 台";
|
|
479
503
|
readonly 'wizard.overview.devicesNone': "暂未配对设备";
|
|
480
504
|
readonly 'wizard.overview.clientCredLabel': "本地配对凭证";
|
|
481
|
-
readonly 'wizard.overview.clientConnLabel': "
|
|
505
|
+
readonly 'wizard.overview.clientConnLabel': "连接状态";
|
|
482
506
|
readonly 'wizard.overview.clientServerLabel': "远端服务端地址";
|
|
483
507
|
readonly 'wizard.overview.startSetup': "开始配置向导";
|
|
484
508
|
readonly 'wizard.overview.reconfigure': "修改接入配置";
|
|
@@ -500,6 +524,26 @@ export declare const zh: {
|
|
|
500
524
|
readonly 'wizard.devicesModal.title': "已配对设备管理";
|
|
501
525
|
readonly 'wizard.devicesModal.subtitle': "查看与管理已配对的手机/网页设备及桌面客户端,支持改名、切换布局或吊销凭证";
|
|
502
526
|
readonly 'wizard.devicesModal.retest': "重新测试连通性";
|
|
527
|
+
readonly 'wizard.overview.clientSyncLabel': "会话与插件同步";
|
|
528
|
+
readonly 'wizard.overview.syncOk': "正常";
|
|
529
|
+
readonly 'wizard.overview.syncBad': "异常";
|
|
530
|
+
readonly 'wizard.overview.syncPending': "未连接";
|
|
531
|
+
readonly 'wizard.overview.clientOnlineCount': "在线 {online} / {total} 台";
|
|
532
|
+
readonly 'wizard.overview.clientOfflineCount': "离线 {count} 台";
|
|
533
|
+
readonly 'wizard.overview.clientRevokedCount': "已吊销 {count} 台";
|
|
534
|
+
readonly 'wizard.overview.clientAllOnline': "全部在线";
|
|
535
|
+
readonly 'wizard.overview.clientServersLabel': "已配对服务端";
|
|
536
|
+
readonly 'wizard.overview.clientPairedFull': "已配满 {count} / {max} 台(已达上限)";
|
|
537
|
+
readonly 'wizard.overview.clientPairedNames': "{names}(上限 {max} 台)";
|
|
538
|
+
readonly 'wizard.overview.limitNote': "已达 {max} 台上限,添加前请先移除旧服务端";
|
|
539
|
+
readonly 'wizard.overview.manageServers': "管理服务端";
|
|
540
|
+
readonly 'wizard.overview.addServer': "+ 添加服务端";
|
|
541
|
+
readonly 'wizard.serversModal.title': "已配对主服务端管理";
|
|
542
|
+
readonly 'wizard.serversModal.subtitle': "最多同时连接 {max} 台主服务端(当前 {count} / {max} 台)";
|
|
543
|
+
readonly 'wizard.serversModal.viewStatus': "查看状态";
|
|
544
|
+
readonly 'wizard.client.poolCapNote': "最多同时连接 {max} 台主服务端(当前已配对 {count} / {max} 台)";
|
|
545
|
+
readonly 'wizard.client.continueAdd': "+ 继续添加另一台";
|
|
546
|
+
readonly 'wizard.client.serverPicker': "选择要查看的服务端";
|
|
503
547
|
};
|
|
504
548
|
/** English dictionary, key-identical to the Chinese source of truth. */
|
|
505
549
|
export declare const en: Record<MobileNavKey, string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,eAAO,MAAM,EAAE,cAAc,CAAA;AAE7B,mEAAmE;AACnE,eAAO,MAAM,EAAE
|
|
1
|
+
{"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,eAAO,MAAM,EAAE,cAAc,CAAA;AAE7B,mEAAmE;AACnE,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAujBL,CAAA;AAEV,wEAAwE;AACxE,eAAO,MAAM,EAAE,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAmjB3C,CAAA;AAED,2EAA2E;AAC3E,MAAM,MAAM,YAAY,GAAG,MAAM,OAAO,EAAE,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SettingsSection.d.ts","sourceRoot":"","sources":["../../../../src/client/settings/SettingsSection.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;
|
|
1
|
+
{"version":3,"file":"SettingsSection.d.ts","sourceRoot":"","sources":["../../../../src/client/settings/SettingsSection.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AA+BjF,OAAO,KAAK,EAWV,qBAAqB,EACtB,MAAM,oCAAoC,CAAA;AAC3C,OAAO,EAAE,EAAE,EAAE,MAAM,eAAe,CAAA;AAGlC,OAAO,KAAK,EAAkB,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAE9E,MAAM,WAAW,oBAAqB,SAAQ,YAAY,CAAC,oBAAoB,CAAC,EAAE,WAAW,CAAC,OAAO,EAAE,CAAC;IACtG,sDAAsD;IACtD,MAAM,EAAE,qBAAqB,CAAA;IAC7B;mDAC+C;IAC/C,MAAM,EAAE,WAAW,CAAA;CACpB;AAiGD,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,+BAW1D"}
|
|
@@ -6,5 +6,5 @@
|
|
|
6
6
|
* styles (the CSS-division rule in AGENTS.md — the shell keeps its own
|
|
7
7
|
* stylesheets, this surface owns its own).
|
|
8
8
|
*/
|
|
9
|
-
export declare const SETTINGS_CSS = "\n[data-zen-remote=\"settings\"] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n max-width: 760px;\n}\n[data-zen-remote=\"settings\"] .zr-settings-summary {\n font-size: 13px;\n color: var(--dsw-alias-label-tertiary);\n margin: 0;\n}\n[data-zen-remote=\"settings\"] .zr-settings-notice {\n font-size: 13px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n padding: 8px 12px;\n background: var(--dsw-alias-bg-module-platform);\n color: var(--dsw-alias-label-secondary);\n margin: 0;\n}\n[data-zen-remote=\"settings\"] .zr-settings-card {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n background: var(--dsw-alias-bg-layer-2);\n padding: 4px 16px;\n}\n[data-zen-remote=\"settings\"] .zr-settings-card-title {\n font-size: 15px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary);\n margin: 12px 0 0;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n[data-zen-remote=\"settings\"] .zr-settings-field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 12px 0;\n}\n[data-zen-remote=\"settings\"] .zr-settings-field + .zr-settings-field {\n border-top: 1px solid var(--dsw-alias-border-l2);\n}\n[data-zen-remote=\"settings\"] .zr-settings-head {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n/* The head's title text: real labels (they name the select/checkbox below)\n and the two .zr-settings-head-title spans whose text names no form control\n (the pairing code readout, the push-test button) share the look. */\n[data-zen-remote=\"settings\"] .zr-settings-head label,\n[data-zen-remote=\"settings\"] .zr-settings-head .zr-settings-head-title {\n flex: 1;\n font-size: 13px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n[data-zen-remote=\"settings\"] .zr-settings-badge {\n font-size: 11px;\n border-radius: 999px;\n padding: 2px 8px;\n background: var(--dsw-alias-bg-module-platform);\n color: var(--dsw-alias-label-secondary);\n}\n[data-zen-remote=\"settings\"] .zr-settings-badge[data-warn=\"true\"] {\n color: var(--dsw-alias-state-warning-primary, #b8860b);\n}\n[data-zen-remote=\"settings\"] .zr-settings-reset {\n font-size: 12px;\n border: none;\n background: none;\n padding: 0;\n cursor: pointer;\n color: var(--dsw-alias-label-secondary);\n}\n[data-zen-remote=\"settings\"] .zr-settings-reset:hover {\n color: var(--dsw-alias-label-primary);\n}\n[data-zen-remote=\"settings\"] input.zr-settings-input,\n[data-zen-remote=\"settings\"] select.zr-settings-input {\n height: 34px;\n border-radius: 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-3);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n padding: 0 10px;\n}\n[data-zen-remote=\"settings\"] select.zr-settings-input {\n max-width: 260px;\n}\n[data-zen-remote=\"settings\"] .zr-settings-hint {\n font-size: 12px;\n color: var(--dsw-alias-label-tertiary);\n margin: 0;\n}\n[data-zen-remote=\"settings\"] .zr-settings-hint[data-invalid=\"true\"] {\n color: var(--dsw-alias-state-error-primary, #d5304f);\n}\n[data-zen-remote=\"settings\"] .zr-settings-check-row {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n[data-zen-remote=\"settings\"] .zr-settings-check-row input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n accent-color: var(--dsw-alias-label-primary);\n}\n[data-zen-remote=\"settings\"] .zr-settings-row {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n[data-zen-remote=\"settings\"] .zr-settings-status-line {\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n margin: 0;\n padding: 10px 0 12px;\n}\n[data-zen-remote=\"settings\"] .zr-settings-status-line[data-down=\"true\"] {\n color: var(--dsw-alias-state-error-primary, #d5304f);\n}\n[data-zen-remote=\"settings\"] .zr-settings-role-cards {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 12px 0;\n}\n[data-zen-remote=\"settings\"] .zr-settings-role-card {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n padding: 10px 12px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n cursor: pointer;\n background: none;\n text-align: left;\n font: inherit;\n color: inherit;\n}\n[data-zen-remote=\"settings\"] .zr-settings-role-card[data-active=\"true\"] {\n border-color: var(--dsw-alias-label-primary);\n}\n[data-zen-remote=\"settings\"] .zr-settings-role-card-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n[data-zen-remote=\"settings\"] .zr-settings-role-card-title input[type=\"radio\"] {\n width: 15px;\n height: 15px;\n accent-color: var(--dsw-alias-label-primary);\n}\n[data-zen-remote=\"settings\"] .zr-settings-code-input {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n letter-spacing: 4px;\n text-transform: uppercase;\n max-width: 220px;\n}\n[data-zen-remote=\"settings\"] .zr-settings-pair-code {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 28px;\n letter-spacing: 4px;\n color: var(--dsw-alias-label-primary);\n margin: 4px 0 0;\n}\n[data-zen-remote=\"settings\"] .zr-settings-device {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 12px 0;\n}\n[data-zen-remote=\"settings\"] .zr-settings-device + .zr-settings-device {\n border-top: 1px solid var(--dsw-alias-border-l2);\n}\n[data-zen-remote=\"settings\"] .zr-settings-device-head {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-wrap: wrap;\n}\n[data-zen-remote=\"settings\"] .zr-settings-device-name {\n font-size: 13px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n[data-zen-remote=\"settings\"] .zr-settings-device-actions {\n display: flex;\n gap: 8px;\n align-items: center;\n flex-wrap: wrap;\n}\n[data-zen-remote=\"settings\"] .zr-settings-device-actions select.zr-settings-input {\n height: 28px;\n max-width: 170px;\n}\n[data-zen-remote=\"settings\"] .zr-settings-share-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 0;\n}\n[data-zen-remote=\"settings\"] .zr-settings-share-row + .zr-settings-share-row {\n border-top: 1px solid var(--dsw-alias-border-l2);\n}\n[data-zen-remote=\"settings\"] .zr-settings-share-row .zr-settings-device-head {\n flex: 1;\n min-width: 0;\n}\n[data-zen-remote=\"settings\"] .zr-settings-badge[data-live=\"true\"] {\n color: var(--dsw-alias-state-success-primary, #16a34a);\n}\n[data-zen-remote=\"settings\"] .zr-settings-footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 0;\n}\n";
|
|
9
|
+
export declare const SETTINGS_CSS = "\n[data-zen-remote=\"settings\"] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n max-width: 760px;\n}\n[data-zen-remote=\"settings\"] .zr-settings-summary {\n font-size: 13px;\n color: var(--dsw-alias-label-tertiary);\n margin: 0;\n}\n[data-zen-remote=\"settings\"] .zr-settings-notice {\n font-size: 13px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n padding: 8px 12px;\n background: var(--dsw-alias-bg-module-platform);\n color: var(--dsw-alias-label-secondary);\n margin: 0;\n}\n[data-zen-remote=\"settings\"] .zr-settings-card {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n background: var(--dsw-alias-bg-layer-2);\n padding: 4px 16px;\n}\n[data-zen-remote=\"settings\"] .zr-settings-card-title {\n font-size: 15px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary);\n margin: 12px 0 0;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n[data-zen-remote=\"settings\"] .zr-settings-field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 12px 0;\n}\n[data-zen-remote=\"settings\"] .zr-settings-field + .zr-settings-field {\n border-top: 1px solid var(--dsw-alias-border-l2);\n}\n[data-zen-remote=\"settings\"] .zr-settings-field[data-disabled=\"true\"] {\n opacity: 0.5;\n}\n[data-zen-remote=\"settings\"] .zr-settings-head {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n/* The head's title text: real labels (they name the select/checkbox below)\n and the two .zr-settings-head-title spans whose text names no form control\n (the pairing code readout, the push-test button) share the look. */\n[data-zen-remote=\"settings\"] .zr-settings-head label,\n[data-zen-remote=\"settings\"] .zr-settings-head .zr-settings-head-title {\n flex: 1;\n font-size: 13px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n[data-zen-remote=\"settings\"] .zr-settings-badge {\n font-size: 11px;\n border-radius: 999px;\n padding: 2px 8px;\n background: var(--dsw-alias-bg-module-platform);\n color: var(--dsw-alias-label-secondary);\n}\n[data-zen-remote=\"settings\"] .zr-settings-badge[data-warn=\"true\"] {\n color: var(--dsw-alias-state-warning-primary, #b8860b);\n}\n[data-zen-remote=\"settings\"] .zr-settings-reset {\n font-size: 12px;\n border: none;\n background: none;\n padding: 0;\n cursor: pointer;\n color: var(--dsw-alias-label-secondary);\n}\n[data-zen-remote=\"settings\"] .zr-settings-reset:hover {\n color: var(--dsw-alias-label-primary);\n}\n[data-zen-remote=\"settings\"] input.zr-settings-input,\n[data-zen-remote=\"settings\"] select.zr-settings-input {\n height: 34px;\n border-radius: 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-3);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n padding: 0 10px;\n}\n[data-zen-remote=\"settings\"] select.zr-settings-input {\n max-width: 260px;\n}\n[data-zen-remote=\"settings\"] .zr-settings-hint {\n font-size: 12px;\n color: var(--dsw-alias-label-tertiary);\n margin: 0;\n}\n[data-zen-remote=\"settings\"] .zr-settings-hint[data-invalid=\"true\"] {\n color: var(--dsw-alias-state-error-primary, #d5304f);\n}\n[data-zen-remote=\"settings\"] .zr-settings-check-row {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n[data-zen-remote=\"settings\"] .zr-settings-check-row input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n accent-color: var(--dsw-alias-label-primary);\n}\n[data-zen-remote=\"settings\"] .zr-settings-row {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n[data-zen-remote=\"settings\"] .zr-settings-status-line {\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n margin: 0;\n padding: 10px 0 12px;\n}\n[data-zen-remote=\"settings\"] .zr-settings-status-line[data-down=\"true\"] {\n color: var(--dsw-alias-state-error-primary, #d5304f);\n}\n[data-zen-remote=\"settings\"] .zr-settings-role-cards {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 12px 0;\n}\n[data-zen-remote=\"settings\"] .zr-settings-role-card {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n padding: 10px 12px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n cursor: pointer;\n background: none;\n text-align: left;\n font: inherit;\n color: inherit;\n}\n[data-zen-remote=\"settings\"] .zr-settings-role-card[data-active=\"true\"] {\n border-color: var(--dsw-alias-label-primary);\n}\n[data-zen-remote=\"settings\"] .zr-settings-role-card-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n[data-zen-remote=\"settings\"] .zr-settings-role-card-title input[type=\"radio\"] {\n width: 15px;\n height: 15px;\n accent-color: var(--dsw-alias-label-primary);\n}\n[data-zen-remote=\"settings\"] .zr-settings-code-input {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n letter-spacing: 4px;\n text-transform: uppercase;\n max-width: 220px;\n}\n[data-zen-remote=\"settings\"] .zr-settings-pair-code {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 28px;\n letter-spacing: 4px;\n color: var(--dsw-alias-label-primary);\n margin: 4px 0 0;\n}\n[data-zen-remote=\"settings\"] .zr-settings-device {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 12px 0;\n}\n[data-zen-remote=\"settings\"] .zr-settings-device + .zr-settings-device {\n border-top: 1px solid var(--dsw-alias-border-l2);\n}\n[data-zen-remote=\"settings\"] .zr-settings-device-head {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-wrap: wrap;\n}\n[data-zen-remote=\"settings\"] .zr-settings-device-name {\n font-size: 13px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n[data-zen-remote=\"settings\"] .zr-settings-device-actions {\n display: flex;\n gap: 8px;\n align-items: center;\n flex-wrap: wrap;\n}\n[data-zen-remote=\"settings\"] .zr-settings-device-actions select.zr-settings-input {\n height: 28px;\n max-width: 170px;\n}\n[data-zen-remote=\"settings\"] .zr-settings-share-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 0;\n}\n[data-zen-remote=\"settings\"] .zr-settings-share-row + .zr-settings-share-row {\n border-top: 1px solid var(--dsw-alias-border-l2);\n}\n[data-zen-remote=\"settings\"] .zr-settings-share-row .zr-settings-device-head {\n flex: 1;\n min-width: 0;\n}\n[data-zen-remote=\"settings\"] .zr-settings-badge[data-live=\"true\"] {\n color: var(--dsw-alias-state-success-primary, #16a34a);\n}\n[data-zen-remote=\"settings\"] .zr-settings-badge[data-invalid=\"true\"] {\n color: var(--dsw-alias-state-error-primary, #d5304f);\n}\n/* MS-7: the full-pool alert must be impossible to miss \u2014 red, bold, framed. */\n[data-zen-remote=\"settings\"] .zr-settings-limit-alert,\n[data-zen-remote=\"settings\"] .zr-settings-limit-alert[data-invalid=\"true\"] {\n font-size: 13px;\n font-weight: 700;\n line-height: 1.5;\n color: var(--dsw-alias-state-error-primary, #d5304f);\n border: 1px solid var(--dsw-alias-state-error-primary, #d5304f);\n border-radius: 8px;\n padding: 8px 12px;\n margin: 8px 0 4px;\n}\n[data-zen-remote=\"settings\"] .zr-settings-footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 0;\n}\n";
|
|
10
10
|
//# sourceMappingURL=settings-css.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-css.d.ts","sourceRoot":"","sources":["../../../../src/client/settings/settings-css.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,eAAO,MAAM,YAAY,
|
|
1
|
+
{"version":3,"file":"settings-css.d.ts","sourceRoot":"","sources":["../../../../src/client/settings/settings-css.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,eAAO,MAAM,YAAY,ivOAoPxB,CAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const REMOTE_SESSION_CSS = "/* ---------- remote session: hide the open-on-the-server-machine entries ----------\n A remote session's files live on the relay SERVER; every \"open\" control here\n would act on the machine the DSH process runs on, not the one the browser is\n on. Hidden while the current session is remote (html[data-zr-remote-session]):\n - [data-open-target] is dsh-client-ui-open-in-app's own mount marker (RT\n dsh-client-ui-open-in-app lib/client.js ~325: the split-button anchor\n React renders with data-open-target={kind}) \u2014 one selector covers the\n session-header \"Open In...\" button, the document-preview actions, AND the\n \"Open / Show in Finder / Choose an application\" buttons of the changes\n panel and the deliverable cards (RT dsh-client-ui-deliverables\n lib/client.js ~1702, ~1963: those cards render the open-in-app package's\n FileRouteAction through the deliverables.file.actions and\n deliverables.review.file.actions slots, the same OpenTargetButton anchor).\n The attribute is the component's own contract, not a generated class. */\nhtml[data-zr-remote-session=\"1\"] [data-open-target] {\n display: none !important;\n}\n\n/* ---------- remote session: hide dsh-better-sidebar's file surfaces (T53, two regimes since PB-14) ----------\n dsh-better-sidebar 0.25.0 is the second big \"open the machine's files\" UI\n AND, since PB-12/13, the first ADAPTER-BRIDGED one: at exactly 0.25.0 its\n /sidebar/api routes, its two WebSockets and its side chat cross the byte\n tunnel and read/write the SERVER's data, gated on the whole-machine-data\n consent. The hiding below therefore applies ONLY while the plugin is NOT\n bridged \u2014 the :not([data-zr-bridge-dsh-better-sidebar=\"1\"]) stamp the\n remote-status poll writes; see the PB-14 note above): bridged, the panels\n are remote-aware and stay visible; unbridged (a different version, the\n server without the adapter's consent), every tab it registers (files/\n editor, git changes, subagent/tasks, side chat, the markdown/html/code\n file viewers) builds its requests from a {sessionId, cwd} scope and POSTs\n them to the plugin's own /sidebar/api/* routes on whichever machine\n answers \u2014 in a remote session that is the SUB-CLIENT's machine (client.js\n call() ~3111, fetchUpload ~3162, encodeHtmlUrl /sidebar/html/ ~3069-3414),\n so the tree would show same-named LOCAL files as if they were the\n session's and an edit would WRITE locally.\n\n Anchors, all the plugin's or the host's own rendered contracts (no hashed\n class names; the one suffix selector, _chipIcon, is unique among the\n profile's packages \u2014 checked dsh-vision-router / dsh-auto-approve /\n dsh-mem0 / dsh-llm-verifier / dsh-plugin-subscriptions /\n @liustack/modsearch / @wxg-prc-cpg/browser-skill-dsh-plugin (modsearch /\n browser-skill) / dshmarket and every @deepseek-ai sidebar package for it):\n\n HONEST LIMITS (T53-fix, adjusted PB-14): unbridged, the plugin's\n components stay mounted and keep silently POSTing READ-ONLY /sidebar/api\n requests to the local machine (session.cwd, changes.ops, the tree reads a\n mounted tab refreshes with) \u2014 the data never leaves that machine, and no\n write can happen because every write control is inside the hidden\n surfaces (the tab body hides its CHILDREN and spends the note copy as a\n ::before, so an already-open tab reads WHY it is empty instead of\n sitting blank). Known boundary: a dsh-resource://file/** address opened\n through sidebarRight.openResource in a remote session (file links in\n chat, deliverables, @-references, skills) is CLAIMED by the plugin's\n editor registration (client.js ~21377: patterns [\"dsh-resource://file/**\"])\n before the host preview sees it \u2014 the right sidebar expands, the rules\n below hide the tab's body content and chip, and the note fills the panel.\n Bridged (0.25.0 + consent), none of this applies: the tab reads the\n server's data through the adapter and stays visible whole.\n\n - [data-dsh-bottom-toggle] \u2014 the header-utilities button that expands the\n bottom workbench (client.js BottomDockToggle ~20863; slot registration\n ~21492-21498, id dsh-better-sidebar:bottom-toggle). Our own phone header\n button drives the OFFICIAL right sidebar (MobileSessionHeader.tsx), so\n hiding this does not strand the phone.\n - [data-dsh-panel-host] \u2014 the fixed viewport layer the plugin appends to\n document.body (client.js ~20763); the bottom workbench panel\n ([data-dsh-bottom-panel]) is its only child, so hiding the layer hides\n the workbench whole (tab strip, + menu, tree, editor and all).\n - --dsh-sidebar-height \u2014 the plugin's layout push: written INLINE on <html>\n while the workbench is open (client.js writeGeometry ~20482-20488) and\n spent by its own layout.css as the center column's margin-bottom\n (client.js layout css ~23009: #root [data-dsh-center-col] { margin-bottom:\n var(--dsh-sidebar-height, 0px) }). Hiding the panel alone would leave\n that reserved band as a blank strip under the conversation, so the remote\n html zeroes the variable. A stylesheet !important beats a non-important\n inline style, and the plugin's JS state is never touched: the moment the\n attribute is removed (back on a local session) its own value applies\n again, transitions included.\n - [data-dsh-native-tab-host] \u2014 the wrapper the plugin renders around EVERY\n tab body it contributes to the host's native right Sidebar\n (client.js NativeTabBody ~21074, marker ~21110/21120). The host's pane\n chrome is untouched: the strip keeps the \"+\" (guide) button and the\n collapse/fullscreen controls, so a tab that was already open leaves no\n dead panel \u2014 an empty body behind a strip that still collapses, and the\n \"+\" re-opens the guide page (whose plugin capsules these rules hide, see\n below). React keeps mounting into the display:none node: no errors, and\n the restore on returning to a local session is instant.\n - [data-dockkit-tab]:has([class$=\"_chipIcon\"]) \u2014 the native tab STRIP's\n chips for plugin tabs, so an already-open tab does not survive as a\n clickable ghost. The chip button is dockkit's ([data-dockkit-tab], dsh-web\n frontend bundle: role=tab, renderTabTitle inside a\n span[data-dockkit-tab-title]); its content is the plugin's\n NativeTabTitle (~21172-21197), which always leads with a\n [class$=\"_chipIcon\"] glyph span because every built-in descriptor ships an\n icon \u2014 a chip with no glyph (an external tab registered through the\n plugin's viewer service without an icon) keeps its chip; its body is\n still hidden by the rule above. Host tabs' chips never contain a\n _chipIcon (checked all four @deepseek-ai sidebar packages), so the\n remote-aware host files page survives alongside.\n - [data-floating-window]:has([data-window-body]) \u2014 the plugin's\n body-PORTALED floating windows (client.js FloatingWindow ~15078-15120):\n the task edit window (teams.taskCreate/Update with rootSessionId via\n /sidebar/api, writeTask ~3124-3140) and the job-output window (host jobs\n kill). Both open from the subagent/tasks tab; portal escapes the tab\n body's display:none, so they need their own rule. Anchored on the\n window's own root attribute plus its own inner body marker, so a foreign\n [data-floating-window] without that shape never matches.\n - guide capsules \u2014 the empty-sidebar doorway buttons the HOST renders from\n the plugin's registrations ([data-sidebar-right-guide-entry=\"<kind>\"], RT\n dsh-client-ui-sidebar-right lib/client.js:466): kinds git / subagent /\n sidechat exist only while this plugin registers them, so those selectors\n are inert without it. The \"files\" capsule is the one ambiguous kind:\n dsh-client-ui-sidebar-files registers the SAME kind (its filesDefinition,\n lib/client.js:14-31) and that page is REMOTE-AWARE (it injects the host's\n remote.workspaceFiles service). T53-fix discriminates on the capsule's\n own rendered contract instead of plugin presence: the host's EntryBox\n renders aria-keyshortcuts from the shortcut matching entry.commandId (RT\n sidebar-right lib/client.js:461-467) \u2014 the host files guide row carries\n commandId \"workspace.files\" (dsh-client-ui-sidebar-files\n lib/client.js:30), while better-sidebar's guide rows carry NO commandId\n (client.js registerNativeSurface ~21385-21400), so its capsule never\n renders the attribute. :not([aria-keyshortcuts]) therefore hides the\n plugin's takeover capsule and spares the host's wherever the host has a\n default binding. Boundary: that \"wherever\" is not everywhere \u2014 the host\n registers workspace.files defaults for desktop:macos/windows/linux and\n web:macos/windows only (dsh-client-ui-sidebar-files lib/client.js:949-977),\n so on any other platform the OFFICIAL capsule also renders without the\n attribute and this rule hides it too (cosmetic; the page stays reachable\n through its shortcut command path and the plugin's takeover is the\n \"files\" implementation on every deployment this plugin pairs with\n better-sidebar anyway).\n\n /* PB-14: every T53 rule below carries\n :not([data-zr-bridge-dsh-better-sidebar=\"1\"]) \u2014 when the adapter\n (PB-12) bridges the plugin, the panels read the SERVER's data through\n the byte tunnel and MUST stay visible; the hiding applies only to the\n unbridged combination, and the empty tab body then carries a note\n instead of blankness. The stamp is written by\n effects/remote-session.ts off the remote-status poll's bridgedPlugins\n list (client-data/remote-status.ts shouldStampBridgeAttribute). */\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) [data-dsh-bottom-toggle] {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) [data-dsh-panel-host] {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) {\n --dsh-sidebar-height: 0px !important;\n}\n/* The unbridged tab body: hide the plugin's own content and spend the\n note copy as a ::before \u2014 an already-open tab reads WHY it is empty\n (0.25.0 keeps tabs mounted, so a stale body would otherwise sit blank).\n --zr-bridge-note is set on <html> by the stamp effect, in the\n browser's language; unset (effect not running yet) the content falls\n through and nothing renders. */\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) [data-dsh-native-tab-host] > * {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) [data-dsh-native-tab-host]::before {\n content: var(--zr-bridge-note);\n display: block;\n padding: 24px 16px;\n font-size: 13px;\n line-height: 1.7;\n color: var(--dsh-fg-muted, #6b7280);\n word-break: break-word;\n}\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) [data-dockkit-tab]:has([class$=\"_chipIcon\"]) {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) [data-floating-window]:has([data-window-body]) {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) [data-sidebar-right-guide-entry=\"git\"],\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) [data-sidebar-right-guide-entry=\"subagent\"],\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) [data-sidebar-right-guide-entry=\"sidechat\"] {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) [data-sidebar-right-guide-entry=\"files\"]:not([aria-keyshortcuts]) {\n display: none !important;\n}\n/* 0.25.0's dock fallback \u2014 the floating quick-open button the plugin pins\n for empty workspaces. Same treatment as every other open-the-machine's-\n files control: hidden while unbridged, untouched when bridged. */\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) [data-dsh-dock-fallback] {\n display: none !important;\n}\n\n/* ---------- T52/T74: model-menu groups follow the session's side ----------\n The model catalog is GLOBAL (one shared load per page), so the merged\n catalog shows the server's groups everywhere; but a selection is only\n runnable on the side the open session lives on \u2014 the interceptor refuses\n the other side with a clear message. Hide what cannot run.\n\n What changed and why the mechanism is a STAMP now (T74): through 0.1.7\n each menu group rendered aria-labelledby=\"<useId>-<group.id>\" (RT017\n dsh-client-ui-model-selection lib/client.js ~824-830) \u2014 the group id was\n IN the attribute, and rules could key on a virtual group's \"zr~\" prefix\n directly. 0.2.0 renders the groups with the primitives' MenuGroup\n instead (RT dsh-client-ui-primitives lib/index.js ~4283-4304): the\n section's aria-labelledby carries ONLY the useId, the heading is a child\n div[data-menu-group-heading], and the menu container is a div whose id\n ends in \"-models\" with role=\"menu\" (RT dsh-client-ui-model-selection\n lib/client.js ~974-980). Two consequences killed the old rules: a group\n section no longer says anywhere in its markup which group it is, and the\n same MenuGroup renders OTHER menus' groups too \u2014 the old\n [role=\"menu\"] section[role=\"group\"] scope alone was too wide and would\n have hidden every unmarked group of every menu in a remote session\n (leaving just the search box), while missing the server's groups in\n local ones.\n\n The new keys on what EVERY version actually renders, the heading text:\n each virtual group's name is prefixed with the invisible WORD JOINER\n (VIRTUAL_GROUP_NAME_MARK, virtual-id.ts; written by mergeModelCatalogs).\n The browser effect (effects/model-group-side.ts) reads each group's\n heading and stamps data-zr-group=\"remote|local\" on the section \u2014 but\n only inside a CONTAINER (the sections' shared parent element) that holds\n at least one marked heading. That container rule is what scopes these\n rules to the model menu alone WITHOUT assuming menu structure: an\n unpaired client's model menu, every other menu, and the whole rest of\n the page hold no marked heading, receive no stamp, and match neither\n rule. And since the merged catalog only ever APPENDS virtual groups to\n the local list, within a decided container the unmarked groups are\n exactly the local ones \u2014 mixed containers (the norm) decide each group\n separately. The menu is a portal under <body>, but <html> is still its\n ancestor, so the html-level session attribute scopes both rules. If the\n effect is not running (uninstalled, or a host-role page that never had\n it), no stamp exists and both rules go inert \u2014 nothing stays hidden.\n\n KNOWN BOUNDARY (accepted, not fixed): in a remote session, searching the\n model menu and pressing Enter can commit a HIDDEN local model \u2014 the\n interceptor refuses it with its usual message. */\nhtml[data-zr-remote-session=\"1\"] section[role=\"group\"][data-zr-group=\"local\"] {\n display: none !important;\n}\nhtml:not([data-zr-remote-session]) section[role=\"group\"][data-zr-group=\"remote\"] {\n display: none !important;\n}\n\n/* ---------- T52-fix: hide the virtual groups in NATIVE <option> pickers ----\n The model menu above is React DOM, but dsh-vision-router's settings render\n its vision-backend picker as a native <select> of <option value={group.id}>\n rows, and its filter (dsh-vision-router lib/client.js:661-670\n filterVisionBackendGroups) drops only vision-http / vision-chain / *-vision\n \u2014 a merged virtual group (\"zr~<id>~\u2026\") survives into that picker even\n though a server model can never be a LOCAL vision backend (the router calls\n providers from the machine it runs on). Native <option> rows honor\n display:none in the dropdown list, so this hides them wherever they appear:\n - no scoping attribute on purpose: a virtual group is not a runnable\n backend in ANY local context, and the option element itself carries the\n value \u2014 no host-depth assumption, no :has();\n - when the vision router (or any other <option>-rendering surface) is not\n installed, nothing matches \u2014 dead rule, zero cost;\n - zen-remote's own surfaces are checked: our settings forms render fixed\n enum options (\"web\" / \"desktop-client\" / role kinds /\n configForm enum strings, src/client/settings/SettingsSection.tsx:641,690-701)\n and none can start with \"zr~\" (virtual group ids only ever exist inside\n model-catalog payloads and model-selection arguments). */\noption[value^=\"zr~\"] {\n display: none !important;\n}\n\n/* ---------- remote session: hide the session-export menu item (T51, T51-fix) ----------\n A remote session's log lives on the relay server and the backend refuses\n /api/session.export for a virtual id with 403 remote-unsupported\n (fetch-route-intercept.ts) \u2014 the item would only ever end in the \"Export\n failed\" modal, so it is hidden IN THE MENU (T51-fix: the anchor button\n stays, because it also opens the \u53CD\u9988 entry, which a remote session can\n still use). The DOM, verified against RT:\n - the Menu renders its anchor and its list as SIBLINGS inside its own\n span root (RT dsh-client-ui-primitives lib/index.js ~4265-4273:\n children = [anchor, portal ? createPortal(list) : list]), and the\n export Menu passes no portal flag (default false, ~3923) \u2014 so the list\n is the anchor's next sibling, matched by the general-sibling\n combinator below;\n - the list surface carries role=\"menu\" (Menu passes it at ~4243;\n MenuSurface spreads ...props onto its root div, ~3778-3795) and the\n items viewport inside it is div[role=\"presentation\"] (~4249-4252);\n - every data item is ONE div (the itemWrap wrapper, ~4143), so\n :first-child of the viewport is the FIRST item \u2014 and the export\n package puts \u4E0B\u8F7D/\u5BFC\u51FA first by construction (RT dsh-session-log-export\n lib/client.js 202-206, the optional feedback entry appended after at\n 207-211).\n The anchor button class suffix is matched the way compat.css.ts matches\n module classes (the hash prefix is build-local, \"_moreButton\" is the\n source name; unique in this slot \u2014 the only other moreButton in the RT\n tree, dsh-client-ui-sidebar-documentpreview lib/client.excel.js, lives in\n the sidebar, never under conversation.session.header.utilities).\n Known costs, accepted: with the feedback UI absent the menu's only item\n is the export, so the opened menu is EMPTY; and keyboard navigation still\n steps into the hidden item (focusable but invisible) until activated or\n escaped \u2014 it cannot be triggered through the visibility, only tabbed\n past blindly. */\nhtml[data-zr-remote-session=\"1\"] [data-slot=\"conversation.session.header.utilities\"] [class$=\"_moreButton\"] ~ [role=\"menu\"] > [role=\"presentation\"] > :first-child {\n display: none !important;\n}\n\n/* ---------- remote session: the \"save to this machine\" action (2.2.6) ----------\n One class, owned by this plugin (no host module class, no hash): the\n deliverable-card entry renders it in the card's own actions cell, the\n document-preview entry in the preview header where open-in-app's control\n sits (that one is hidden remotely by the [data-open-target] rule above,\n so this is the only action left there). Both entries only MOUNT for a\n virtual session, so the html attribute gate is belt-and-braces, not the\n decision.\n The palette variables are the host's own (label-secondary / border-l1 /\n interactive-bg-hover / state-error), which keeps light/dark identical to\n the cards around it without copying a theme. */\nhtml[data-zr-remote-session=\"1\"] .zr-download-action {\n box-sizing: border-box;\n flex: none;\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary, #6b7280);\n background: transparent;\n border: 0.5px solid var(--dsw-alias-border-l1, #d9dde3);\n border-radius: var(--dsw-radius-sm, 4px);\n padding: 1px 8px;\n cursor: pointer;\n white-space: nowrap;\n}\nhtml[data-zr-remote-session=\"1\"] .zr-download-action:hover {\n color: var(--dsw-alias-label-primary, #111827);\n background: var(--dsw-alias-interactive-bg-hover, rgba(0, 0, 0, 0.05));\n}\nhtml[data-zr-remote-session=\"1\"] .zr-download-action[data-phase=\"busy\"] {\n cursor: progress;\n opacity: 0.7;\n}\nhtml[data-zr-remote-session=\"1\"] .zr-download-action[data-phase=\"error\"] {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n border-color: var(--dsw-alias-state-error-primary, #dc2626);\n}\n";
|
|
1
|
+
export declare const REMOTE_SESSION_CSS = "/* ---------- remote session: hide the open-on-the-server-machine entries ----------\n A remote session's files live on the relay SERVER; every \"open\" control here\n would act on the machine the DSH process runs on, not the one the browser is\n on. Hidden while the current session is remote (html[data-zr-remote-session]):\n - [data-open-target] is dsh-client-ui-open-in-app's own mount marker (RT\n dsh-client-ui-open-in-app lib/client.js ~325: the split-button anchor\n React renders with data-open-target={kind}) \u2014 one selector covers the\n session-header \"Open In...\" button, the document-preview actions, AND the\n \"Open / Show in Finder / Choose an application\" buttons of the changes\n panel and the deliverable cards (RT dsh-client-ui-deliverables\n lib/client.js ~1702, ~1963: those cards render the open-in-app package's\n FileRouteAction through the deliverables.file.actions and\n deliverables.review.file.actions slots, the same OpenTargetButton anchor).\n The attribute is the component's own contract, not a generated class. */\nhtml[data-zr-remote-session=\"1\"] [data-open-target] {\n display: none !important;\n}\n\n/* ---------- remote session: hide dsh-better-sidebar's file surfaces (T53, two regimes since PB-14) ----------\n dsh-better-sidebar 0.25.0 is the second big \"open the machine's files\" UI\n AND, since PB-12/13, the first ADAPTER-BRIDGED one: at exactly 0.25.0 its\n /sidebar/api routes, its two WebSockets and its side chat cross the byte\n tunnel and read/write the SERVER's data, gated on the whole-machine-data\n consent. The hiding below therefore applies ONLY while the plugin is NOT\n bridged \u2014 the :not([data-zr-bridge-dsh-better-sidebar=\"1\"]) stamp the\n remote-status poll writes; see the PB-14 note above): bridged, the panels\n are remote-aware and stay visible; unbridged (a different version, the\n server without the adapter's consent), every tab it registers (files/\n editor, git changes, subagent/tasks, side chat, the markdown/html/code\n file viewers) builds its requests from a {sessionId, cwd} scope and POSTs\n them to the plugin's own /sidebar/api/* routes on whichever machine\n answers \u2014 in a remote session that is the SUB-CLIENT's machine (client.js\n call() ~3111, fetchUpload ~3162, encodeHtmlUrl /sidebar/html/ ~3069-3414),\n so the tree would show same-named LOCAL files as if they were the\n session's and an edit would WRITE locally.\n\n Anchors, all the plugin's or the host's own rendered contracts (no hashed\n class names; the one suffix selector, _chipIcon, is unique among the\n profile's packages \u2014 checked dsh-vision-router / dsh-auto-approve /\n dsh-mem0 / dsh-llm-verifier / dsh-plugin-subscriptions /\n @liustack/modsearch / @wxg-prc-cpg/browser-skill-dsh-plugin (modsearch /\n browser-skill) / dshmarket and every @deepseek-ai sidebar package for it):\n\n HONEST LIMITS (T53-fix, adjusted PB-14): unbridged, the plugin's\n components stay mounted and keep silently POSTing READ-ONLY /sidebar/api\n requests to the local machine (session.cwd, changes.ops, the tree reads a\n mounted tab refreshes with) \u2014 the data never leaves that machine, and no\n write can happen because every write control is inside the hidden\n surfaces (the tab body hides its CHILDREN and spends the note copy as a\n ::before, so an already-open tab reads WHY it is empty instead of\n sitting blank). Known boundary: a dsh-resource://file/** address opened\n through sidebarRight.openResource in a remote session (file links in\n chat, deliverables, @-references, skills) is CLAIMED by the plugin's\n editor registration (client.js ~21377: patterns [\"dsh-resource://file/**\"])\n before the host preview sees it \u2014 the right sidebar expands, the rules\n below hide the tab's body content and chip, and the note fills the panel.\n Bridged (0.25.0 + consent), none of this applies: the tab reads the\n server's data through the adapter and stays visible whole.\n\n - [data-dsh-bottom-toggle] \u2014 the header-utilities button that expands the\n bottom workbench (client.js BottomDockToggle ~20863; slot registration\n ~21492-21498, id dsh-better-sidebar:bottom-toggle). Our own phone header\n button drives the OFFICIAL right sidebar (MobileSessionHeader.tsx), so\n hiding this does not strand the phone.\n - [data-dsh-panel-host] \u2014 the fixed viewport layer the plugin appends to\n document.body (client.js ~20763); the bottom workbench panel\n ([data-dsh-bottom-panel]) is its only child, so hiding the layer hides\n the workbench whole (tab strip, + menu, tree, editor and all).\n - --dsh-sidebar-height \u2014 the plugin's layout push: written INLINE on <html>\n while the workbench is open (client.js writeGeometry ~20482-20488) and\n spent by its own layout.css as the center column's margin-bottom\n (client.js layout css ~23009: #root [data-dsh-center-col] { margin-bottom:\n var(--dsh-sidebar-height, 0px) }). Hiding the panel alone would leave\n that reserved band as a blank strip under the conversation, so the remote\n html zeroes the variable. A stylesheet !important beats a non-important\n inline style, and the plugin's JS state is never touched: the moment the\n attribute is removed (back on a local session) its own value applies\n again, transitions included.\n - [data-dsh-native-tab-host] \u2014 the wrapper the plugin renders around EVERY\n tab body it contributes to the host's native right Sidebar\n (client.js NativeTabBody ~21074, marker ~21110/21120). The host's pane\n chrome is untouched: the strip keeps the \"+\" (guide) button and the\n collapse/fullscreen controls, so a tab that was already open leaves no\n dead panel \u2014 an empty body behind a strip that still collapses, and the\n \"+\" re-opens the guide page (whose plugin capsules these rules hide, see\n below). React keeps mounting into the display:none node: no errors, and\n the restore on returning to a local session is instant.\n - [data-dockkit-tab]:has([class$=\"_chipIcon\"]) \u2014 the native tab STRIP's\n chips for plugin tabs, so an already-open tab does not survive as a\n clickable ghost. The chip button is dockkit's ([data-dockkit-tab], dsh-web\n frontend bundle: role=tab, renderTabTitle inside a\n span[data-dockkit-tab-title]); its content is the plugin's\n NativeTabTitle (~21172-21197), which always leads with a\n [class$=\"_chipIcon\"] glyph span because every built-in descriptor ships an\n icon \u2014 a chip with no glyph (an external tab registered through the\n plugin's viewer service without an icon) keeps its chip; its body is\n still hidden by the rule above. Host tabs' chips never contain a\n _chipIcon (checked all four @deepseek-ai sidebar packages), so the\n remote-aware host files page survives alongside.\n - [data-floating-window]:has([data-window-body]) \u2014 the plugin's\n body-PORTALED floating windows (client.js FloatingWindow ~15078-15120):\n the task edit window (teams.taskCreate/Update with rootSessionId via\n /sidebar/api, writeTask ~3124-3140) and the job-output window (host jobs\n kill). Both open from the subagent/tasks tab; portal escapes the tab\n body's display:none, so they need their own rule. Anchored on the\n window's own root attribute plus its own inner body marker, so a foreign\n [data-floating-window] without that shape never matches.\n - guide capsules \u2014 the empty-sidebar doorway buttons the HOST renders from\n the plugin's registrations ([data-sidebar-right-guide-entry=\"<kind>\"], RT\n dsh-client-ui-sidebar-right lib/client.js:466): kinds git / subagent /\n sidechat exist only while this plugin registers them, so those selectors\n are inert without it. The \"files\" capsule is the one ambiguous kind:\n dsh-client-ui-sidebar-files registers the SAME kind (its filesDefinition,\n lib/client.js:14-31) and that page is REMOTE-AWARE (it injects the host's\n remote.workspaceFiles service). T53-fix discriminates on the capsule's\n own rendered contract instead of plugin presence: the host's EntryBox\n renders aria-keyshortcuts from the shortcut matching entry.commandId (RT\n sidebar-right lib/client.js:461-467) \u2014 the host files guide row carries\n commandId \"workspace.files\" (dsh-client-ui-sidebar-files\n lib/client.js:30), while better-sidebar's guide rows carry NO commandId\n (client.js registerNativeSurface ~21385-21400), so its capsule never\n renders the attribute. :not([aria-keyshortcuts]) therefore hides the\n plugin's takeover capsule and spares the host's wherever the host has a\n default binding. Boundary: that \"wherever\" is not everywhere \u2014 the host\n registers workspace.files defaults for desktop:macos/windows/linux and\n web:macos/windows only (dsh-client-ui-sidebar-files lib/client.js:949-977),\n so on any other platform the OFFICIAL capsule also renders without the\n attribute and this rule hides it too (cosmetic; the page stays reachable\n through its shortcut command path and the plugin's takeover is the\n \"files\" implementation on every deployment this plugin pairs with\n better-sidebar anyway).\n\n /* PB-14: every T53 rule below carries\n :not([data-zr-bridge-dsh-better-sidebar=\"1\"]) \u2014 when the adapter\n (PB-12) bridges the plugin, the panels read the SERVER's data through\n the byte tunnel and MUST stay visible; the hiding applies only to the\n unbridged combination, and the empty tab body then carries a note\n instead of blankness. The stamp is written by\n effects/remote-session.ts off the remote-status poll's bridgedPlugins\n list (client-data/remote-status.ts shouldStampBridgeAttribute). */\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) [data-dsh-bottom-toggle] {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) [data-dsh-panel-host] {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) {\n --dsh-sidebar-height: 0px !important;\n}\n/* The unbridged tab body: hide the plugin's own content and spend the\n note copy as a ::before \u2014 an already-open tab reads WHY it is empty\n (0.25.0 keeps tabs mounted, so a stale body would otherwise sit blank).\n --zr-bridge-note is set on <html> by the stamp effect, in the\n browser's language; unset (effect not running yet) the content falls\n through and nothing renders. */\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) [data-dsh-native-tab-host] > * {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) [data-dsh-native-tab-host]::before {\n content: var(--zr-bridge-note);\n display: block;\n padding: 24px 16px;\n font-size: 13px;\n line-height: 1.7;\n color: var(--dsh-fg-muted, #6b7280);\n word-break: break-word;\n}\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) [data-dockkit-tab]:has([class$=\"_chipIcon\"]) {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) [data-floating-window]:has([data-window-body]) {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) [data-sidebar-right-guide-entry=\"git\"],\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) [data-sidebar-right-guide-entry=\"subagent\"],\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) [data-sidebar-right-guide-entry=\"sidechat\"] {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) [data-sidebar-right-guide-entry=\"files\"]:not([aria-keyshortcuts]) {\n display: none !important;\n}\n/* 0.25.0's dock fallback \u2014 the floating quick-open button the plugin pins\n for empty workspaces. Same treatment as every other open-the-machine's-\n files control: hidden while unbridged, untouched when bridged. */\nhtml[data-zr-remote-session=\"1\"]:not([data-zr-bridge-dsh-better-sidebar=\"1\"]) [data-dsh-dock-fallback] {\n display: none !important;\n}\n\n/* ---------- T52/T74: model-menu groups follow the session's side ----------\n The model catalog is GLOBAL (one shared load per page), so the merged\n catalog shows the server's groups everywhere; but a selection is only\n runnable on the side the open session lives on \u2014 the interceptor refuses\n the other side with a clear message. Hide what cannot run.\n\n What changed and why the mechanism is a STAMP now (T74): through 0.1.7\n each menu group rendered aria-labelledby=\"<useId>-<group.id>\" (RT017\n dsh-client-ui-model-selection lib/client.js ~824-830) \u2014 the group id was\n IN the attribute, and rules could key on a virtual group's \"zr~\" prefix\n directly. 0.2.0 renders the groups with the primitives' MenuGroup\n instead (RT dsh-client-ui-primitives lib/index.js ~4283-4304): the\n section's aria-labelledby carries ONLY the useId, the heading is a child\n div[data-menu-group-heading], and the menu container is a div whose id\n ends in \"-models\" with role=\"menu\" (RT dsh-client-ui-model-selection\n lib/client.js ~974-980). Two consequences killed the old rules: a group\n section no longer says anywhere in its markup which group it is, and the\n same MenuGroup renders OTHER menus' groups too \u2014 the old\n [role=\"menu\"] section[role=\"group\"] scope alone was too wide and would\n have hidden every unmarked group of every menu in a remote session\n (leaving just the search box), while missing the server's groups in\n local ones.\n\n The new keys on what EVERY version actually renders, the heading text:\n each virtual group's name is prefixed with the invisible WORD JOINER\n (VIRTUAL_GROUP_NAME_MARK, virtual-id.ts; written by mergeModelCatalogs).\n The browser effect (effects/model-group-side.ts) reads each group's\n heading and stamps data-zr-group=\"remote|local\" on the section \u2014 but\n only inside a CONTAINER (the sections' shared parent element) that holds\n at least one marked heading. That container rule is what scopes these\n rules to the model menu alone WITHOUT assuming menu structure: an\n unpaired client's model menu, every other menu, and the whole rest of\n the page hold no marked heading, receive no stamp, and match neither\n rule. And since the merged catalog only ever APPENDS virtual groups to\n the local list, within a decided container the unmarked groups are\n exactly the local ones \u2014 mixed containers (the norm) decide each group\n separately. The menu is a portal under <body>, but <html> is still its\n ancestor, so the html-level session attribute scopes both rules. If the\n effect is not running (uninstalled, or a host-role page that never had\n it), no stamp exists and both rules go inert \u2014 nothing stays hidden.\n\n KNOWN BOUNDARY (accepted, not fixed): in a remote session, searching the\n model menu and pressing Enter can commit a HIDDEN local model \u2014 the\n interceptor refuses it with its usual message.\n\n MS-4, several paired servers: each remote group heading also carries its\n server id (zero-width bits after the mark, virtual-id.ts\n encodeServerIdZeroWidth), and the effect reads the open session's server\n off html[data-zr-remote-server] (effects/remote-session.ts). A remote\n group of a DIFFERENT server is stamped \"remote-other\": hidden inside a\n remote session (only the open session's own server's models can run\n there) and, like every remote group, outside one. */\nhtml[data-zr-remote-session=\"1\"] section[role=\"group\"][data-zr-group=\"local\"] {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"] section[role=\"group\"][data-zr-group=\"remote-other\"] {\n display: none !important;\n}\nhtml:not([data-zr-remote-session]) section[role=\"group\"][data-zr-group=\"remote\"] {\n display: none !important;\n}\nhtml:not([data-zr-remote-session]) section[role=\"group\"][data-zr-group=\"remote-other\"] {\n display: none !important;\n}\n\n/* ---------- T52-fix: hide the virtual groups in NATIVE <option> pickers ----\n The model menu above is React DOM, but dsh-vision-router's settings render\n its vision-backend picker as a native <select> of <option value={group.id}>\n rows, and its filter (dsh-vision-router lib/client.js:661-670\n filterVisionBackendGroups) drops only vision-http / vision-chain / *-vision\n \u2014 a merged virtual group (\"zr~<id>~\u2026\") survives into that picker even\n though a server model can never be a LOCAL vision backend (the router calls\n providers from the machine it runs on). Native <option> rows honor\n display:none in the dropdown list, so this hides them wherever they appear:\n - no scoping attribute on purpose: a virtual group is not a runnable\n backend in ANY local context, and the option element itself carries the\n value \u2014 no host-depth assumption, no :has();\n - when the vision router (or any other <option>-rendering surface) is not\n installed, nothing matches \u2014 dead rule, zero cost;\n - zen-remote's own surfaces are checked: our settings forms render fixed\n enum options (\"web\" / \"desktop-client\" / role kinds /\n configForm enum strings, src/client/settings/SettingsSection.tsx:641,690-701)\n and none can start with \"zr~\" (virtual group ids only ever exist inside\n model-catalog payloads and model-selection arguments). */\noption[value^=\"zr~\"] {\n display: none !important;\n}\n\n/* ---------- remote session: hide the session-export menu item (T51, T51-fix) ----------\n A remote session's log lives on the relay server and the backend refuses\n /api/session.export for a virtual id with 403 remote-unsupported\n (fetch-route-intercept.ts) \u2014 the item would only ever end in the \"Export\n failed\" modal, so it is hidden IN THE MENU (T51-fix: the anchor button\n stays, because it also opens the \u53CD\u9988 entry, which a remote session can\n still use). The DOM, verified against RT:\n - the Menu renders its anchor and its list as SIBLINGS inside its own\n span root (RT dsh-client-ui-primitives lib/index.js ~4265-4273:\n children = [anchor, portal ? createPortal(list) : list]), and the\n export Menu passes no portal flag (default false, ~3923) \u2014 so the list\n is the anchor's next sibling, matched by the general-sibling\n combinator below;\n - the list surface carries role=\"menu\" (Menu passes it at ~4243;\n MenuSurface spreads ...props onto its root div, ~3778-3795) and the\n items viewport inside it is div[role=\"presentation\"] (~4249-4252);\n - every data item is ONE div (the itemWrap wrapper, ~4143), so\n :first-child of the viewport is the FIRST item \u2014 and the export\n package puts \u4E0B\u8F7D/\u5BFC\u51FA first by construction (RT dsh-session-log-export\n lib/client.js 202-206, the optional feedback entry appended after at\n 207-211).\n The anchor button class suffix is matched the way compat.css.ts matches\n module classes (the hash prefix is build-local, \"_moreButton\" is the\n source name; unique in this slot \u2014 the only other moreButton in the RT\n tree, dsh-client-ui-sidebar-documentpreview lib/client.excel.js, lives in\n the sidebar, never under conversation.session.header.utilities).\n Known costs, accepted: with the feedback UI absent the menu's only item\n is the export, so the opened menu is EMPTY; and keyboard navigation still\n steps into the hidden item (focusable but invisible) until activated or\n escaped \u2014 it cannot be triggered through the visibility, only tabbed\n past blindly. */\nhtml[data-zr-remote-session=\"1\"] [data-slot=\"conversation.session.header.utilities\"] [class$=\"_moreButton\"] ~ [role=\"menu\"] > [role=\"presentation\"] > :first-child {\n display: none !important;\n}\n\n/* ---------- remote session: the \"save to this machine\" action (2.2.6) ----------\n One class, owned by this plugin (no host module class, no hash): the\n deliverable-card entry renders it in the card's own actions cell, the\n document-preview entry in the preview header where open-in-app's control\n sits (that one is hidden remotely by the [data-open-target] rule above,\n so this is the only action left there). Both entries only MOUNT for a\n virtual session, so the html attribute gate is belt-and-braces, not the\n decision.\n The palette variables are the host's own (label-secondary / border-l1 /\n interactive-bg-hover / state-error), which keeps light/dark identical to\n the cards around it without copying a theme. */\nhtml[data-zr-remote-session=\"1\"] .zr-download-action {\n box-sizing: border-box;\n flex: none;\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary, #6b7280);\n background: transparent;\n border: 0.5px solid var(--dsw-alias-border-l1, #d9dde3);\n border-radius: var(--dsw-radius-sm, 4px);\n padding: 1px 8px;\n cursor: pointer;\n white-space: nowrap;\n}\nhtml[data-zr-remote-session=\"1\"] .zr-download-action:hover {\n color: var(--dsw-alias-label-primary, #111827);\n background: var(--dsw-alias-interactive-bg-hover, rgba(0, 0, 0, 0.05));\n}\nhtml[data-zr-remote-session=\"1\"] .zr-download-action[data-phase=\"busy\"] {\n cursor: progress;\n opacity: 0.7;\n}\nhtml[data-zr-remote-session=\"1\"] .zr-download-action[data-phase=\"error\"] {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n border-color: var(--dsw-alias-state-error-primary, #dc2626);\n}\n";
|
|
2
2
|
//# sourceMappingURL=remote-session.css.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-session.css.d.ts","sourceRoot":"","sources":["../../../../src/client/styles/remote-session.css.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,kBAAkB,
|
|
1
|
+
{"version":3,"file":"remote-session.css.d.ts","sourceRoot":"","sources":["../../../../src/client/styles/remote-session.css.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,kBAAkB,6irBA4V9B,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GatewayWizard.d.ts","sourceRoot":"","sources":["../../../../src/client/wizard/GatewayWizard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AACjF,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"GatewayWizard.d.ts","sourceRoot":"","sources":["../../../../src/client/wizard/GatewayWizard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AACjF,OAAO,KAAK,EAOV,qBAAqB,EACtB,MAAM,oCAAoC,CAAA;AAwD3C,OAAO,EAAE,EAAE,EAAE,MAAM,eAAe,CAAA;AAMlC,MAAM,WAAW,kBAAmB,SAAQ,YAAY,CAAC,uBAAuB,CAAC,EAAE,WAAW,CAAC,OAAO,EAAE,CAAC;IACvG,qEAAqE;IACrE,MAAM,EAAE,qBAAqB,CAAA;IAC7B,2EAA2E;IAC3E,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3G;AAuHD,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,SAAS,CAy1ElE"}
|