ds-harness-remote 0.4.7 → 0.4.9

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/dist/client.js CHANGED
@@ -1697,7 +1697,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
1697
1697
  var CONTROL_RPC_PREFIX = "/ds-harness-remote";
1698
1698
 
1699
1699
  // src/client.ts
1700
- var clientModuleId = "ds-harness-remote", pendingWorkspaceSelectionKey = "dsh-remote:pending-workspace-selection";
1700
+ var clientModuleId = "ds-harness-remote", pendingWorkspaceSelectionKey = "dsh-remote:pending-workspace-selection", deepSeekWorkspaceIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAACVBMVEUAAADy8vXx8fUsA3vyAAAAAXRSTlMAQObYZgAAAOxJREFUWMPtlsEOwyAMQxP+/6OnTZMGxHGcot3wDYgfhkJbs6urprzveGtu9d1NgEdto8w93GuA7zPS2RFg7ynsCOAokbtAmLr2YaeKgJ6fxpT8jCAC0qSqPyNoO5DXdvyouj4ClFAdYaDxK09uiBDCIYBf6CxLesnR0uF2pG+JmhCqrUb0AOvjjoQaYDTCEAAgMg5grhAeAQIB+/M15IcKlnUIp4CkTCd0AKb4zVsRSJVGYEVzT0agK107IMGMEurvromEpaX4wzk/IKw378kq4LafED6Oowxfk7AP2q8W16EdM3p29Eyvrv6vF0WIBfBziKyCAAAAAElFTkSuQmCC", gptWorkspaceIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAclBMVEX////v7+++wMf////s7O3k5OTExcrX2Ny6vMTv8PPW19yXmqRqboJmaHd3eoaqrLPs7fGMjpfb3eKlpq1eYXOxs7pWWWd+gY5HSVdRVGVub3k+QU74+Pg4OkcvMT1ISlUoKjUiIy4fICueoKkaGyUSFB21Bp+qAAAAAXRSTlMAQObYZgAABChJREFUWMPtl916qjoQhlsdEwIECEgMYCBxx/u/xT1DrFUL1LO1DtY8LSLJvPnmB4gfH//sr7TPDfvdebf/xXZbkE/4zZ0MVhGHd9zJDsv+7F3//Z69tT5wljAu3tXw+TIlzXKJlhflYmJ+5uF5WpWhb54X+C/zZCmT2wJA4dJZwus0UYjIGqWyMhVbEp4yKNRRqlv0opW5PJLJ4rFJXvP4JKDRMqturBZjkMVJFYjR6iHQDQDI4+k2k51wZbWrqwp4mR/1CVYATyko9TFGxBUqL5IvMbXSWt0T8bkGgFLqgqZBI/Uxbx5UAxLaNcCNLBpttM7wbCc1pmJOpWAsDtey68UaQMyrFgb9uxLPjqg3+nGluyKN0XUdWw0BJ0NvTFFqgzpr9J+Dh4w0Ga1qkqBNswagxdRgFPAbgHRQG5jumGWyMxrTIaRRa4AzFs0YrNMXgI4MJWnsKYFhGNMnIh/mBOPsV8CZBFjN9w8ArowxnZzDr5IcvxTaKpxJCVsoI3SWysz1UM4AqQdzlCgho1IKrK+x1mKFzisANtgEU8E7GwHDgOqxe4w9tnM166wbaA2xBMBLrTWcAGYGdCiYVUJUrMCF+7l6gklrW1RwPi8ByjuActANqhKzVWoYrFGcCFzbDgNaBrTWpncFQMcI2DfWoAiDqRCiHcYM/ZdCEKkZqfR8spj4F0CiJjv2gHL6URNoCQDaYacL6O1oFDO2eQDUFP7AKdCRdC4CRDZaNifbjA41l/uYb/SZMAFNTBGzY7sG4J2jTsJgToOzIzXF3HZqBpSOAGduXbkGEKV1OqVGqRJpRxtvwbSw5IqAiUJItwBCOT9R32FCGo3nCkAN3t0UTBRC6zDONcBeOee9pr4T+ASbnDOdc5OmtREwEEB5w8Wqgt4bOV5c7Lt9iiK8zdP/IsBbutUGX4gNwEVCqd3FUt/xYnRWt7BvPBYQjwjAGXa3ASguHVAZ/WXKlA3eZDX1wRegFsr7E2wAlB9xFbx/7MV70kFT8aqNgLL3F8nFBmA3hrn/IJHjKJOK2oj1WI4Z4FzwN/81AOhgYD6v2xbIvaZIurLC9AfvB1WLTYAoXejF1xeBL5cpBIyEbmxkZymIXwDQh1BAfOrhI1lfwtgz8tozF5T4ttf3+32AyxC6klwAgw/YVTHpoK82xYt3wLP/Bw4AAI4D7/01TLKXBj9NEz2wEuGiKpoy68S/FwCLMQAZ3gXhihaCa25vQo6RyToOz9PE6wYjJgGi1YnqZX8qMIK+TDlnargGzSv4NvFjlwXf/nfLLMrAB4O/Xl3BH0d+RIASFgDA8IYMIXgr2+cBsbDdPSwAAHjSZFmb3txETCKIxc0uWwI8rxsLJcTiVndNwyMgKljbbNN2/zcEAja2+4RgIDYN2Bu/WtAOaEodnu2dnzz/7I/Y/w/LaEcX/MdfAAAAAElFTkSuQmCC";
1701
1701
  function storedWorkspaceSelection() {
1702
1702
  let raw = window.sessionStorage.getItem(pendingWorkspaceSelectionKey);
1703
1703
  if (raw !== null)
@@ -1831,8 +1831,6 @@ Minimum version required to store current data is: ` + bestVersion + `.
1831
1831
  remoteProgressUsingPrefix: "Using ",
1832
1832
  remoteProgressLoadingWorkspaces: "Loading workspaces",
1833
1833
  remoteProgressLoadingWorkspacesDetail: "Reading the remote Harness workspace list through the tunnel.",
1834
- remoteProgressOpeningWorkspace: "Opening workspace",
1835
- remoteProgressOpeningWorkspaceDetail: "Asking the Host to prepare the selected working directory.",
1836
1834
  remoteProgressSwitchingWorkspace: "Switching interface",
1837
1835
  remoteProgressSwitchingWorkspaceDetail: "Handing the remote workspace to the local Harness UI.",
1838
1836
  remoteProgressReady: "Ready",
@@ -1853,6 +1851,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
1853
1851
  noCodexWorkspaces: "No CodeX workspaces yet.",
1854
1852
  cancelAddWorkspace: "Cancel",
1855
1853
  confirmAddWorkspace: "Add and open",
1854
+ showAllWorkspaces: "Show all DSH workspaces",
1856
1855
  showAllCodexWorkspaces: "Show all CodeX workspaces",
1857
1856
  remoteModeLabel: "Remote mode \xB7 {name}",
1858
1857
  remoteNetworkP2p: "P2P",
@@ -2039,8 +2038,6 @@ Minimum version required to store current data is: ` + bestVersion + `.
2039
2038
  remoteProgressUsingPrefix: "\u5DF2\u8FDE\u63A5 ",
2040
2039
  remoteProgressLoadingWorkspaces: "\u6B63\u5728\u52A0\u8F7D\u5DE5\u4F5C\u533A",
2041
2040
  remoteProgressLoadingWorkspacesDetail: "\u901A\u8FC7\u96A7\u9053\u8BFB\u53D6\u8FDC\u7AEF Harness \u5DE5\u4F5C\u533A\u5217\u8868\u3002",
2042
- remoteProgressOpeningWorkspace: "\u6B63\u5728\u6253\u5F00\u5DE5\u4F5C\u533A",
2043
- remoteProgressOpeningWorkspaceDetail: "\u6B63\u5728\u8BF7\u6C42 Host \u51C6\u5907\u6240\u9009\u5DE5\u4F5C\u76EE\u5F55\u3002",
2044
2041
  remoteProgressSwitchingWorkspace: "\u6B63\u5728\u5207\u6362\u754C\u9762",
2045
2042
  remoteProgressSwitchingWorkspaceDetail: "\u6B63\u5728\u628A\u8FDC\u7AEF\u5DE5\u4F5C\u533A\u4EA4\u7ED9\u672C\u5730 Harness UI\u3002",
2046
2043
  remoteProgressReady: "\u5DF2\u5C31\u7EEA",
@@ -2061,6 +2058,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
2061
2058
  noCodexWorkspaces: "\u8FD8\u6CA1\u6709 CodeX \u5DE5\u4F5C\u533A\u3002",
2062
2059
  cancelAddWorkspace: "\u53D6\u6D88",
2063
2060
  confirmAddWorkspace: "\u786E\u8BA4\u5E76\u6253\u5F00",
2061
+ showAllWorkspaces: "\u663E\u793A\u5168\u90E8 DSH \u5DE5\u4F5C\u533A",
2064
2062
  showAllCodexWorkspaces: "\u663E\u793A\u5168\u90E8 CodeX \u5DE5\u4F5C\u533A",
2065
2063
  remoteModeLabel: "\u8FDC\u7A0B\u6A21\u5F0F \xB7 {name}",
2066
2064
  remoteNetworkP2p: "P2P",
@@ -2150,12 +2148,6 @@ Minimum version required to store current data is: ` + bestVersion + `.
2150
2148
  function normalizedPreferredTransports(value) {
2151
2149
  return value === void 0 || value.length === 0 ? [...defaultPreferredTransports] : [...value];
2152
2150
  }
2153
- function initialProbeTransports(value) {
2154
- let transports = normalizedPreferredTransports(value);
2155
- if (transports.length === 1) return transports;
2156
- let directTransports = transports.filter((transport) => transport === "lan" || transport === "p2p");
2157
- return directTransports.length > 0 ? directTransports : transports.includes("turn") ? ["turn"] : ["relay"];
2158
- }
2159
2151
  function formatLocalTime(value) {
2160
2152
  let date = new Date(value);
2161
2153
  return Number.isNaN(date.getTime()) ? "\u2014" : date.toLocaleString();
@@ -2185,22 +2177,6 @@ Minimum version required to store current data is: ` + bestVersion + `.
2185
2177
  function transportProgressCopy(value) {
2186
2178
  return value === "lan" ? { label: "remoteProgressProbeLan", detail: "remoteProgressProbeLanDetail" } : value === "p2p" ? { label: "remoteProgressProbeP2p", detail: "remoteProgressProbeP2pDetail" } : value === "turn" ? { label: "remoteProgressProbeTurn", detail: "remoteProgressProbeTurnDetail" } : { label: "remoteProgressProbeRelay", detail: "remoteProgressProbeRelayDetail" };
2187
2179
  }
2188
- function connectHostProgressSteps(preferredTransports) {
2189
- let transports = normalizedPreferredTransports(preferredTransports), probeTransports = initialProbeTransports(preferredTransports);
2190
- return [
2191
- { label: "remoteProgressCheckingHost", detail: "remoteProgressCheckingHostDetail", percent: 12 },
2192
- { label: "remoteProgressAuthorizingPeer", detail: "remoteProgressAuthorizingPeerDetail", percent: 30, delayMs: 280 },
2193
- ...probeTransports.map((transport, index) => ({
2194
- ...transportProgressCopy(transport),
2195
- percent: Math.min(76, 42 + index * 10),
2196
- delayMs: 680 + index * 360,
2197
- transports: probeTransports,
2198
- activeTransport: transport,
2199
- routeVerb: "trying"
2200
- })),
2201
- { label: "remoteProgressLoadingWorkspaces", detail: "remoteProgressLoadingWorkspacesDetail", percent: 84, delayMs: 1520, transports }
2202
- ];
2203
- }
2204
2180
  function statusTransportPreference(status) {
2205
2181
  if (status?.transport === "LAN") return "lan";
2206
2182
  if (status?.transport === "P2P") return "p2p";
@@ -2214,11 +2190,49 @@ Minimum version required to store current data is: ` + bestVersion + `.
2214
2190
  label: "remoteProgressReady",
2215
2191
  detail: "remoteProgressReadyDetail",
2216
2192
  percent: 100,
2217
- transports: [activeTransport],
2218
- activeTransport,
2193
+ transports: normalizedPreferredTransports(status?.preferredTransports),
2194
+ activeTransports: [activeTransport],
2219
2195
  routeVerb: "using"
2220
2196
  };
2221
2197
  }
2198
+ function loadingProgressPercent(elapsedMs) {
2199
+ return elapsedMs >= 6800 ? 96 : elapsedMs >= 3800 ? 93 : elapsedMs >= 1600 ? 89 : 84;
2200
+ }
2201
+ function observedConnectionProgress(status, targetDeviceId, preferredTransports, connectedStep, connectedAt) {
2202
+ let transports = normalizedPreferredTransports(status.preferredTransports ?? preferredTransports), connection = status.connectionProgress;
2203
+ if (connection?.targetDeviceId === targetDeviceId) {
2204
+ if (connection.phase === "checking-host")
2205
+ return { label: "remoteProgressCheckingHost", detail: "remoteProgressCheckingHostDetail", percent: 12 };
2206
+ if (connection.phase === "authorizing-peer")
2207
+ return { label: "remoteProgressAuthorizingPeer", detail: "remoteProgressAuthorizingPeerDetail", percent: 30 };
2208
+ let activeTransports = connection.activeTransports?.filter((transport) => transports.includes(transport)) ?? [];
2209
+ if (connection.phase === "probing") {
2210
+ let activeIndex = Math.max(0, ...activeTransports.map((transport) => transports.indexOf(transport)));
2211
+ return {
2212
+ ...activeTransports.length === 1 ? transportProgressCopy(activeTransports[0]) : { label: "remoteProgressOpeningChannel", detail: "remoteProgressOpeningChannelDetail" },
2213
+ percent: Math.min(76, 42 + activeIndex * 10),
2214
+ transports,
2215
+ activeTransports,
2216
+ routeVerb: "trying"
2217
+ };
2218
+ }
2219
+ return {
2220
+ ...connectedStep,
2221
+ percent: loadingProgressPercent(connectedAt === void 0 ? 0 : Date.now() - connectedAt),
2222
+ transports,
2223
+ activeTransports,
2224
+ routeVerb: "using"
2225
+ };
2226
+ }
2227
+ if (status.connectedTargetDeviceId !== targetDeviceId) return;
2228
+ let activeTransport = statusTransportPreference(status);
2229
+ return {
2230
+ ...connectedStep,
2231
+ percent: loadingProgressPercent(connectedAt === void 0 ? 0 : Date.now() - connectedAt),
2232
+ transports,
2233
+ ...activeTransport === void 0 ? {} : { activeTransports: [activeTransport], routeVerb: "using" }
2234
+ };
2235
+ }
2222
2236
  function connectionErrorMessage(code, t) {
2223
2237
  return t(code === "ACCOUNT_AUTH_REQUIRED" || code === "AUTH_INVALID" || code === "TOKEN_EXPIRED" ? "connectionAuthorizationExpired" : code === "DEVICE_REVOKED" ? "connectionDeviceRevoked" : code === "DEVICE_OWNERSHIP_REQUIRED" ? "connectionOwnershipRequired" : code === "RATE_LIMITED" ? "connectionRateLimited" : code === "UNSUPPORTED_VERSION" ? "connectionVersionMismatch" : code === "INVALID_MESSAGE" ? "connectionInvalidResponse" : code === "CONNECTION_FAILED" || code === "SERVER_NOT_CONFIGURED" ? "connectionReachability" : "connectionUnexpected");
2224
2238
  }
@@ -2241,7 +2255,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
2241
2255
  function RemoteProgressView(props) {
2242
2256
  let progress = props.progress;
2243
2257
  if (progress === void 0) return null;
2244
- let percent = Math.max(0, Math.min(100, Math.round(progress.percent))), activeTransportIndex = progress.transports?.findIndex((transport) => transport === progress.activeTransport) ?? -1, detail = progress.transports !== void 0 && progress.activeTransport !== void 0 && activeTransportIndex > -1 ? React.createElement(
2258
+ let percent = Math.max(0, Math.min(100, Math.round(progress.percent))), activeTransports = new Set(progress.activeTransports ?? []), detail = progress.transports !== void 0 && activeTransports.size > 0 ? React.createElement(
2245
2259
  "span",
2246
2260
  { className: "dshRemoteProgressRoute" },
2247
2261
  props.t(progress.routeVerb === "using" ? "remoteProgressUsingPrefix" : "remoteProgressTryingPrefix"),
@@ -2250,7 +2264,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
2250
2264
  { key: `${transport}:${index}` },
2251
2265
  index === 0 ? null : React.createElement("span", { className: "dshRemoteProgressRouteArrow", "aria-hidden": !0 }, " -> "),
2252
2266
  React.createElement("span", {
2253
- className: index === activeTransportIndex ? "isActive" : void 0
2267
+ className: activeTransports.has(transport) ? "isActive" : void 0
2254
2268
  }, transportDiagnosticLabel(transport))
2255
2269
  ))
2256
2270
  ) : props.t(progress.detail);
@@ -2278,25 +2292,35 @@ Minimum version required to store current data is: ` + bestVersion + `.
2278
2292
  }, React.createElement("span", { style: { transform: `scaleX(${percent / 100})` } }))
2279
2293
  );
2280
2294
  }
2281
- async function runRemoteProgress(steps, setProgress, progressRun, action, readyProgress) {
2295
+ async function runConnectHostProgress(preferredTransports, targetDeviceId, control, connectedStep, setProgress, progressRun, action, readyProgress) {
2282
2296
  let runId = progressRun.current + 1;
2283
2297
  progressRun.current = runId;
2284
- let apply2 = (next) => {
2298
+ let polling = !0, pollTimer, connectedAt, apply2 = (next) => {
2285
2299
  progressRun.current === runId && setProgress(next);
2286
- }, [first, ...rest] = steps;
2287
- first !== void 0 && apply2(first);
2288
- let timers = rest.map((step) => window.setTimeout(() => apply2(step), step.delayMs ?? 0));
2300
+ }, poll = async () => {
2301
+ try {
2302
+ let status = await control("status");
2303
+ if (!polling || progressRun.current !== runId) return;
2304
+ (status.connectionProgress?.phase === "connected" || status.connectedTargetDeviceId === targetDeviceId) && connectedAt === void 0 && (connectedAt = Date.now());
2305
+ let next = observedConnectionProgress(status, targetDeviceId, preferredTransports, connectedStep, connectedAt);
2306
+ next !== void 0 && apply2(next);
2307
+ } catch {
2308
+ } finally {
2309
+ polling && progressRun.current === runId && (pollTimer = window.setTimeout(() => {
2310
+ poll();
2311
+ }, 300));
2312
+ }
2313
+ };
2314
+ apply2({ label: "remoteProgressCheckingHost", detail: "remoteProgressCheckingHostDetail", percent: 12 });
2315
+ let pending = action();
2316
+ poll();
2289
2317
  try {
2290
- let result = await action();
2291
- return apply2(readyProgress?.(result) ?? { label: "remoteProgressReady", detail: "remoteProgressReadyDetail", percent: 100 }), await new Promise((resolve) => window.setTimeout(resolve, 520)), result;
2318
+ let result = await pending;
2319
+ return polling = !1, pollTimer !== void 0 && window.clearTimeout(pollTimer), apply2(readyProgress?.(result) ?? { label: "remoteProgressReady", detail: "remoteProgressReadyDetail", percent: 100 }), await new Promise((resolve) => window.setTimeout(resolve, 520)), result;
2292
2320
  } finally {
2293
- timers.forEach((timer) => window.clearTimeout(timer)), progressRun.current === runId && setProgress(void 0);
2321
+ polling = !1, pollTimer !== void 0 && window.clearTimeout(pollTimer), progressRun.current === runId && setProgress(void 0);
2294
2322
  }
2295
2323
  }
2296
- let openWorkspaceProgressSteps = [
2297
- { label: "remoteProgressOpeningWorkspace", detail: "remoteProgressOpeningWorkspaceDetail", percent: 30 },
2298
- { label: "remoteProgressSwitchingWorkspace", detail: "remoteProgressSwitchingWorkspaceDetail", percent: 74, delayMs: 520 }
2299
- ];
2300
2324
  function RemotePluginOptions(props) {
2301
2325
  let { t } = props, [open, setOpen] = React.useState(!1), [serverUrl, setServerUrl] = React.useState(""), [codexEnabled, setCodexEnabled] = React.useState(!0), role = "host", [registrationCode, setRegistrationCode] = React.useState(""), [associations, setAssociations] = React.useState({}), [loaded, setLoaded] = React.useState(!1), [writable, setWritable] = React.useState(!1), [busy, setBusy] = React.useState(!1), [codexBusy, setCodexBusy] = React.useState(!1), [reconnectBusy, setReconnectBusy] = React.useState(!1), [hostStatus, setHostStatus] = React.useState(void 0), [notice, setNotice] = React.useState(void 0), [error, setError] = React.useState(void 0), [settingsView, setSettingsView] = React.useState(void 0), persistedServerUrl = settingsView?.config.serverUrl ?? "https://dsh.r2049.cn", association = associations.client ?? associations.host, serverDirty = settingsView !== void 0 && serverUrl !== persistedServerUrl, draftDirty = serverDirty, applyView = (view) => {
2302
2326
  setSettingsView(view), setServerUrl(view.config.serverUrl ?? "https://dsh.r2049.cn"), setCodexEnabled(view.config.codex?.enabled ?? !0), setAssociations(view.associations ?? (view.association === void 0 ? {} : { host: view.association })), setWritable(view.writable), setLoaded(!0);
@@ -2555,7 +2579,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
2555
2579
  );
2556
2580
  }
2557
2581
  function RemoteWorkspaceAction(props) {
2558
- let { t } = props, [open, setOpen] = React.useState(!1), [status, setStatus] = React.useState(void 0), [devices, setDevices] = React.useState([]), [selectedHost, setSelectedHost] = React.useState(void 0), [workspaces, setWorkspaces] = React.useState([]), [codexWorkspaces, setCodexWorkspaces] = React.useState([]), [workspaceBackend, setWorkspaceBackend] = React.useState("harness"), [codexWorkspaceId, setCodexWorkspaceId] = React.useState(void 0), [directory, setDirectory] = React.useState(void 0), [path, setPath] = React.useState(""), [addingWorkspace, setAddingWorkspace] = React.useState(!1), [showAllCodexWorkspaces, setShowAllCodexWorkspaces] = React.useState(!1), codexWorkspaceHeadingId = "dsh-remote-codex-workspace-heading", codexWorkspaceListId = "dsh-remote-codex-workspace-list", [busy, setBusy] = React.useState(!1), [needsAuthorization, setNeedsAuthorization] = React.useState(!1), [email, setEmail] = React.useState(""), [password, setPassword] = React.useState(""), [loginMethod, setLoginMethod] = React.useState(props.preferredQrProvider), [loginMethodManuallySelected, setLoginMethodManuallySelected] = React.useState(!1), [qrSession, setQrSession] = React.useState(void 0), [qrImage, setQrImage] = React.useState(void 0), [qrExpired, setQrExpired] = React.useState(!1), [progress, setProgress] = React.useState(void 0), progressRun = React.useRef(0), qrFlowRun = React.useRef(0), [notice, setNotice] = React.useState(void 0), [error, setError] = React.useState(void 0);
2582
+ let { t } = props, [open, setOpen] = React.useState(!1), [status, setStatus] = React.useState(void 0), [devices, setDevices] = React.useState([]), [selectedHost, setSelectedHost] = React.useState(void 0), [workspaces, setWorkspaces] = React.useState([]), [codexWorkspaces, setCodexWorkspaces] = React.useState([]), [workspaceBackend, setWorkspaceBackend] = React.useState("harness"), [codexWorkspaceId, setCodexWorkspaceId] = React.useState(void 0), [directory, setDirectory] = React.useState(void 0), [path, setPath] = React.useState(""), [addingWorkspace, setAddingWorkspace] = React.useState(!1), [showAllWorkspaces, setShowAllWorkspaces] = React.useState(!1), [showAllCodexWorkspaces, setShowAllCodexWorkspaces] = React.useState(!1), workspaceListId = "dsh-remote-workspace-list", codexWorkspaceHeadingId = "dsh-remote-codex-workspace-heading", codexWorkspaceListId = "dsh-remote-codex-workspace-list", [busy, setBusy] = React.useState(!1), [needsAuthorization, setNeedsAuthorization] = React.useState(!1), [email, setEmail] = React.useState(""), [password, setPassword] = React.useState(""), [loginMethod, setLoginMethod] = React.useState(props.preferredQrProvider), [loginMethodManuallySelected, setLoginMethodManuallySelected] = React.useState(!1), [qrSession, setQrSession] = React.useState(void 0), [qrImage, setQrImage] = React.useState(void 0), [qrExpired, setQrExpired] = React.useState(!1), [progress, setProgress] = React.useState(void 0), progressRun = React.useRef(0), qrFlowRun = React.useRef(0), [notice, setNotice] = React.useState(void 0), [error, setError] = React.useState(void 0);
2559
2583
  React.useEffect(() => {
2560
2584
  if (!open) return;
2561
2585
  let closeOnEscape = (event) => {
@@ -2634,10 +2658,13 @@ Minimum version required to store current data is: ` + bestVersion + `.
2634
2658
  disabled: busy,
2635
2659
  onClick: () => selectLoginMethod(provider)
2636
2660
  }, t(provider === "github" ? "githubLogin" : "zhihuLogin")), selectHost = async (host) => {
2637
- setBusy(!0), setError(void 0), setCodexWorkspaces([]), setShowAllCodexWorkspaces(!1);
2661
+ setBusy(!0), setError(void 0), setCodexWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1);
2638
2662
  try {
2639
- let result = await runRemoteProgress(
2640
- connectHostProgressSteps(status?.preferredTransports),
2663
+ let result = await runConnectHostProgress(
2664
+ status?.preferredTransports,
2665
+ host.deviceId,
2666
+ props.control,
2667
+ { label: "remoteProgressLoadingWorkspaces", detail: "remoteProgressLoadingWorkspacesDetail" },
2641
2668
  setProgress,
2642
2669
  progressRun,
2643
2670
  async () => {
@@ -2673,7 +2700,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
2673
2700
  }
2674
2701
  }
2675
2702
  }, startAddingWorkspace = (backend) => {
2676
- setAddingWorkspace(!0), setWorkspaceBackend(backend), setCodexWorkspaceId(void 0), setShowAllCodexWorkspaces(!1), setDirectory(void 0), setPath(""), browseDirectory();
2703
+ setAddingWorkspace(!0), setWorkspaceBackend(backend), setCodexWorkspaceId(void 0), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setDirectory(void 0), setPath(""), browseDirectory();
2677
2704
  }, cancelAddingWorkspace = () => {
2678
2705
  setAddingWorkspace(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setDirectory(void 0), setPath("");
2679
2706
  }, refreshRemote = async () => {
@@ -2681,17 +2708,17 @@ Minimum version required to store current data is: ` + bestVersion + `.
2681
2708
  try {
2682
2709
  let nextStatus = await props.control("status");
2683
2710
  if (setStatus(nextStatus), !nextStatus.available) {
2684
- setDevices([]), setNeedsAuthorization(!1), setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setShowAllCodexWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
2711
+ setDevices([]), setNeedsAuthorization(!1), setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
2685
2712
  return;
2686
2713
  }
2687
2714
  try {
2688
2715
  let nextDevices = await props.control("devices");
2689
2716
  if (setDevices(nextDevices), setNeedsAuthorization(!1), selectedHost !== void 0) {
2690
2717
  let nextSelectedHost = nextDevices.find((device) => device.deviceId === selectedHost.deviceId);
2691
- nextSelectedHost === void 0 ? (setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setShowAllCodexWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0)) : setSelectedHost(nextSelectedHost);
2718
+ nextSelectedHost === void 0 ? (setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0)) : setSelectedHost(nextSelectedHost);
2692
2719
  }
2693
2720
  } catch {
2694
- setDevices([]), setNeedsAuthorization(!0), setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setShowAllCodexWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
2721
+ setDevices([]), setNeedsAuthorization(!0), setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
2695
2722
  }
2696
2723
  } catch (reason) {
2697
2724
  setError(messageOf(reason));
@@ -2699,7 +2726,9 @@ Minimum version required to store current data is: ` + bestVersion + `.
2699
2726
  setBusy(!1);
2700
2727
  }
2701
2728
  }, show = async () => {
2702
- setShowAllCodexWorkspaces(!1), setOpen(!0), await refreshRemote();
2729
+ setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setOpen(!0), await refreshRemote();
2730
+ }, chooseAnotherHost = () => {
2731
+ setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setDirectory(void 0), setPath(""), setAddingWorkspace(!1), setError(void 0);
2703
2732
  }, signInClient = async () => {
2704
2733
  if (!(email.trim() === "" || password === "")) {
2705
2734
  setBusy(!0), setError(void 0);
@@ -2736,32 +2765,31 @@ Minimum version required to store current data is: ` + bestVersion + `.
2736
2765
  } finally {
2737
2766
  setBusy(!1);
2738
2767
  }
2739
- }, openWorkspace = async () => {
2740
- if (!(selectedHost === void 0 || path.trim() === "" || !addingWorkspace && workspaceBackend === "codex" && codexWorkspaceId === void 0)) {
2768
+ }, openWorkspace = async (selection) => {
2769
+ let targetBackend = selection?.backend ?? workspaceBackend, targetPath = (selection?.path ?? path).trim(), targetCodexWorkspaceId = selection?.backend === "codex" ? selection.workspaceId : selection === void 0 ? codexWorkspaceId : void 0, createWorkspace = selection === void 0 && addingWorkspace;
2770
+ if (!(selectedHost === void 0 || targetPath === "" || !createWorkspace && targetBackend === "codex" && targetCodexWorkspaceId === void 0)) {
2741
2771
  setBusy(!0), setError(void 0);
2742
2772
  try {
2743
- let nextStatus = await runRemoteProgress(
2744
- openWorkspaceProgressSteps,
2745
- setProgress,
2746
- progressRun,
2747
- () => workspaceBackend === "codex" ? addingWorkspace ? props.control("codex.workspace.create", {
2748
- targetDeviceId: selectedHost.deviceId,
2749
- path: path.trim()
2750
- }) : props.control("codex.workspace.open", {
2751
- targetDeviceId: selectedHost.deviceId,
2752
- workspaceId: codexWorkspaceId
2753
- }) : props.control("workspace.open", {
2754
- targetDeviceId: selectedHost.deviceId,
2755
- path: path.trim()
2756
- }),
2757
- connectedProgress
2758
- );
2773
+ let nextStatus = await (targetBackend === "codex" ? createWorkspace ? props.control("codex.workspace.create", {
2774
+ targetDeviceId: selectedHost.deviceId,
2775
+ path: targetPath
2776
+ }) : props.control("codex.workspace.open", {
2777
+ targetDeviceId: selectedHost.deviceId,
2778
+ workspaceId: targetCodexWorkspaceId
2779
+ }) : props.control("workspace.open", {
2780
+ targetDeviceId: selectedHost.deviceId,
2781
+ path: targetPath
2782
+ }));
2759
2783
  setStatus(nextStatus), nextStatus.workspaceSelection !== void 0 && window.sessionStorage.setItem(pendingWorkspaceSelectionKey, JSON.stringify(nextStatus.workspaceSelection)), window.location.reload();
2760
2784
  } catch (reason) {
2761
2785
  setError(messageOf(reason)), setBusy(!1);
2762
2786
  }
2763
2787
  }
2764
- }, remoteLabel = status?.mode === "remote" ? t("activeRemote", { name: status.target?.name ?? t("host") }) : t("remoteEntry"), visibleCodexWorkspaces = showAllCodexWorkspaces ? codexWorkspaces : codexWorkspaces.slice(0, 3), codexAvailable = status?.remoteFeatures?.codex === !0;
2788
+ }, remoteLabel = status?.mode === "remote" ? t("activeRemote", { name: status.target?.name ?? t("host") }) : t("remoteEntry"), visibleWorkspaces = showAllWorkspaces ? workspaces : workspaces.slice(0, 3), visibleCodexWorkspaces = showAllCodexWorkspaces ? codexWorkspaces : codexWorkspaces.slice(0, 3), codexAvailable = status?.remoteFeatures?.codex === !0, selectedHostDetails = selectedHost === void 0 ? void 0 : [
2789
+ formatPlatform(selectedHost.platform),
2790
+ selectedHost.harnessVersion === void 0 ? void 0 : t("harnessVersion", { version: selectedHost.harnessVersion }),
2791
+ selectedHost.clientVersion === void 0 ? void 0 : t("pluginVersion", { version: selectedHost.clientVersion })
2792
+ ].filter(Boolean).join(" \xB7 ");
2765
2793
  return React.createElement(
2766
2794
  React.Fragment,
2767
2795
  null,
@@ -2803,19 +2831,31 @@ Minimum version required to store current data is: ` + bestVersion + `.
2803
2831
  }
2804
2832
  }, React.createElement(
2805
2833
  "section",
2806
- { className: "dshRemotePage", role: "dialog", "aria-modal": !0, "aria-label": t("remoteTitle") },
2834
+ {
2835
+ className: `dshRemotePage${selectedHost === void 0 ? "" : " hasSelectedHost"}`,
2836
+ role: "dialog",
2837
+ "aria-modal": !0,
2838
+ "aria-label": selectedHost?.name ?? t("remoteTitle")
2839
+ },
2807
2840
  React.createElement(
2808
2841
  "header",
2809
2842
  { className: "dshRemotePageHeader" },
2810
2843
  React.createElement(
2811
2844
  "div",
2812
2845
  { className: "dshRemotePageIntro" },
2813
- React.createElement("strong", null, t("remoteTitle")),
2814
- React.createElement("p", null, t("remoteDescription"))
2846
+ React.createElement("strong", null, selectedHost?.name ?? t("remoteTitle")),
2847
+ React.createElement("p", null, selectedHostDetails ?? t("remoteDescription"))
2815
2848
  ),
2816
2849
  React.createElement(
2817
2850
  "div",
2818
2851
  { className: "dshRemotePageActions" },
2852
+ selectedHost === void 0 ? null : React.createElement("button", {
2853
+ type: "button",
2854
+ className: "dshRemotePageBack",
2855
+ disabled: busy,
2856
+ title: t("backToHosts"),
2857
+ onClick: chooseAnotherHost
2858
+ }, t("backToHosts")),
2819
2859
  React.createElement("button", {
2820
2860
  type: "button",
2821
2861
  className: "dshRemotePageRefresh",
@@ -2824,7 +2864,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
2824
2864
  "aria-label": t("refreshRemote"),
2825
2865
  onClick: () => void refreshRemote()
2826
2866
  }, t("refreshRemoteShort")),
2827
- React.createElement("button", { type: "button", onClick: () => setOpen(!1), "aria-label": t("close") }, "\xD7")
2867
+ React.createElement("button", { type: "button", className: "dshRemotePageClose", onClick: () => setOpen(!1), "aria-label": t("close") }, "\xD7")
2828
2868
  )
2829
2869
  ),
2830
2870
  React.createElement(
@@ -2942,7 +2982,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
2942
2982
  needsAuthorization ? null : React.createElement(
2943
2983
  React.Fragment,
2944
2984
  null,
2945
- React.createElement(
2985
+ selectedHost === void 0 ? React.createElement(
2946
2986
  "section",
2947
2987
  { className: "dshRemoteHosts", "aria-label": t("chooseHost") },
2948
2988
  React.createElement(
@@ -2971,19 +3011,9 @@ Minimum version required to store current data is: ` + bestVersion + `.
2971
3011
  disabled: busy,
2972
3012
  onClick: () => void logoutRemote()
2973
3013
  }, t("exitRemoteAccount"))
2974
- ),
2975
- selectedHost === void 0 ? null : React.createElement(
2976
- "div",
2977
- { className: "dshRemoteSectionActions" },
2978
- React.createElement("button", {
2979
- type: "button",
2980
- onClick: () => {
2981
- setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setShowAllCodexWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setDirectory(void 0), setPath(""), setAddingWorkspace(!1), setError(void 0);
2982
- }
2983
- }, t("backToHosts"))
2984
3014
  )
2985
3015
  ),
2986
- selectedHost === void 0 ? React.createElement("div", { className: "dshRemoteHostList" }, devices.length === 0 ? React.createElement("p", null, t(busy ? "checkingConnection" : "noRemoteHosts")) : devices.map((device) => React.createElement(
3016
+ React.createElement("div", { className: "dshRemoteHostList" }, devices.length === 0 ? React.createElement("p", null, t(busy ? "checkingConnection" : "noRemoteHosts")) : devices.map((device) => React.createElement(
2987
3017
  "button",
2988
3018
  {
2989
3019
  type: "button",
@@ -3002,13 +3032,8 @@ Minimum version required to store current data is: ` + bestVersion + `.
3002
3032
  ].filter(Boolean).join(" \xB7 "))
3003
3033
  ),
3004
3034
  React.createElement("small", null, t(device.online ? "online" : "offline"))
3005
- ))) : React.createElement(
3006
- "div",
3007
- { className: "dshRemoteSelectedHost" },
3008
- React.createElement("span", null, selectedHost.name),
3009
- React.createElement("small", null, [formatPlatform(selectedHost.platform), t("online")].join(" \xB7 "))
3010
- )
3011
- ),
3035
+ )))
3036
+ ) : null,
3012
3037
  React.createElement(RemoteProgressView, { progress, t }),
3013
3038
  selectedHost === void 0 ? React.createElement("p", { className: "dshRemoteHint" }, t("selectHostHint")) : React.createElement(
3014
3039
  "section",
@@ -3066,22 +3091,35 @@ Minimum version required to store current data is: ` + bestVersion + `.
3066
3091
  React.createElement(
3067
3092
  "div",
3068
3093
  { className: "dshRemoteWorkspaceLists" },
3069
- React.createElement("div", { className: "dshRemoteDirectoryList" }, workspaces.length === 0 ? React.createElement("p", null, t("noRemoteWorkspaces")) : workspaces.map((workspace) => React.createElement(
3070
- "button",
3071
- {
3094
+ React.createElement(
3095
+ "div",
3096
+ { id: workspaceListId, className: "dshRemoteDirectoryList" },
3097
+ workspaces.length === 0 ? React.createElement("p", null, t("noRemoteWorkspaces")) : visibleWorkspaces.map((workspace) => React.createElement(
3098
+ "button",
3099
+ {
3100
+ type: "button",
3101
+ key: workspace.workspaceId,
3102
+ disabled: busy,
3103
+ className: workspaceBackend === "harness" && path === workspace.path ? "isSelected" : "",
3104
+ "aria-pressed": workspaceBackend === "harness" && path === workspace.path,
3105
+ onClick: () => {
3106
+ setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(workspace.path);
3107
+ },
3108
+ onDoubleClick: () => void openWorkspace({ backend: "harness", path: workspace.path })
3109
+ },
3110
+ React.createElement("img", { className: "dshRemoteWorkspaceIcon", src: deepSeekWorkspaceIcon, alt: "", "aria-hidden": !0 }),
3111
+ React.createElement("span", null, workspace.title),
3112
+ React.createElement("small", null, workspace.path)
3113
+ )),
3114
+ workspaces.length <= 3 || showAllWorkspaces ? null : React.createElement("button", {
3072
3115
  type: "button",
3073
- key: workspace.workspaceId,
3116
+ className: "dshRemoteWorkspaceMore",
3074
3117
  disabled: busy,
3075
- className: workspaceBackend === "harness" && path === workspace.path ? "isSelected" : "",
3076
- "aria-pressed": workspaceBackend === "harness" && path === workspace.path,
3077
- onClick: () => {
3078
- setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(workspace.path);
3079
- }
3080
- },
3081
- React.createElement("span", { "aria-hidden": !0 }, "\u25B1"),
3082
- React.createElement("span", null, workspace.title),
3083
- React.createElement("small", null, workspace.path)
3084
- )))
3118
+ "aria-controls": workspaceListId,
3119
+ "aria-label": t("showAllWorkspaces"),
3120
+ onClick: () => setShowAllWorkspaces(!0)
3121
+ }, React.createElement("span", { "aria-hidden": !0 }, "\u2026"))
3122
+ )
3085
3123
  ),
3086
3124
  !codexAvailable && codexWorkspaces.length === 0 ? null : React.createElement(
3087
3125
  "section",
@@ -3125,20 +3163,25 @@ Minimum version required to store current data is: ` + bestVersion + `.
3125
3163
  "aria-pressed": workspaceBackend === "codex" && codexWorkspaceId === workspace.workspaceId,
3126
3164
  onClick: () => {
3127
3165
  setWorkspaceBackend("codex"), setCodexWorkspaceId(workspace.workspaceId), setPath(workspace.path);
3128
- }
3166
+ },
3167
+ onDoubleClick: () => void openWorkspace({
3168
+ backend: "codex",
3169
+ path: workspace.path,
3170
+ workspaceId: workspace.workspaceId
3171
+ })
3129
3172
  },
3130
- React.createElement("span", { className: "dshRemoteCodexMark", "aria-hidden": !0 }, "C"),
3173
+ React.createElement("img", { className: "dshRemoteWorkspaceIcon isGpt", src: gptWorkspaceIcon, alt: "", "aria-hidden": !0 }),
3131
3174
  React.createElement("span", null, workspace.title),
3132
3175
  React.createElement("small", null, `${workspace.path} \xB7 ${workspace.sessionCount}`)
3133
3176
  ))),
3134
3177
  codexWorkspaces.length <= 3 || showAllCodexWorkspaces ? null : React.createElement("button", {
3135
3178
  type: "button",
3136
- className: "dshRemoteCodexWorkspaceMore",
3179
+ className: "dshRemoteWorkspaceMore",
3137
3180
  disabled: busy,
3138
3181
  "aria-controls": codexWorkspaceListId,
3139
3182
  "aria-label": t("showAllCodexWorkspaces"),
3140
3183
  onClick: () => setShowAllCodexWorkspaces(!0)
3141
- }, "\u2026")
3184
+ }, React.createElement("span", { "aria-hidden": !0 }, "\u2026"))
3142
3185
  )
3143
3186
  ),
3144
3187
  React.createElement(
@@ -3186,8 +3229,11 @@ Minimum version required to store current data is: ` + bestVersion + `.
3186
3229
  setBusy(!0), setError(void 0);
3187
3230
  try {
3188
3231
  let action = () => props.control("mode.set", { mode, ...targetDeviceId === void 0 ? {} : { targetDeviceId } });
3189
- setStatus(mode === "remote" ? await runRemoteProgress(
3190
- connectHostProgressSteps(status?.preferredTransports),
3232
+ setStatus(mode === "remote" && targetDeviceId !== void 0 ? await runConnectHostProgress(
3233
+ status?.preferredTransports,
3234
+ targetDeviceId,
3235
+ props.control,
3236
+ { label: "remoteProgressSwitchingWorkspace", detail: "remoteProgressSwitchingWorkspaceDetail" },
3191
3237
  setProgress,
3192
3238
  progressRun,
3193
3239
  action,
@@ -3501,17 +3547,16 @@ Minimum version required to store current data is: ` + bestVersion + `.
3501
3547
  ".dshRemoteSessionHeader{left:auto;right:148px;transform:none;max-width:calc(100vw - 420px)}@media(max-width:760px){.dshRemoteSessionHeader{left:auto;right:104px;transform:none;max-width:calc(100vw - 124px)}}",
3502
3548
  ".dshRemoteModeButton:focus-visible,.dshRemotePage button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}",
3503
3549
  ".dshRemotePage{width:min(720px,100%);max-height:min(760px,calc(100vh - 40px));display:flex;flex-direction:column;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border-radius:14px;overflow:hidden;animation:dshRemotePageIn .18s cubic-bezier(.25,1,.5,1)}",
3504
- ".dshRemotePageHeader{min-height:72px;display:flex;align-items:center;justify-content:space-between;gap:24px;padding:14px 24px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dshRemotePageIntro{min-width:0;flex:1}.dshRemotePageHeader strong{display:block;font-size:18px;line-height:1.4}.dshRemotePageHeader p{min-width:0;max-width:70ch;margin:3px 0 0;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:1.5}.dshRemotePageActions{flex:0 0 auto;display:flex;align-items:center;gap:4px}.dshRemotePageActions>button{height:40px;display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;border:0;border-radius:8px;background:transparent;color:inherit;line-height:1;cursor:pointer}.dshRemotePageActions>button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.dshRemotePageActions>button:disabled{opacity:.45;cursor:default}.dshRemotePageRefresh{min-width:48px;padding:0 10px;font:inherit;font-size:13px}.dshRemotePageActions>button:not(.dshRemotePageRefresh){width:40px;padding:0;font-size:24px}",
3550
+ ".dshRemotePageHeader{min-height:72px;display:flex;align-items:center;justify-content:space-between;gap:24px;padding:14px 24px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dshRemotePageIntro{min-width:0;flex:1}.dshRemotePageHeader strong{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:18px;line-height:1.4}.dshRemotePageHeader p{min-width:0;max-width:70ch;margin:3px 0 0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:1.5}.dshRemotePageActions{flex:0 0 auto;display:flex;align-items:center;gap:4px}.dshRemotePageActions>button{height:40px;display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;border:0;border-radius:8px;background:transparent;color:inherit;line-height:1;cursor:pointer}.dshRemotePageActions>button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.dshRemotePageActions>button:disabled{opacity:.45;cursor:default}.dshRemotePageBack,.dshRemotePageRefresh{min-width:48px;padding:0 10px;font:inherit;font-size:13px}.dshRemotePageBack{color:var(--dsw-alias-label-secondary)!important}.dshRemotePageClose{width:40px;padding:0;font-size:24px}",
3505
3551
  ".dshRemotePageBody{padding:24px;overflow:auto;display:flex;flex-direction:column;gap:24px}.dshRemotePageBody button{font:inherit;color:inherit}",
3506
3552
  ".dshRemoteSectionHeading{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:10px}.dshRemoteSectionTitle{min-width:0;display:flex;align-items:center;gap:10px}.dshRemoteSectionTitle>strong{font-size:14px}.dshRemoteSectionActions{display:flex;align-items:center;gap:14px}.dshRemoteSectionActions>button{border:0;background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer;padding:5px 0;font-size:12px}.dshRemoteSectionActions>button:hover:not(:disabled){color:var(--dsw-alias-label-primary);text-decoration:underline}",
3507
3553
  ".dshRemoteCancelWorkspace{min-height:36px;border:0;background:transparent;color:var(--dsw-alias-label-secondary);padding:6px 0;cursor:pointer}.dshRemoteCancelWorkspace:hover:not(:disabled){color:var(--dsw-alias-label-primary);text-decoration:underline}.dshRemoteCancelWorkspace:disabled{opacity:.5;cursor:default}",
3508
- ".dshRemoteHostList{display:flex;flex-direction:column;border-top:1px solid var(--dsw-alias-border-l2)}.dshRemoteHostList>button{min-height:58px;display:flex;align-items:center;justify-content:space-between;gap:16px;text-align:left;border:0;border-bottom:1px solid var(--dsw-alias-border-l2);background:transparent;padding:10px 4px;cursor:pointer}.dshRemoteHostList>button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.dshRemoteHostList>button:disabled{opacity:.5;cursor:default}.dshRemoteHostList>button>span{min-width:0;display:flex;flex-direction:column;gap:3px}.dshRemoteHostList>button strong{font-size:14px;font-weight:500}.dshRemoteHostList small,.dshRemoteSelectedHost small{color:var(--dsw-alias-label-secondary);font-size:12px}",
3509
- ".dshRemoteSelectedHost{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 14px;border-radius:10px;background:var(--dsw-alias-bg-layer-2)}",
3554
+ ".dshRemoteHostList{display:flex;flex-direction:column;border-top:1px solid var(--dsw-alias-border-l2)}.dshRemoteHostList>button{min-height:58px;display:flex;align-items:center;justify-content:space-between;gap:16px;text-align:left;border:0;border-bottom:1px solid var(--dsw-alias-border-l2);background:transparent;padding:10px 4px;cursor:pointer}.dshRemoteHostList>button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.dshRemoteHostList>button:disabled{opacity:.5;cursor:default}.dshRemoteHostList>button>span{min-width:0;display:flex;flex-direction:column;gap:3px}.dshRemoteHostList>button strong{font-size:14px;font-weight:500}.dshRemoteHostList small{color:var(--dsw-alias-label-secondary);font-size:12px}",
3510
3555
  '.dshRemoteProgress{display:flex;flex-direction:column;gap:8px;margin:12px 0;padding:12px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-layer-2)}.dshRemoteProgressHeader{display:flex;align-items:center;justify-content:space-between;gap:12px}.dshRemoteProgressHeader strong{font-size:13px;font-weight:600}.dshRemoteProgressHeader span{color:var(--dsw-alias-label-secondary);font-size:12px}.dshRemoteProgressBar{height:6px;overflow:hidden;border-radius:999px;background:var(--dsw-alias-bg-layer-3)}.dshRemoteProgressBar>span{display:block;width:100%;height:100%;border-radius:inherit;background:var(--dsw-alias-brand-primary);transform-origin:left center;transition:transform .22s ease-out}[dir="rtl"] .dshRemoteProgressBar>span{transform-origin:right center}.dshRemoteProgress p{margin:0;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.45}.dshRemoteProgressRoute{font-weight:500}.dshRemoteProgressRoute .isActive{color:var(--dsw-alias-state-success-primary);font-weight:700}.dshRemoteProgressRouteArrow{color:var(--dsw-alias-label-tertiary)}@media(prefers-reduced-motion:reduce){.dshRemoteProgressBar>span{transition:none}}',
3511
3556
  '.dshRemoteBrowser{display:flex;flex-direction:column}.dshRemoteCrumbs{display:flex;align-items:center;gap:4px;overflow:auto;padding:2px 0 10px}.dshRemoteCrumbs>button{flex:0 0 auto;border:0;background:transparent;color:var(--dsw-alias-label-secondary);padding:5px 7px;border-radius:6px;cursor:pointer}.dshRemoteCrumbs>button:not(:last-child)::after{content:" /";color:var(--dsw-alias-label-tertiary)}.dshRemoteCrumbs>button:disabled{color:var(--dsw-alias-label-primary);font-weight:600}',
3512
- ".dshRemoteWorkspaceLists{max-height:min(360px,42vh);overflow-y:auto;overscroll-behavior:contain;scrollbar-gutter:stable;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-label-tertiary) transparent}.dshRemoteWorkspaceLists::-webkit-scrollbar{width:8px}.dshRemoteWorkspaceLists::-webkit-scrollbar-thumb{border:2px solid transparent;border-radius:8px;background:var(--dsw-alias-label-tertiary);background-clip:padding-box}.dshRemoteWorkspaceLists::-webkit-scrollbar-track{background:transparent}",
3513
- ".dshRemoteDirectoryList{min-height:72px;display:flex;flex-direction:column;border-top:1px solid var(--dsw-alias-border-l2)}.dshRemoteDirectoryList>button{min-height:52px;display:grid;grid-template-columns:auto minmax(0,1fr);column-gap:10px;text-align:left;border:0;border-bottom:1px solid var(--dsw-alias-border-l2);background:transparent;padding:8px 4px;cursor:pointer}.dshRemoteDirectoryList>button:hover,.dshRemoteDirectoryList>button.isSelected{background:var(--dsw-alias-interactive-bg-hover)}.dshRemoteDirectoryList>button.isSelected{color:var(--dsw-alias-label-primary)}.dshRemoteDirectoryList>button>span:first-child{grid-row:1/3}.dshRemoteDirectoryList>button>span:not(:first-child),.dshRemoteDirectoryList>button>small{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dshRemoteDirectoryList>button>small{grid-column:2;color:var(--dsw-alias-label-secondary)}.dshRemoteDirectoryList>p,.dshRemoteHint{margin:12px 0;color:var(--dsw-alias-label-secondary);font-size:13px}",
3514
- ".dshRemoteAddWorkspace{box-sizing:border-box;width:40px;height:40px;display:inline-grid;place-items:center;flex:0 0 auto;border:0;border-radius:8px;background:transparent;color:var(--dsw-alias-label-secondary);padding:0;cursor:pointer}.dshRemoteAddWorkspace:hover:not(:disabled){color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.dshRemoteAddWorkspace:disabled{opacity:.5;cursor:default}.dshRemoteAddWorkspaceIcon{width:20px;height:20px}.dshRemoteCodexWorkspaceGroup{margin-top:16px}.dshRemoteWorkspaceSourceHeading{min-height:44px;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 4px 7px}.dshRemoteWorkspaceSourceText{min-width:0;display:flex;flex-direction:column;gap:2px}.dshRemoteWorkspaceSourceText>strong{font-size:13px}.dshRemoteWorkspaceSourceText>small{color:var(--dsw-alias-label-secondary);font-size:11px}.dshRemoteCodexWorkspaceList{min-height:0;max-height:min(260px,32vh);overflow-y:auto;overscroll-behavior:contain}.dshRemoteCodexWorkspaceMore{width:100%;min-height:48px;border:0;border-bottom:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-secondary);padding:8px 4px;text-align:center;font-size:12px;cursor:pointer}.dshRemoteCodexWorkspaceMore:hover:not(:disabled){color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.dshRemoteCodexWorkspaceMore:disabled{opacity:.5;cursor:default}.dshRemoteCodexMark{box-sizing:border-box;width:22px;height:22px;display:grid;place-items:center;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;color:var(--dsw-alias-label-primary);font-size:11px;font-weight:650}",
3557
+ ".dshRemoteWorkspaceLists{overflow:visible}",
3558
+ ".dshRemoteDirectoryList{min-height:72px;display:flex;flex-direction:column;border-top:1px solid var(--dsw-alias-border-l2)}.dshRemoteDirectoryList>button{min-height:52px;display:grid;grid-template-columns:auto minmax(0,1fr);column-gap:10px;text-align:left;border:0;border-bottom:1px solid var(--dsw-alias-border-l2);background:transparent;padding:8px 4px;cursor:pointer}.dshRemoteDirectoryList>button:hover,.dshRemoteDirectoryList>button.isSelected{background:var(--dsw-alias-interactive-bg-hover)}.dshRemoteDirectoryList>button.isSelected{color:var(--dsw-alias-label-primary)}.dshRemoteDirectoryList>button>span:first-child,.dshRemoteDirectoryList>button>.dshRemoteWorkspaceIcon{grid-row:1/3}.dshRemoteWorkspaceIcon{box-sizing:border-box;width:22px;height:22px;align-self:center;object-fit:contain}.dshRemoteWorkspaceIcon.isGpt{border-radius:6px}.dshRemoteDirectoryList>button>span:not(:first-child),.dshRemoteDirectoryList>button>small{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dshRemoteDirectoryList>button>small{grid-column:2;color:var(--dsw-alias-label-secondary)}.dshRemoteDirectoryList>p,.dshRemoteHint{margin:12px 0;color:var(--dsw-alias-label-secondary);font-size:13px}",
3559
+ ".dshRemoteAddWorkspace{box-sizing:border-box;width:40px;height:40px;display:inline-grid;place-items:center;flex:0 0 auto;border:0;border-radius:8px;background:transparent;color:var(--dsw-alias-label-secondary);padding:0;cursor:pointer}.dshRemoteAddWorkspace:hover:not(:disabled){color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}.dshRemoteAddWorkspace:disabled{opacity:.5;cursor:default}.dshRemoteAddWorkspaceIcon{width:20px;height:20px}.dshRemoteCodexWorkspaceGroup{margin-top:16px}.dshRemoteWorkspaceSourceHeading{min-height:44px;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 4px 7px}.dshRemoteWorkspaceSourceText{min-width:0;display:flex;flex-direction:column;gap:2px}.dshRemoteWorkspaceSourceText>strong{font-size:13px}.dshRemoteWorkspaceSourceText>small{color:var(--dsw-alias-label-secondary);font-size:11px}.dshRemoteCodexWorkspaceList{min-height:0}.dshRemoteDirectoryList>.dshRemoteWorkspaceMore,.dshRemoteCodexWorkspaceGroup>.dshRemoteWorkspaceMore{box-sizing:border-box;width:100%;min-height:48px;display:flex;align-items:center;justify-content:center;border:0;border-bottom:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-secondary);padding:8px 4px;text-align:center;font-size:16px;cursor:pointer}.dshRemoteWorkspaceMore>span{display:block;line-height:1;transform:translateY(-2px)}.dshRemoteWorkspaceMore:hover:not(:disabled){color:var(--dsw-alias-label-primary);background:transparent}.dshRemoteWorkspaceMore:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.dshRemoteWorkspaceMore:disabled{opacity:.5;cursor:default}",
3515
3560
  ".dshRemoteFolderBrowser{margin-top:14px}.dshRemoteFolderBrowser>p,.dshRemoteFolderList>p{margin:12px 0;color:var(--dsw-alias-label-secondary);font-size:13px}.dshRemoteFolderList{max-height:260px;overflow:auto;border-block:1px solid var(--dsw-alias-border-l2)}.dshRemoteFolderList>button{width:100%;min-height:42px;display:flex;align-items:center;gap:9px;border:0;border-bottom:1px solid var(--dsw-alias-border-l2);background:transparent;padding:7px 6px;text-align:left;cursor:pointer}.dshRemoteFolderList>button:hover{background:var(--dsw-alias-interactive-bg-hover)}.dshRemoteFolderBrowser>small{display:block;margin-top:8px;color:var(--dsw-alias-state-warn-label)}",
3516
3561
  ".dshRemotePathField{display:flex;flex-direction:column;gap:6px;margin-top:20px}.dshRemotePathField>span{font-size:13px;font-weight:600}.dshRemotePathField>input{min-height:40px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-3);color:inherit;padding:0 12px;font:inherit}.dshRemotePathField>small{color:var(--dsw-alias-label-secondary)}",
3517
3562
  ".dshRemoteOpenBar{position:sticky;bottom:-96px;display:flex;align-items:center;justify-content:space-between;gap:20px;margin-top:20px;padding:14px 0;background:var(--dsw-alias-bg-layer-1);border-top:1px solid var(--dsw-alias-border-l2)}.dshRemoteOpenBar>div{min-width:0;display:flex;flex-direction:column;gap:3px}.dshRemoteOpenBar span{color:var(--dsw-alias-label-secondary);font-size:12px}.dshRemoteOpenBar strong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:13px}.dshRemoteOpenBar>button,.dshRemoteEnable>button{min-height:40px;flex:0 0 auto;border:0;border-radius:8px;background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-1);padding:8px 16px;cursor:pointer}.dshRemoteOpenBar>button:disabled,.dshRemoteEnable>button:disabled{opacity:.5;cursor:default}",
@@ -3523,7 +3568,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
3523
3568
  '.dshRemoteHostControlToggle{display:flex;align-items:center;gap:7px;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px;white-space:nowrap;cursor:default}.dshRemoteHostControlToggle>input{appearance:none;box-sizing:border-box;position:relative;width:32px;height:18px;flex:0 0 auto;margin:0;border:1px solid var(--dsw-alias-label-secondary);border-radius:999px;background:var(--dsw-alias-bg-layer-3);cursor:pointer;box-shadow:inset 0 0 0 1px var(--dsw-alias-border-l2);transition:background .16s ease-out,border-color .16s ease-out,box-shadow .16s ease-out}.dshRemoteHostControlToggle>input::after{content:"";position:absolute;top:2px;left:2px;width:12px;height:12px;border-radius:50%;background:var(--dsw-alias-label-secondary);transition:transform .16s ease-out,background .16s ease-out}.dshRemoteHostControlToggle>input:checked{border-color:var(--dsw-alias-state-success-primary);background:var(--dsw-alias-state-success-primary);box-shadow:none}.dshRemoteHostControlToggle>input:checked::after{transform:translateX(14px);background:var(--dsw-alias-bg-layer-1)}.dshRemoteHostControlToggle>input:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.dshRemoteHostControlToggle>input:disabled{opacity:.5;cursor:default}@media(prefers-reduced-motion:reduce){.dshRemoteHostControlToggle>input,.dshRemoteHostControlToggle>input::after{transition:none}}',
3524
3569
  ".dshRemoteAccountExit{flex:0 0 auto;border:0;background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer;padding:5px 0;font-size:12px;line-height:1.5;white-space:nowrap}.dshRemoteAccountExit:hover:not(:disabled){color:var(--dsw-alias-label-primary);text-decoration:underline}.dshRemoteAccountExit:disabled{opacity:.5;cursor:default;text-decoration:none}",
3525
3570
  ".dshRemoteLocalLink{align-self:flex-start;border:0;background:transparent;color:var(--dsw-alias-label-secondary);padding:4px 0;cursor:pointer}.dshRemoteLocalLink:hover{color:var(--dsw-alias-label-primary)}",
3526
- "@keyframes dshRemotePageIn{from{opacity:0;transform:translateY(6px) scale(.99)}to{opacity:1;transform:none}}@media(prefers-reduced-motion:reduce){.dshRemotePage{animation:none}}@media(max-width:620px){.dshRemoteBackdrop{padding:12px}.dshRemotePage{max-height:calc(100vh - 24px)}.dshRemotePageHeader{padding:12px 16px}.dshRemoteSectionHeading{align-items:flex-start;flex-direction:column;gap:8px}.dshRemoteWorkspaceHeading{align-items:center;flex-direction:row}.dshRemoteSectionActions{width:100%;justify-content:space-between}.dshRemotePageBody{padding:20px 16px}.dshRemoteOpenBar{align-items:flex-end}.dshRemoteOpenBar>button{min-height:48px}}",
3571
+ "@keyframes dshRemotePageIn{from{opacity:0;transform:translateY(6px) scale(.99)}to{opacity:1;transform:none}}@media(prefers-reduced-motion:reduce){.dshRemotePage{animation:none}}@media(max-width:620px){.dshRemoteBackdrop{padding:12px}.dshRemotePage{max-height:calc(100vh - 24px)}.dshRemotePageHeader{gap:8px;padding:12px 16px}.dshRemotePage.hasSelectedHost .dshRemotePageBack{max-width:112px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dshRemoteSectionHeading{align-items:flex-start;flex-direction:column;gap:8px}.dshRemoteWorkspaceHeading{align-items:center;flex-direction:row}.dshRemoteSectionActions{width:100%;justify-content:space-between}.dshRemotePageBody{padding:20px 16px}.dshRemoteOpenBar{align-items:flex-end}.dshRemoteOpenBar>button{min-height:48px}}",
3527
3572
  ".dshRemoteBackdrop{position:fixed;inset:0;z-index:1000;background:var(--dsw-alias-bg-mask-3);display:grid;place-items:center;padding:20px}",
3528
3573
  ".dshRemoteDialog{width:min(460px,100%);max-height:80vh;overflow:auto;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l2);border-radius:14px;padding:18px;display:grid;gap:12px;box-shadow:var(--dsw-shadow-lv2)}",
3529
3574
  ".dshRemoteDialog button,.dshRemoteDialog input{font:inherit;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:9px 10px;background:transparent;color:inherit}",