ds-harness-remote 0.5.7 → 0.5.10
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/acp/adapter.d.ts +1 -1
- package/dist/acp/adapter.d.ts.map +1 -1
- package/dist/acp/adapters/antigravity/transcript-loader.d.ts.map +1 -1
- package/dist/acp/adapters/antigravity/transcript-loader.js +4 -1
- package/dist/acp/adapters/antigravity/transcript-loader.js.map +1 -1
- package/dist/acp/adapters/claude-history.d.ts +3 -0
- package/dist/acp/adapters/claude-history.d.ts.map +1 -0
- package/dist/acp/adapters/claude-history.js +118 -0
- package/dist/acp/adapters/claude-history.js.map +1 -0
- package/dist/acp/adapters/claude-process.d.ts +21 -0
- package/dist/acp/adapters/claude-process.d.ts.map +1 -0
- package/dist/acp/adapters/claude-process.js +147 -0
- package/dist/acp/adapters/claude-process.js.map +1 -0
- package/dist/acp/adapters/cursor-process.d.ts +9 -4
- package/dist/acp/adapters/cursor-process.d.ts.map +1 -1
- package/dist/acp/adapters/cursor-process.js +31 -3
- package/dist/acp/adapters/cursor-process.js.map +1 -1
- package/dist/acp/adapters/opencode-process.d.ts +67 -0
- package/dist/acp/adapters/opencode-process.d.ts.map +1 -0
- package/dist/acp/adapters/opencode-process.js +272 -0
- package/dist/acp/adapters/opencode-process.js.map +1 -0
- package/dist/acp/adapters/opencode.d.ts +8 -0
- package/dist/acp/adapters/opencode.d.ts.map +1 -0
- package/dist/acp/adapters/opencode.js +8 -0
- package/dist/acp/adapters/opencode.js.map +1 -0
- package/dist/acp/adapters/pi-process.d.ts +42 -0
- package/dist/acp/adapters/pi-process.d.ts.map +1 -0
- package/dist/acp/adapters/pi-process.js +410 -0
- package/dist/acp/adapters/pi-process.js.map +1 -0
- package/dist/acp/gateway.d.ts +10 -0
- package/dist/acp/gateway.d.ts.map +1 -1
- package/dist/acp/gateway.js +344 -103
- package/dist/acp/gateway.js.map +1 -1
- package/dist/acp/method-policy.d.ts +19 -19
- package/dist/acp/method-policy.js +5 -5
- package/dist/acp/method-policy.js.map +1 -1
- package/dist/acp/pi-tool-result.d.ts +9 -0
- package/dist/acp/pi-tool-result.d.ts.map +1 -0
- package/dist/acp/pi-tool-result.js +22 -0
- package/dist/acp/pi-tool-result.js.map +1 -0
- package/dist/acp/virtual-catalog.d.ts +50 -0
- package/dist/acp/virtual-catalog.d.ts.map +1 -0
- package/dist/acp/virtual-catalog.js +103 -0
- package/dist/acp/virtual-catalog.js.map +1 -0
- package/dist/acp/virtual-contract.d.ts +165 -0
- package/dist/acp/virtual-contract.d.ts.map +1 -0
- package/dist/acp/virtual-contract.js +216 -0
- package/dist/acp/virtual-contract.js.map +1 -0
- package/dist/acp/virtual-event-carrier.d.ts +50 -0
- package/dist/acp/virtual-event-carrier.d.ts.map +1 -0
- package/dist/acp/virtual-event-carrier.js +222 -0
- package/dist/acp/virtual-event-carrier.js.map +1 -0
- package/dist/acp/virtual-harness.d.ts +13 -112
- package/dist/acp/virtual-harness.d.ts.map +1 -1
- package/dist/acp/virtual-harness.js +129 -911
- package/dist/acp/virtual-harness.js.map +1 -1
- package/dist/acp/virtual-live.d.ts +78 -0
- package/dist/acp/virtual-live.d.ts.map +1 -0
- package/dist/acp/virtual-live.js +513 -0
- package/dist/acp/virtual-live.js.map +1 -0
- package/dist/acp/workspace-tools.js +2 -2
- package/dist/acp/workspace-tools.js.map +1 -1
- package/dist/acp.d.ts.map +1 -1
- package/dist/acp.js +1 -0
- package/dist/acp.js.map +1 -1
- package/dist/client/header.d.ts +10 -0
- package/dist/client/header.d.ts.map +1 -0
- package/dist/client/header.js +169 -0
- package/dist/client/header.js.map +1 -0
- package/dist/client/icons.d.ts +3 -0
- package/dist/client/icons.d.ts.map +1 -0
- package/dist/client/icons.js +3 -0
- package/dist/client/icons.js.map +1 -0
- package/dist/client/navigation.d.ts +5 -0
- package/dist/client/navigation.d.ts.map +1 -0
- package/dist/client/navigation.js +30 -0
- package/dist/client/navigation.js.map +1 -0
- package/dist/client/presentation.d.ts +17 -0
- package/dist/client/presentation.d.ts.map +1 -0
- package/dist/client/presentation.js +208 -0
- package/dist/client/presentation.js.map +1 -0
- package/dist/client/progress.d.ts +10 -0
- package/dist/client/progress.d.ts.map +1 -0
- package/dist/client/progress.js +82 -0
- package/dist/client/progress.js.map +1 -0
- package/dist/client/settings.d.ts +10 -0
- package/dist/client/settings.d.ts.map +1 -0
- package/dist/client/settings.js +335 -0
- package/dist/client/settings.js.map +1 -0
- package/dist/client/shell.d.ts +6 -0
- package/dist/client/shell.d.ts.map +1 -0
- package/dist/client/shell.js +128 -0
- package/dist/client/shell.js.map +1 -0
- package/dist/client/types.d.ts +264 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +2 -0
- package/dist/client/types.js.map +1 -0
- package/dist/client/workspaces.d.ts +11 -0
- package/dist/client/workspaces.d.ts.map +1 -0
- package/dist/client/workspaces.js +1179 -0
- package/dist/client/workspaces.js.map +1 -0
- package/dist/client-capabilities.d.ts +6 -0
- package/dist/client-capabilities.d.ts.map +1 -0
- package/dist/client-capabilities.js +88 -0
- package/dist/client-capabilities.js.map +1 -0
- package/dist/client-codex-streams.d.ts +23 -0
- package/dist/client-codex-streams.d.ts.map +1 -0
- package/dist/client-codex-streams.js +156 -0
- package/dist/client-codex-streams.js.map +1 -0
- package/dist/client-connection.d.ts +38 -0
- package/dist/client-connection.d.ts.map +1 -0
- package/dist/client-connection.js +210 -0
- package/dist/client-connection.js.map +1 -0
- package/dist/client-control.d.ts +48 -0
- package/dist/client-control.d.ts.map +1 -0
- package/dist/client-control.js +273 -0
- package/dist/client-control.js.map +1 -0
- package/dist/client-locale.d.ts +8 -0
- package/dist/client-locale.d.ts.map +1 -1
- package/dist/client-locale.js +16 -0
- package/dist/client-locale.js.map +1 -1
- package/dist/client-runtime-contract.d.ts +161 -0
- package/dist/client-runtime-contract.d.ts.map +1 -0
- package/dist/client-runtime-contract.js +127 -0
- package/dist/client-runtime-contract.js.map +1 -0
- package/dist/client-runtime.d.ts +24 -126
- package/dist/client-runtime.d.ts.map +1 -1
- package/dist/client-runtime.js +171 -867
- package/dist/client-runtime.js.map +1 -1
- package/dist/client-secure-transport.d.ts +1 -0
- package/dist/client-secure-transport.d.ts.map +1 -1
- package/dist/client-secure-transport.js +35 -16
- package/dist/client-secure-transport.js.map +1 -1
- package/dist/client-workspace-queries.d.ts +12 -0
- package/dist/client-workspace-queries.d.ts.map +1 -0
- package/dist/client-workspace-queries.js +66 -0
- package/dist/client-workspace-queries.js.map +1 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.github.js +2091 -1896
- package/dist/client.js +2091 -1896
- package/dist/client.js.map +1 -1
- package/dist/codex/domain.d.ts.map +1 -1
- package/dist/codex/domain.js +67 -46
- package/dist/codex/domain.js.map +1 -1
- package/dist/codex/method-policy.d.ts +9 -9
- package/dist/codex/virtual-catalog.d.ts +90 -0
- package/dist/codex/virtual-catalog.d.ts.map +1 -0
- package/dist/codex/virtual-catalog.js +317 -0
- package/dist/codex/virtual-catalog.js.map +1 -0
- package/dist/codex/virtual-contract.d.ts +96 -0
- package/dist/codex/virtual-contract.d.ts.map +1 -0
- package/dist/codex/virtual-contract.js +192 -0
- package/dist/codex/virtual-contract.js.map +1 -0
- package/dist/codex/virtual-event-carrier.d.ts +52 -0
- package/dist/codex/virtual-event-carrier.d.ts.map +1 -0
- package/dist/codex/virtual-event-carrier.js +212 -0
- package/dist/codex/virtual-event-carrier.js.map +1 -0
- package/dist/codex/virtual-harness.d.ts +16 -117
- package/dist/codex/virtual-harness.d.ts.map +1 -1
- package/dist/codex/virtual-harness.js +123 -1909
- package/dist/codex/virtual-harness.js.map +1 -1
- package/dist/codex/virtual-history.d.ts +74 -0
- package/dist/codex/virtual-history.d.ts.map +1 -0
- package/dist/codex/virtual-history.js +546 -0
- package/dist/codex/virtual-history.js.map +1 -0
- package/dist/codex/virtual-live.d.ts +75 -0
- package/dist/codex/virtual-live.d.ts.map +1 -0
- package/dist/codex/virtual-live.js +563 -0
- package/dist/codex/virtual-live.js.map +1 -0
- package/dist/codex/virtual-values.d.ts +29 -0
- package/dist/codex/virtual-values.d.ts.map +1 -0
- package/dist/codex/virtual-values.js +75 -0
- package/dist/codex/virtual-values.js.map +1 -0
- package/dist/config.js +4 -4
- package/dist/config.js.map +1 -1
- package/dist/control-runtime.js +2 -2
- package/dist/control-runtime.js.map +1 -1
- package/dist/harness-remote-bridge.d.ts +2 -1
- package/dist/harness-remote-bridge.d.ts.map +1 -1
- package/dist/harness-remote-bridge.js +13 -5
- package/dist/harness-remote-bridge.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23304 -15332
- package/dist/index.js.map +4 -4
- package/dist/plugin-route-dispatcher.d.ts +2 -2
- package/dist/plugin-route-dispatcher.d.ts.map +1 -1
- package/dist/plugin-route-dispatcher.js +2 -2
- package/dist/plugin-route-dispatcher.js.map +1 -1
- package/dist/remote-terminal-controller.d.ts +90 -0
- package/dist/remote-terminal-controller.d.ts.map +1 -0
- package/dist/remote-terminal-controller.js +494 -0
- package/dist/remote-terminal-controller.js.map +1 -0
- package/dist/remote-terminal-provider.d.ts +46 -0
- package/dist/remote-terminal-provider.d.ts.map +1 -0
- package/dist/remote-terminal-provider.js +147 -0
- package/dist/remote-terminal-provider.js.map +1 -0
- package/dist/remote-typert-gateway.js +7 -1
- package/dist/remote-typert-gateway.js.map +1 -1
- package/dist/server-api.d.ts +3 -0
- package/dist/server-api.d.ts.map +1 -1
- package/dist/server-api.js +24 -9
- package/dist/server-api.js.map +1 -1
- package/dist/server-connection.d.ts +1 -0
- package/dist/server-connection.d.ts.map +1 -1
- package/dist/server-connection.js +8 -1
- package/dist/server-connection.js.map +1 -1
- package/dist/service.d.ts +1 -1
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +15 -8
- package/dist/service.js.map +1 -1
- package/dist/terminal-carrier-compat.d.ts +14 -0
- package/dist/terminal-carrier-compat.d.ts.map +1 -0
- package/dist/terminal-carrier-compat.js +259 -0
- package/dist/terminal-carrier-compat.js.map +1 -0
- package/dist/terminal-policy.d.ts +6 -0
- package/dist/terminal-policy.d.ts.map +1 -1
- package/dist/terminal-policy.js +24 -6
- package/dist/terminal-policy.js.map +1 -1
- package/dist/typert-gateway-contract.d.ts +6 -1
- package/dist/typert-gateway-contract.d.ts.map +1 -1
- package/dist/typert-gateway-switch.d.ts +2 -1
- package/dist/typert-gateway-switch.d.ts.map +1 -1
- package/dist/typert-gateway-switch.js +39 -18
- package/dist/typert-gateway-switch.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/dist/workspace-bridge.d.ts +6 -89
- package/dist/workspace-bridge.d.ts.map +1 -1
- package/dist/workspace-bridge.js +37 -294
- package/dist/workspace-bridge.js.map +1 -1
- package/dsh-plugin.json +1 -1
- package/package.json +24 -20
package/dist/client.js
CHANGED
|
@@ -1619,295 +1619,6 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
1619
1619
|
}
|
|
1620
1620
|
});
|
|
1621
1621
|
|
|
1622
|
-
// src/client.ts
|
|
1623
|
-
var import_qrcode = __toESM(require_browser(), 1);
|
|
1624
|
-
|
|
1625
|
-
// src/remote-file-content-provider.ts
|
|
1626
|
-
function shouldUseRemoteFileViewer(status) {
|
|
1627
|
-
return status.mode === "remote" && status.remoteFeatures?.fileViewer === !0;
|
|
1628
|
-
}
|
|
1629
|
-
var REMOTE_FILE_SAVE_AS_MAX_BYTES = 100 * 1024 * 1024, REMOTE_FILE_FAST_SAVE_AS_MAX_BYTES = 1024 * 1024 * 1024;
|
|
1630
|
-
function shouldAllowRemoteFileSaveAs(status) {
|
|
1631
|
-
return shouldUseRemoteFileViewer(status) && (status.transport === "LAN" || status.transport === "P2P" || status.transport === "TURN");
|
|
1632
|
-
}
|
|
1633
|
-
function remoteFileSaveAsMaxBytes(status) {
|
|
1634
|
-
return status.transport === "LAN" || status.transport === "P2P" ? REMOTE_FILE_FAST_SAVE_AS_MAX_BYTES : REMOTE_FILE_SAVE_AS_MAX_BYTES;
|
|
1635
|
-
}
|
|
1636
|
-
function createRemoteFileContentProvider(call, options = {}) {
|
|
1637
|
-
return {
|
|
1638
|
-
id: "dsh-remote-files",
|
|
1639
|
-
priority: 1e4,
|
|
1640
|
-
supports: () => !0,
|
|
1641
|
-
saveAsAllowed: () => ({
|
|
1642
|
-
allowed: currentSaveAsAllowed(options.saveAsAllowed),
|
|
1643
|
-
maxBytes: currentSaveAsMaxBytes(options.saveAsMaxBytes)
|
|
1644
|
-
}),
|
|
1645
|
-
async stat(locator, signal) {
|
|
1646
|
-
let value = await call("fileviewer.stat", { path: locator }, signal);
|
|
1647
|
-
if (value.exists)
|
|
1648
|
-
return {
|
|
1649
|
-
name: value.name,
|
|
1650
|
-
size: value.isDirectory ? 0 : value.size,
|
|
1651
|
-
mime: value.mime,
|
|
1652
|
-
mtimeMs: value.mtimeMs,
|
|
1653
|
-
isDirectory: value.isDirectory
|
|
1654
|
-
};
|
|
1655
|
-
},
|
|
1656
|
-
async read(locator, request) {
|
|
1657
|
-
if (!Number.isInteger(request.offset) || request.offset < 0) throw new Error("A non-negative integer offset is required.");
|
|
1658
|
-
if (!Number.isInteger(request.length) || request.length <= 0) throw new Error("A positive integer length is required.");
|
|
1659
|
-
let chunks = [], received = 0;
|
|
1660
|
-
for (; received < request.length; ) {
|
|
1661
|
-
request.signal.throwIfAborted();
|
|
1662
|
-
let length = Math.min(524288, request.length - received), offset = request.offset + received, range = await call("fileviewer.readRange", { path: locator, offset, length }, request.signal);
|
|
1663
|
-
if (range.offset !== offset) throw new Error("The Remote Host returned a mismatched file range.");
|
|
1664
|
-
let bytes = decodeBase64(range.data);
|
|
1665
|
-
if (bytes.byteLength > length) throw new Error("The Remote Host returned more file bytes than requested.");
|
|
1666
|
-
if (chunks.push(bytes), received += bytes.byteLength, range.eof || bytes.byteLength === 0) break;
|
|
1667
|
-
}
|
|
1668
|
-
let merged = new Uint8Array(received), cursor = 0;
|
|
1669
|
-
for (let chunk of chunks)
|
|
1670
|
-
merged.set(chunk, cursor), cursor += chunk.byteLength;
|
|
1671
|
-
return merged;
|
|
1672
|
-
},
|
|
1673
|
-
async list(locator, signal) {
|
|
1674
|
-
return (await call("fileviewer.list", { path: locator }, signal)).entries.map((entry) => ({
|
|
1675
|
-
locator: entry.path,
|
|
1676
|
-
name: entry.name,
|
|
1677
|
-
size: entry.isDirectory ? 0 : entry.size ?? 0,
|
|
1678
|
-
mtimeMs: entry.mtimeMs,
|
|
1679
|
-
isDirectory: entry.isDirectory
|
|
1680
|
-
}));
|
|
1681
|
-
}
|
|
1682
|
-
};
|
|
1683
|
-
}
|
|
1684
|
-
function currentSaveAsAllowed(value) {
|
|
1685
|
-
return typeof value == "function" ? value() : value === !0;
|
|
1686
|
-
}
|
|
1687
|
-
function currentSaveAsMaxBytes(value) {
|
|
1688
|
-
return typeof value == "function" ? value() : value ?? REMOTE_FILE_SAVE_AS_MAX_BYTES;
|
|
1689
|
-
}
|
|
1690
|
-
function decodeBase64(value) {
|
|
1691
|
-
let binary = atob(value), bytes = new Uint8Array(binary.length);
|
|
1692
|
-
for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index);
|
|
1693
|
-
return bytes;
|
|
1694
|
-
}
|
|
1695
|
-
|
|
1696
|
-
// src/control-route.ts
|
|
1697
|
-
var CONTROL_RPC_PREFIX = "/ds-harness-remote", STATUS_STREAM_ENDPOINT = "status.events", STATUS_STREAM_PATH = `${CONTROL_RPC_PREFIX}/${STATUS_STREAM_ENDPOINT}`;
|
|
1698
|
-
|
|
1699
|
-
// src/plugin-route-client.ts
|
|
1700
|
-
var PluginRouteFailure = class extends Error {
|
|
1701
|
-
constructor(code, message) {
|
|
1702
|
-
super(message);
|
|
1703
|
-
this.code = code;
|
|
1704
|
-
}
|
|
1705
|
-
};
|
|
1706
|
-
function createPluginRouteFetch(original, baseUrl, options = {}) {
|
|
1707
|
-
let routeUrl = new URL("api/bot", baseUrl), nextRpcId = 0, control = async (method, payload, signal) => {
|
|
1708
|
-
let rpcId = `plugin-route-${++nextRpcId}`, response = await original(new URL(`${CONTROL_RPC_PREFIX.slice(1)}/${method}`, baseUrl), {
|
|
1709
|
-
method: "POST",
|
|
1710
|
-
credentials: "same-origin",
|
|
1711
|
-
headers: { "content-type": "application/json" },
|
|
1712
|
-
body: JSON.stringify({ type: "client-request", rpcId, method, payload }),
|
|
1713
|
-
signal
|
|
1714
|
-
});
|
|
1715
|
-
if (!response.ok) throw new PluginRouteFailure("remote-plugin/control-unavailable", `The local Remote control request failed (HTTP ${response.status}). Reload the Remote plugin.`);
|
|
1716
|
-
let envelope = await response.json();
|
|
1717
|
-
if (!isRecord(envelope) || envelope.type !== "server-response" || envelope.rpcId !== rpcId || !isRecord(envelope.result))
|
|
1718
|
-
throw new PluginRouteFailure("remote-plugin/control-invalid", "The local Remote control response is invalid. Reload the Remote plugin.");
|
|
1719
|
-
if (envelope.result.ok !== !0) {
|
|
1720
|
-
let error = isRecord(envelope.result.error) ? envelope.result.error : void 0, code = (isRecord(error?.details) ? error.details : void 0)?.remoteCode ?? error?.code;
|
|
1721
|
-
throw code === "FEATURE_NOT_SUPPORTED" || code === "METHOD_NOT_FOUND" ? new PluginRouteFailure("remote-plugin/host-unsupported", "The selected Host does not support plugin route forwarding. Update and reload Remote on the Host, then reconnect.") : code === "REMOTE_NOT_CONNECTED" || code === "TRANSPORT_CLOSED" ? new PluginRouteFailure("remote-plugin/disconnected", "The Remote Host is disconnected. Reconnect to load DS Bot.") : code === "INVALID_MESSAGE" ? new PluginRouteFailure("remote-plugin/operation-not-allowed", "This DS Bot operation is not allowed over Remote. Use the Host locally.") : new PluginRouteFailure("remote-plugin/control-rejected", "The Remote plugin route request was rejected by the control channel.");
|
|
1722
|
-
}
|
|
1723
|
-
return envelope.result.value;
|
|
1724
|
-
};
|
|
1725
|
-
return async (input, init) => {
|
|
1726
|
-
let requestUrl = new URL(input instanceof Request ? input.url : String(input), baseUrl);
|
|
1727
|
-
if ((init?.method ?? (input instanceof Request ? input.method : "GET")).toUpperCase() !== "POST" || requestUrl.href !== routeUrl.href) return original(input, init);
|
|
1728
|
-
let lifetime = (init?.signal !== void 0 ? init.signal ?? void 0 : input instanceof Request ? input.signal : void 0) ?? AbortSignal.timeout(45e3);
|
|
1729
|
-
try {
|
|
1730
|
-
lifetime.throwIfAborted();
|
|
1731
|
-
let status = await control("status", {}, AbortSignal.any([lifetime, AbortSignal.timeout(1e4)]));
|
|
1732
|
-
if (lifetime.throwIfAborted(), !isRecord(status)) throw new PluginRouteFailure("remote-plugin/authority-unavailable", "The Remote plugin route authority is unavailable.");
|
|
1733
|
-
if (status.mode === "local") return original(input, init);
|
|
1734
|
-
if (status.mode !== "remote") throw new PluginRouteFailure("remote-plugin/authority-unavailable", "The Remote plugin route authority is unavailable.");
|
|
1735
|
-
if (status.connected !== !0) throw new PluginRouteFailure("remote-plugin/disconnected", "The Remote Host is disconnected. Reconnect to load DS Bot.");
|
|
1736
|
-
if (!isRecord(status.remoteFeatures) || status.remoteFeatures.pluginRoute !== !0) throw new PluginRouteFailure("remote-plugin/host-unsupported", "The selected Host does not support plugin route forwarding. Update and reload Remote on the Host, then reconnect.");
|
|
1737
|
-
if (status.backend !== void 0 && status.backend !== "harness") throw new PluginRouteFailure("remote-plugin/backend-unsupported", "DS Bot requires the Remote Harness catalog. Select a Harness workspace on this Host.");
|
|
1738
|
-
let body = await (input instanceof Request ? new Request(input, init) : new Request(requestUrl, init)).clone().json();
|
|
1739
|
-
if (!isRecord(body)) throw new Error("The plugin route body must be a JSON object.");
|
|
1740
|
-
let result = await control("plugin.route", { route: "api/bot", body }, lifetime);
|
|
1741
|
-
if (!isRecord(result) || !Number.isInteger(result.status) || result.status < 200 || result.status > 599)
|
|
1742
|
-
throw new Error("The plugin route response is invalid.");
|
|
1743
|
-
let statusCode = result.status;
|
|
1744
|
-
if (statusCode === 404) throw new PluginRouteFailure("remote-plugin/bot-not-loaded", "The Host has no DS Bot route. Enable ds-bot in the same DSH instance/profile as the connected Host.");
|
|
1745
|
-
if (statusCode === 503) throw new PluginRouteFailure("remote-plugin/host-carrier-unavailable", "The Host plugin route carrier is unavailable. Update and reload Remote on the Host.");
|
|
1746
|
-
if (statusCode >= 200 && statusCode < 300 && options.beforeResponse !== void 0)
|
|
1747
|
-
try {
|
|
1748
|
-
await waitWithSignal(options.beforeResponse(status, body, result.json, lifetime), lifetime);
|
|
1749
|
-
} catch {
|
|
1750
|
-
throw lifetime.throwIfAborted(), new PluginRouteFailure("remote-plugin/catalog-unavailable", "The Remote Harness Session catalog is not ready. Reconnect before loading DS Bot.");
|
|
1751
|
-
}
|
|
1752
|
-
return lifetime.throwIfAborted(), new Response([204, 205, 304].includes(statusCode) ? null : JSON.stringify(result.json ?? null), {
|
|
1753
|
-
status: statusCode,
|
|
1754
|
-
headers: { "content-type": "application/json" }
|
|
1755
|
-
});
|
|
1756
|
-
} catch (error) {
|
|
1757
|
-
return lifetime.throwIfAborted(), new Response(JSON.stringify({
|
|
1758
|
-
ok: !1,
|
|
1759
|
-
error: {
|
|
1760
|
-
code: error instanceof PluginRouteFailure ? error.code : "remote-plugin/unavailable",
|
|
1761
|
-
message: error instanceof PluginRouteFailure ? error.message : "The Remote plugin route is unavailable.",
|
|
1762
|
-
details: {}
|
|
1763
|
-
}
|
|
1764
|
-
}), { status: 200, headers: { "content-type": "application/json" } });
|
|
1765
|
-
}
|
|
1766
|
-
};
|
|
1767
|
-
}
|
|
1768
|
-
function createPluginRouteCatalogGuard(readSessions) {
|
|
1769
|
-
return async (_status, body, json, signal) => {
|
|
1770
|
-
if (!isRecord(json) || json.ok !== !0 || !isRecord(json.value)) return;
|
|
1771
|
-
let required = botSessionIds(body.endpoint, json.value);
|
|
1772
|
-
if (required.size === 0) return;
|
|
1773
|
-
let sessions = await readSessions(), containsSessions = () => {
|
|
1774
|
-
let snapshot = sessions.list.getSnapshot(), known = new Set(snapshot.ids);
|
|
1775
|
-
return snapshot.phase === "ready" && [...required].every((id) => known.has(id));
|
|
1776
|
-
};
|
|
1777
|
-
for (let attempt = 0; attempt < 2; attempt++) {
|
|
1778
|
-
if (signal.throwIfAborted(), containsSessions()) return;
|
|
1779
|
-
if (sessions.refresh === void 0) break;
|
|
1780
|
-
await sessions.refresh();
|
|
1781
|
-
}
|
|
1782
|
-
if (signal.throwIfAborted(), !containsSessions()) throw new Error("The Remote Session catalog does not contain the published Sessions.");
|
|
1783
|
-
};
|
|
1784
|
-
}
|
|
1785
|
-
function botSessionIds(endpoint, value) {
|
|
1786
|
-
let ids = /* @__PURE__ */ new Set(), add = (id) => {
|
|
1787
|
-
if (id != null) {
|
|
1788
|
-
if (typeof id != "string" || id.length === 0) throw new Error("Invalid Bot Session identity.");
|
|
1789
|
-
ids.add(id);
|
|
1790
|
-
}
|
|
1791
|
-
}, addArray = (input) => {
|
|
1792
|
-
if (input !== void 0) {
|
|
1793
|
-
if (!Array.isArray(input)) throw new Error("Invalid Bot Session identities.");
|
|
1794
|
-
input.forEach(add);
|
|
1795
|
-
}
|
|
1796
|
-
}, bot = (input) => {
|
|
1797
|
-
if (!isRecord(input)) throw new Error("Invalid Bot catalog entry.");
|
|
1798
|
-
add(input.id), add(input.sessionId), addArray(input.parts), Array.isArray(input.segments) && input.segments.forEach((segment) => {
|
|
1799
|
-
if (!isRecord(segment)) throw new Error("Invalid Bot Session segment.");
|
|
1800
|
-
add(segment.sessionId);
|
|
1801
|
-
});
|
|
1802
|
-
}, room = (input) => {
|
|
1803
|
-
if (!isRecord(input)) throw new Error("Invalid Bot room entry.");
|
|
1804
|
-
add(input.id), addArray(input.parts), isRecord(input.sessions) && Object.values(input.sessions).forEach(add);
|
|
1805
|
-
}, agent = (input) => {
|
|
1806
|
-
if (!isRecord(input)) throw new Error("Invalid Bot agent entry.");
|
|
1807
|
-
addArray(input.sessions);
|
|
1808
|
-
}, roster = () => {
|
|
1809
|
-
for (let [key, visit] of [["bots", bot], ["rooms", room], ["agents", agent]])
|
|
1810
|
-
if (value[key] !== void 0) {
|
|
1811
|
-
if (!Array.isArray(value[key])) throw new Error("Invalid Bot roster.");
|
|
1812
|
-
value[key].forEach(visit);
|
|
1813
|
-
}
|
|
1814
|
-
};
|
|
1815
|
-
switch (endpoint) {
|
|
1816
|
-
case "state":
|
|
1817
|
-
case "delete-bot":
|
|
1818
|
-
case "delete-room":
|
|
1819
|
-
case "set-main":
|
|
1820
|
-
case "remove-agent":
|
|
1821
|
-
roster();
|
|
1822
|
-
break;
|
|
1823
|
-
case "create-bot":
|
|
1824
|
-
case "duplicate-bot":
|
|
1825
|
-
case "update-bot":
|
|
1826
|
-
bot(value);
|
|
1827
|
-
break;
|
|
1828
|
-
case "create-room":
|
|
1829
|
-
room(value);
|
|
1830
|
-
break;
|
|
1831
|
-
case "update-room":
|
|
1832
|
-
room(value.room);
|
|
1833
|
-
break;
|
|
1834
|
-
case "add-agent":
|
|
1835
|
-
agent(value);
|
|
1836
|
-
break;
|
|
1837
|
-
case "agent-session":
|
|
1838
|
-
case "agent-adopt":
|
|
1839
|
-
add(value.sessionId);
|
|
1840
|
-
break;
|
|
1841
|
-
case "set-flags":
|
|
1842
|
-
Array.isArray(value.sessions) ? agent(value) : Array.isArray(value.members) ? room(value) : bot(value);
|
|
1843
|
-
break;
|
|
1844
|
-
}
|
|
1845
|
-
return ids;
|
|
1846
|
-
}
|
|
1847
|
-
function waitWithSignal(pending, signal) {
|
|
1848
|
-
return new Promise((resolve, reject) => {
|
|
1849
|
-
let onAbort = () => reject(signal.reason);
|
|
1850
|
-
signal.addEventListener("abort", onAbort, { once: !0 }), signal.aborted && onAbort(), pending.then(resolve, reject).finally(() => signal.removeEventListener("abort", onAbort));
|
|
1851
|
-
});
|
|
1852
|
-
}
|
|
1853
|
-
function isRecord(value) {
|
|
1854
|
-
return typeof value == "object" && value !== null && !Array.isArray(value);
|
|
1855
|
-
}
|
|
1856
|
-
|
|
1857
|
-
// src/status-stream.ts
|
|
1858
|
-
function parseStatus(data) {
|
|
1859
|
-
if (typeof data == "string")
|
|
1860
|
-
try {
|
|
1861
|
-
let parsed = JSON.parse(data);
|
|
1862
|
-
return parsed === null || typeof parsed != "object" ? void 0 : parsed;
|
|
1863
|
-
} catch {
|
|
1864
|
-
return;
|
|
1865
|
-
}
|
|
1866
|
-
}
|
|
1867
|
-
function createStatusFeed(options) {
|
|
1868
|
-
let listeners = /* @__PURE__ */ new Set(), pollIntervalMs = options.pollIntervalMs ?? 1500, openTimeoutMs = options.openTimeoutMs ?? 4e3, createSource = options.createSource ?? ((url) => new EventSource(url)), status, source, openTimer, pollTimer, publish = (next) => {
|
|
1869
|
-
status = next;
|
|
1870
|
-
for (let listener of [...listeners]) listener(next);
|
|
1871
|
-
}, teardown = () => {
|
|
1872
|
-
openTimer !== void 0 && (clearTimeout(openTimer), openTimer = void 0), pollTimer !== void 0 && (clearInterval(pollTimer), pollTimer = void 0), source?.close(), source = void 0;
|
|
1873
|
-
}, poll = () => {
|
|
1874
|
-
options.readStatus().then((next) => {
|
|
1875
|
-
pollTimer !== void 0 && publish(next);
|
|
1876
|
-
}).catch(() => {
|
|
1877
|
-
});
|
|
1878
|
-
}, fallbackToPolling = (reason) => {
|
|
1879
|
-
pollTimer !== void 0 || listeners.size === 0 || (openTimer !== void 0 && (clearTimeout(openTimer), openTimer = void 0), source?.close(), source = void 0, options.onFallback?.(reason), poll(), pollTimer = setInterval(poll, pollIntervalMs));
|
|
1880
|
-
}, openStream = () => {
|
|
1881
|
-
let opened;
|
|
1882
|
-
try {
|
|
1883
|
-
opened = createSource(options.url);
|
|
1884
|
-
} catch {
|
|
1885
|
-
fallbackToPolling("unsupported");
|
|
1886
|
-
return;
|
|
1887
|
-
}
|
|
1888
|
-
source = opened;
|
|
1889
|
-
let received = !1;
|
|
1890
|
-
openTimer = setTimeout(() => {
|
|
1891
|
-
received || fallbackToPolling("silent");
|
|
1892
|
-
}, openTimeoutMs), opened.onmessage = (event) => {
|
|
1893
|
-
received = !0, openTimer !== void 0 && (clearTimeout(openTimer), openTimer = void 0);
|
|
1894
|
-
let next = parseStatus(event.data);
|
|
1895
|
-
next !== void 0 && publish(next);
|
|
1896
|
-
}, opened.onerror = () => {
|
|
1897
|
-
opened.readyState === 2 && fallbackToPolling("unavailable");
|
|
1898
|
-
};
|
|
1899
|
-
};
|
|
1900
|
-
return {
|
|
1901
|
-
getSnapshot: () => status,
|
|
1902
|
-
subscribe: (listener) => (listeners.add(listener), status !== void 0 && listener(status), listeners.size === 1 && openStream(), () => {
|
|
1903
|
-
listeners.delete(listener), listeners.size === 0 && teardown();
|
|
1904
|
-
}),
|
|
1905
|
-
close: () => {
|
|
1906
|
-
listeners.clear(), teardown();
|
|
1907
|
-
}
|
|
1908
|
-
};
|
|
1909
|
-
}
|
|
1910
|
-
|
|
1911
1622
|
// src/client-locale.ts
|
|
1912
1623
|
var localeNamespace = "ds-harness-remote", en = {
|
|
1913
1624
|
terminalRemote: "Remote terminal",
|
|
@@ -2063,15 +1774,21 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2063
1774
|
addCodexWorkspace: "Add CodeX workspace",
|
|
2064
1775
|
addCursorWorkspace: "Add Cursor workspace",
|
|
2065
1776
|
addAntigravityWorkspace: "Add Antigravity workspace",
|
|
1777
|
+
addPiWorkspace: "Add PI workspace",
|
|
1778
|
+
addOpencodeWorkspace: "Add OpenCode workspace",
|
|
2066
1779
|
noCodexWorkspaces: "No CodeX workspaces yet.",
|
|
2067
1780
|
noCursorWorkspaces: "No Cursor workspaces yet. Add a project directory to start.",
|
|
2068
1781
|
noAntigravityWorkspaces: "No Antigravity workspaces yet. Add a project directory to start.",
|
|
1782
|
+
noPiWorkspaces: "No PI workspaces yet. Add a project directory to start.",
|
|
1783
|
+
noOpencodeWorkspaces: "No OpenCode workspaces yet. Add a project directory to start.",
|
|
2069
1784
|
cancelAddWorkspace: "Cancel",
|
|
2070
1785
|
confirmAddWorkspace: "Add and open",
|
|
2071
1786
|
showAllWorkspaces: "Show all DSH workspaces",
|
|
2072
1787
|
showAllCodexWorkspaces: "Show all CodeX workspaces",
|
|
2073
1788
|
showAllCursorWorkspaces: "Show all Cursor workspaces",
|
|
2074
1789
|
showAllAntigravityWorkspaces: "Show all Antigravity workspaces",
|
|
1790
|
+
showAllPiWorkspaces: "Show all PI workspaces",
|
|
1791
|
+
showAllOpencodeWorkspaces: "Show all OpenCode workspaces",
|
|
2075
1792
|
remoteModeLabel: "Remote mode \xB7 {name}",
|
|
2076
1793
|
remoteNetworkP2p: "P2P",
|
|
2077
1794
|
remoteNetworkTurn: "TURN",
|
|
@@ -2166,6 +1883,8 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2166
1883
|
codexVirtualWorkspace: "CodeX virtual workspace",
|
|
2167
1884
|
cursorVirtualWorkspace: "Cursor virtual workspace",
|
|
2168
1885
|
antigravityVirtualWorkspace: "Antigravity virtual workspace",
|
|
1886
|
+
piVirtualWorkspace: "PI virtual workspace",
|
|
1887
|
+
opencodeVirtualWorkspace: "OpenCode virtual workspace",
|
|
2169
1888
|
codexVirtualSessions: "Sessions"
|
|
2170
1889
|
}, zh = {
|
|
2171
1890
|
terminalRemote: "\u8FDC\u7A0B\u7EC8\u7AEF",
|
|
@@ -2321,15 +2040,21 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2321
2040
|
addCodexWorkspace: "\u6DFB\u52A0 CodeX \u5DE5\u4F5C\u533A",
|
|
2322
2041
|
addCursorWorkspace: "\u6DFB\u52A0 Cursor \u5DE5\u4F5C\u533A",
|
|
2323
2042
|
addAntigravityWorkspace: "\u6DFB\u52A0 Antigravity \u5DE5\u4F5C\u533A",
|
|
2043
|
+
addPiWorkspace: "\u6DFB\u52A0 PI \u5DE5\u4F5C\u533A",
|
|
2044
|
+
addOpencodeWorkspace: "\u6DFB\u52A0 OpenCode \u5DE5\u4F5C\u533A",
|
|
2324
2045
|
noCodexWorkspaces: "\u8FD8\u6CA1\u6709 CodeX \u5DE5\u4F5C\u533A\u3002",
|
|
2325
2046
|
noCursorWorkspaces: "\u8FD8\u6CA1\u6709 Cursor \u5DE5\u4F5C\u533A\u3002\u6DFB\u52A0\u9879\u76EE\u76EE\u5F55\u5373\u53EF\u5F00\u59CB\u3002",
|
|
2326
2047
|
noAntigravityWorkspaces: "\u8FD8\u6CA1\u6709 Antigravity \u5DE5\u4F5C\u533A\u3002\u6DFB\u52A0\u9879\u76EE\u76EE\u5F55\u5373\u53EF\u5F00\u59CB\u3002",
|
|
2048
|
+
noPiWorkspaces: "\u8FD8\u6CA1\u6709 PI \u5DE5\u4F5C\u533A\u3002\u6DFB\u52A0\u9879\u76EE\u76EE\u5F55\u5373\u53EF\u5F00\u59CB\u3002",
|
|
2049
|
+
noOpencodeWorkspaces: "\u8FD8\u6CA1\u6709 OpenCode \u5DE5\u4F5C\u533A\u3002\u6DFB\u52A0\u9879\u76EE\u76EE\u5F55\u5373\u53EF\u5F00\u59CB\u3002",
|
|
2327
2050
|
cancelAddWorkspace: "\u53D6\u6D88",
|
|
2328
2051
|
confirmAddWorkspace: "\u786E\u8BA4\u5E76\u6253\u5F00",
|
|
2329
2052
|
showAllWorkspaces: "\u663E\u793A\u5168\u90E8 DSH \u5DE5\u4F5C\u533A",
|
|
2330
2053
|
showAllCodexWorkspaces: "\u663E\u793A\u5168\u90E8 CodeX \u5DE5\u4F5C\u533A",
|
|
2331
2054
|
showAllCursorWorkspaces: "\u663E\u793A\u5168\u90E8 Cursor \u5DE5\u4F5C\u533A",
|
|
2332
2055
|
showAllAntigravityWorkspaces: "\u663E\u793A\u5168\u90E8 Antigravity \u5DE5\u4F5C\u533A",
|
|
2056
|
+
showAllPiWorkspaces: "\u663E\u793A\u5168\u90E8 PI \u5DE5\u4F5C\u533A",
|
|
2057
|
+
showAllOpencodeWorkspaces: "\u663E\u793A\u5168\u90E8 OpenCode \u5DE5\u4F5C\u533A",
|
|
2333
2058
|
remoteModeLabel: "\u8FDC\u7A0B\u6A21\u5F0F \xB7 {name}",
|
|
2334
2059
|
remoteNetworkP2p: "P2P",
|
|
2335
2060
|
remoteNetworkTurn: "TURN",
|
|
@@ -2424,49 +2149,13 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2424
2149
|
codexVirtualWorkspace: "CodeX \u5DE5\u4F5C\u533A",
|
|
2425
2150
|
cursorVirtualWorkspace: "Cursor \u5DE5\u4F5C\u533A",
|
|
2426
2151
|
antigravityVirtualWorkspace: "Antigravity \u5DE5\u4F5C\u533A",
|
|
2152
|
+
piVirtualWorkspace: "PI \u5DE5\u4F5C\u533A",
|
|
2153
|
+
opencodeVirtualWorkspace: "OpenCode \u5DE5\u4F5C\u533A",
|
|
2427
2154
|
codexVirtualSessions: "Sessions"
|
|
2428
2155
|
};
|
|
2429
2156
|
|
|
2430
|
-
// src/client.ts
|
|
2431
|
-
var
|
|
2432
|
-
function storedWorkspaceSelection() {
|
|
2433
|
-
let raw = window.sessionStorage.getItem(pendingWorkspaceSelectionKey);
|
|
2434
|
-
if (raw !== null)
|
|
2435
|
-
try {
|
|
2436
|
-
let value = JSON.parse(raw);
|
|
2437
|
-
if (typeof value.targetDeviceId != "string" || typeof value.workspaceId != "string") throw new Error("invalid");
|
|
2438
|
-
if (value.backend !== void 0 && value.backend !== "harness" && value.backend !== "codex" && value.backend !== "cursor" && value.backend !== "antigravity") throw new Error("invalid");
|
|
2439
|
-
if (value.sessionId !== void 0 && typeof value.sessionId != "string") throw new Error("invalid");
|
|
2440
|
-
return value;
|
|
2441
|
-
} catch {
|
|
2442
|
-
window.sessionStorage.removeItem(pendingWorkspaceSelectionKey);
|
|
2443
|
-
return;
|
|
2444
|
-
}
|
|
2445
|
-
}
|
|
2446
|
-
function workspacesReady(snapshot) {
|
|
2447
|
-
return snapshot.baselinesReady === !0 || snapshot.phase === "ready";
|
|
2448
|
-
}
|
|
2449
|
-
var defaultPreferredTransports = ["lan", "p2p", "turn", "relay"], controlRouteBackoffStepsMs = [1e3, 2e3, 5e3, 1e4, 3e4], ControlRouteUnavailableError = class extends Error {
|
|
2450
|
-
constructor(message) {
|
|
2451
|
-
super(message), this.name = "ControlRouteUnavailableError";
|
|
2452
|
-
}
|
|
2453
|
-
}, originalPluginFetch = window.fetch, readyPluginSessions, pluginSessions = new Promise((resolve) => {
|
|
2454
|
-
readyPluginSessions = resolve;
|
|
2455
|
-
}), pluginRouteFetch = typeof originalPluginFetch == "function" && typeof document < "u" ? createPluginRouteFetch(originalPluginFetch.bind(window), document.baseURI, {
|
|
2456
|
-
beforeResponse: createPluginRouteCatalogGuard(() => pluginSessions)
|
|
2457
|
-
}) : void 0;
|
|
2458
|
-
pluginRouteFetch !== void 0 && (window.fetch = pluginRouteFetch);
|
|
2459
|
-
function controlRouteUnavailableStatus() {
|
|
2460
|
-
return {
|
|
2461
|
-
mode: "local",
|
|
2462
|
-
available: !1,
|
|
2463
|
-
controlUnavailable: !0,
|
|
2464
|
-
connected: !1,
|
|
2465
|
-
transport: "Disconnected",
|
|
2466
|
-
remoteFeatures: { commandList: !1, fileViewer: !1, terminal: !1, codex: !1, pluginRoute: !1, cursor: !1, antigravity: !1 },
|
|
2467
|
-
hostAuthorizationAvailable: !1
|
|
2468
|
-
};
|
|
2469
|
-
}
|
|
2157
|
+
// src/client/presentation.ts
|
|
2158
|
+
var defaultPreferredTransports = ["lan", "p2p", "turn", "relay"];
|
|
2470
2159
|
function normalizedPreferredTransports(value) {
|
|
2471
2160
|
return value === void 0 || value.length === 0 ? [...defaultPreferredTransports] : [...value];
|
|
2472
2161
|
}
|
|
@@ -2564,1427 +2253,2230 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2564
2253
|
function connectionStatusClass(status) {
|
|
2565
2254
|
return status?.online ? " isOnline" : status?.reconnecting ? " isReconnecting" : status === void 0 ? "" : " isOffline";
|
|
2566
2255
|
}
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2256
|
+
function messageOf(reason) {
|
|
2257
|
+
return reason instanceof Error ? reason.message : String(reason);
|
|
2258
|
+
}
|
|
2259
|
+
function formatPlatform(value) {
|
|
2260
|
+
let normalized = value.toLowerCase();
|
|
2261
|
+
return normalized === "darwin" || normalized === "macos" ? "macOS" : normalized === "win32" || normalized === "windows" ? "Windows" : normalized === "linux" ? "Linux" : normalized === "android" ? "Android" : value;
|
|
2262
|
+
}
|
|
2263
|
+
function connectedClientModeLabel(mode, t) {
|
|
2264
|
+
return t(mode === "LAN" ? "remoteNetworkLan" : mode === "P2P" ? "remoteNetworkP2p" : mode === "TURN" ? "remoteNetworkTurn" : mode === "Relay" ? "remoteNetworkRelay" : "connected");
|
|
2265
|
+
}
|
|
2266
|
+
|
|
2267
|
+
// src/client/header.ts
|
|
2268
|
+
function createRemoteSessionHeaderAction(React) {
|
|
2269
|
+
function RemoteSessionHeaderAction(props) {
|
|
2270
|
+
let { t } = props, status = React.useSyncExternalStore(
|
|
2271
|
+
props.statusFeed.subscribe,
|
|
2272
|
+
props.statusFeed.getSnapshot,
|
|
2273
|
+
props.statusFeed.getSnapshot
|
|
2274
|
+
), [busy, setBusy] = React.useState(!1), [routeOpen, setRouteOpen] = React.useState(!1);
|
|
2275
|
+
if (React.useEffect(() => {
|
|
2276
|
+
if (status?.mode === "remote")
|
|
2277
|
+
return hideLocalSessionActions();
|
|
2278
|
+
}, [status?.mode]), React.useEffect(() => (document.documentElement.classList.toggle(
|
|
2279
|
+
"dshRemoteCodexTargetActive",
|
|
2280
|
+
status?.mode === "remote" && status.backend === "codex"
|
|
2281
|
+
), document.documentElement.classList.toggle(
|
|
2282
|
+
"dshRemoteCursorTargetActive",
|
|
2283
|
+
status?.mode === "remote" && status.backend === "cursor"
|
|
2284
|
+
), document.documentElement.classList.toggle(
|
|
2285
|
+
"dshRemoteAntigravityTargetActive",
|
|
2286
|
+
status?.mode === "remote" && status.backend === "antigravity"
|
|
2287
|
+
), document.documentElement.classList.toggle(
|
|
2288
|
+
"dshRemotePiTargetActive",
|
|
2289
|
+
status?.mode === "remote" && status.backend === "pi"
|
|
2290
|
+
), document.documentElement.classList.toggle(
|
|
2291
|
+
"dshRemoteOpencodeTargetActive",
|
|
2292
|
+
status?.mode === "remote" && status.backend === "opencode"
|
|
2293
|
+
), () => {
|
|
2294
|
+
document.documentElement.classList.remove("dshRemoteCodexTargetActive"), document.documentElement.classList.remove("dshRemoteCursorTargetActive"), document.documentElement.classList.remove("dshRemoteAntigravityTargetActive"), document.documentElement.classList.remove("dshRemotePiTargetActive"), document.documentElement.classList.remove("dshRemoteOpencodeTargetActive");
|
|
2295
|
+
}), [status?.mode, status?.backend]), React.useEffect(() => {
|
|
2296
|
+
if (!routeOpen) return;
|
|
2297
|
+
let closeOnEscape = (event) => {
|
|
2298
|
+
event.key === "Escape" && setRouteOpen(!1);
|
|
2299
|
+
};
|
|
2300
|
+
return document.addEventListener("keydown", closeOnEscape), () => document.removeEventListener("keydown", closeOnEscape);
|
|
2301
|
+
}, [routeOpen]), status?.mode !== "remote") return null;
|
|
2302
|
+
let exit = async () => {
|
|
2303
|
+
setBusy(!0);
|
|
2304
|
+
try {
|
|
2305
|
+
await props.control("mode.set", { mode: "local" }), window.location.reload();
|
|
2306
|
+
} finally {
|
|
2307
|
+
setBusy(!1);
|
|
2308
|
+
}
|
|
2309
|
+
}, transport = status.network?.webRtc?.mode ?? status.transport ?? "Disconnected", networkLabel = t(transport === "P2P" ? "remoteNetworkP2p" : transport === "TURN" ? "remoteNetworkTurn" : transport === "Relay" ? "remoteNetworkRelay" : transport === "LAN" ? "remoteNetworkLan" : "remoteNetworkOffline"), networkOnline = status.connected === !0 && transport !== "Disconnected", routeVia = t(transport === "P2P" ? "connectionRouteP2p" : transport === "TURN" ? "connectionRouteTurn" : transport === "Relay" ? "connectionRouteRelay" : "connectionRouteLan"), routeViaDetail = t(transport === "P2P" ? "connectionRouteP2pDetail" : transport === "TURN" ? "connectionRouteTurnDetail" : transport === "Relay" ? "connectionRouteRelayDetail" : "connectionRouteLanDetail"), network = status.network, webRtc = network?.webRtc, controlStateLabel = network?.controlChannelState === "connecting" ? t("controlStateConnecting") : network?.controlChannelState === "open" ? t("controlStateOpen") : network?.controlChannelState === "closing" ? t("controlStateClosing") : t("controlStateClosed"), detailValue = (value) => value === void 0 || value === "" ? t("notProvided") : String(value), candidateLabel = (value) => value === "host" ? t("candidateHost") : value === "srflx" ? t("candidateSrflx") : value === "prflx" ? t("candidatePrflx") : value === "relay" ? t("candidateRelay") : detailValue(value), fact = (label, value, mono = !1) => React.createElement(
|
|
2310
|
+
"div",
|
|
2311
|
+
null,
|
|
2312
|
+
React.createElement("dt", null, label),
|
|
2313
|
+
React.createElement("dd", { className: mono ? "isMono" : void 0, title: mono ? value : void 0 }, value)
|
|
2314
|
+
);
|
|
2315
|
+
return React.createElement(
|
|
2316
|
+
"div",
|
|
2317
|
+
{ className: "dshRemoteSessionHeader", role: "status" },
|
|
2318
|
+
React.createElement("svg", {
|
|
2319
|
+
viewBox: "0 0 24 24",
|
|
2320
|
+
fill: "none",
|
|
2321
|
+
stroke: "currentColor",
|
|
2322
|
+
strokeWidth: 1.7,
|
|
2323
|
+
strokeLinecap: "round",
|
|
2324
|
+
strokeLinejoin: "round",
|
|
2325
|
+
"aria-hidden": !0
|
|
2326
|
+
}, React.createElement("rect", { x: 3, y: 4, width: 18, height: 13, rx: 2 }), React.createElement("path", { d: "M8 21h8M12 17v4" })),
|
|
2327
|
+
React.createElement("span", { className: "dshRemoteSessionTarget" }, t("remoteModeLabel", { name: status.target?.name ?? t("host") })),
|
|
2328
|
+
React.createElement("button", {
|
|
2329
|
+
type: "button",
|
|
2330
|
+
className: `dshRemoteNetwork${networkOnline ? " isOnline" : " isOffline"}`,
|
|
2331
|
+
title: networkLabel,
|
|
2332
|
+
disabled: !networkOnline,
|
|
2333
|
+
"aria-haspopup": "dialog",
|
|
2334
|
+
"aria-expanded": routeOpen,
|
|
2335
|
+
onClick: () => setRouteOpen((value) => !value)
|
|
2336
|
+
}, React.createElement("i", { "aria-hidden": !0 }), networkLabel),
|
|
2337
|
+
networkOnline ? React.createElement("span", { className: "dshRemoteEncrypted" }, t("remoteLinkEncrypted")) : null,
|
|
2338
|
+
React.createElement("button", { type: "button", className: "dshRemoteHeaderExitLink", disabled: busy, onClick: () => void exit() }, t("exitRemote")),
|
|
2339
|
+
routeOpen ? React.createElement("div", {
|
|
2340
|
+
className: "dshRemoteRouteBackdrop",
|
|
2341
|
+
role: "presentation",
|
|
2342
|
+
onMouseDown: (event) => {
|
|
2343
|
+
event.target === event.currentTarget && setRouteOpen(!1);
|
|
2344
|
+
}
|
|
2345
|
+
}, React.createElement(
|
|
2346
|
+
"section",
|
|
2595
2347
|
{
|
|
2596
|
-
className: "
|
|
2597
|
-
role: "
|
|
2598
|
-
"aria-
|
|
2348
|
+
className: "dshRemoteRoutePanel",
|
|
2349
|
+
role: "dialog",
|
|
2350
|
+
"aria-label": t("connectionRouteTitle")
|
|
2599
2351
|
},
|
|
2600
2352
|
React.createElement(
|
|
2601
|
-
"
|
|
2602
|
-
|
|
2603
|
-
React.createElement("strong", null,
|
|
2604
|
-
React.createElement("
|
|
2353
|
+
"header",
|
|
2354
|
+
null,
|
|
2355
|
+
React.createElement("strong", null, t("connectionRouteTitle")),
|
|
2356
|
+
React.createElement("button", { type: "button", "aria-label": t("close"), onClick: () => setRouteOpen(!1) }, "\xD7")
|
|
2605
2357
|
),
|
|
2606
|
-
React.createElement(
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2358
|
+
React.createElement(
|
|
2359
|
+
"ol",
|
|
2360
|
+
null,
|
|
2361
|
+
React.createElement(
|
|
2362
|
+
"li",
|
|
2363
|
+
null,
|
|
2364
|
+
React.createElement("small", null, t("connectionRouteFrom")),
|
|
2365
|
+
React.createElement("strong", null, network?.local.name ?? t("connectionRouteCurrentDevice")),
|
|
2366
|
+
network === void 0 ? null : React.createElement("span", null, `${network.local.platform} \xB7 ${shortDeviceId(network.local.deviceId)}`)
|
|
2367
|
+
),
|
|
2368
|
+
React.createElement(
|
|
2369
|
+
"li",
|
|
2370
|
+
null,
|
|
2371
|
+
React.createElement("small", null, t("connectionRouteVia")),
|
|
2372
|
+
React.createElement("strong", null, routeVia),
|
|
2373
|
+
React.createElement("span", null, routeViaDetail)
|
|
2374
|
+
),
|
|
2375
|
+
React.createElement(
|
|
2376
|
+
"li",
|
|
2377
|
+
null,
|
|
2378
|
+
React.createElement("small", null, t("connectionRouteTo")),
|
|
2379
|
+
React.createElement("strong", null, network?.remote.name ?? status.target?.name ?? t("host")),
|
|
2380
|
+
React.createElement("span", null, network === void 0 ? t("connectionRouteHost") : `${network.remote.platform} \xB7 ${shortDeviceId(network.remote.deviceId)}`)
|
|
2381
|
+
)
|
|
2382
|
+
),
|
|
2383
|
+
network === void 0 ? null : React.createElement(
|
|
2384
|
+
"section",
|
|
2385
|
+
{ className: "dshRemoteRouteSection" },
|
|
2386
|
+
React.createElement("h3", null, t("connectionDetailsConnection")),
|
|
2387
|
+
React.createElement(
|
|
2388
|
+
"dl",
|
|
2389
|
+
null,
|
|
2390
|
+
fact(t("connectionId"), detailValue(network.connectionId), !0),
|
|
2391
|
+
fact(t("connectedAt"), network.connectedAt === void 0 ? t("notProvided") : formatLocalTime(network.connectedAt)),
|
|
2392
|
+
fact(t("preferredTransports"), network.preferredTransports.map((value) => transportLabel(value, t)).join(" \u2192 ")),
|
|
2393
|
+
fact(t("controlChannel"), `WebSocket \xB7 ${controlStateLabel}`),
|
|
2394
|
+
fact(t("controlAddress"), network.controlChannelUrl, !0)
|
|
2395
|
+
)
|
|
2396
|
+
),
|
|
2397
|
+
webRtc === void 0 ? null : React.createElement(
|
|
2398
|
+
"section",
|
|
2399
|
+
{ className: "dshRemoteRouteSection" },
|
|
2400
|
+
React.createElement("h3", null, t("connectionDetailsWebRtc")),
|
|
2401
|
+
React.createElement(
|
|
2402
|
+
"dl",
|
|
2403
|
+
null,
|
|
2404
|
+
fact(t("peerState"), `${webRtc.connectionState} \xB7 ICE ${webRtc.iceConnectionState}`),
|
|
2405
|
+
fact(t("dataChannel"), detailValue(webRtc.dataChannelState)),
|
|
2406
|
+
fact(t("localCandidate"), candidateLabel(webRtc.localCandidateType)),
|
|
2407
|
+
fact(t("remoteCandidate"), candidateLabel(webRtc.remoteCandidateType)),
|
|
2408
|
+
fact(t("localAddress"), detailValue(webRtc.localAddress), !0),
|
|
2409
|
+
fact(t("remoteAddress"), detailValue(webRtc.remoteAddress), !0),
|
|
2410
|
+
fact(t("networkProtocol"), detailValue(webRtc.protocol?.toUpperCase())),
|
|
2411
|
+
fact(t("relayProtocol"), detailValue(webRtc.relayProtocol?.toUpperCase())),
|
|
2412
|
+
fact(t("roundTripTime"), webRtc.currentRoundTripTimeMs === void 0 ? t("notProvided") : `${webRtc.currentRoundTripTimeMs.toLocaleString()} ms`),
|
|
2413
|
+
fact(t("availableBitrate"), webRtc.availableOutgoingBitrate === void 0 ? t("notProvided") : formatBitrate(webRtc.availableOutgoingBitrate)),
|
|
2414
|
+
fact(t("bytesSent"), webRtc.bytesSent === void 0 ? t("notProvided") : formatByteSize(webRtc.bytesSent)),
|
|
2415
|
+
fact(t("bytesReceived"), webRtc.bytesReceived === void 0 ? t("notProvided") : formatByteSize(webRtc.bytesReceived))
|
|
2416
|
+
)
|
|
2417
|
+
),
|
|
2418
|
+
React.createElement("p", null, t("connectionRouteEncrypted"))
|
|
2419
|
+
)) : null
|
|
2420
|
+
);
|
|
2421
|
+
}
|
|
2422
|
+
return RemoteSessionHeaderAction;
|
|
2423
|
+
}
|
|
2424
|
+
function hideLocalSessionActions() {
|
|
2425
|
+
let selector = 'button,a,[role="button"]', hiddenAttribute = "data-dsh-remote-hidden-action", localAction = /(?:open|打开).{0,12}vs\s*code|vs\s*code.{0,12}(?:open|打开)|session\s*logs?|download.{0,12}session\s*logs?|会话日志|下载.{0,8}日志/i, inspect = (root) => {
|
|
2426
|
+
let candidates = root instanceof Element && root.matches(selector) ? [root, ...Array.from(root.querySelectorAll(selector))] : Array.from(root.querySelectorAll(selector));
|
|
2427
|
+
for (let candidate of candidates) {
|
|
2428
|
+
if (candidate.closest(".dshRemoteSessionHeader") !== null) continue;
|
|
2429
|
+
let label = [
|
|
2430
|
+
candidate.getAttribute("aria-label"),
|
|
2431
|
+
candidate.getAttribute("title"),
|
|
2432
|
+
candidate.getAttribute("data-tooltip"),
|
|
2433
|
+
candidate.textContent
|
|
2434
|
+
].filter(Boolean).join(" ");
|
|
2435
|
+
localAction.test(label) && candidate.setAttribute(hiddenAttribute, "");
|
|
2616
2436
|
}
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2437
|
+
};
|
|
2438
|
+
inspect(document.body);
|
|
2439
|
+
let observer = new MutationObserver((records) => {
|
|
2440
|
+
for (let record of records) {
|
|
2441
|
+
record.type === "attributes" && inspect(record.target);
|
|
2442
|
+
for (let node of Array.from(record.addedNodes))
|
|
2443
|
+
node instanceof Element && inspect(node);
|
|
2444
|
+
}
|
|
2445
|
+
});
|
|
2446
|
+
return observer.observe(document.body, {
|
|
2447
|
+
subtree: !0,
|
|
2448
|
+
childList: !0,
|
|
2449
|
+
attributes: !0,
|
|
2450
|
+
attributeFilter: ["aria-label", "title", "data-tooltip"]
|
|
2451
|
+
}), () => {
|
|
2452
|
+
observer.disconnect(), document.querySelectorAll(`[${hiddenAttribute}]`).forEach((element) => element.removeAttribute(hiddenAttribute));
|
|
2453
|
+
};
|
|
2454
|
+
}
|
|
2455
|
+
|
|
2456
|
+
// src/client/navigation.ts
|
|
2457
|
+
var pendingWorkspaceSelectionKey = "dsh-remote:pending-workspace-selection";
|
|
2458
|
+
function storedWorkspaceSelection() {
|
|
2459
|
+
let raw = window.sessionStorage.getItem(pendingWorkspaceSelectionKey);
|
|
2460
|
+
if (raw !== null)
|
|
2461
|
+
try {
|
|
2462
|
+
let value = JSON.parse(raw);
|
|
2463
|
+
if (typeof value.targetDeviceId != "string" || typeof value.workspaceId != "string") throw new Error("invalid");
|
|
2464
|
+
if (value.backend !== void 0 && value.backend !== "harness" && value.backend !== "codex" && value.backend !== "cursor" && value.backend !== "antigravity" && value.backend !== "pi" && value.backend !== "opencode") throw new Error("invalid");
|
|
2465
|
+
if (value.sessionId !== void 0 && typeof value.sessionId != "string") throw new Error("invalid");
|
|
2466
|
+
return value;
|
|
2467
|
+
} catch {
|
|
2468
|
+
window.sessionStorage.removeItem(pendingWorkspaceSelectionKey);
|
|
2469
|
+
return;
|
|
2470
|
+
}
|
|
2471
|
+
}
|
|
2472
|
+
function workspacesReady(snapshot) {
|
|
2473
|
+
return snapshot.baselinesReady === !0 || snapshot.phase === "ready";
|
|
2474
|
+
}
|
|
2475
|
+
|
|
2476
|
+
// src/client/progress.ts
|
|
2477
|
+
function createRemoteProgressView(React) {
|
|
2478
|
+
function RemoteProgressView(props) {
|
|
2479
|
+
let progress = props.progress;
|
|
2480
|
+
if (progress === void 0) return null;
|
|
2481
|
+
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(
|
|
2482
|
+
"span",
|
|
2483
|
+
{ className: "dshRemoteProgressRoute" },
|
|
2484
|
+
props.t(progress.routeVerb === "using" ? "remoteProgressUsingPrefix" : "remoteProgressTryingPrefix"),
|
|
2485
|
+
progress.transports.map((transport, index) => React.createElement(
|
|
2486
|
+
React.Fragment,
|
|
2487
|
+
{ key: `${transport}:${index}` },
|
|
2488
|
+
index === 0 ? null : React.createElement("span", { className: "dshRemoteProgressRouteArrow", "aria-hidden": !0 }, " -> "),
|
|
2489
|
+
React.createElement("span", {
|
|
2490
|
+
className: activeTransports.has(transport) ? "isActive" : void 0
|
|
2491
|
+
}, transportDiagnosticLabel(transport))
|
|
2492
|
+
))
|
|
2493
|
+
) : props.t(progress.detail);
|
|
2494
|
+
return React.createElement(
|
|
2495
|
+
"div",
|
|
2496
|
+
{
|
|
2497
|
+
className: "dshRemoteProgress",
|
|
2498
|
+
role: "status",
|
|
2499
|
+
"aria-live": "polite"
|
|
2500
|
+
},
|
|
2501
|
+
React.createElement(
|
|
2502
|
+
"div",
|
|
2503
|
+
{ className: "dshRemoteProgressHeader" },
|
|
2504
|
+
React.createElement("strong", null, props.t(progress.label)),
|
|
2505
|
+
React.createElement("span", null, `${percent}%`)
|
|
2506
|
+
),
|
|
2507
|
+
React.createElement("p", null, detail),
|
|
2508
|
+
React.createElement("div", {
|
|
2509
|
+
className: "dshRemoteProgressBar",
|
|
2510
|
+
role: "progressbar",
|
|
2511
|
+
"aria-valuemin": 0,
|
|
2512
|
+
"aria-valuemax": 100,
|
|
2513
|
+
"aria-valuenow": percent,
|
|
2514
|
+
"aria-label": props.t(progress.label)
|
|
2515
|
+
}, React.createElement("span", { style: { transform: `scaleX(${percent / 100})` } }))
|
|
2516
|
+
);
|
|
2517
|
+
}
|
|
2518
|
+
return RemoteProgressView;
|
|
2519
|
+
}
|
|
2520
|
+
async function runConnectHostProgress(preferredTransports, targetDeviceId, control, connectedStep, setProgress, progressRun, action, readyProgress) {
|
|
2521
|
+
let runId = progressRun.current + 1;
|
|
2522
|
+
progressRun.current = runId;
|
|
2523
|
+
let polling = !0, pollTimer, connectedAt, apply = (next) => {
|
|
2524
|
+
progressRun.current === runId && setProgress(next);
|
|
2525
|
+
}, poll = async () => {
|
|
2526
|
+
try {
|
|
2527
|
+
let status = await control("status");
|
|
2528
|
+
if (!polling || progressRun.current !== runId) return;
|
|
2529
|
+
(status.connectionProgress?.phase === "connected" || status.connectedTargetDeviceId === targetDeviceId) && connectedAt === void 0 && (connectedAt = Date.now());
|
|
2530
|
+
let next = observedConnectionProgress(status, targetDeviceId, preferredTransports, connectedStep, connectedAt);
|
|
2531
|
+
next !== void 0 && apply(next);
|
|
2532
|
+
} catch {
|
|
2533
|
+
} finally {
|
|
2534
|
+
polling && progressRun.current === runId && (pollTimer = window.setTimeout(() => {
|
|
2535
|
+
poll();
|
|
2536
|
+
}, 300));
|
|
2645
2537
|
}
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
let view = await props.control("settings.logout");
|
|
2683
|
-
applyView(view), setRegistrationCode(""), setNotice({ key: "signedOut" });
|
|
2684
|
-
} catch (reason) {
|
|
2685
|
-
setError(messageOf(reason));
|
|
2686
|
-
} finally {
|
|
2687
|
-
setBusy(!1);
|
|
2688
|
-
}
|
|
2689
|
-
}, reconnectHost = async () => {
|
|
2690
|
-
setReconnectBusy(!0), setError(void 0), setNotice(void 0);
|
|
2691
|
-
try {
|
|
2692
|
-
let status = await props.control("host.reconnect");
|
|
2693
|
-
setHostStatus(status.host), setNotice({ key: "reconnectStarted" });
|
|
2694
|
-
} catch (reason) {
|
|
2695
|
-
setError(messageOf(reason));
|
|
2696
|
-
} finally {
|
|
2697
|
-
setReconnectBusy(!1);
|
|
2698
|
-
}
|
|
2699
|
-
}, setCurrentDeviceControl = async (enabled) => {
|
|
2700
|
-
setBusy(!0), setError(void 0), setNotice(void 0);
|
|
2701
|
-
try {
|
|
2702
|
-
let status = await props.control("host.authorization.set", { enabled });
|
|
2703
|
-
setHostStatus(status.host);
|
|
2704
|
-
} catch (reason) {
|
|
2705
|
-
setError(messageOf(reason));
|
|
2706
|
-
} finally {
|
|
2707
|
-
setBusy(!1);
|
|
2708
|
-
}
|
|
2709
|
-
}, setTerminalRemote = async (enabled) => {
|
|
2710
|
-
let previous = terminalEnabled, portsDraft = previewPorts;
|
|
2711
|
-
setTerminalEnabled(enabled), setTerminalBusy(!0), setError(void 0), setNotice(void 0);
|
|
2712
|
-
try {
|
|
2713
|
-
let view = await props.control("settings.development.set", { terminalEnabled: enabled });
|
|
2714
|
-
applyView(view), setPreviewPorts(portsDraft), setNotice({ key: "terminalSaved" });
|
|
2715
|
-
} catch (reason) {
|
|
2716
|
-
setTerminalEnabled(previous), setError(messageOf(reason));
|
|
2717
|
-
} finally {
|
|
2718
|
-
setTerminalBusy(!1);
|
|
2719
|
-
}
|
|
2720
|
-
}, savePreviewPorts = async () => {
|
|
2721
|
-
setPortsBusy(!0), setError(void 0), setNotice(void 0);
|
|
2722
|
-
try {
|
|
2723
|
-
let ports = previewPorts.trim() === "" ? [] : previewPorts.split(/[,,]/).map((value) => Number(value.trim())), view = await props.control("settings.development.set", { ports });
|
|
2724
|
-
applyView(view), setNotice({ key: "developmentSaved" });
|
|
2725
|
-
} catch (reason) {
|
|
2726
|
-
setError(messageOf(reason));
|
|
2727
|
-
} finally {
|
|
2728
|
-
setPortsBusy(!1);
|
|
2729
|
-
}
|
|
2730
|
-
}, checkAcp = async (backend) => {
|
|
2731
|
-
if (!acpChecking[backend]) {
|
|
2732
|
-
setAcpChecking((current) => ({ ...current, [backend]: !0 })), setAcpCheckResults((current) => ({ ...current, [backend]: void 0 })), setError(void 0);
|
|
2733
|
-
try {
|
|
2734
|
-
let view = await props.control("settings.get");
|
|
2735
|
-
applyView(view);
|
|
2736
|
-
let available = view.acpAvailability?.[backend] === !0;
|
|
2737
|
-
!available && view.writable && view.config.acp?.backends?.some((item) => item.id === backend && item.enabled !== !1) && applyView(await props.control("settings.acp.set", { backend, enabled: !1 })), setAcpCheckResults((current) => ({ ...current, [backend]: available })), setNotice({ key: available ? "acpAvailable" : "acpUnavailable" }), window.setTimeout(() => setAcpCheckResults((current) => ({ ...current, [backend]: void 0 })), 5e3);
|
|
2738
|
-
} catch (reason) {
|
|
2739
|
-
setError(messageOf(reason));
|
|
2740
|
-
} finally {
|
|
2741
|
-
setAcpChecking((current) => ({ ...current, [backend]: !1 }));
|
|
2742
|
-
}
|
|
2743
|
-
}
|
|
2744
|
-
}, addAcp = async () => {
|
|
2745
|
-
setBusy(!0), setError(void 0);
|
|
2538
|
+
};
|
|
2539
|
+
apply({ label: "remoteProgressCheckingHost", detail: "remoteProgressCheckingHostDetail", percent: 12 });
|
|
2540
|
+
let pending = action();
|
|
2541
|
+
poll();
|
|
2542
|
+
try {
|
|
2543
|
+
let result = await pending;
|
|
2544
|
+
return polling = !1, pollTimer !== void 0 && window.clearTimeout(pollTimer), apply(readyProgress?.(result) ?? { label: "remoteProgressReady", detail: "remoteProgressReadyDetail", percent: 100 }), await new Promise((resolve) => window.setTimeout(resolve, 520)), result;
|
|
2545
|
+
} finally {
|
|
2546
|
+
polling = !1, pollTimer !== void 0 && window.clearTimeout(pollTimer), progressRun.current === runId && setProgress(void 0);
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2549
|
+
|
|
2550
|
+
// src/client/settings.ts
|
|
2551
|
+
function createRemotePluginOptions(React) {
|
|
2552
|
+
function RemotePluginOptions(props) {
|
|
2553
|
+
let { t } = props, [open, setOpen] = React.useState(props.view === "page"), [serverUrl, setServerUrl] = React.useState(""), [portsBusy, setPortsBusy] = React.useState(!1), [previewPorts, setPreviewPorts] = React.useState(""), 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), [terminalEnabled, setTerminalEnabled] = React.useState(!1), [terminalBusy, setTerminalBusy] = React.useState(!1), [acpBackends, setAcpBackends] = React.useState([]), [acpAvailability, setAcpAvailability] = React.useState({}), [acpChecking, setAcpChecking] = React.useState({}), [acpCheckResults, setAcpCheckResults] = React.useState({}), [addingAcp, setAddingAcp] = React.useState(!1), [acpName, setAcpName] = React.useState(""), [acpCommand, setAcpCommand] = React.useState(""), [acpArguments, setAcpArguments] = React.useState("acp"), [reconnectBusy, setReconnectBusy] = React.useState(!1), [hostStatus, setHostStatus] = React.useState(void 0), [hostName, setHostName] = React.useState(""), [hostDeviceId, setHostDeviceId] = React.useState(""), [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) => {
|
|
2554
|
+
setSettingsView(view), setServerUrl(view.config.serverUrl ?? "https://dsh.r2049.cn"), setTerminalEnabled(view.config.terminal?.enabled ?? !0), setPreviewPorts((view.config.loopback?.ports ?? []).join(", ")), setAcpBackends((view.config.acp?.backends ?? []).map((item) => ({ id: item.id, enabled: item.enabled !== !1 }))), setAcpAvailability(view.acpAvailability ?? {}), setAssociations(view.associations ?? (view.association === void 0 ? {} : { host: view.association })), setWritable(view.writable), setLoaded(!0);
|
|
2555
|
+
}, load = async () => {
|
|
2556
|
+
let [view, status] = await Promise.all([
|
|
2557
|
+
props.control("settings.get"),
|
|
2558
|
+
props.control("status").catch(() => {
|
|
2559
|
+
})
|
|
2560
|
+
]);
|
|
2561
|
+
applyView(view), setHostStatus(status?.host), setHostName(status?.deviceName ?? ""), setHostDeviceId(status?.host?.deviceId ?? "");
|
|
2562
|
+
};
|
|
2563
|
+
React.useEffect(() => {
|
|
2564
|
+
load().catch((reason) => setError(messageOf(reason)));
|
|
2565
|
+
}, []), React.useEffect(() => {
|
|
2566
|
+
if (association !== void 0)
|
|
2567
|
+
return props.statusFeed.subscribe((status) => {
|
|
2568
|
+
setHostStatus(status.host), setHostName(status.deviceName ?? ""), setHostDeviceId(status.host?.deviceId ?? "");
|
|
2569
|
+
});
|
|
2570
|
+
}, [association !== void 0]);
|
|
2571
|
+
let save = async (event) => {
|
|
2572
|
+
if (event?.preventDefault(), !(!writable || !serverDirty)) {
|
|
2573
|
+
setBusy(!0), setNotice(void 0), setError(void 0);
|
|
2746
2574
|
try {
|
|
2747
|
-
let view = await props.control("settings.
|
|
2748
|
-
|
|
2749
|
-
command: acpCommand.trim(),
|
|
2750
|
-
args: acpArguments.trim() === "" ? [] : acpArguments.trim().split(/\s+/)
|
|
2575
|
+
let view = await props.control("settings.server.set", {
|
|
2576
|
+
serverUrl
|
|
2751
2577
|
});
|
|
2752
|
-
applyView(view),
|
|
2578
|
+
applyView(view), setNotice({ key: "serverSaved" });
|
|
2753
2579
|
} catch (reason) {
|
|
2754
2580
|
setError(messageOf(reason));
|
|
2755
2581
|
} finally {
|
|
2756
2582
|
setBusy(!1);
|
|
2757
2583
|
}
|
|
2758
|
-
}
|
|
2759
|
-
|
|
2584
|
+
}
|
|
2585
|
+
}, logout = async () => {
|
|
2586
|
+
setBusy(!0), setError(void 0), setNotice(void 0);
|
|
2587
|
+
try {
|
|
2588
|
+
let view = await props.control("settings.logout");
|
|
2589
|
+
applyView(view), setRegistrationCode(""), setNotice({ key: "signedOut" });
|
|
2590
|
+
} catch (reason) {
|
|
2591
|
+
setError(messageOf(reason));
|
|
2592
|
+
} finally {
|
|
2593
|
+
setBusy(!1);
|
|
2594
|
+
}
|
|
2595
|
+
}, reconnectHost = async () => {
|
|
2596
|
+
setReconnectBusy(!0), setError(void 0), setNotice(void 0);
|
|
2597
|
+
try {
|
|
2598
|
+
let status = await props.control("host.reconnect");
|
|
2599
|
+
setHostStatus(status.host), setNotice({ key: "reconnectStarted" });
|
|
2600
|
+
} catch (reason) {
|
|
2601
|
+
setError(messageOf(reason));
|
|
2602
|
+
} finally {
|
|
2603
|
+
setReconnectBusy(!1);
|
|
2604
|
+
}
|
|
2605
|
+
}, setCurrentDeviceControl = async (enabled) => {
|
|
2606
|
+
setBusy(!0), setError(void 0), setNotice(void 0);
|
|
2607
|
+
try {
|
|
2608
|
+
let status = await props.control("host.authorization.set", { enabled });
|
|
2609
|
+
setHostStatus(status.host);
|
|
2610
|
+
} catch (reason) {
|
|
2611
|
+
setError(messageOf(reason));
|
|
2612
|
+
} finally {
|
|
2613
|
+
setBusy(!1);
|
|
2614
|
+
}
|
|
2615
|
+
}, setTerminalRemote = async (enabled) => {
|
|
2616
|
+
let previous = terminalEnabled, portsDraft = previewPorts;
|
|
2617
|
+
setTerminalEnabled(enabled), setTerminalBusy(!0), setError(void 0), setNotice(void 0);
|
|
2618
|
+
try {
|
|
2619
|
+
let view = await props.control("settings.development.set", { terminalEnabled: enabled });
|
|
2620
|
+
applyView(view), setPreviewPorts(portsDraft), setNotice({ key: "terminalSaved" });
|
|
2621
|
+
} catch (reason) {
|
|
2622
|
+
setTerminalEnabled(previous), setError(messageOf(reason));
|
|
2623
|
+
} finally {
|
|
2624
|
+
setTerminalBusy(!1);
|
|
2625
|
+
}
|
|
2626
|
+
}, savePreviewPorts = async () => {
|
|
2627
|
+
setPortsBusy(!0), setError(void 0), setNotice(void 0);
|
|
2628
|
+
try {
|
|
2629
|
+
let ports = previewPorts.trim() === "" ? [] : previewPorts.split(/[,,]/).map((value) => Number(value.trim())), view = await props.control("settings.development.set", { ports });
|
|
2630
|
+
applyView(view), setNotice({ key: "developmentSaved" });
|
|
2631
|
+
} catch (reason) {
|
|
2632
|
+
setError(messageOf(reason));
|
|
2633
|
+
} finally {
|
|
2634
|
+
setPortsBusy(!1);
|
|
2635
|
+
}
|
|
2636
|
+
}, checkAcp = async (backend) => {
|
|
2637
|
+
if (!acpChecking[backend]) {
|
|
2638
|
+
setAcpChecking((current) => ({ ...current, [backend]: !0 })), setAcpCheckResults((current) => ({ ...current, [backend]: void 0 })), setError(void 0);
|
|
2760
2639
|
try {
|
|
2761
|
-
let view = await props.control("settings.
|
|
2640
|
+
let view = await props.control("settings.get");
|
|
2762
2641
|
applyView(view);
|
|
2642
|
+
let available = view.acpAvailability?.[backend] === !0;
|
|
2643
|
+
!available && view.writable && view.config.acp?.backends?.some((item) => item.id === backend && item.enabled !== !1) && applyView(await props.control("settings.acp.set", { backend, enabled: !1 })), setAcpCheckResults((current) => ({ ...current, [backend]: available })), setNotice({ key: available ? "acpAvailable" : "acpUnavailable" }), window.setTimeout(() => setAcpCheckResults((current) => ({ ...current, [backend]: void 0 })), 5e3);
|
|
2763
2644
|
} catch (reason) {
|
|
2764
2645
|
setError(messageOf(reason));
|
|
2765
2646
|
} finally {
|
|
2766
|
-
|
|
2647
|
+
setAcpChecking((current) => ({ ...current, [backend]: !1 }));
|
|
2767
2648
|
}
|
|
2768
|
-
}
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2649
|
+
}
|
|
2650
|
+
}, addAcp = async () => {
|
|
2651
|
+
setBusy(!0), setError(void 0);
|
|
2652
|
+
try {
|
|
2653
|
+
let view = await props.control("settings.acp.add", {
|
|
2654
|
+
id: acpName.trim(),
|
|
2655
|
+
command: acpCommand.trim(),
|
|
2656
|
+
args: acpArguments.trim() === "" ? [] : acpArguments.trim().split(/\s+/)
|
|
2657
|
+
});
|
|
2658
|
+
applyView(view), setAddingAcp(!1), setAcpName(""), setAcpCommand(""), setAcpArguments("acp");
|
|
2659
|
+
} catch (reason) {
|
|
2660
|
+
setError(messageOf(reason));
|
|
2661
|
+
} finally {
|
|
2662
|
+
setBusy(!1);
|
|
2663
|
+
}
|
|
2664
|
+
}, removeAcp = async (backend) => {
|
|
2665
|
+
setBusy(!0), setError(void 0);
|
|
2666
|
+
try {
|
|
2667
|
+
let view = await props.control("settings.acp.remove", { id: backend });
|
|
2668
|
+
applyView(view);
|
|
2669
|
+
} catch (reason) {
|
|
2670
|
+
setError(messageOf(reason));
|
|
2671
|
+
} finally {
|
|
2672
|
+
setBusy(!1);
|
|
2673
|
+
}
|
|
2674
|
+
}, discard = () => {
|
|
2675
|
+
settingsView !== void 0 && applyView(settingsView), setRegistrationCode(""), setNotice(void 0), setError(void 0);
|
|
2676
|
+
}, developmentSetting = React.createElement(
|
|
2677
|
+
"section",
|
|
2678
|
+
{ className: "dshRemoteDevelopmentSettings" },
|
|
2679
|
+
React.createElement(
|
|
2680
|
+
"div",
|
|
2681
|
+
{ className: "dshRemoteAuthorizationSetting" },
|
|
2682
|
+
React.createElement(
|
|
2683
|
+
"div",
|
|
2684
|
+
null,
|
|
2685
|
+
React.createElement("strong", null, t("terminalRemote")),
|
|
2686
|
+
React.createElement("p", null, t("terminalRemoteHint"))
|
|
2687
|
+
),
|
|
2688
|
+
React.createElement("input", {
|
|
2689
|
+
type: "checkbox",
|
|
2690
|
+
role: "switch",
|
|
2691
|
+
checked: terminalEnabled,
|
|
2692
|
+
disabled: busy || terminalBusy || !writable,
|
|
2693
|
+
"aria-label": t("terminalRemote"),
|
|
2694
|
+
onChange: (event) => void setTerminalRemote(event.target.checked)
|
|
2695
|
+
})
|
|
2696
|
+
),
|
|
2697
|
+
React.createElement(
|
|
2698
|
+
"div",
|
|
2699
|
+
{ className: "dshRemotePathField" },
|
|
2700
|
+
React.createElement("label", { htmlFor: "dsh-remote-preview-ports" }, t("previewPorts")),
|
|
2701
|
+
React.createElement(
|
|
2702
|
+
"div",
|
|
2703
|
+
{ className: "dshRemotePortsRow" },
|
|
2704
|
+
React.createElement("input", {
|
|
2705
|
+
id: "dsh-remote-preview-ports",
|
|
2706
|
+
value: previewPorts,
|
|
2707
|
+
maxLength: 128,
|
|
2708
|
+
size: 24,
|
|
2709
|
+
disabled: !writable,
|
|
2710
|
+
placeholder: "3000, 5173",
|
|
2711
|
+
"aria-label": t("previewPorts"),
|
|
2712
|
+
onChange: (event) => setPreviewPorts(event.target.value)
|
|
2713
|
+
}),
|
|
2714
|
+
React.createElement("button", {
|
|
2715
|
+
type: "button",
|
|
2716
|
+
disabled: portsBusy || terminalBusy || !writable,
|
|
2717
|
+
onClick: () => void savePreviewPorts()
|
|
2718
|
+
}, t("developmentSave"))
|
|
2719
|
+
),
|
|
2720
|
+
React.createElement("small", null, t("previewPortsHint"))
|
|
2721
|
+
)
|
|
2722
|
+
), acpSetting = React.createElement(
|
|
2723
|
+
"details",
|
|
2724
|
+
{ className: "dshRemoteAuthorizationSetting dshRemoteAcpSetting" },
|
|
2725
|
+
React.createElement(
|
|
2726
|
+
"summary",
|
|
2727
|
+
null,
|
|
2773
2728
|
React.createElement(
|
|
2774
2729
|
"div",
|
|
2775
|
-
{ className: "
|
|
2730
|
+
{ className: "dshRemoteAcpSummaryText" },
|
|
2731
|
+
React.createElement("strong", null, t("agentBackends")),
|
|
2732
|
+
React.createElement("p", null, t("acpHint"), React.createElement("a", {
|
|
2733
|
+
href: "https://github.com/liguobao/ds-harness-remote/blob/feat/cursor-remote/docs/acp-remote.md",
|
|
2734
|
+
target: "_blank",
|
|
2735
|
+
rel: "noopener noreferrer",
|
|
2736
|
+
onClick: (event) => event.stopPropagation()
|
|
2737
|
+
}, t("acpDocumentation")))
|
|
2738
|
+
)
|
|
2739
|
+
),
|
|
2740
|
+
React.createElement(
|
|
2741
|
+
"div",
|
|
2742
|
+
{ className: "dshRemoteAcpList" },
|
|
2743
|
+
acpBackends.map((item) => React.createElement(
|
|
2744
|
+
"div",
|
|
2745
|
+
{ key: item.id, className: "dshRemoteAuthorizationSetting" },
|
|
2746
|
+
React.createElement("div", null, React.createElement("strong", null, item.id === "codex" ? "CodeX" : item.id === "cursor" ? "Cursor" : item.id === "antigravity" ? "AGY" : item.id === "pi" ? "PI" : item.id === "opencode" ? "OpenCode" : item.id), null),
|
|
2776
2747
|
React.createElement(
|
|
2777
|
-
"
|
|
2778
|
-
|
|
2779
|
-
React.createElement(
|
|
2780
|
-
|
|
2748
|
+
"span",
|
|
2749
|
+
{ className: "dshRemoteAcpCheckCell" },
|
|
2750
|
+
React.createElement(
|
|
2751
|
+
"a",
|
|
2752
|
+
{ href: `#check-acp-${item.id}`, className: `dshRemoteAcpCheckLink${acpChecking[item.id] ? " isChecking" : acpCheckResults[item.id] === void 0 ? "" : acpCheckResults[item.id] ? " isPassed" : " isFailed"}`, onClick: (event) => {
|
|
2753
|
+
event.preventDefault(), checkAcp(item.id);
|
|
2754
|
+
} },
|
|
2755
|
+
acpChecking[item.id] ? t("checkingAcp") : acpCheckResults[item.id] === void 0 ? t("checkAcp") : t(acpCheckResults[item.id] ? "acpCheckPassed" : "acpCheckFailed")
|
|
2756
|
+
)
|
|
2781
2757
|
),
|
|
2758
|
+
["codex", "cursor", "antigravity", "pi", "opencode"].includes(item.id) ? null : React.createElement("a", { href: `#remove-acp-${item.id}`, className: "dshRemoteAcpRemoveLink", onClick: (event) => {
|
|
2759
|
+
event.preventDefault(), removeAcp(item.id);
|
|
2760
|
+
} }, t("removeAcp")),
|
|
2782
2761
|
React.createElement("input", {
|
|
2783
2762
|
type: "checkbox",
|
|
2784
2763
|
role: "switch",
|
|
2785
|
-
checked:
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
onChange: (event) => void
|
|
2764
|
+
checked: settingsView?.config.acp?.enabled === !0 && item.enabled && acpAvailability[item.id] === !0,
|
|
2765
|
+
"aria-label": item.id,
|
|
2766
|
+
disabled: busy || !writable || acpChecking[item.id] === !0 || acpAvailability[item.id] !== !0,
|
|
2767
|
+
onChange: (event) => void props.control("settings.acp.set", { backend: item.id, enabled: event.target.checked }).then((view) => {
|
|
2768
|
+
applyView(view), setAcpBackends((view.config.acp?.backends ?? []).map((v) => ({ id: v.id, enabled: v.enabled !== !1 })));
|
|
2769
|
+
}).catch((reason) => setError(messageOf(reason)))
|
|
2789
2770
|
})
|
|
2790
|
-
),
|
|
2791
|
-
React.createElement(
|
|
2771
|
+
)),
|
|
2772
|
+
addingAcp ? React.createElement(
|
|
2792
2773
|
"div",
|
|
2793
|
-
{ className: "
|
|
2794
|
-
React.createElement("label", {
|
|
2795
|
-
React.createElement(
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
type: "button",
|
|
2810
|
-
disabled: portsBusy || terminalBusy || !writable,
|
|
2811
|
-
onClick: () => void savePreviewPorts()
|
|
2812
|
-
}, t("developmentSave"))
|
|
2813
|
-
),
|
|
2814
|
-
React.createElement("small", null, t("previewPortsHint"))
|
|
2815
|
-
)
|
|
2816
|
-
), acpSetting = React.createElement(
|
|
2817
|
-
"details",
|
|
2818
|
-
{ className: "dshRemoteAuthorizationSetting dshRemoteAcpSetting" },
|
|
2774
|
+
{ className: "dshRemoteAcpAddForm" },
|
|
2775
|
+
React.createElement("label", null, t("acpName"), React.createElement("input", { value: acpName, size: 16, placeholder: t("acpName"), "aria-label": t("acpName"), onChange: (event) => setAcpName(event.target.value) })),
|
|
2776
|
+
React.createElement("label", null, t("acpCommand"), React.createElement("input", { value: acpCommand, size: 20, placeholder: t("acpCommand"), "aria-label": t("acpCommand"), onChange: (event) => setAcpCommand(event.target.value) })),
|
|
2777
|
+
React.createElement("label", null, t("acpArguments"), React.createElement("input", { value: acpArguments, size: 20, placeholder: t("acpArguments"), "aria-label": t("acpArguments"), onChange: (event) => setAcpArguments(event.target.value) })),
|
|
2778
|
+
React.createElement("button", { type: "button", disabled: busy || acpName.trim() === "" || acpCommand.trim() === "", onClick: () => void addAcp() }, t("addAcp"))
|
|
2779
|
+
) : React.createElement("a", { href: "#add-acp", className: "dshRemoteAcpAddLink", onClick: (event) => {
|
|
2780
|
+
event.preventDefault(), setAddingAcp(!0);
|
|
2781
|
+
} }, t("addAcp"))
|
|
2782
|
+
)
|
|
2783
|
+
);
|
|
2784
|
+
return props.view === "summary" ? React.createElement("span", null, t("pluginDescription")) : React.createElement(
|
|
2785
|
+
props.view === "page" ? "div" : "li",
|
|
2786
|
+
{ className: `dshRemotePluginCard${open ? " isOpen" : ""}${props.view === "page" ? " dshRemotePluginModern" : ""}` },
|
|
2787
|
+
React.createElement(
|
|
2788
|
+
"div",
|
|
2789
|
+
{ className: "dshRemotePluginCardHeader" },
|
|
2819
2790
|
React.createElement(
|
|
2820
|
-
"
|
|
2821
|
-
|
|
2791
|
+
"button",
|
|
2792
|
+
{
|
|
2793
|
+
type: "button",
|
|
2794
|
+
className: "dshRemotePluginCardToggle",
|
|
2795
|
+
"aria-expanded": open,
|
|
2796
|
+
"aria-label": t(open ? "collapseSettings" : "expandSettings", { name: t("pluginTitle") }),
|
|
2797
|
+
onClick: () => setOpen((current) => !current)
|
|
2798
|
+
},
|
|
2822
2799
|
React.createElement(
|
|
2823
|
-
"
|
|
2824
|
-
{ className: "
|
|
2825
|
-
React.createElement("strong", null, t("
|
|
2826
|
-
React.createElement("
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
)
|
|
2833
|
-
),
|
|
2834
|
-
React.createElement(
|
|
2835
|
-
"div",
|
|
2836
|
-
{ className: "dshRemoteAcpList" },
|
|
2837
|
-
acpBackends.map((item) => React.createElement(
|
|
2838
|
-
"div",
|
|
2839
|
-
{ key: item.id, className: "dshRemoteAuthorizationSetting" },
|
|
2840
|
-
React.createElement("div", null, React.createElement("strong", null, item.id === "codex" ? "CodeX" : item.id === "cursor" ? "Cursor" : item.id === "antigravity" ? "AGY" : item.id), null),
|
|
2841
|
-
React.createElement(
|
|
2842
|
-
"span",
|
|
2843
|
-
{ className: "dshRemoteAcpCheckCell" },
|
|
2844
|
-
React.createElement(
|
|
2845
|
-
"a",
|
|
2846
|
-
{ href: `#check-acp-${item.id}`, className: `dshRemoteAcpCheckLink${acpChecking[item.id] ? " isChecking" : acpCheckResults[item.id] === void 0 ? "" : acpCheckResults[item.id] ? " isPassed" : " isFailed"}`, onClick: (event) => {
|
|
2847
|
-
event.preventDefault(), checkAcp(item.id);
|
|
2848
|
-
} },
|
|
2849
|
-
acpChecking[item.id] ? t("checkingAcp") : acpCheckResults[item.id] === void 0 ? t("checkAcp") : t(acpCheckResults[item.id] ? "acpCheckPassed" : "acpCheckFailed")
|
|
2850
|
-
)
|
|
2851
|
-
),
|
|
2852
|
-
["codex", "cursor", "antigravity"].includes(item.id) ? null : React.createElement("a", { href: `#remove-acp-${item.id}`, className: "dshRemoteAcpRemoveLink", onClick: (event) => {
|
|
2853
|
-
event.preventDefault(), removeAcp(item.id);
|
|
2854
|
-
} }, t("removeAcp")),
|
|
2855
|
-
React.createElement("input", {
|
|
2856
|
-
type: "checkbox",
|
|
2857
|
-
role: "switch",
|
|
2858
|
-
checked: settingsView?.config.acp?.enabled === !0 && item.enabled && acpAvailability[item.id] === !0,
|
|
2859
|
-
"aria-label": item.id,
|
|
2860
|
-
disabled: busy || !writable || acpChecking[item.id] === !0 || acpAvailability[item.id] !== !0,
|
|
2861
|
-
onChange: (event) => void props.control("settings.acp.set", { backend: item.id, enabled: event.target.checked }).then((view) => {
|
|
2862
|
-
applyView(view), setAcpBackends((view.config.acp?.backends ?? []).map((v) => ({ id: v.id, enabled: v.enabled !== !1 })));
|
|
2863
|
-
}).catch((reason) => setError(messageOf(reason)))
|
|
2864
|
-
})
|
|
2865
|
-
)),
|
|
2866
|
-
addingAcp ? React.createElement(
|
|
2867
|
-
"div",
|
|
2868
|
-
{ className: "dshRemoteAcpAddForm" },
|
|
2869
|
-
React.createElement("label", null, t("acpName"), React.createElement("input", { value: acpName, size: 16, placeholder: t("acpName"), "aria-label": t("acpName"), onChange: (event) => setAcpName(event.target.value) })),
|
|
2870
|
-
React.createElement("label", null, t("acpCommand"), React.createElement("input", { value: acpCommand, size: 20, placeholder: t("acpCommand"), "aria-label": t("acpCommand"), onChange: (event) => setAcpCommand(event.target.value) })),
|
|
2871
|
-
React.createElement("label", null, t("acpArguments"), React.createElement("input", { value: acpArguments, size: 20, placeholder: t("acpArguments"), "aria-label": t("acpArguments"), onChange: (event) => setAcpArguments(event.target.value) })),
|
|
2872
|
-
React.createElement("button", { type: "button", disabled: busy || acpName.trim() === "" || acpCommand.trim() === "", onClick: () => void addAcp() }, t("addAcp"))
|
|
2873
|
-
) : React.createElement("a", { href: "#add-acp", className: "dshRemoteAcpAddLink", onClick: (event) => {
|
|
2874
|
-
event.preventDefault(), setAddingAcp(!0);
|
|
2875
|
-
} }, t("addAcp"))
|
|
2800
|
+
"span",
|
|
2801
|
+
{ className: "dshRemotePluginCardHeading" },
|
|
2802
|
+
React.createElement("strong", null, t("pluginTitle")),
|
|
2803
|
+
React.createElement("span", null, t("pluginDescription"))
|
|
2804
|
+
),
|
|
2805
|
+
draftDirty ? React.createElement("span", { className: "dshRemotePluginCardStatus" }, t("unsaved")) : association === void 0 ? null : React.createElement("span", {
|
|
2806
|
+
className: `dshRemotePluginCardStatus${connectionStatusClass(hostStatus)}`
|
|
2807
|
+
}, hostStatus === void 0 ? t("associated") : connectionStatusLabel(hostStatus, t)),
|
|
2808
|
+
React.createElement("span", { className: "dshRemotePluginCardChevron", "aria-hidden": !0 }, "\u2304")
|
|
2876
2809
|
)
|
|
2877
|
-
)
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
{ className:
|
|
2881
|
-
React.createElement(
|
|
2810
|
+
),
|
|
2811
|
+
open ? React.createElement(
|
|
2812
|
+
"div",
|
|
2813
|
+
{ className: "dshRemotePluginCardBody" },
|
|
2814
|
+
loaded ? association !== void 0 ? React.createElement(
|
|
2882
2815
|
"div",
|
|
2883
|
-
{ className: "
|
|
2816
|
+
{ className: "dshRemoteSettings" },
|
|
2884
2817
|
React.createElement(
|
|
2885
|
-
"button",
|
|
2886
|
-
{
|
|
2887
|
-
type: "button",
|
|
2888
|
-
className: "dshRemotePluginCardToggle",
|
|
2889
|
-
"aria-expanded": open,
|
|
2890
|
-
"aria-label": t(open ? "collapseSettings" : "expandSettings", { name: t("pluginTitle") }),
|
|
2891
|
-
onClick: () => setOpen((current) => !current)
|
|
2892
|
-
},
|
|
2893
|
-
React.createElement(
|
|
2894
|
-
"span",
|
|
2895
|
-
{ className: "dshRemotePluginCardHeading" },
|
|
2896
|
-
React.createElement("strong", null, t("pluginTitle")),
|
|
2897
|
-
React.createElement("span", null, t("pluginDescription"))
|
|
2898
|
-
),
|
|
2899
|
-
draftDirty ? React.createElement("span", { className: "dshRemotePluginCardStatus" }, t("unsaved")) : association === void 0 ? null : React.createElement("span", {
|
|
2900
|
-
className: `dshRemotePluginCardStatus${connectionStatusClass(hostStatus)}`
|
|
2901
|
-
}, hostStatus === void 0 ? t("associated") : connectionStatusLabel(hostStatus, t)),
|
|
2902
|
-
React.createElement("span", { className: "dshRemotePluginCardChevron", "aria-hidden": !0 }, "\u2304")
|
|
2903
|
-
)
|
|
2904
|
-
),
|
|
2905
|
-
open ? React.createElement(
|
|
2906
|
-
"div",
|
|
2907
|
-
{ className: "dshRemotePluginCardBody" },
|
|
2908
|
-
loaded ? association !== void 0 ? React.createElement(
|
|
2909
2818
|
"div",
|
|
2910
|
-
{ className: "
|
|
2911
|
-
React.createElement(
|
|
2912
|
-
"div",
|
|
2913
|
-
{ className: "dshRemoteSettingsTop" },
|
|
2914
|
-
React.createElement(
|
|
2915
|
-
"div",
|
|
2916
|
-
{ className: "dshRemoteAssociation" },
|
|
2917
|
-
React.createElement("span", null, t(association.account === void 0 ? "authorization" : "account")),
|
|
2918
|
-
React.createElement("strong", null, association.account ?? t("authorizationComplete")),
|
|
2919
|
-
React.createElement("p", null, association.account === void 0 ? serverUrl : t("authorizedOn", { role: "Remote", serverUrl }))
|
|
2920
|
-
)
|
|
2921
|
-
),
|
|
2819
|
+
{ className: "dshRemoteSettingsTop" },
|
|
2922
2820
|
React.createElement(
|
|
2923
2821
|
"div",
|
|
2924
|
-
{ className: "
|
|
2925
|
-
React.createElement(
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
null,
|
|
2934
|
-
React.createElement("span", null, t("deviceId")),
|
|
2935
|
-
React.createElement("code", null, hostDeviceId || "\u2014")
|
|
2936
|
-
)
|
|
2937
|
-
),
|
|
2822
|
+
{ className: "dshRemoteAssociation" },
|
|
2823
|
+
React.createElement("span", null, t(association.account === void 0 ? "authorization" : "account")),
|
|
2824
|
+
React.createElement("strong", null, association.account ?? t("authorizationComplete")),
|
|
2825
|
+
React.createElement("p", null, association.account === void 0 ? serverUrl : t("authorizedOn", { role: "Remote", serverUrl }))
|
|
2826
|
+
)
|
|
2827
|
+
),
|
|
2828
|
+
React.createElement(
|
|
2829
|
+
"div",
|
|
2830
|
+
{ className: "dshRemoteHostIdentity" },
|
|
2938
2831
|
React.createElement(
|
|
2939
2832
|
"div",
|
|
2940
|
-
|
|
2941
|
-
React.createElement("
|
|
2942
|
-
React.createElement("
|
|
2943
|
-
id: "dsh-remote-server-url-authorized",
|
|
2944
|
-
type: "url",
|
|
2945
|
-
value: serverUrl,
|
|
2946
|
-
disabled: !0,
|
|
2947
|
-
required: !0,
|
|
2948
|
-
placeholder: "https://dsh.r2049.cn",
|
|
2949
|
-
onChange: (event) => {
|
|
2950
|
-
setServerUrl(event.target.value), setNotice(void 0);
|
|
2951
|
-
}
|
|
2952
|
-
}),
|
|
2953
|
-
React.createElement("p", null, t("serverUrlHint"))
|
|
2833
|
+
null,
|
|
2834
|
+
React.createElement("span", null, t("hostName")),
|
|
2835
|
+
React.createElement("strong", null, hostName || "\u2014")
|
|
2954
2836
|
),
|
|
2955
|
-
developmentSetting,
|
|
2956
|
-
acpSetting,
|
|
2957
2837
|
React.createElement(
|
|
2958
2838
|
"div",
|
|
2959
|
-
|
|
2960
|
-
React.createElement(
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2839
|
+
null,
|
|
2840
|
+
React.createElement("span", null, t("deviceId")),
|
|
2841
|
+
React.createElement("code", null, hostDeviceId || "\u2014")
|
|
2842
|
+
)
|
|
2843
|
+
),
|
|
2844
|
+
React.createElement(
|
|
2845
|
+
"div",
|
|
2846
|
+
{ className: "dshRemoteField" },
|
|
2847
|
+
React.createElement("label", { htmlFor: "dsh-remote-server-url-authorized" }, t("serverUrl")),
|
|
2848
|
+
React.createElement("input", {
|
|
2849
|
+
id: "dsh-remote-server-url-authorized",
|
|
2850
|
+
type: "url",
|
|
2851
|
+
value: serverUrl,
|
|
2852
|
+
disabled: !0,
|
|
2853
|
+
required: !0,
|
|
2854
|
+
placeholder: "https://dsh.r2049.cn",
|
|
2855
|
+
onChange: (event) => {
|
|
2856
|
+
setServerUrl(event.target.value), setNotice(void 0);
|
|
2857
|
+
}
|
|
2858
|
+
}),
|
|
2859
|
+
React.createElement("p", null, t("serverUrlHint"))
|
|
2860
|
+
),
|
|
2861
|
+
developmentSetting,
|
|
2862
|
+
acpSetting,
|
|
2863
|
+
React.createElement(
|
|
2864
|
+
"div",
|
|
2865
|
+
{ className: "dshRemoteAuthorizationSetting" },
|
|
2975
2866
|
React.createElement(
|
|
2976
2867
|
"div",
|
|
2977
|
-
|
|
2978
|
-
React.createElement(
|
|
2979
|
-
|
|
2980
|
-
{ className: "dshRemoteConnectionSummary" },
|
|
2981
|
-
React.createElement("span", null, t("connection")),
|
|
2982
|
-
React.createElement(
|
|
2983
|
-
"strong",
|
|
2984
|
-
null,
|
|
2985
|
-
React.createElement("span", {
|
|
2986
|
-
className: `dshRemoteConnectionDot${connectionStatusClass(hostStatus)}`,
|
|
2987
|
-
"aria-hidden": !0
|
|
2988
|
-
}),
|
|
2989
|
-
connectionStatusLabel(hostStatus, t)
|
|
2990
|
-
),
|
|
2991
|
-
React.createElement("p", null, hostStatus === void 0 ? t("checkingConnection") : hostStatus.lastActiveAt === void 0 ? t("neverConnected") : t("lastActive", { time: formatLocalTime(hostStatus.lastActiveAt) }))
|
|
2992
|
-
),
|
|
2993
|
-
React.createElement("button", {
|
|
2994
|
-
type: "button",
|
|
2995
|
-
className: "dshRemoteReconnect",
|
|
2996
|
-
disabled: reconnectBusy || hostStatus?.configured === !1,
|
|
2997
|
-
onClick: () => void reconnectHost()
|
|
2998
|
-
}, t(reconnectBusy ? "reconnectingAction" : "reconnect"))
|
|
2868
|
+
null,
|
|
2869
|
+
React.createElement("strong", null, t("allowControlCurrentDevice")),
|
|
2870
|
+
React.createElement("p", null, t("thisMachineHost"))
|
|
2999
2871
|
),
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
React.createElement("button", { type: "button", className: "dshRemoteDiscard", disabled: busy, onClick: discard }, t("discard")),
|
|
3013
|
-
React.createElement("button", { type: "button", className: "dshRemoteSave", disabled: busy || !writable, onClick: () => void save() }, t(busy ? "saving" : "save")),
|
|
3014
|
-
React.createElement("button", { type: "button", className: "dshRemoteDiscard", disabled: busy || !writable, onClick: () => void logout() }, t(busy ? "signingOut" : "signOut"))
|
|
3015
|
-
) : React.createElement("button", {
|
|
3016
|
-
type: "button",
|
|
3017
|
-
className: "dshRemoteDiscard",
|
|
3018
|
-
disabled: busy || !writable,
|
|
3019
|
-
onClick: () => void logout()
|
|
3020
|
-
}, t(busy ? "signingOut" : "signOut"))
|
|
3021
|
-
)
|
|
3022
|
-
) : React.createElement(
|
|
3023
|
-
"form",
|
|
3024
|
-
{ className: "dshRemoteSettings", noValidate: !0, onSubmit: (event) => void save(event) },
|
|
2872
|
+
React.createElement("input", {
|
|
2873
|
+
type: "checkbox",
|
|
2874
|
+
role: "switch",
|
|
2875
|
+
disabled: busy,
|
|
2876
|
+
"aria-label": t("allowControlCurrentDevice"),
|
|
2877
|
+
checked: hostStatus?.authorized === !0,
|
|
2878
|
+
onChange: (event) => void setCurrentDeviceControl(event.target.checked)
|
|
2879
|
+
})
|
|
2880
|
+
),
|
|
2881
|
+
React.createElement(
|
|
2882
|
+
"div",
|
|
2883
|
+
{ className: "dshRemoteConnection", "aria-live": "polite" },
|
|
3025
2884
|
React.createElement(
|
|
3026
2885
|
"div",
|
|
3027
|
-
{ className: "
|
|
2886
|
+
{ className: "dshRemoteConnectionSummary" },
|
|
2887
|
+
React.createElement("span", null, t("connection")),
|
|
3028
2888
|
React.createElement(
|
|
3029
|
-
"
|
|
2889
|
+
"strong",
|
|
3030
2890
|
null,
|
|
3031
|
-
React.createElement("span",
|
|
3032
|
-
|
|
2891
|
+
React.createElement("span", {
|
|
2892
|
+
className: `dshRemoteConnectionDot${connectionStatusClass(hostStatus)}`,
|
|
2893
|
+
"aria-hidden": !0
|
|
2894
|
+
}),
|
|
2895
|
+
connectionStatusLabel(hostStatus, t)
|
|
3033
2896
|
),
|
|
3034
|
-
React.createElement(
|
|
3035
|
-
"div",
|
|
3036
|
-
null,
|
|
3037
|
-
React.createElement("span", null, t("deviceId")),
|
|
3038
|
-
React.createElement("code", null, hostDeviceId || "\u2014")
|
|
3039
|
-
)
|
|
2897
|
+
React.createElement("p", null, hostStatus === void 0 ? t("checkingConnection") : hostStatus.lastActiveAt === void 0 ? t("neverConnected") : t("lastActive", { time: formatLocalTime(hostStatus.lastActiveAt) }))
|
|
3040
2898
|
),
|
|
2899
|
+
React.createElement("button", {
|
|
2900
|
+
type: "button",
|
|
2901
|
+
className: "dshRemoteReconnect",
|
|
2902
|
+
disabled: reconnectBusy || hostStatus?.configured === !1,
|
|
2903
|
+
onClick: () => void reconnectHost()
|
|
2904
|
+
}, t(reconnectBusy ? "reconnectingAction" : "reconnect"))
|
|
2905
|
+
),
|
|
2906
|
+
hostStatus?.error === void 0 || hostStatus.online ? null : React.createElement("p", { className: "dshRemoteConnectionIssue", role: "status" }, connectionErrorMessage(hostStatus.error, t)),
|
|
2907
|
+
writable ? null : React.createElement("p", { className: "dshRemoteError" }, t("readOnly")),
|
|
2908
|
+
React.createElement(
|
|
2909
|
+
"div",
|
|
2910
|
+
{ className: "dshRemoteSettingsFooter" },
|
|
2911
|
+
React.createElement("p", {
|
|
2912
|
+
className: error !== void 0 ? "dshRemoteError" : "dshRemoteNotice",
|
|
2913
|
+
role: error !== void 0 ? "alert" : "status"
|
|
2914
|
+
}, error ?? (notice === void 0 ? "" : t(notice.key, notice.params))),
|
|
2915
|
+
draftDirty ? React.createElement(
|
|
2916
|
+
React.Fragment,
|
|
2917
|
+
null,
|
|
2918
|
+
React.createElement("button", { type: "button", className: "dshRemoteDiscard", disabled: busy, onClick: discard }, t("discard")),
|
|
2919
|
+
React.createElement("button", { type: "button", className: "dshRemoteSave", disabled: busy || !writable, onClick: () => void save() }, t(busy ? "saving" : "save")),
|
|
2920
|
+
React.createElement("button", { type: "button", className: "dshRemoteDiscard", disabled: busy || !writable, onClick: () => void logout() }, t(busy ? "signingOut" : "signOut"))
|
|
2921
|
+
) : React.createElement("button", {
|
|
2922
|
+
type: "button",
|
|
2923
|
+
className: "dshRemoteDiscard",
|
|
2924
|
+
disabled: busy || !writable,
|
|
2925
|
+
onClick: () => void logout()
|
|
2926
|
+
}, t(busy ? "signingOut" : "signOut"))
|
|
2927
|
+
)
|
|
2928
|
+
) : React.createElement(
|
|
2929
|
+
"form",
|
|
2930
|
+
{ className: "dshRemoteSettings", noValidate: !0, onSubmit: (event) => void save(event) },
|
|
2931
|
+
React.createElement(
|
|
2932
|
+
"div",
|
|
2933
|
+
{ className: "dshRemoteHostIdentity" },
|
|
3041
2934
|
React.createElement(
|
|
3042
2935
|
"div",
|
|
3043
|
-
|
|
3044
|
-
React.createElement("
|
|
3045
|
-
React.createElement("
|
|
3046
|
-
id: "dsh-remote-server-url",
|
|
3047
|
-
type: "url",
|
|
3048
|
-
value: serverUrl,
|
|
3049
|
-
disabled: busy || !writable,
|
|
3050
|
-
required: !0,
|
|
3051
|
-
placeholder: "https://dsh.r2049.cn",
|
|
3052
|
-
onChange: (event) => {
|
|
3053
|
-
setServerUrl(event.target.value), setNotice(void 0);
|
|
3054
|
-
}
|
|
3055
|
-
}),
|
|
3056
|
-
React.createElement("p", null, t("serverUrlHint"))
|
|
2936
|
+
null,
|
|
2937
|
+
React.createElement("span", null, t("hostName")),
|
|
2938
|
+
React.createElement("strong", null, hostName || "\u2014")
|
|
3057
2939
|
),
|
|
3058
|
-
developmentSetting,
|
|
3059
|
-
acpSetting,
|
|
3060
|
-
React.createElement("p", { className: "dshRemoteSettingsState" }, t("authorizeFromRemote")),
|
|
3061
|
-
writable ? null : React.createElement("p", { className: "dshRemoteError" }, t("readOnly")),
|
|
3062
2940
|
React.createElement(
|
|
3063
2941
|
"div",
|
|
3064
|
-
|
|
3065
|
-
React.createElement("
|
|
3066
|
-
|
|
3067
|
-
role: error !== void 0 ? "alert" : "status"
|
|
3068
|
-
}, error ?? (notice === void 0 ? "" : t(notice.key, notice.params))),
|
|
3069
|
-
React.createElement("button", { type: "button", className: "dshRemoteDiscard", disabled: busy || !draftDirty, onClick: discard }, t("discard")),
|
|
3070
|
-
React.createElement("button", { type: "submit", className: "dshRemoteSave", disabled: busy || !writable || !serverDirty }, t(busy ? "saving" : "save"))
|
|
2942
|
+
null,
|
|
2943
|
+
React.createElement("span", null, t("deviceId")),
|
|
2944
|
+
React.createElement("code", null, hostDeviceId || "\u2014")
|
|
3071
2945
|
)
|
|
3072
|
-
)
|
|
3073
|
-
|
|
3074
|
-
|
|
2946
|
+
),
|
|
2947
|
+
React.createElement(
|
|
2948
|
+
"div",
|
|
2949
|
+
{ className: "dshRemoteField" },
|
|
2950
|
+
React.createElement("label", { htmlFor: "dsh-remote-server-url" }, t("serverUrl")),
|
|
2951
|
+
React.createElement("input", {
|
|
2952
|
+
id: "dsh-remote-server-url",
|
|
2953
|
+
type: "url",
|
|
2954
|
+
value: serverUrl,
|
|
2955
|
+
disabled: busy || !writable,
|
|
2956
|
+
required: !0,
|
|
2957
|
+
placeholder: "https://dsh.r2049.cn",
|
|
2958
|
+
onChange: (event) => {
|
|
2959
|
+
setServerUrl(event.target.value), setNotice(void 0);
|
|
2960
|
+
}
|
|
2961
|
+
}),
|
|
2962
|
+
React.createElement("p", null, t("serverUrlHint"))
|
|
2963
|
+
),
|
|
2964
|
+
developmentSetting,
|
|
2965
|
+
acpSetting,
|
|
2966
|
+
React.createElement("p", { className: "dshRemoteSettingsState" }, t("authorizeFromRemote")),
|
|
2967
|
+
writable ? null : React.createElement("p", { className: "dshRemoteError" }, t("readOnly")),
|
|
2968
|
+
React.createElement(
|
|
2969
|
+
"div",
|
|
2970
|
+
{ className: "dshRemoteSettingsFooter" },
|
|
2971
|
+
React.createElement("p", {
|
|
2972
|
+
className: error !== void 0 ? "dshRemoteError" : "dshRemoteNotice",
|
|
2973
|
+
role: error !== void 0 ? "alert" : "status"
|
|
2974
|
+
}, error ?? (notice === void 0 ? "" : t(notice.key, notice.params))),
|
|
2975
|
+
React.createElement("button", { type: "button", className: "dshRemoteDiscard", disabled: busy || !draftDirty, onClick: discard }, t("discard")),
|
|
2976
|
+
React.createElement("button", { type: "submit", className: "dshRemoteSave", disabled: busy || !writable || !serverDirty }, t(busy ? "saving" : "save"))
|
|
2977
|
+
)
|
|
2978
|
+
) : React.createElement("p", { className: "dshRemoteSettingsState" }, error ?? t("loadingSettings"))
|
|
2979
|
+
) : null
|
|
2980
|
+
);
|
|
2981
|
+
}
|
|
2982
|
+
return RemotePluginOptions;
|
|
2983
|
+
}
|
|
2984
|
+
|
|
2985
|
+
// src/client/shell.ts
|
|
2986
|
+
function installStyle(clientModuleId2) {
|
|
2987
|
+
let style = document.createElement("style");
|
|
2988
|
+
return style.dataset.plugin = clientModuleId2, style.dataset.pluginCss = "dsh-remote", style.textContent = [
|
|
2989
|
+
'html.dshRemoteTargetActive button[aria-label="\u6DFB\u52A0\u5DE5\u4F5C\u533A"],html.dshRemoteTargetActive button[aria-label="Add workspace"]{display:none!important}',
|
|
2990
|
+
'html.dshRemoteCodexTargetActive [data-composer-card] button[aria-haspopup="listbox"][aria-label="\u6307\u4EE4"],html.dshRemoteCodexTargetActive [data-composer-card] button[aria-haspopup="listbox"][aria-label="Commands"]{display:none!important}',
|
|
2991
|
+
"[data-dsh-remote-hidden-action]{display:none!important}",
|
|
2992
|
+
// The 0.1.6 right sidebar occupies the same shell header area as the
|
|
2993
|
+
// remote status strip. Hide the strip while that sidebar is expanded;
|
|
2994
|
+
// the sidebar itself remains the active context for terminal/files.
|
|
2995
|
+
":has([data-sidebar-right-open]) .dshRemoteSessionHeader{display:none!important}",
|
|
2996
|
+
// TerminalRecovery renders a retry action in the conversation header.
|
|
2997
|
+
// A failed remote terminal is reported when its tab is opened/closed;
|
|
2998
|
+
// keeping this background recovery action out of the top-left header
|
|
2999
|
+
// avoids overlapping the session controls.
|
|
3000
|
+
'[title^="\u6062\u590D\u7EC8\u7AEF\u5931\u8D25"],[title^="Terminal recovery failed"]{display:none!important}',
|
|
3001
|
+
".dshRemoteTerminalUnavailable{box-sizing:border-box;margin:12px;padding:12px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-2);font-size:13px;line-height:1.5}",
|
|
3002
|
+
".dshRemoteModeButton{min-height:36px;border:0;background:transparent;color:var(--dsw-alias-label-primary);display:flex;align-items:center;gap:8px;padding:0 10px;border-radius:8px}.dshRemoteModeButton:is(button){cursor:pointer}",
|
|
3003
|
+
".dshRemoteModeButton:is(button):hover{background:var(--dsw-alias-interactive-bg-hover)}",
|
|
3004
|
+
// Keep additive footer actions in reading order above the Settings seat.
|
|
3005
|
+
'[class*="_footArea"]:has(.dshRemoteSidebarEntry){flex-direction:column!important;align-items:stretch;gap:0}[class*="_footerActions"]:has(.dshRemoteSidebarEntry){display:flex!important;flex-direction:column;align-items:stretch}[class*="_footerActions"]:has(.dshRemoteSidebarEntry.isRail){align-items:center}',
|
|
3006
|
+
'[class*="_footerActions"]:has(.dshRemoteSidebarEntry.isWide) .bt-return{justify-content:flex-start}',
|
|
3007
|
+
// Bot mode seats its account beside Connect plugins. Keep that row intact
|
|
3008
|
+
// and let Remote span a separate row underneath it.
|
|
3009
|
+
'[class*="_footArea"]:has(.bt-connect-wrap):has(.dshRemoteSidebarEntry.isWide){display:grid!important;grid-template-columns:36px minmax(0,1fr);align-items:center;gap:8px 9px}[class*="_footArea"]:has(.bt-connect-wrap):has(.dshRemoteSidebarEntry.isWide)>[class*="_footerActions"]{display:contents!important}[class*="_footArea"]:has(.bt-connect-wrap):has(.dshRemoteSidebarEntry.isWide)>[class*="_footerActions"]>div:not(.dshRemoteSidebarEntry){display:contents!important}',
|
|
3010
|
+
'[class*="_footArea"]:has(.bt-connect-wrap):has(.dshRemoteSidebarEntry.isWide) .bt-connect-wrap{grid-column:2;grid-row:1}[class*="_footArea"]:has(.bt-connect-wrap):has(.dshRemoteSidebarEntry.isWide)>[class*="_settingsArea"]{grid-column:1;grid-row:1;width:36px!important}[class*="_footArea"]:has(.bt-connect-wrap):has(.dshRemoteSidebarEntry.isWide) .dshRemoteSidebarEntry.isWide{display:block!important;grid-column:1/-1;grid-row:2;margin:0}',
|
|
3011
|
+
'[class*="_footArea"]:has(.bt-connect-wrap):has(.bt-foot-account):has(.dshRemoteSidebarEntry.isWide){grid-template-columns:36px minmax(0,1fr) 36px}[class*="_footArea"]:has(.bt-connect-wrap):has(.bt-foot-account):has(.dshRemoteSidebarEntry.isWide) .bt-foot-account{grid-column:1;grid-row:1}[class*="_footArea"]:has(.bt-connect-wrap):has(.bt-foot-account):has(.dshRemoteSidebarEntry.isWide)>[class*="_settingsArea"]{grid-column:3}',
|
|
3012
|
+
".dshRemoteSidebarEntry{box-sizing:border-box;flex:none;width:36px;min-width:36px;display:block}.dshRemoteSidebarEntry .dshRemoteModeButton{box-sizing:border-box;width:36px;height:36px;min-height:36px;justify-content:center;gap:0;padding:0;border-radius:50%}.dshRemoteSidebarEntry.isWide{width:100%;min-width:0;height:36px;margin:4px 0}.dshRemoteSidebarEntry.isWide .dshRemoteModeButton{width:100%;min-width:0;justify-content:flex-start;gap:8px;padding:0 14px;border-radius:8px;font:inherit;font-size:14px;line-height:20px;text-align:start}.dshRemoteSidebarLabel{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dshRemoteSidebarEntry.isRail{height:54px}.dshRemoteSidebarEntry.isRail .dshRemoteModeButton{margin:8px 0 10px}.dshRemoteSidebarEntry.isActive .dshRemoteComputerIcon{color:var(--dsw-alias-brand-primary)}.dshRemoteSidebarEntry .dshRemoteModeButton:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.dshRemoteSidebarEntry .dshRemoteModeButton:disabled{opacity:.45;cursor:default}",
|
|
3013
|
+
".dshRemoteComputerIcon{box-sizing:border-box;width:18px;height:18px;flex:0 0 18px;color:var(--dsw-alias-label-secondary)}",
|
|
3014
|
+
".dshRemoteSidebarEntry.isWide{position:relative}.dshRemoteSidebarEntry.isWide.isActive .dshRemoteModeButton{padding-inline-end:64px}.dshRemoteExitLink{position:absolute;inset-block-start:0;inset-inline-end:8px;min-width:44px;height:36px;border:0;border-radius:8px;background:transparent;color:var(--dsw-alias-label-secondary);padding:0 6px;font:inherit;font-size:12px;line-height:20px;white-space:nowrap;cursor:pointer}.dshRemoteExitLink:hover:not(:disabled){color:var(--dsw-alias-label-primary);text-decoration:underline}.dshRemoteExitLink:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.dshRemoteExitLink:disabled{opacity:.45;cursor:default}",
|
|
3015
|
+
// The strip sits inside the 40px Windows caption row, which the shell declares as the
|
|
3016
|
+
// window drag region. Without an explicit opt-out every press starts a window drag and
|
|
3017
|
+
// never reaches these buttons; the shell's own caption controls (sidebar toggle, new
|
|
3018
|
+
// session, the caption menus) opt out of that region the same way.
|
|
3019
|
+
'.dshRemoteSessionHeader{position:fixed;z-index:25;-webkit-app-region:no-drag;top:12px;left:50%;transform:translateX(-50%);max-width:calc(100vw - 360px);height:28px;display:inline-flex;align-items:center;gap:7px;color:var(--dsw-alias-label-secondary);font-size:12px;white-space:nowrap}.dshRemoteSessionHeader>svg{width:15px;height:15px;flex:0 0 auto}.dshRemoteSessionTarget{min-width:0;max-width:260px;overflow:hidden;text-overflow:ellipsis}.dshRemoteNetwork{flex:0 0 auto;border:0;background:transparent;color:inherit;font:inherit;padding:3px 2px;display:inline-flex;align-items:center;gap:5px;cursor:pointer}.dshRemoteNetwork:hover:not(:disabled){color:var(--dsw-alias-label-primary);text-decoration:underline}.dshRemoteNetwork:disabled{cursor:default}.dshRemoteNetwork>i{width:6px;height:6px;border-radius:50%;background:var(--dsw-alias-label-tertiary)}.dshRemoteNetwork.isOnline>i{background:var(--dsw-alias-state-success-primary)}.dshRemoteNetwork.isOffline{color:var(--dsw-alias-state-error-primary)}.dshRemoteNetwork.isOffline>i{background:currentColor}.dshRemoteEncrypted{flex:0 0 auto;color:var(--dsw-alias-label-tertiary)}.dshRemoteHeaderExitLink{flex:0 0 auto;border:0;background:transparent;color:var(--dsw-alias-label-secondary);padding:3px 2px;font:inherit;text-decoration:none;cursor:pointer}.dshRemoteHeaderExitLink:hover{text-decoration:underline;color:var(--dsw-alias-label-primary)}.dshRemoteHeaderExitLink:disabled{opacity:.45;cursor:default;text-decoration:none}.dshRemoteNetwork:focus-visible,.dshRemoteHeaderExitLink:focus-visible,.dshRemoteRoutePanel>header button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.dshRemoteRouteBackdrop{position:fixed;inset:0;z-index:26;-webkit-app-region:no-drag}.dshRemoteRoutePanel{box-sizing:border-box;position:absolute;top:48px;right:28px;width:min(680px,calc(100vw - 32px));max-height:calc(100vh - 72px);overflow:auto;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:12px;padding:16px;white-space:normal}.dshRemoteRoutePanel>header{position:sticky;top:-16px;z-index:1;display:flex;align-items:center;justify-content:space-between;margin:-16px -16px 0;padding:16px;background:var(--dsw-alias-bg-layer-1)}.dshRemoteRoutePanel>header strong{font-size:14px}.dshRemoteRoutePanel>header button{width:28px;height:28px;border:0;border-radius:7px;background:transparent;color:inherit;font-size:20px;cursor:pointer}.dshRemoteRoutePanel>header button:hover{background:var(--dsw-alias-interactive-bg-hover)}.dshRemoteRoutePanel ol{display:flex;align-items:stretch;margin:12px 0 0;padding:0 0 16px;border-bottom:1px solid var(--dsw-alias-border-l2);list-style:none}.dshRemoteRoutePanel li{position:relative;min-width:0;flex:1;display:flex;flex-direction:column;gap:4px;padding-right:20px}.dshRemoteRoutePanel li:not(:last-child)::after{content:"\u2192";position:absolute;right:7px;top:21px;color:var(--dsw-alias-label-tertiary)}.dshRemoteRoutePanel li small{color:var(--dsw-alias-label-tertiary)}.dshRemoteRoutePanel li strong,.dshRemoteRoutePanel li span{overflow:hidden;text-overflow:ellipsis}.dshRemoteRoutePanel li strong{font-size:13px}.dshRemoteRoutePanel li span{color:var(--dsw-alias-label-secondary);font-size:11px}.dshRemoteRouteSection{padding-top:16px}.dshRemoteRouteSection h3{margin:0 0 10px;font-size:12px;font-weight:600;color:var(--dsw-alias-label-secondary)}.dshRemoteRouteSection dl{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 24px;margin:0}.dshRemoteRouteSection dl>div{min-width:0;display:grid;grid-template-columns:minmax(104px,auto) minmax(0,1fr);gap:10px;padding:7px 0;border-bottom:1px solid var(--dsw-alias-border-l2);font-size:12px;line-height:1.45}.dshRemoteRouteSection dt{color:var(--dsw-alias-label-tertiary)}.dshRemoteRouteSection dd{min-width:0;margin:0;text-align:right;overflow-wrap:anywhere}.dshRemoteRouteSection dd.isMono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px}.dshRemoteRoutePanel>p{margin:16px 0 0;padding-top:12px;border-top:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5}@media(max-width:620px){.dshRemoteSessionHeader{top:8px;max-width:calc(100vw - 112px)}.dshRemoteSessionHeader>svg{display:none}.dshRemoteSessionTarget{max-width:130px}.dshRemoteEncrypted{display:none}.dshRemoteRoutePanel{top:42px;right:12px;max-height:calc(100vh - 56px)}.dshRemoteRoutePanel ol{flex-direction:column;gap:18px}.dshRemoteRoutePanel li:not(:last-child)::after{content:"\u2193";top:auto;right:auto;bottom:-16px;left:3px}.dshRemoteRouteSection dl{grid-template-columns:1fr}.dshRemoteRouteSection dl>div{grid-template-columns:1fr;gap:2px}.dshRemoteRouteSection dd{text-align:left}}',
|
|
3020
|
+
".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)}}",
|
|
3021
|
+
".dshRemoteModeButton:focus-visible,.dshRemotePage button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}",
|
|
3022
|
+
".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)}",
|
|
3023
|
+
".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}",
|
|
3024
|
+
".dshRemotePageBody{padding:24px;overflow:auto;display:flex;flex-direction:column;gap:24px}.dshRemotePageBody button{font:inherit;color:inherit}",
|
|
3025
|
+
".dshRemotePageTitleRow{display:flex;align-items:center;gap:10px;min-width:0}.dshRemotePageTitleRow>strong{min-width:0;flex:0 1 auto}.dshRemoteStarLink{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:400;text-decoration:none}.dshRemoteStarLink:hover{color:var(--dsw-alias-label-primary);text-decoration:underline;text-underline-offset:3px}.dshRemoteStarLink:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:3px;border-radius:3px}",
|
|
3026
|
+
".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}",
|
|
3027
|
+
".dshRemoteSectionTitle{flex:1}.dshRemoteSectionTitle>.dshRemoteConnectedMenu{margin-left:auto}",
|
|
3028
|
+
'.dshRemoteAcpSetting{display:block!important;width:100%;padding:0}.dshRemoteAcpSetting>summary{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%;cursor:pointer;list-style:none}.dshRemoteAcpSetting>summary::-webkit-details-marker{display:none}.dshRemoteAcpSetting>summary::after{content:"\u2304";color:var(--dsw-alias-label-secondary);transition:transform .18s ease-out}.dshRemoteAcpSetting[open]>summary::after{transform:rotate(180deg)}.dshRemoteAcpSummaryText{min-width:0}.dshRemoteAcpSummaryText strong{display:block}.dshRemoteAcpSummaryText p{margin:4px 0 0;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.4}.dshRemoteAcpCheckLink{grid-column:2;grid-row:1;color:var(--dsw-alias-brand-primary);font-size:12px;text-decoration:underline;text-underline-offset:3px}.dshRemoteAcpCheckLink:hover{color:var(--dsw-alias-label-primary)}.dshRemoteAcpCheckResult{grid-column:3;grid-row:1;font-size:11px;line-height:1.4;white-space:nowrap}.dshRemoteAcpCheckResult.isPassed{color:var(--dsw-alias-state-success-primary)}.dshRemoteAcpCheckResult.isFailed{color:var(--dsw-alias-state-danger-primary)}.dshRemoteAcpList{display:flex;flex-direction:column;gap:0;margin-top:12px;padding-top:0;border-top:0}.dshRemoteAcpList>.dshRemoteAuthorizationSetting{display:grid;width:100%;grid-template-columns:minmax(0,1fr) auto auto auto auto;align-items:center;column-gap:18px;line-height:1.4}.dshRemoteAcpList>.dshRemoteAuthorizationSetting>span:first-child{min-width:0;line-height:1.4}.dshRemoteAcpList>.dshRemoteAuthorizationSetting>input{grid-column:4;grid-row:1}',
|
|
3029
|
+
".dshRemoteAcpAddLink{align-self:flex-start;margin-top:12px;color:var(--dsw-alias-brand-primary);font-size:12px;text-decoration:underline;text-underline-offset:3px}.dshRemoteAcpAddForm{display:grid;grid-template-columns:minmax(100px,.8fr) minmax(140px,1fr) minmax(100px,1fr) auto;gap:8px;margin-top:12px}.dshRemoteAcpAddForm input{min-width:0;height:34px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-2);color:inherit;padding:0 10px}.dshRemoteAcpAddForm button{border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:transparent;color:var(--dsw-alias-label-primary);padding:0 12px;cursor:pointer;font:inherit;font-size:12px}.dshRemoteAcpAddForm button:hover{background:var(--dsw-alias-interactive-bg-hover)}.dshRemoteAcpRemoveLink{grid-column:3;grid-row:1;color:var(--dsw-alias-label-secondary);font-size:12px;text-decoration:underline;text-underline-offset:3px}.dshRemoteAcpRemoveLink:hover{color:var(--dsw-alias-state-danger-primary)}",
|
|
3030
|
+
".dshRemoteAcpCheckResult.isPassed,.dshRemoteAcpCheckResult.isFailed{color:var(--dsw-alias-label-secondary)}",
|
|
3031
|
+
".dshRemoteAcpList>.dshRemoteAuthorizationSetting{grid-template-columns:minmax(0,1fr) 190px 40px 56px;column-gap:18px}.dshRemoteAcpCheckCell{grid-column:2;display:flex;align-items:center;gap:10px;min-width:0}.dshRemoteAcpCheckLink,.dshRemoteAcpRemoveLink{justify-self:start}.dshRemoteAcpCheckResult{position:static}",
|
|
3032
|
+
".dshRemoteAcpCheckLink.isPassed{color:var(--dsw-alias-state-success-primary)}.dshRemoteAcpCheckLink.isFailed{color:var(--dsw-alias-state-danger-primary)}.dshRemoteAcpCheckLink.isChecking{color:var(--dsw-alias-label-secondary)}",
|
|
3033
|
+
".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}",
|
|
3034
|
+
'.dshRemoteHostList{display:flex;flex-direction:column;border-top:1px solid var(--dsw-alias-border-l2);max-height:296px;overflow-y:auto;overscroll-behavior:contain;scrollbar-gutter:stable}.dshRemoteHostList.isCollapsed{max-height:none;overflow-y:visible}.dshRemoteHostList>button{min-height:58px;flex:0 0 auto;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[aria-current="true"]{background:var(--dsw-alias-interactive-bg-hover)}.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}',
|
|
3035
|
+
'.dshRemoteConnectedMenu{position:relative;flex:0 0 auto;margin-right:4px}.dshRemoteConnectedCount{appearance:none;display:inline-flex;align-items:center;justify-content:center;height:22px;border:0;border-radius:999px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);box-shadow:0 1px 2px rgba(0,0,0,.18),0 0 0 1px rgba(255,255,255,.04) inset;padding:0 10px;font:inherit;font-size:11px;font-weight:500;line-height:17px;white-space:nowrap;cursor:default}.dshRemoteConnectedCount.isOnline{color:var(--dsw-alias-state-success-primary)}.dshRemoteConnectedCount.isInteractive{cursor:pointer}.dshRemoteConnectedCount.isInteractive:hover{filter:brightness(1.08)}.dshRemoteConnectedCount:disabled{opacity:1;cursor:default}.dshRemoteConnectedCount:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.dshRemoteConnectedPanel{position:absolute;top:calc(100% + 8px);right:0;z-index:4;width:min(320px,calc(100vw - 48px));max-height:min(280px,40vh);overflow:auto;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-bg-layer-2);box-shadow:0 10px 28px rgba(0,0,0,.28);padding:10px 12px}.dshRemoteConnectedPanelTitle{display:block;margin:0 0 6px;color:var(--dsw-alias-label-primary);font-size:12px;font-weight:600}.dshRemoteClientList{display:flex;flex-direction:column}.dshRemoteClientRow{min-height:44px;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 0;border-bottom:1px solid var(--dsw-alias-border-l2)}.dshRemoteClientRow:last-child{border-bottom:0}.dshRemoteClientRow>span{min-width:0;display:flex;flex-direction:column;gap:2px}.dshRemoteClientRow strong{font-size:13px;font-weight:500}.dshRemoteClientRow small{color:var(--dsw-alias-label-secondary);font-size:11px}.dshRemoteClientOnline{display:inline-flex;align-items:center;gap:6px;color:var(--dsw-alias-state-success-primary)!important}.dshRemoteClientOnline::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor}',
|
|
3036
|
+
".dshRemoteConnectedCount{height:auto;border-radius:0;background:transparent;box-shadow:none;padding:0 4px;text-decoration:underline;text-decoration-color:color-mix(in srgb,currentColor 45%,transparent);text-underline-offset:3px}.dshRemoteConnectedCount.isInteractive:hover{filter:none;text-decoration-color:currentColor}.dshRemoteConnectedCount:focus-visible{outline-offset:3px;border-radius:3px}",
|
|
3037
|
+
'.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}}',
|
|
3038
|
+
'.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}',
|
|
3039
|
+
".dshRemoteWorkspaceLists{overflow:visible}",
|
|
3040
|
+
".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}",
|
|
3041
|
+
".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}",
|
|
3042
|
+
".dshRemotePreviewAction,.dshRemotePreviewForm{display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap}.dshRemotePreviewForm input{width:90px;color:inherit;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);padding:6px}.dshRemotePreviewForm [role=alert]{max-width:360px;white-space:normal}.dshRemoteDevelopmentSettings{width:100%;margin:16px 0}.dshRemoteDevelopmentSettings .dshRemotePathField{display:flex;flex-direction:column;gap:6px;margin:8px 0}.dshRemoteDevelopmentSettings .dshRemotePathField>label{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:1.5}.dshRemoteDevelopmentSettings .dshRemotePortsRow{display:flex;gap:8px;align-items:stretch;width:100%}.dshRemoteDevelopmentSettings .dshRemotePortsRow>input{box-sizing:border-box;width:100%;flex:1;min-width:0;height:34px;border:.5px solid var(--dsw-alias-border-l4);border-radius:8px;background:var(--dsw-alias-bg-layer-3);color:inherit;padding:0 12px;font:inherit;font-size:13px;line-height:1.5}.dshRemoteDevelopmentSettings button{min-height:34px;color:inherit;background:var(--dsw-alias-bg-layer-1);border:.5px solid var(--dsw-alias-border-l2);border-radius:8px;padding:5px 14px;white-space:nowrap;font-size:13px;line-height:1.5}.dshRemoteAcpAddForm>label{display:flex;min-width:0;flex-direction:column;gap:5px;color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:1.5}.dshRemoteAcpAddForm>label>input{box-sizing:border-box;width:100%;height:34px;border:.5px solid var(--dsw-alias-border-l4);border-radius:8px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);padding:0 12px;font:inherit;font-size:13px;line-height:1.5}",
|
|
3043
|
+
".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)}",
|
|
3044
|
+
".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)}",
|
|
3045
|
+
".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}",
|
|
3046
|
+
".dshRemoteEnable{box-sizing:border-box;width:min(440px,100%);max-width:100%;min-height:388px;margin:0 auto;display:flex;flex-direction:column;align-items:stretch;gap:10px}.dshRemoteEnable p{margin:0;color:var(--dsw-alias-label-secondary);line-height:1.5}",
|
|
3047
|
+
'.dshRemoteLoginTabs{width:min(440px,100%);display:flex;border-bottom:1px solid var(--dsw-alias-border-l2)}.dshRemoteLoginTabs>button{position:relative;min-height:38px;border:0;background:transparent;color:var(--dsw-alias-label-secondary);padding:6px 14px;font:inherit;font-size:13px;cursor:pointer}.dshRemoteLoginTabs>button:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.dshRemoteLoginTabs>button.isActive{color:var(--dsw-alias-label-primary);font-weight:600}.dshRemoteLoginTabs>button.isActive::after{content:"";position:absolute;right:12px;bottom:-1px;left:12px;height:2px;border-radius:2px 2px 0 0;background:var(--dsw-alias-brand-primary)}.dshRemoteLoginTabs>button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px;border-radius:6px}',
|
|
3048
|
+
".dshRemoteClientLogin{width:min(440px,100%);display:flex;flex-direction:column;gap:8px}.dshRemoteClientLogin 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}.dshRemoteClientLogin button{align-self:flex-start;min-height:40px;border:0;border-radius:8px;background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-1);padding:8px 16px;cursor:pointer}",
|
|
3049
|
+
".dshRemoteQrLogin{width:min(440px,100%);display:flex;flex-direction:column;align-items:center;gap:8px;padding:6px 0 2px;text-align:center}.dshRemoteQrLogin img,.dshRemoteQrPlaceholder{box-sizing:border-box;width:200px;height:200px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:#fff;padding:8px}.dshRemoteQrOpen{display:flex;flex-direction:column;align-items:center;gap:5px;color:var(--dsw-alias-label-secondary);font-size:12px;text-decoration:none}.dshRemoteQrOpen:hover{color:var(--dsw-alias-label-primary);text-decoration:underline}.dshRemoteQrOpen:hover img{border-color:var(--dsw-alias-label-dimmed)}.dshRemoteQrOpen:focus-visible{border-radius:12px;outline:2px solid var(--dsw-alias-brand-primary);outline-offset:3px}.dshRemoteQrPlaceholder{display:flex;align-items:center;justify-content:center;color:var(--dsw-alias-label-secondary)}.dshRemoteQrLogin>strong{font-size:14px}.dshRemoteQrLogin>p{max-width:48ch;margin:0;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5}.dshRemoteQrLogin>.dshRemoteServiceAddress{margin-top:2px;color:var(--dsw-alias-label-tertiary)}.dshRemoteServiceAddress>a{color:var(--dsw-alias-label-secondary);text-decoration:none}.dshRemoteServiceAddress>a:hover{color:var(--dsw-alias-label-primary);text-decoration:underline}.dshRemoteQrLogin>button,.dshRemoteClientLogin>.dshRemoteLoginSwitch{min-height:32px;border:0;background:transparent;color:var(--dsw-alias-label-secondary);padding:4px 8px;font:inherit;font-size:12px;cursor:pointer}.dshRemoteQrLogin>button:hover,.dshRemoteClientLogin>.dshRemoteLoginSwitch:hover{color:var(--dsw-alias-label-primary);text-decoration:underline}.dshRemoteClientLogin>.dshRemoteLoginSwitch{align-self:flex-start;background:transparent;color:var(--dsw-alias-label-secondary);padding-left:0}",
|
|
3050
|
+
".dshRemoteLoginHeading{box-sizing:border-box;width:100%;display:flex;align-items:baseline;gap:10px;overflow:hidden;white-space:nowrap}.dshRemoteLoginTitle{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dshRemoteLoginHeading>span{flex:0 0 auto;color:var(--dsw-alias-label-secondary);font-size:13px;font-weight:400}.dshRemoteLoginTabs{box-sizing:border-box;width:100%;flex-wrap:nowrap;overflow-x:auto}.dshRemoteLoginTabs>button{min-width:max-content;flex:1 0 auto;display:flex;align-items:center;justify-content:center;padding:6px 10px;white-space:nowrap;text-align:center}.dshRemoteLoginTabs>button.isActive::after{right:0;left:0;bottom:0;border-radius:0}.dshRemoteClientLogin,.dshRemoteQrLogin{box-sizing:border-box;width:100%;height:300px;min-height:300px}.dshRemoteClientLogin{align-items:stretch;padding-top:16px}.dshRemoteClientLogin>button{align-self:stretch;width:100%}.dshRemoteQrLogin{padding-top:12px}",
|
|
3051
|
+
'.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}}',
|
|
3052
|
+
".dshRemoteAccountFooter{display:flex;align-items:center;justify-content:space-between;gap:12px;border-top:1px solid var(--dsw-alias-border-l2);padding-top:14px;color:var(--dsw-alias-label-secondary);font-size:12px}.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}",
|
|
3053
|
+
".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)}",
|
|
3054
|
+
"@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}}",
|
|
3055
|
+
".dshRemoteBackdrop{position:fixed;inset:0;z-index:1000;background:var(--dsw-alias-bg-mask-3);display:grid;place-items:center;padding:20px}",
|
|
3056
|
+
".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)}",
|
|
3057
|
+
".dshRemoteDialog button,.dshRemoteDialog input{font:inherit;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:9px 10px;background:transparent;color:inherit}",
|
|
3058
|
+
".dshRemoteDialog button:not(:disabled){cursor:pointer}.dshRemoteDialog button:disabled{opacity:.5}",
|
|
3059
|
+
".dshRemoteHeader{display:flex;align-items:center;justify-content:space-between}.dshRemoteHeader button{border:0;font-size:22px;padding:0 6px}",
|
|
3060
|
+
".dshRemoteDevices{display:grid;gap:8px}.dshRemoteDevices p{margin:4px 0;color:var(--dsw-alias-label-secondary)}",
|
|
3061
|
+
".dshRemoteError{margin:0;color:var(--dsw-alias-state-error-primary)}",
|
|
3062
|
+
".dshRemoteHostAccount{display:grid;gap:8px;border-top:1px solid var(--dsw-alias-border-l3);padding-top:12px}.dshRemoteHostAccount p{margin:0;color:var(--dsw-alias-label-secondary);font-size:13px}",
|
|
3063
|
+
".dshRemoteLogin{display:grid;grid-template-columns:1fr 1fr;gap:8px}.dshRemoteLogin button{grid-column:1/-1}",
|
|
3064
|
+
// The plugin manager already supplies DSH's detail page chrome and
|
|
3065
|
+
// spacing for `view: page`. Keep the legacy card only for older hosts;
|
|
3066
|
+
// current DSH must not get a second, old-style card inside that page.
|
|
3067
|
+
".dshRemotePluginCard{list-style:none;border:.5px solid var(--dsw-alias-border-l4);background:var(--dsw-alias-bg-layer-3);border-radius:var(--dsw-radius-xl,16px);transition:border-color .16s,background .16s}",
|
|
3068
|
+
".dshRemotePluginModern{box-sizing:border-box;width:100%;max-width:none;box-shadow:none;border:0;background:transparent;border-radius:0}.dshRemotePluginModern>.dshRemotePluginCardHeader{display:none}.dshRemotePluginModern>.dshRemotePluginCardBody{border-top:0;margin:0;padding:0}",
|
|
3069
|
+
".dshRemotePluginCard:hover{border-color:var(--dsw-alias-label-dimmed)}.dshRemotePluginCard.isOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}",
|
|
3070
|
+
".dshRemotePluginCard.dshRemotePluginModern:hover,.dshRemotePluginCard.dshRemotePluginModern.isOpen{border-color:transparent;background:transparent}",
|
|
3071
|
+
".dshRemotePluginCardHeader{display:flex;align-items:center}.dshRemotePluginCardToggle{appearance:none;width:100%;min-width:0;font:inherit;color:inherit;text-align:left;cursor:pointer;background:transparent;border:0;border-radius:12px;display:flex;align-items:center;gap:12px;padding:14px 16px}.dshRemotePluginCardToggle:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}",
|
|
3072
|
+
".dshRemotePluginCardHeading{display:flex;flex-direction:column;gap:4px;min-width:0;flex:1}.dshRemotePluginCardHeading>strong{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.dshRemotePluginCardHeading>span{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.dshRemotePluginCardStatus{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.dshRemotePluginCardStatus.isOnline{color:var(--dsw-alias-state-success-primary)}.dshRemotePluginCardStatus.isReconnecting{color:var(--dsw-alias-state-warn-label)}.dshRemotePluginCardStatus.isOffline{color:var(--dsw-alias-state-error-primary)}.dshRemotePluginCardChevron{color:var(--dsw-alias-label-tertiary);font-size:18px;line-height:14px;transition:transform .16s}.dshRemotePluginCard.isOpen .dshRemotePluginCardChevron{transform:rotate(180deg)}",
|
|
3073
|
+
".dshRemotePluginCardBody{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}.dshRemoteSettings{display:flex;flex-direction:column;max-width:none}.dshRemoteSettingsTop{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;padding:0 0 12px}.dshRemoteSettingsState{margin:0;color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}",
|
|
3074
|
+
".dshRemotePluginModern .dshRemoteField input{border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md,8px);height:40px}.dshRemotePluginModern .dshRemoteSettingsFooter button{border-radius:var(--dsw-radius-md,8px);min-height:32px}",
|
|
3075
|
+
".dshRemoteHostIdentity{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;padding:12px 0;border-top:1px solid var(--dsw-alias-border-l2);border-bottom:1px solid var(--dsw-alias-border-l2)}.dshRemoteHostIdentity>div{min-width:0;display:flex;flex-direction:column;gap:3px}.dshRemoteHostIdentity span{color:var(--dsw-alias-label-tertiary);font-size:12px}.dshRemoteHostIdentity strong,.dshRemoteHostIdentity code{min-width:0;overflow-wrap:anywhere;color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500}.dshRemoteHostIdentity code{font-family:var(--dsw-font-mono,ui-monospace,SFMono-Regular,Menlo,monospace);font-weight:400}",
|
|
3076
|
+
".dshRemoteField{display:flex;flex-direction:column;gap:6px;padding:12px 0}.dshRemoteField+.dshRemoteField{border-top:1px solid var(--dsw-alias-border-l2)}.dshRemoteField label{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:1.5}.dshRemoteField input{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.dshRemoteField input:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.dshRemoteField input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.dshRemoteField p{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}",
|
|
3077
|
+
'.dshRemoteAuthorizationSetting{border-top:1px solid var(--dsw-alias-border-l2);display:flex;align-items:center;justify-content:space-between;gap:20px;padding:12px 0}.dshRemoteAuthorizationSetting>div{min-width:0}.dshRemoteAuthorizationSetting strong{font-size:13px;font-weight:500}.dshRemoteAuthorizationSetting p{margin:3px 0 0;color:var(--dsw-alias-label-tertiary);font-size:12px}.dshRemoteAuthorizationSetting>input{appearance:none;position:relative;width:38px;height:22px;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}.dshRemoteAuthorizationSetting>input::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--dsw-alias-label-secondary);transition:transform .16s ease-out,background .16s ease-out}.dshRemoteAuthorizationSetting>input:checked{border-color:var(--dsw-alias-state-success-primary);background:var(--dsw-alias-state-success-primary);box-shadow:none}.dshRemoteAuthorizationSetting>input:checked::after{transform:translateX(16px);background:var(--dsw-alias-bg-layer-1)}.dshRemoteAuthorizationSetting>input:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.dshRemoteAuthorizationSetting>input:disabled{opacity:.5;cursor:default}@media(prefers-reduced-motion:reduce){.dshRemoteAuthorizationSetting>input,.dshRemoteAuthorizationSetting>input::after{transition:none}}',
|
|
3078
|
+
".dshRemoteAssociation{min-width:0;flex:1;display:flex;flex-direction:column;gap:4px}.dshRemoteAssociation>span{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}.dshRemoteAssociation strong{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:1.5}.dshRemoteAssociation p{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}",
|
|
3079
|
+
".dshRemoteConnection{border-top:1px solid var(--dsw-alias-border-l2);display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 0}.dshRemoteConnectionSummary{min-width:0;display:flex;flex-direction:column;gap:4px}.dshRemoteConnectionSummary>span{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}.dshRemoteConnectionSummary strong{display:flex;align-items:center;gap:7px;color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:1.5}.dshRemoteConnectionSummary p,.dshRemoteConnectionIssue{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}.dshRemoteConnectionDot{width:8px;height:8px;flex:0 0 auto;border-radius:999px;background:var(--dsw-alias-label-tertiary)}.dshRemoteConnectionDot.isOnline{background:var(--dsw-alias-state-success-primary)}.dshRemoteConnectionDot.isReconnecting{background:var(--dsw-alias-state-warn-primary)}.dshRemoteConnectionDot.isOffline{background:var(--dsw-alias-state-error-primary)}.dshRemoteConnectionIssue{color:var(--dsw-alias-state-error-primary);padding:0 0 12px}.dshRemoteReconnect{appearance:none;flex:0 0 auto;font:inherit;cursor:pointer;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:transparent;color:var(--dsw-alias-label-secondary);min-height:34px;padding:5px 14px;font-size:13px;line-height:1.5}.dshRemoteReconnect:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed);background:var(--dsw-alias-interactive-bg-hover)}.dshRemoteReconnect:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.dshRemoteReconnect:disabled{opacity:.4;cursor:default}",
|
|
3080
|
+
".dshRemoteSettingsFooter{border-top:1px solid var(--dsw-alias-border-l2);display:flex;justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px}.dshRemoteSettingsFooter .dshRemoteError,.dshRemoteNotice{min-width:0;flex:1;margin:0;font-size:12px;line-height:1.5}.dshRemoteNotice{color:var(--dsw-alias-label-tertiary)}.dshRemoteDiscard,.dshRemoteSave{appearance:none;font:inherit;cursor:pointer;border:1px solid transparent;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}.dshRemoteDiscard{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:transparent}.dshRemoteDiscard:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed)}.dshRemoteSave{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}.dshRemoteDiscard:disabled,.dshRemoteSave:disabled{opacity:.4;cursor:default}.dshRemoteDiscard:focus-visible,.dshRemoteSave:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}",
|
|
3081
|
+
"@media(max-width:620px){.dshRemotePluginCardStatus{display:none}.dshRemoteSettingsTop{gap:10px}.dshRemoteConnection{align-items:flex-start}.dshRemoteReconnect{min-height:40px}.dshRemotePortsRow{flex-direction:column}.dshRemoteAcpAddForm{grid-template-columns:1fr}.dshRemoteAcpAddForm button{min-height:40px}}"
|
|
3082
|
+
].join(""), document.head.append(style), () => style.remove();
|
|
3083
|
+
}
|
|
3084
|
+
function installTerminalAvailabilityNotice(feed, t) {
|
|
3085
|
+
let latest, notice, update = () => {
|
|
3086
|
+
let terminal = document.querySelector("[data-sidebar-terminal]"), unavailable = latest?.mode === "remote" && latest.remoteFeatures?.terminal !== !0;
|
|
3087
|
+
if (!terminal || !unavailable) {
|
|
3088
|
+
notice?.remove(), notice = void 0;
|
|
3089
|
+
return;
|
|
3075
3090
|
}
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
let remoteActive = status?.mode === "remote";
|
|
3108
|
-
return document.documentElement.classList.toggle("dshRemoteTargetActive", remoteActive), () => {
|
|
3109
|
-
remoteActive && document.documentElement.classList.remove("dshRemoteTargetActive");
|
|
3110
|
-
};
|
|
3111
|
-
}, [status?.mode]);
|
|
3112
|
-
let startQrLogin = async (provider) => {
|
|
3113
|
-
let run = ++qrFlowRun.current;
|
|
3114
|
-
setBusy(!0), setError(void 0), setQrExpired(!1);
|
|
3115
|
-
try {
|
|
3116
|
-
let session = await props.control("client.account.qr.start", { provider }), image = await import_qrcode.default.toDataURL(session.scanUrl, {
|
|
3117
|
-
width: 184,
|
|
3118
|
-
margin: 1,
|
|
3119
|
-
errorCorrectionLevel: "L"
|
|
3120
|
-
});
|
|
3121
|
-
if (run !== qrFlowRun.current) return;
|
|
3122
|
-
setQrSession(session), setQrImage(image);
|
|
3123
|
-
} catch (reason) {
|
|
3124
|
-
run === qrFlowRun.current && setError(messageOf(reason));
|
|
3125
|
-
} finally {
|
|
3126
|
-
run === qrFlowRun.current && setBusy(!1);
|
|
3091
|
+
notice !== void 0 && notice.isConnected || (notice = document.createElement("div"), notice.className = "dshRemoteTerminalUnavailable", notice.setAttribute("role", "alert"), notice.textContent = t("terminalRemoteUnavailable"), terminal.prepend(notice));
|
|
3092
|
+
}, unsubscribe = feed.subscribe((status) => {
|
|
3093
|
+
latest = status, update();
|
|
3094
|
+
}), observer = new MutationObserver(update);
|
|
3095
|
+
return observer.observe(document.body, { childList: !0, subtree: !0 }), update(), () => {
|
|
3096
|
+
unsubscribe(), observer.disconnect(), notice?.remove();
|
|
3097
|
+
};
|
|
3098
|
+
}
|
|
3099
|
+
|
|
3100
|
+
// src/client/workspaces.ts
|
|
3101
|
+
var import_qrcode = __toESM(require_browser(), 1);
|
|
3102
|
+
|
|
3103
|
+
// src/client/icons.ts
|
|
3104
|
+
var 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";
|
|
3105
|
+
|
|
3106
|
+
// src/client/workspaces.ts
|
|
3107
|
+
function createRemoteWorkspaceAction(React) {
|
|
3108
|
+
let RemoteProgressView = createRemoteProgressView(React);
|
|
3109
|
+
function RemoteWorkspaceAction(props) {
|
|
3110
|
+
let { t } = props, [open, setOpen] = React.useState(!1), [status, setStatus] = React.useState(void 0), [devices, setDevices] = React.useState([]), [selectedHost, setSelectedHost] = React.useState(void 0), [connectingHost, setConnectingHost] = React.useState(void 0), [workspaces, setWorkspaces] = React.useState([]), [codexWorkspaces, setCodexWorkspaces] = React.useState([]), [cursorWorkspaces, setCursorWorkspaces] = React.useState([]), [antigravityWorkspaces, setAntigravityWorkspaces] = React.useState([]), [piWorkspaces, setPiWorkspaces] = React.useState([]), [opencodeWorkspaces, setOpencodeWorkspaces] = React.useState([]), [workspaceBackend, setWorkspaceBackend] = React.useState("harness"), [codexWorkspaceId, setCodexWorkspaceId] = React.useState(void 0), [cursorWorkspaceId, setCursorWorkspaceId] = React.useState(void 0), [antigravityWorkspaceId, setAntigravityWorkspaceId] = React.useState(void 0), [piWorkspaceId, setPiWorkspaceId] = React.useState(void 0), [opencodeWorkspaceId, setOpencodeWorkspaceId] = 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), [devicesOpen, setDevicesOpen] = React.useState(!1), [showAllCursorWorkspaces, setShowAllCursorWorkspaces] = React.useState(!1), [showAllAntigravityWorkspaces, setShowAllAntigravityWorkspaces] = React.useState(!1), [showAllPiWorkspaces, setShowAllPiWorkspaces] = React.useState(!1), [showAllOpencodeWorkspaces, setShowAllOpencodeWorkspaces] = React.useState(!1), workspaceListId = "dsh-remote-workspace-list", codexWorkspaceHeadingId = "dsh-remote-codex-workspace-heading", codexWorkspaceListId = "dsh-remote-codex-workspace-list", cursorWorkspaceHeadingId = "dsh-remote-cursor-workspace-heading", cursorWorkspaceListId = "dsh-remote-cursor-workspace-list", antigravityWorkspaceHeadingId = "dsh-remote-antigravity-workspace-heading", piWorkspaceHeadingId = "dsh-remote-pi-workspace-heading", opencodeWorkspaceHeadingId = "dsh-remote-opencode-workspace-heading", antigravityWorkspaceListId = "dsh-remote-antigravity-workspace-list", piWorkspaceListId = "dsh-remote-pi-workspace-list", opencodeWorkspaceListId = "dsh-remote-opencode-workspace-list", [busy, setBusy] = React.useState(!1), [needsAuthorization, setNeedsAuthorization] = React.useState(!1), [email, setEmail] = React.useState(""), [password, setPassword] = React.useState(""), [loginServerUrl, setLoginServerUrl] = React.useState("https://dsh.r2049.cn"), [loginMethod, setLoginMethod] = React.useState("password"), loginMethodManuallySelected = React.useRef(!1), [oauthProviders, setOAuthProviders] = React.useState([]), [providersLoading, setProvidersLoading] = React.useState(!1), [providersFailed, setProvidersFailed] = React.useState(!1), [providerReload, setProviderReload] = React.useState(0), [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);
|
|
3111
|
+
React.useEffect(() => {
|
|
3112
|
+
open || (setDevicesOpen(!1), qrFlowRun.current += 1, setBusy(!1));
|
|
3113
|
+
}, [open]), React.useEffect(() => {
|
|
3114
|
+
if (!open) return;
|
|
3115
|
+
let closeOnEscape = (event) => {
|
|
3116
|
+
if (event.key === "Escape") {
|
|
3117
|
+
if (devicesOpen) {
|
|
3118
|
+
event.stopPropagation(), setDevicesOpen(!1);
|
|
3119
|
+
return;
|
|
3120
|
+
}
|
|
3121
|
+
setOpen(!1);
|
|
3127
3122
|
}
|
|
3128
3123
|
};
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3124
|
+
return window.addEventListener("keydown", closeOnEscape), () => window.removeEventListener("keydown", closeOnEscape);
|
|
3125
|
+
}, [open, devicesOpen]), React.useEffect(() => {
|
|
3126
|
+
if (!devicesOpen) return;
|
|
3127
|
+
let closeOnPointer = (event) => {
|
|
3128
|
+
let target = event.target;
|
|
3129
|
+
target instanceof Element && target.closest(".dshRemoteConnectedMenu") === null && setDevicesOpen(!1);
|
|
3130
|
+
};
|
|
3131
|
+
return window.addEventListener("mousedown", closeOnPointer), () => window.removeEventListener("mousedown", closeOnPointer);
|
|
3132
|
+
}, [devicesOpen]), React.useEffect(() => {
|
|
3133
|
+
(status?.host?.connectedClients?.length ?? 0) === 0 && setDevicesOpen(!1);
|
|
3134
|
+
}, [status?.host?.connectedClients?.length]), React.useEffect(() => {
|
|
3135
|
+
props.control("status").then(setStatus).catch(() => {
|
|
3136
|
+
});
|
|
3137
|
+
}, []), React.useEffect(() => {
|
|
3138
|
+
status?.serverUrl !== void 0 && loginServerUrl === "https://dsh.r2049.cn" && setLoginServerUrl(status.serverUrl);
|
|
3139
|
+
}, [status?.serverUrl]), React.useEffect(() => {
|
|
3140
|
+
let remoteActive = status?.mode === "remote";
|
|
3141
|
+
return document.documentElement.classList.toggle("dshRemoteTargetActive", remoteActive), () => {
|
|
3142
|
+
remoteActive && document.documentElement.classList.remove("dshRemoteTargetActive");
|
|
3143
|
+
};
|
|
3144
|
+
}, [status?.mode]);
|
|
3145
|
+
let startQrLogin = async (provider) => {
|
|
3146
|
+
let run = ++qrFlowRun.current;
|
|
3147
|
+
setBusy(!0), setError(void 0), setQrExpired(!1);
|
|
3148
|
+
try {
|
|
3149
|
+
let session = await props.control("client.account.qr.start", { provider }), image = await import_qrcode.default.toDataURL(session.scanUrl, {
|
|
3150
|
+
width: 184,
|
|
3151
|
+
margin: 1,
|
|
3152
|
+
errorCorrectionLevel: "L"
|
|
3153
|
+
});
|
|
3154
|
+
if (run !== qrFlowRun.current) return;
|
|
3155
|
+
setQrSession(session), setQrImage(image);
|
|
3156
|
+
} catch (reason) {
|
|
3157
|
+
run === qrFlowRun.current && setError(messageOf(reason));
|
|
3158
|
+
} finally {
|
|
3159
|
+
run === qrFlowRun.current && setBusy(!1);
|
|
3160
|
+
}
|
|
3161
|
+
};
|
|
3162
|
+
React.useEffect(() => {
|
|
3163
|
+
if (!open || !needsAuthorization) return;
|
|
3164
|
+
let active = !0;
|
|
3165
|
+
return qrFlowRun.current += 1, setBusy(!1), setQrSession(void 0), setQrImage(void 0), setQrExpired(!1), setOAuthProviders([]), setProvidersLoading(!0), setProvidersFailed(!1), props.control("client.account.providers").then((items) => {
|
|
3166
|
+
if (!active) return;
|
|
3167
|
+
let available = items.filter((item) => item.qrStartUrl != null);
|
|
3168
|
+
setOAuthProviders(available), setLoginMethod((current) => {
|
|
3169
|
+
if (loginMethodManuallySelected.current && (current === "password" || available.some((item) => `oauth:${item.id}` === current))) return current;
|
|
3170
|
+
let preferred = available.find((item) => item.id === props.preferredQrProvider) ?? available[0];
|
|
3171
|
+
return preferred === void 0 ? "password" : `oauth:${preferred.id}`;
|
|
3172
|
+
});
|
|
3173
|
+
}).catch((reason) => {
|
|
3174
|
+
active && (setProvidersFailed(!0), setLoginMethod("password"), setError(messageOf(reason)));
|
|
3175
|
+
}).finally(() => {
|
|
3176
|
+
active && setProvidersLoading(!1);
|
|
3177
|
+
}), () => {
|
|
3178
|
+
active = !1;
|
|
3179
|
+
};
|
|
3180
|
+
}, [open, needsAuthorization, status?.serverUrl, props.preferredQrProvider, providerReload]), React.useEffect(() => {
|
|
3181
|
+
!open || !needsAuthorization || providersLoading || loginMethod === "password" || !oauthProviders.some((item) => `oauth:${item.id}` === loginMethod) || qrSession !== void 0 || qrExpired || startQrLogin(loginMethod.slice(6));
|
|
3182
|
+
}, [open, needsAuthorization, providersLoading, oauthProviders, loginMethod, qrSession, qrExpired]), React.useEffect(() => {
|
|
3183
|
+
if (!open || loginMethod === "password" || qrSession === void 0) return;
|
|
3184
|
+
let active = !0, polling = !1, settled = !1, run = qrFlowRun.current, timer, poll = () => {
|
|
3185
|
+
polling || settled || (polling = !0, props.control("client.account.qr.poll", { qrId: qrSession.qrId }).then(async (result) => {
|
|
3186
|
+
if (!(!active || settled || run !== qrFlowRun.current))
|
|
3187
|
+
if (result.status === "complete") {
|
|
3188
|
+
settled = !0, timer !== void 0 && window.clearInterval(timer), setBusy(!0), setError(void 0), setQrExpired(!1), setNeedsAuthorization(!1);
|
|
3189
|
+
try {
|
|
3190
|
+
let [nextDevices, nextStatus] = await Promise.all([
|
|
3191
|
+
props.control("devices"),
|
|
3192
|
+
props.control("status")
|
|
3193
|
+
]);
|
|
3194
|
+
active && run === qrFlowRun.current && (setDevices(nextDevices), setStatus(nextStatus));
|
|
3195
|
+
} catch (reason) {
|
|
3196
|
+
active && run === qrFlowRun.current && setError(messageOf(reason));
|
|
3197
|
+
} finally {
|
|
3198
|
+
run === qrFlowRun.current && (setQrSession(void 0), setQrImage(void 0), setBusy(!1));
|
|
3199
|
+
}
|
|
3200
|
+
} else result.status === "expired" && (settled = !0, timer !== void 0 && window.clearInterval(timer), setQrExpired(!0), setQrSession(void 0), setQrImage(void 0));
|
|
3140
3201
|
}).catch((reason) => {
|
|
3141
|
-
active &&
|
|
3202
|
+
active && !settled && run === qrFlowRun.current && setError(messageOf(reason));
|
|
3142
3203
|
}).finally(() => {
|
|
3143
|
-
|
|
3144
|
-
})
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
"aria-controls": `dsh-remote-oauth:${provider.id}-panel`,
|
|
3187
|
-
className: loginMethod === `oauth:${provider.id}` ? "isActive" : "",
|
|
3188
|
-
disabled: busy,
|
|
3189
|
-
onClick: () => selectLoginMethod(`oauth:${provider.id}`)
|
|
3190
|
-
}, t("providerLogin", { provider: provider.displayName })), selectHost = async (host) => {
|
|
3191
|
-
setBusy(!0), setError(void 0), setConnectingHost(host), setCodexWorkspaces([]), setCursorWorkspaces([]), setAntigravityWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setShowAllCursorWorkspaces(!1), setShowAllAntigravityWorkspaces(!1);
|
|
3192
|
-
try {
|
|
3193
|
-
let result = await runConnectHostProgress(
|
|
3194
|
-
status?.preferredTransports,
|
|
3195
|
-
host.deviceId,
|
|
3196
|
-
props.control,
|
|
3197
|
-
{ label: "remoteProgressLoadingWorkspaces", detail: "remoteProgressLoadingWorkspacesDetail" },
|
|
3198
|
-
setProgress,
|
|
3199
|
-
progressRun,
|
|
3200
|
-
async () => {
|
|
3201
|
-
let nextWorkspaces = await props.control("workspaces.list", {
|
|
3202
|
-
targetDeviceId: host.deviceId
|
|
3203
|
-
}), nextCodexWorkspaces = await props.control("codex.workspaces.list", {
|
|
3204
|
-
targetDeviceId: host.deviceId
|
|
3205
|
-
}).catch(() => []), nextCursorWorkspaces = await props.control("cursor.workspaces.list", {
|
|
3206
|
-
targetDeviceId: host.deviceId
|
|
3207
|
-
}).catch(() => []), nextAntigravityWorkspaces = await props.control("antigravity.workspaces.list", {
|
|
3208
|
-
targetDeviceId: host.deviceId
|
|
3209
|
-
}).catch(() => []), nextStatus = await props.control("status").catch(() => {
|
|
3210
|
-
});
|
|
3211
|
-
return nextStatus !== void 0 && setStatus(nextStatus), {
|
|
3212
|
-
workspaces: nextWorkspaces,
|
|
3213
|
-
codexWorkspaces: nextCodexWorkspaces,
|
|
3214
|
-
cursorWorkspaces: nextCursorWorkspaces,
|
|
3215
|
-
antigravityWorkspaces: nextAntigravityWorkspaces,
|
|
3216
|
-
status: nextStatus
|
|
3217
|
-
};
|
|
3218
|
-
},
|
|
3219
|
-
(result2) => connectedProgress(result2.status)
|
|
3220
|
-
);
|
|
3221
|
-
setWorkspaces(result.workspaces), setCodexWorkspaces(result.codexWorkspaces), setCursorWorkspaces(result.cursorWorkspaces), setAntigravityWorkspaces(result.antigravityWorkspaces), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setCursorWorkspaceId(void 0), setAntigravityWorkspaceId(void 0), setSelectedHost(host), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
|
|
3222
|
-
} catch (reason) {
|
|
3223
|
-
setError(messageOf(reason));
|
|
3224
|
-
} finally {
|
|
3225
|
-
setConnectingHost(void 0), setBusy(!1);
|
|
3226
|
-
}
|
|
3227
|
-
}, browseDirectory = async (nextPath) => {
|
|
3228
|
-
if (selectedHost !== void 0) {
|
|
3229
|
-
setBusy(!0), setError(void 0);
|
|
3230
|
-
try {
|
|
3231
|
-
let listing = await props.control("directory.list", {
|
|
3232
|
-
targetDeviceId: selectedHost.deviceId,
|
|
3233
|
-
...nextPath === void 0 ? {} : { path: nextPath }
|
|
3204
|
+
polling = !1;
|
|
3205
|
+
}));
|
|
3206
|
+
};
|
|
3207
|
+
return poll(), timer = window.setInterval(poll, 1500), () => {
|
|
3208
|
+
active = !1, timer !== void 0 && window.clearInterval(timer);
|
|
3209
|
+
};
|
|
3210
|
+
}, [open, loginMethod, qrSession]);
|
|
3211
|
+
let selectLoginMethod = (method) => {
|
|
3212
|
+
loginMethodManuallySelected.current = !0, method !== loginMethod && (qrFlowRun.current += 1, setLoginMethod(method), setQrSession(void 0), setQrImage(void 0), setQrExpired(!1), setError(void 0));
|
|
3213
|
+
}, orderedQrProviders = [...oauthProviders].sort((a, b) => +(b.id === props.preferredQrProvider) - +(a.id === props.preferredQrProvider)), selectedProvider = oauthProviders.find((item) => `oauth:${item.id}` === loginMethod), scanLabel = t("scanWithProvider", { provider: selectedProvider?.displayName ?? "" }), qrLoginTab = (provider) => React.createElement("button", {
|
|
3214
|
+
key: provider.id,
|
|
3215
|
+
type: "button",
|
|
3216
|
+
role: "tab",
|
|
3217
|
+
id: `dsh-remote-oauth:${provider.id}-tab`,
|
|
3218
|
+
"aria-selected": loginMethod === `oauth:${provider.id}`,
|
|
3219
|
+
"aria-controls": `dsh-remote-oauth:${provider.id}-panel`,
|
|
3220
|
+
className: loginMethod === `oauth:${provider.id}` ? "isActive" : "",
|
|
3221
|
+
disabled: busy,
|
|
3222
|
+
onClick: () => selectLoginMethod(`oauth:${provider.id}`)
|
|
3223
|
+
}, t("providerLogin", { provider: provider.displayName })), selectHost = async (host) => {
|
|
3224
|
+
setBusy(!0), setError(void 0), setConnectingHost(host), setCodexWorkspaces([]), setCursorWorkspaces([]), setAntigravityWorkspaces([]), setPiWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setShowAllCursorWorkspaces(!1), setShowAllAntigravityWorkspaces(!1), setShowAllPiWorkspaces(!1);
|
|
3225
|
+
try {
|
|
3226
|
+
let result = await runConnectHostProgress(
|
|
3227
|
+
status?.preferredTransports,
|
|
3228
|
+
host.deviceId,
|
|
3229
|
+
props.control,
|
|
3230
|
+
{ label: "remoteProgressLoadingWorkspaces", detail: "remoteProgressLoadingWorkspacesDetail" },
|
|
3231
|
+
setProgress,
|
|
3232
|
+
progressRun,
|
|
3233
|
+
async () => {
|
|
3234
|
+
let nextWorkspaces = await props.control("workspaces.list", {
|
|
3235
|
+
targetDeviceId: host.deviceId
|
|
3236
|
+
}), nextCodexWorkspaces = await props.control("codex.workspaces.list", {
|
|
3237
|
+
targetDeviceId: host.deviceId
|
|
3238
|
+
}).catch(() => []), nextCursorWorkspaces = await props.control("cursor.workspaces.list", {
|
|
3239
|
+
targetDeviceId: host.deviceId
|
|
3240
|
+
}).catch(() => []), nextAntigravityWorkspaces = await props.control("antigravity.workspaces.list", {
|
|
3241
|
+
targetDeviceId: host.deviceId
|
|
3242
|
+
}).catch(() => []), nextPiWorkspaces = await props.control("pi.workspaces.list", {
|
|
3243
|
+
targetDeviceId: host.deviceId
|
|
3244
|
+
}).catch(() => []), nextOpencodeWorkspaces = await props.control("opencode.workspaces.list", {
|
|
3245
|
+
targetDeviceId: host.deviceId
|
|
3246
|
+
}).catch(() => []), nextStatus = await props.control("status").catch(() => {
|
|
3234
3247
|
});
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
+
return nextStatus !== void 0 && setStatus(nextStatus), {
|
|
3249
|
+
workspaces: nextWorkspaces,
|
|
3250
|
+
codexWorkspaces: nextCodexWorkspaces,
|
|
3251
|
+
cursorWorkspaces: nextCursorWorkspaces,
|
|
3252
|
+
antigravityWorkspaces: nextAntigravityWorkspaces,
|
|
3253
|
+
piWorkspaces: nextPiWorkspaces,
|
|
3254
|
+
status: nextStatus
|
|
3255
|
+
};
|
|
3256
|
+
},
|
|
3257
|
+
(result2) => connectedProgress(result2.status)
|
|
3258
|
+
);
|
|
3259
|
+
setWorkspaces(result.workspaces), setCodexWorkspaces(result.codexWorkspaces), setCursorWorkspaces(result.cursorWorkspaces), setAntigravityWorkspaces(result.antigravityWorkspaces), setPiWorkspaces(result.piWorkspaces), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setCursorWorkspaceId(void 0), setAntigravityWorkspaceId(void 0), setPiWorkspaceId(void 0), setSelectedHost(host), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
|
|
3260
|
+
} catch (reason) {
|
|
3261
|
+
setError(messageOf(reason));
|
|
3262
|
+
} finally {
|
|
3263
|
+
setConnectingHost(void 0), setBusy(!1);
|
|
3264
|
+
}
|
|
3265
|
+
}, browseDirectory = async (nextPath) => {
|
|
3266
|
+
if (selectedHost !== void 0) {
|
|
3267
|
+
setBusy(!0), setError(void 0);
|
|
3248
3268
|
try {
|
|
3249
|
-
let
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
try {
|
|
3255
|
-
let nextDevices = await props.control("devices");
|
|
3256
|
-
if (setDevices(nextDevices), setNeedsAuthorization(!1), selectedHost !== void 0) {
|
|
3257
|
-
let nextSelectedHost = nextDevices.find((device) => device.deviceId === selectedHost.deviceId);
|
|
3258
|
-
nextSelectedHost === void 0 ? (setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setCursorWorkspaces([]), setAntigravityWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setShowAllCursorWorkspaces(!1), setShowAllAntigravityWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setCursorWorkspaceId(void 0), setAntigravityWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0)) : (setSelectedHost(nextSelectedHost), props.control("workspaces.list", { targetDeviceId: nextSelectedHost.deviceId }).then((w) => setWorkspaces(w)).catch(() => {
|
|
3259
|
-
}), props.control("codex.workspaces.list", { targetDeviceId: nextSelectedHost.deviceId }).then((w) => setCodexWorkspaces(w)).catch(() => {
|
|
3260
|
-
}), props.control("cursor.workspaces.list", { targetDeviceId: nextSelectedHost.deviceId }).then((w) => setCursorWorkspaces(w)).catch(() => {
|
|
3261
|
-
}), props.control("antigravity.workspaces.list", { targetDeviceId: nextSelectedHost.deviceId }).then((w) => setAntigravityWorkspaces(w)).catch(() => {
|
|
3262
|
-
}));
|
|
3263
|
-
}
|
|
3264
|
-
} catch {
|
|
3265
|
-
setDevices([]), setNeedsAuthorization(!0), setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setCursorWorkspaces([]), setAntigravityWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setShowAllCursorWorkspaces(!1), setShowAllAntigravityWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setCursorWorkspaceId(void 0), setAntigravityWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
|
|
3266
|
-
}
|
|
3269
|
+
let listing = await props.control("directory.list", {
|
|
3270
|
+
targetDeviceId: selectedHost.deviceId,
|
|
3271
|
+
...nextPath === void 0 ? {} : { path: nextPath }
|
|
3272
|
+
});
|
|
3273
|
+
setDirectory(listing), setCodexWorkspaceId(void 0), setCursorWorkspaceId(void 0), setAntigravityWorkspaceId(void 0), setPiWorkspaceId(void 0), setPath(listing.path);
|
|
3267
3274
|
} catch (reason) {
|
|
3268
3275
|
setError(messageOf(reason));
|
|
3269
3276
|
} finally {
|
|
3270
3277
|
setBusy(!1);
|
|
3271
3278
|
}
|
|
3272
|
-
}
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
try {
|
|
3285
|
-
await props.control("settings.configure", {
|
|
3286
|
-
role: "client",
|
|
3287
|
-
serverUrl: loginServerUrl.trim(),
|
|
3288
|
-
email: email.trim(),
|
|
3289
|
-
password
|
|
3290
|
-
}), setDevices(await props.control("devices")), setStatus(await props.control("status")), setNeedsAuthorization(!1), setPassword("");
|
|
3291
|
-
} catch (reason) {
|
|
3292
|
-
setError(messageOf(reason));
|
|
3293
|
-
} finally {
|
|
3294
|
-
setBusy(!1);
|
|
3295
|
-
}
|
|
3279
|
+
}
|
|
3280
|
+
}, startAddingWorkspace = (backend) => {
|
|
3281
|
+
setAddingWorkspace(!0), setWorkspaceBackend(backend), setCodexWorkspaceId(void 0), setCursorWorkspaceId(void 0), setAntigravityWorkspaceId(void 0), setPiWorkspaceId(void 0), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setShowAllCursorWorkspaces(!1), setShowAllAntigravityWorkspaces(!1), setShowAllPiWorkspaces(!1), setDirectory(void 0), setPath(""), browseDirectory();
|
|
3282
|
+
}, cancelAddingWorkspace = () => {
|
|
3283
|
+
setAddingWorkspace(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setCursorWorkspaceId(void 0), setAntigravityWorkspaceId(void 0), setPiWorkspaceId(void 0), setDirectory(void 0), setPath("");
|
|
3284
|
+
}, refreshRemote = async () => {
|
|
3285
|
+
setBusy(!0), setNotice(void 0), setError(void 0);
|
|
3286
|
+
try {
|
|
3287
|
+
let nextStatus = await props.control("status");
|
|
3288
|
+
if (setStatus(nextStatus), !nextStatus.available) {
|
|
3289
|
+
setDevices([]), setNeedsAuthorization(!1), setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setCursorWorkspaces([]), setAntigravityWorkspaces([]), setPiWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setShowAllCursorWorkspaces(!1), setShowAllAntigravityWorkspaces(!1), setShowAllPiWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setCursorWorkspaceId(void 0), setAntigravityWorkspaceId(void 0), setPiWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
|
|
3290
|
+
return;
|
|
3296
3291
|
}
|
|
3297
|
-
}, openLocalWorkspaces = async () => {
|
|
3298
|
-
setBusy(!0), setError(void 0);
|
|
3299
3292
|
try {
|
|
3300
|
-
await props.control("
|
|
3301
|
-
|
|
3302
|
-
|
|
3293
|
+
let nextDevices = await props.control("devices");
|
|
3294
|
+
if (setDevices(nextDevices), setNeedsAuthorization(!1), selectedHost !== void 0) {
|
|
3295
|
+
let nextSelectedHost = nextDevices.find((device) => device.deviceId === selectedHost.deviceId);
|
|
3296
|
+
nextSelectedHost === void 0 ? (setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setCursorWorkspaces([]), setAntigravityWorkspaces([]), setPiWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setShowAllCursorWorkspaces(!1), setShowAllAntigravityWorkspaces(!1), setShowAllPiWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setCursorWorkspaceId(void 0), setAntigravityWorkspaceId(void 0), setPiWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0)) : (setSelectedHost(nextSelectedHost), props.control("workspaces.list", { targetDeviceId: nextSelectedHost.deviceId }).then((w) => setWorkspaces(w)).catch(() => {
|
|
3297
|
+
}), props.control("codex.workspaces.list", { targetDeviceId: nextSelectedHost.deviceId }).then((w) => setCodexWorkspaces(w)).catch(() => {
|
|
3298
|
+
}), props.control("cursor.workspaces.list", { targetDeviceId: nextSelectedHost.deviceId }).then((w) => setCursorWorkspaces(w)).catch(() => {
|
|
3299
|
+
}), props.control("antigravity.workspaces.list", { targetDeviceId: nextSelectedHost.deviceId }).then((w) => setAntigravityWorkspaces(w)).catch(() => {
|
|
3300
|
+
}), props.control("pi.workspaces.list", { targetDeviceId: nextSelectedHost.deviceId }).then((w) => setPiWorkspaces(w)).catch(() => {
|
|
3301
|
+
}));
|
|
3302
|
+
}
|
|
3303
|
+
} catch {
|
|
3304
|
+
setDevices([]), setNeedsAuthorization(!0), setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setCursorWorkspaces([]), setAntigravityWorkspaces([]), setPiWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setShowAllCursorWorkspaces(!1), setShowAllAntigravityWorkspaces(!1), setShowAllPiWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setCursorWorkspaceId(void 0), setAntigravityWorkspaceId(void 0), setPiWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
|
|
3303
3305
|
}
|
|
3304
|
-
}
|
|
3306
|
+
} catch (reason) {
|
|
3307
|
+
setError(messageOf(reason));
|
|
3308
|
+
} finally {
|
|
3309
|
+
setBusy(!1);
|
|
3310
|
+
}
|
|
3311
|
+
}, show = async () => {
|
|
3312
|
+
setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setShowAllCursorWorkspaces(!1), setShowAllAntigravityWorkspaces(!1), setShowAllPiWorkspaces(!1), setOpen(!0), await refreshRemote();
|
|
3313
|
+
};
|
|
3314
|
+
React.useEffect(() => {
|
|
3315
|
+
if (!(!open || selectedHost !== void 0))
|
|
3316
|
+
return props.statusFeed.subscribe(setStatus);
|
|
3317
|
+
}, [open, selectedHost]);
|
|
3318
|
+
let chooseAnotherHost = () => {
|
|
3319
|
+
setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setCursorWorkspaces([]), setAntigravityWorkspaces([]), setPiWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setShowAllCursorWorkspaces(!1), setShowAllAntigravityWorkspaces(!1), setShowAllPiWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setCursorWorkspaceId(void 0), setAntigravityWorkspaceId(void 0), setPiWorkspaceId(void 0), setDirectory(void 0), setPath(""), setAddingWorkspace(!1), setError(void 0);
|
|
3320
|
+
}, signInClient = async () => {
|
|
3321
|
+
if (!(email.trim() === "" || password === "" || loginServerUrl.trim() === "")) {
|
|
3305
3322
|
setBusy(!0), setError(void 0);
|
|
3306
3323
|
try {
|
|
3307
|
-
|
|
3324
|
+
await props.control("settings.configure", {
|
|
3325
|
+
role: "client",
|
|
3326
|
+
serverUrl: loginServerUrl.trim(),
|
|
3327
|
+
email: email.trim(),
|
|
3328
|
+
password
|
|
3329
|
+
}), setDevices(await props.control("devices")), setStatus(await props.control("status")), setNeedsAuthorization(!1), setPassword("");
|
|
3308
3330
|
} catch (reason) {
|
|
3309
3331
|
setError(messageOf(reason));
|
|
3310
3332
|
} finally {
|
|
3311
3333
|
setBusy(!1);
|
|
3312
3334
|
}
|
|
3313
|
-
}
|
|
3335
|
+
}
|
|
3336
|
+
}, openLocalWorkspaces = async () => {
|
|
3337
|
+
setBusy(!0), setError(void 0);
|
|
3338
|
+
try {
|
|
3339
|
+
await props.control("mode.set", { mode: "local" }), window.location.reload();
|
|
3340
|
+
} catch (reason) {
|
|
3341
|
+
setError(messageOf(reason)), setBusy(!1);
|
|
3342
|
+
}
|
|
3343
|
+
}, setCurrentDeviceControl = async (enabled) => {
|
|
3344
|
+
setBusy(!0), setError(void 0);
|
|
3345
|
+
try {
|
|
3346
|
+
setStatus(await props.control("host.authorization.set", { enabled }));
|
|
3347
|
+
} catch (reason) {
|
|
3348
|
+
setError(messageOf(reason));
|
|
3349
|
+
} finally {
|
|
3350
|
+
setBusy(!1);
|
|
3351
|
+
}
|
|
3352
|
+
}, logoutRemote = async () => {
|
|
3353
|
+
setBusy(!0), setError(void 0);
|
|
3354
|
+
try {
|
|
3355
|
+
await props.control("settings.logout"), setDevices([]), setNeedsAuthorization(!0), setQrSession(void 0), setQrImage(void 0), setQrExpired(!1), setStatus(await props.control("status"));
|
|
3356
|
+
} catch (reason) {
|
|
3357
|
+
setError(messageOf(reason));
|
|
3358
|
+
} finally {
|
|
3359
|
+
setBusy(!1);
|
|
3360
|
+
}
|
|
3361
|
+
}, openWorkspace = async (selection) => {
|
|
3362
|
+
let targetBackend = selection?.backend ?? workspaceBackend, targetPath = (selection?.path ?? path).trim(), targetCodexWorkspaceId = selection?.backend === "codex" ? selection.workspaceId : selection === void 0 ? codexWorkspaceId : void 0, targetCursorWorkspaceId = selection?.backend === "cursor" ? selection.workspaceId : selection === void 0 ? cursorWorkspaceId : void 0, targetAntigravityWorkspaceId = selection?.backend === "antigravity" ? selection.workspaceId : selection === void 0 ? antigravityWorkspaceId : void 0, targetPiWorkspaceId = selection?.backend === "pi" ? selection.workspaceId : selection === void 0 ? piWorkspaceId : void 0, targetOpencodeWorkspaceId = selection?.backend === "opencode" ? selection.workspaceId : selection === void 0 ? opencodeWorkspaceId : void 0, createWorkspace = selection === void 0 && addingWorkspace;
|
|
3363
|
+
if (!(selectedHost === void 0 || targetPath === "" || !createWorkspace && targetBackend === "codex" && targetCodexWorkspaceId === void 0 || !createWorkspace && targetBackend === "cursor" && targetCursorWorkspaceId === void 0 && targetPath === "" || !createWorkspace && targetBackend === "antigravity" && targetAntigravityWorkspaceId === void 0 && targetPath === "")) {
|
|
3314
3364
|
setBusy(!0), setError(void 0);
|
|
3315
3365
|
try {
|
|
3316
|
-
|
|
3366
|
+
let nextStatus = await (targetBackend === "codex" ? createWorkspace ? props.control("codex.workspace.create", {
|
|
3367
|
+
targetDeviceId: selectedHost.deviceId,
|
|
3368
|
+
path: targetPath
|
|
3369
|
+
}) : props.control("codex.workspace.open", {
|
|
3370
|
+
targetDeviceId: selectedHost.deviceId,
|
|
3371
|
+
workspaceId: targetCodexWorkspaceId
|
|
3372
|
+
}) : targetBackend === "cursor" ? createWorkspace || targetCursorWorkspaceId === void 0 ? props.control("cursor.workspace.create", {
|
|
3373
|
+
targetDeviceId: selectedHost.deviceId,
|
|
3374
|
+
path: targetPath
|
|
3375
|
+
}) : props.control("cursor.workspace.open", {
|
|
3376
|
+
targetDeviceId: selectedHost.deviceId,
|
|
3377
|
+
workspaceId: targetCursorWorkspaceId
|
|
3378
|
+
}) : targetBackend === "antigravity" ? createWorkspace || targetAntigravityWorkspaceId === void 0 ? props.control("antigravity.workspace.create", {
|
|
3379
|
+
targetDeviceId: selectedHost.deviceId,
|
|
3380
|
+
path: targetPath
|
|
3381
|
+
}) : props.control("antigravity.workspace.open", {
|
|
3382
|
+
targetDeviceId: selectedHost.deviceId,
|
|
3383
|
+
workspaceId: targetAntigravityWorkspaceId
|
|
3384
|
+
}) : targetBackend === "pi" ? createWorkspace || targetPiWorkspaceId === void 0 ? props.control("pi.workspace.create", {
|
|
3385
|
+
targetDeviceId: selectedHost.deviceId,
|
|
3386
|
+
path: targetPath
|
|
3387
|
+
}) : props.control("pi.workspace.open", {
|
|
3388
|
+
targetDeviceId: selectedHost.deviceId,
|
|
3389
|
+
workspaceId: targetPiWorkspaceId
|
|
3390
|
+
}) : targetBackend === "opencode" ? createWorkspace || targetOpencodeWorkspaceId === void 0 ? props.control("opencode.workspace.create", {
|
|
3391
|
+
targetDeviceId: selectedHost.deviceId,
|
|
3392
|
+
path: targetPath
|
|
3393
|
+
}) : props.control("opencode.workspace.open", {
|
|
3394
|
+
targetDeviceId: selectedHost.deviceId,
|
|
3395
|
+
workspaceId: targetOpencodeWorkspaceId
|
|
3396
|
+
}) : props.control("workspace.open", {
|
|
3397
|
+
targetDeviceId: selectedHost.deviceId,
|
|
3398
|
+
path: targetPath
|
|
3399
|
+
}));
|
|
3400
|
+
setStatus(nextStatus), nextStatus.workspaceSelection !== void 0 && window.sessionStorage.setItem(pendingWorkspaceSelectionKey, JSON.stringify(nextStatus.workspaceSelection)), window.location.reload();
|
|
3317
3401
|
} catch (reason) {
|
|
3318
|
-
setError(messageOf(reason));
|
|
3319
|
-
} finally {
|
|
3320
|
-
setBusy(!1);
|
|
3402
|
+
setError(messageOf(reason)), setBusy(!1);
|
|
3321
3403
|
}
|
|
3322
|
-
}
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
path: targetPath
|
|
3342
|
-
}) : props.control("antigravity.workspace.open", {
|
|
3343
|
-
targetDeviceId: selectedHost.deviceId,
|
|
3344
|
-
workspaceId: targetAntigravityWorkspaceId
|
|
3345
|
-
}) : props.control("workspace.open", {
|
|
3346
|
-
targetDeviceId: selectedHost.deviceId,
|
|
3347
|
-
path: targetPath
|
|
3348
|
-
}));
|
|
3349
|
-
setStatus(nextStatus), nextStatus.workspaceSelection !== void 0 && window.sessionStorage.setItem(pendingWorkspaceSelectionKey, JSON.stringify(nextStatus.workspaceSelection)), window.location.reload();
|
|
3350
|
-
} catch (reason) {
|
|
3351
|
-
setError(messageOf(reason)), setBusy(!1);
|
|
3352
|
-
}
|
|
3404
|
+
}
|
|
3405
|
+
}, remoteLabel = status?.mode === "remote" ? t("activeRemote", { name: status.target?.name ?? t("host") }) : t("remoteEntry"), remoteActionLabel = status?.mode === "remote" ? `${remoteLabel} \xB7 ${t("exitRemote")}` : remoteLabel, visibleWorkspaces = showAllWorkspaces ? workspaces : workspaces.slice(0, 3), visibleCodexWorkspaces = showAllCodexWorkspaces ? codexWorkspaces : codexWorkspaces.slice(0, 3), visibleCursorWorkspaces = showAllCursorWorkspaces ? cursorWorkspaces : cursorWorkspaces.slice(0, 3), visibleAntigravityWorkspaces = showAllAntigravityWorkspaces ? antigravityWorkspaces : antigravityWorkspaces.slice(0, 3), visiblePiWorkspaces = showAllPiWorkspaces ? piWorkspaces : piWorkspaces.slice(0, 3), visibleOpencodeWorkspaces = showAllOpencodeWorkspaces ? opencodeWorkspaces : opencodeWorkspaces.slice(0, 3), codexAvailable = status?.remoteFeatures?.codex === !0, cursorAvailable = status?.remoteFeatures?.cursor === !0, antigravityAvailable = status?.remoteFeatures?.antigravity === !0, piAvailable = status?.remoteFeatures?.pi === !0, opencodeAvailable = status?.remoteFeatures?.opencode === !0, selectedHostDetails = selectedHost === void 0 ? void 0 : [
|
|
3406
|
+
formatPlatform(selectedHost.platform),
|
|
3407
|
+
selectedHost.harnessVersion === void 0 ? void 0 : t("harnessVersion", { version: selectedHost.harnessVersion }),
|
|
3408
|
+
selectedHost.clientVersion === void 0 ? void 0 : t("pluginVersion", { version: selectedHost.clientVersion })
|
|
3409
|
+
].filter(Boolean).join(" \xB7 "), connectedClients = status?.host?.connectedClients ?? [], connectedCount = connectedClients.length, connectedCountLabel = t("connectedClientCount", { count: connectedCount }), connectedMenu = !needsAuthorization && status?.hostAuthorizationAvailable === !0 ? React.createElement(
|
|
3410
|
+
"div",
|
|
3411
|
+
{
|
|
3412
|
+
className: `dshRemoteConnectedMenu${devicesOpen ? " isOpen" : ""}`
|
|
3413
|
+
},
|
|
3414
|
+
React.createElement("a", {
|
|
3415
|
+
href: connectedCount > 0 ? "#connected-devices" : void 0,
|
|
3416
|
+
className: `dshRemoteConnectedCount${connectedCount > 0 ? " isOnline isInteractive" : ""}`,
|
|
3417
|
+
"aria-expanded": connectedCount > 0 ? devicesOpen : void 0,
|
|
3418
|
+
"aria-haspopup": connectedCount > 0 ? "dialog" : void 0,
|
|
3419
|
+
title: connectedCountLabel,
|
|
3420
|
+
"aria-label": connectedCountLabel,
|
|
3421
|
+
onClick: (event) => {
|
|
3422
|
+
event.preventDefault(), connectedCount !== 0 && setDevicesOpen((current) => !current);
|
|
3353
3423
|
}
|
|
3354
|
-
},
|
|
3355
|
-
|
|
3356
|
-
selectedHost.harnessVersion === void 0 ? void 0 : t("harnessVersion", { version: selectedHost.harnessVersion }),
|
|
3357
|
-
selectedHost.clientVersion === void 0 ? void 0 : t("pluginVersion", { version: selectedHost.clientVersion })
|
|
3358
|
-
].filter(Boolean).join(" \xB7 "), connectedClients = status?.host?.connectedClients ?? [], connectedCount = connectedClients.length, connectedCountLabel = t("connectedClientCount", { count: connectedCount }), connectedMenu = !needsAuthorization && status?.hostAuthorizationAvailable === !0 ? React.createElement(
|
|
3424
|
+
}, connectedCountLabel),
|
|
3425
|
+
devicesOpen && connectedCount > 0 ? React.createElement(
|
|
3359
3426
|
"div",
|
|
3360
3427
|
{
|
|
3361
|
-
className:
|
|
3428
|
+
className: "dshRemoteConnectedPanel",
|
|
3429
|
+
id: "connected-devices",
|
|
3430
|
+
role: "dialog",
|
|
3431
|
+
"aria-label": t("currentConnectedDevices")
|
|
3362
3432
|
},
|
|
3363
|
-
React.createElement("
|
|
3364
|
-
href: connectedCount > 0 ? "#connected-devices" : void 0,
|
|
3365
|
-
className: `dshRemoteConnectedCount${connectedCount > 0 ? " isOnline isInteractive" : ""}`,
|
|
3366
|
-
"aria-expanded": connectedCount > 0 ? devicesOpen : void 0,
|
|
3367
|
-
"aria-haspopup": connectedCount > 0 ? "dialog" : void 0,
|
|
3368
|
-
title: connectedCountLabel,
|
|
3369
|
-
"aria-label": connectedCountLabel,
|
|
3370
|
-
onClick: (event) => {
|
|
3371
|
-
event.preventDefault(), connectedCount !== 0 && setDevicesOpen((current) => !current);
|
|
3372
|
-
}
|
|
3373
|
-
}, connectedCountLabel),
|
|
3374
|
-
devicesOpen && connectedCount > 0 ? React.createElement(
|
|
3375
|
-
"div",
|
|
3376
|
-
{
|
|
3377
|
-
className: "dshRemoteConnectedPanel",
|
|
3378
|
-
id: "connected-devices",
|
|
3379
|
-
role: "dialog",
|
|
3380
|
-
"aria-label": t("currentConnectedDevices")
|
|
3381
|
-
},
|
|
3382
|
-
React.createElement("strong", { className: "dshRemoteConnectedPanelTitle" }, t("currentConnectedDevices")),
|
|
3383
|
-
React.createElement(
|
|
3384
|
-
"div",
|
|
3385
|
-
{ className: "dshRemoteClientList", "aria-label": t("currentConnectedDevices") },
|
|
3386
|
-
...connectedClients.map((client) => React.createElement(
|
|
3387
|
-
"div",
|
|
3388
|
-
{
|
|
3389
|
-
key: client.deviceId,
|
|
3390
|
-
className: "dshRemoteClientRow"
|
|
3391
|
-
},
|
|
3392
|
-
React.createElement(
|
|
3393
|
-
"span",
|
|
3394
|
-
null,
|
|
3395
|
-
React.createElement("strong", null, client.name.trim() === "" ? t("unknownDevice") : client.name),
|
|
3396
|
-
React.createElement("small", null, [
|
|
3397
|
-
client.platform === void 0 ? void 0 : formatPlatform(client.platform),
|
|
3398
|
-
connectedClientModeLabel(client.mode, t)
|
|
3399
|
-
].filter(Boolean).join(" \xB7 "))
|
|
3400
|
-
),
|
|
3401
|
-
React.createElement("small", { className: "dshRemoteClientOnline" }, t("connected"))
|
|
3402
|
-
))
|
|
3403
|
-
)
|
|
3404
|
-
) : null
|
|
3405
|
-
) : null, listedHosts = connectingHost === void 0 ? devices : [connectingHost];
|
|
3406
|
-
return React.createElement(
|
|
3407
|
-
React.Fragment,
|
|
3408
|
-
null,
|
|
3433
|
+
React.createElement("strong", { className: "dshRemoteConnectedPanelTitle" }, t("currentConnectedDevices")),
|
|
3409
3434
|
React.createElement(
|
|
3410
3435
|
"div",
|
|
3411
|
-
{ className:
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
type: "button",
|
|
3415
|
-
disabled: status?.mode === "remote" && busy,
|
|
3416
|
-
onClick: () => void (status?.mode === "remote" ? openLocalWorkspaces() : show())
|
|
3417
|
-
},
|
|
3418
|
-
className: "dshRemoteModeButton",
|
|
3419
|
-
title: props.wide ? remoteLabel : remoteActionLabel,
|
|
3420
|
-
"aria-label": props.wide ? remoteLabel : remoteActionLabel
|
|
3421
|
-
}, React.createElement(
|
|
3422
|
-
"svg",
|
|
3436
|
+
{ className: "dshRemoteClientList", "aria-label": t("currentConnectedDevices") },
|
|
3437
|
+
...connectedClients.map((client) => React.createElement(
|
|
3438
|
+
"div",
|
|
3423
3439
|
{
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
fill: "none",
|
|
3427
|
-
stroke: "currentColor",
|
|
3428
|
-
strokeWidth: 1.7,
|
|
3429
|
-
strokeLinecap: "round",
|
|
3430
|
-
strokeLinejoin: "round",
|
|
3431
|
-
"aria-hidden": !0
|
|
3440
|
+
key: client.deviceId,
|
|
3441
|
+
className: "dshRemoteClientRow"
|
|
3432
3442
|
},
|
|
3433
|
-
React.createElement(
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3443
|
+
React.createElement(
|
|
3444
|
+
"span",
|
|
3445
|
+
null,
|
|
3446
|
+
React.createElement("strong", null, client.name.trim() === "" ? t("unknownDevice") : client.name),
|
|
3447
|
+
React.createElement("small", null, [
|
|
3448
|
+
client.platform === void 0 ? void 0 : formatPlatform(client.platform),
|
|
3449
|
+
connectedClientModeLabel(client.mode, t)
|
|
3450
|
+
].filter(Boolean).join(" \xB7 "))
|
|
3451
|
+
),
|
|
3452
|
+
React.createElement("small", { className: "dshRemoteClientOnline" }, t("connected"))
|
|
3453
|
+
))
|
|
3454
|
+
)
|
|
3455
|
+
) : null
|
|
3456
|
+
) : null, listedHosts = connectingHost === void 0 ? devices : [connectingHost];
|
|
3457
|
+
return React.createElement(
|
|
3458
|
+
React.Fragment,
|
|
3459
|
+
null,
|
|
3460
|
+
React.createElement(
|
|
3461
|
+
"div",
|
|
3462
|
+
{ className: `dshRemoteSidebarEntry${status?.mode === "remote" ? " isActive" : ""}${props.wide ? " isWide" : " isRail"}` },
|
|
3463
|
+
React.createElement(status?.mode === "remote" && props.wide ? "div" : "button", {
|
|
3464
|
+
...status?.mode === "remote" && props.wide ? {} : {
|
|
3437
3465
|
type: "button",
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
className: "dshRemoteBackdrop",
|
|
3445
|
-
role: "presentation",
|
|
3446
|
-
onMouseDown: (event) => {
|
|
3447
|
-
event.target === event.currentTarget && setOpen(!1);
|
|
3448
|
-
}
|
|
3466
|
+
disabled: status?.mode === "remote" && busy,
|
|
3467
|
+
onClick: () => void (status?.mode === "remote" ? openLocalWorkspaces() : show())
|
|
3468
|
+
},
|
|
3469
|
+
className: "dshRemoteModeButton",
|
|
3470
|
+
title: props.wide ? remoteLabel : remoteActionLabel,
|
|
3471
|
+
"aria-label": props.wide ? remoteLabel : remoteActionLabel
|
|
3449
3472
|
}, React.createElement(
|
|
3450
|
-
"
|
|
3473
|
+
"svg",
|
|
3451
3474
|
{
|
|
3452
|
-
className:
|
|
3453
|
-
|
|
3454
|
-
"
|
|
3455
|
-
|
|
3475
|
+
className: "dshRemoteComputerIcon",
|
|
3476
|
+
viewBox: "0 0 24 24",
|
|
3477
|
+
fill: "none",
|
|
3478
|
+
stroke: "currentColor",
|
|
3479
|
+
strokeWidth: 1.7,
|
|
3480
|
+
strokeLinecap: "round",
|
|
3481
|
+
strokeLinejoin: "round",
|
|
3482
|
+
"aria-hidden": !0
|
|
3456
3483
|
},
|
|
3484
|
+
React.createElement("rect", { x: 3, y: 4, width: 18, height: 13, rx: 2 }),
|
|
3485
|
+
React.createElement("path", { d: "M8 21h8M12 17v4" })
|
|
3486
|
+
), props.wide ? React.createElement("span", { className: "dshRemoteSidebarLabel" }, remoteLabel) : null),
|
|
3487
|
+
status?.mode === "remote" && props.wide ? React.createElement("button", {
|
|
3488
|
+
type: "button",
|
|
3489
|
+
className: "dshRemoteExitLink",
|
|
3490
|
+
disabled: busy,
|
|
3491
|
+
onClick: () => void openLocalWorkspaces()
|
|
3492
|
+
}, t("exitRemote")) : null
|
|
3493
|
+
),
|
|
3494
|
+
open ? React.createElement("div", {
|
|
3495
|
+
className: "dshRemoteBackdrop",
|
|
3496
|
+
role: "presentation",
|
|
3497
|
+
onMouseDown: (event) => {
|
|
3498
|
+
event.target === event.currentTarget && setOpen(!1);
|
|
3499
|
+
}
|
|
3500
|
+
}, React.createElement(
|
|
3501
|
+
"section",
|
|
3502
|
+
{
|
|
3503
|
+
className: `dshRemotePage${selectedHost === void 0 ? "" : " hasSelectedHost"}`,
|
|
3504
|
+
role: "dialog",
|
|
3505
|
+
"aria-modal": !0,
|
|
3506
|
+
"aria-label": selectedHost?.name ?? t("remoteTitle")
|
|
3507
|
+
},
|
|
3508
|
+
React.createElement(
|
|
3509
|
+
"header",
|
|
3510
|
+
{ className: "dshRemotePageHeader" },
|
|
3457
3511
|
React.createElement(
|
|
3458
|
-
"
|
|
3459
|
-
{ className: "
|
|
3512
|
+
"div",
|
|
3513
|
+
{ className: "dshRemotePageIntro" },
|
|
3460
3514
|
React.createElement(
|
|
3461
3515
|
"div",
|
|
3462
|
-
{ className: "
|
|
3463
|
-
React.createElement(
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
target: "_blank",
|
|
3471
|
-
rel: "noreferrer"
|
|
3472
|
-
}, t("starProject")) : null
|
|
3473
|
-
),
|
|
3474
|
-
React.createElement("p", null, selectedHostDetails ?? t("remoteDescription"))
|
|
3516
|
+
{ className: "dshRemotePageTitleRow" },
|
|
3517
|
+
React.createElement("strong", null, selectedHost?.name ?? t("remoteTitle")),
|
|
3518
|
+
selectedHost === void 0 ? React.createElement("a", {
|
|
3519
|
+
className: "dshRemoteStarLink",
|
|
3520
|
+
href: "https://github.com/liguobao/ds-harness-remote",
|
|
3521
|
+
target: "_blank",
|
|
3522
|
+
rel: "noreferrer"
|
|
3523
|
+
}, t("starProject")) : null
|
|
3475
3524
|
),
|
|
3476
|
-
React.createElement(
|
|
3477
|
-
"div",
|
|
3478
|
-
{ className: "dshRemotePageActions" },
|
|
3479
|
-
selectedHost === void 0 ? null : React.createElement("button", {
|
|
3480
|
-
type: "button",
|
|
3481
|
-
className: "dshRemotePageBack",
|
|
3482
|
-
disabled: busy,
|
|
3483
|
-
title: t("backToHosts"),
|
|
3484
|
-
onClick: chooseAnotherHost
|
|
3485
|
-
}, t("backToHosts")),
|
|
3486
|
-
React.createElement("button", {
|
|
3487
|
-
type: "button",
|
|
3488
|
-
className: "dshRemotePageRefresh",
|
|
3489
|
-
disabled: busy,
|
|
3490
|
-
title: t("refreshRemote"),
|
|
3491
|
-
"aria-label": t("refreshRemote"),
|
|
3492
|
-
onClick: () => void refreshRemote()
|
|
3493
|
-
}, t("refreshRemoteShort")),
|
|
3494
|
-
React.createElement("button", { type: "button", className: "dshRemotePageClose", onClick: () => setOpen(!1), "aria-label": t("close") }, "\xD7")
|
|
3495
|
-
)
|
|
3525
|
+
React.createElement("p", null, selectedHostDetails ?? t("remoteDescription"))
|
|
3496
3526
|
),
|
|
3497
3527
|
React.createElement(
|
|
3498
|
-
"
|
|
3499
|
-
{ className: "
|
|
3500
|
-
|
|
3528
|
+
"div",
|
|
3529
|
+
{ className: "dshRemotePageActions" },
|
|
3530
|
+
selectedHost === void 0 ? null : React.createElement("button", {
|
|
3501
3531
|
type: "button",
|
|
3502
|
-
className: "
|
|
3532
|
+
className: "dshRemotePageBack",
|
|
3503
3533
|
disabled: busy,
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3534
|
+
title: t("backToHosts"),
|
|
3535
|
+
onClick: chooseAnotherHost
|
|
3536
|
+
}, t("backToHosts")),
|
|
3537
|
+
React.createElement("button", {
|
|
3538
|
+
type: "button",
|
|
3539
|
+
className: "dshRemotePageRefresh",
|
|
3540
|
+
disabled: busy,
|
|
3541
|
+
title: t("refreshRemote"),
|
|
3542
|
+
"aria-label": t("refreshRemote"),
|
|
3543
|
+
onClick: () => void refreshRemote()
|
|
3544
|
+
}, t("refreshRemoteShort")),
|
|
3545
|
+
React.createElement("button", { type: "button", className: "dshRemotePageClose", onClick: () => setOpen(!1), "aria-label": t("close") }, "\xD7")
|
|
3546
|
+
)
|
|
3547
|
+
),
|
|
3548
|
+
React.createElement(
|
|
3549
|
+
"main",
|
|
3550
|
+
{ className: "dshRemotePageBody" },
|
|
3551
|
+
status?.mode === "remote" ? React.createElement("button", {
|
|
3552
|
+
type: "button",
|
|
3553
|
+
className: "dshRemoteLocalLink",
|
|
3554
|
+
disabled: busy,
|
|
3555
|
+
onClick: () => void openLocalWorkspaces()
|
|
3556
|
+
}, t("openLocalWorkspaces")) : null,
|
|
3557
|
+
React.createElement(
|
|
3558
|
+
React.Fragment,
|
|
3559
|
+
null,
|
|
3560
|
+
needsAuthorization ? React.createElement(
|
|
3561
|
+
"section",
|
|
3562
|
+
{ className: "dshRemoteEnable" },
|
|
3563
|
+
React.createElement(
|
|
3564
|
+
"div",
|
|
3565
|
+
{ className: "dshRemoteLoginHeading" },
|
|
3566
|
+
React.createElement("strong", { className: "dshRemoteLoginTitle" }, t("signInClient")),
|
|
3567
|
+
React.createElement("span", null, t("signInClientDescription"))
|
|
3568
|
+
),
|
|
3569
|
+
React.createElement(
|
|
3570
|
+
"div",
|
|
3571
|
+
{ className: "dshRemoteLoginTabs", role: "tablist" },
|
|
3572
|
+
...orderedQrProviders.map(qrLoginTab),
|
|
3573
|
+
React.createElement("button", {
|
|
3574
|
+
type: "button",
|
|
3575
|
+
role: "tab",
|
|
3576
|
+
id: "dsh-remote-password-tab",
|
|
3577
|
+
"aria-selected": loginMethod === "password",
|
|
3578
|
+
"aria-controls": "dsh-remote-password-panel",
|
|
3579
|
+
className: loginMethod === "password" ? "isActive" : "",
|
|
3580
|
+
disabled: busy,
|
|
3581
|
+
onClick: () => selectLoginMethod("password")
|
|
3582
|
+
}, t("accountPasswordLogin"))
|
|
3583
|
+
),
|
|
3584
|
+
providersLoading ? React.createElement("p", { role: "status" }, t("loadingLoginProviders")) : null,
|
|
3585
|
+
providersFailed ? React.createElement("button", {
|
|
3586
|
+
type: "button",
|
|
3587
|
+
onClick: () => {
|
|
3588
|
+
setError(void 0), setProviderReload((value) => value + 1);
|
|
3589
|
+
}
|
|
3590
|
+
}, t("retryLoginProviders")) : null,
|
|
3591
|
+
!providersLoading && !providersFailed && oauthProviders.length === 0 ? React.createElement("p", { role: "status" }, t("noLoginProviders")) : null,
|
|
3592
|
+
loginMethod !== "password" && selectedProvider !== void 0 ? React.createElement(
|
|
3593
|
+
"div",
|
|
3594
|
+
{
|
|
3595
|
+
className: "dshRemoteQrLogin",
|
|
3596
|
+
role: "tabpanel",
|
|
3597
|
+
id: `dsh-remote-${loginMethod}-panel`,
|
|
3598
|
+
"aria-labelledby": `dsh-remote-${loginMethod}-tab`
|
|
3599
|
+
},
|
|
3600
|
+
qrImage === void 0 ? React.createElement(
|
|
3601
|
+
"div",
|
|
3602
|
+
{ className: "dshRemoteQrPlaceholder", "aria-busy": busy },
|
|
3603
|
+
qrExpired ? React.createElement("p", null, t("qrLoginExpired")) : React.createElement("span", null, t("checkingConnection"))
|
|
3604
|
+
) : qrSession !== void 0 ? React.createElement(
|
|
3605
|
+
"a",
|
|
3606
|
+
{
|
|
3607
|
+
className: "dshRemoteQrOpen",
|
|
3608
|
+
href: qrSession.scanUrl,
|
|
3609
|
+
target: "_blank",
|
|
3610
|
+
rel: "noopener noreferrer",
|
|
3611
|
+
"aria-label": t("openInBrowser")
|
|
3612
|
+
},
|
|
3613
|
+
React.createElement("img", {
|
|
3614
|
+
src: qrImage,
|
|
3615
|
+
width: 184,
|
|
3616
|
+
height: 184,
|
|
3617
|
+
alt: scanLabel
|
|
3618
|
+
}),
|
|
3619
|
+
React.createElement("span", null, t("openInBrowser"), " \u2197")
|
|
3620
|
+
) : null,
|
|
3621
|
+
React.createElement("strong", null, scanLabel),
|
|
3622
|
+
React.createElement("p", null, t("scanLoginHint")),
|
|
3623
|
+
status?.serverUrl === void 0 ? null : React.createElement(
|
|
3624
|
+
"p",
|
|
3625
|
+
{ className: "dshRemoteServiceAddress" },
|
|
3626
|
+
t("currentServiceAddress"),
|
|
3627
|
+
" ",
|
|
3628
|
+
React.createElement("a", {
|
|
3629
|
+
href: status.serverUrl,
|
|
3630
|
+
target: "_blank",
|
|
3631
|
+
rel: "noreferrer"
|
|
3632
|
+
}, status.serverUrl)
|
|
3633
|
+
),
|
|
3634
|
+
qrExpired ? React.createElement("button", {
|
|
3635
|
+
type: "button",
|
|
3636
|
+
disabled: busy,
|
|
3637
|
+
onClick: () => setQrExpired(!1)
|
|
3638
|
+
}, t("refreshQrCode")) : null
|
|
3639
|
+
) : React.createElement(
|
|
3640
|
+
"div",
|
|
3641
|
+
{
|
|
3642
|
+
className: "dshRemoteClientLogin",
|
|
3643
|
+
role: "tabpanel",
|
|
3644
|
+
id: "dsh-remote-password-panel",
|
|
3645
|
+
"aria-labelledby": "dsh-remote-password-tab"
|
|
3646
|
+
},
|
|
3647
|
+
React.createElement("input", {
|
|
3648
|
+
type: "url",
|
|
3649
|
+
value: loginServerUrl,
|
|
3650
|
+
disabled: busy,
|
|
3651
|
+
autoComplete: "url",
|
|
3652
|
+
placeholder: t("serverUrl"),
|
|
3653
|
+
"aria-label": t("serverUrl"),
|
|
3654
|
+
onChange: (event) => setLoginServerUrl(event.target.value)
|
|
3655
|
+
}),
|
|
3656
|
+
React.createElement("input", {
|
|
3657
|
+
type: "email",
|
|
3658
|
+
value: email,
|
|
3659
|
+
disabled: busy,
|
|
3660
|
+
autoComplete: "username",
|
|
3661
|
+
placeholder: t("account"),
|
|
3662
|
+
"aria-label": t("account"),
|
|
3663
|
+
onChange: (event) => setEmail(event.target.value)
|
|
3664
|
+
}),
|
|
3665
|
+
React.createElement("input", {
|
|
3666
|
+
type: "password",
|
|
3667
|
+
value: password,
|
|
3668
|
+
disabled: busy,
|
|
3669
|
+
autoComplete: "current-password",
|
|
3670
|
+
placeholder: t("password"),
|
|
3671
|
+
"aria-label": t("password"),
|
|
3672
|
+
onChange: (event) => setPassword(event.target.value)
|
|
3673
|
+
}),
|
|
3674
|
+
React.createElement("button", { type: "button", disabled: busy || loginServerUrl.trim() === "" || email.trim() === "" || password === "", onClick: () => void signInClient() }, t(busy ? "signingIn" : "startSignIn"))
|
|
3675
|
+
)
|
|
3676
|
+
) : null,
|
|
3677
|
+
needsAuthorization ? null : React.createElement(
|
|
3507
3678
|
React.Fragment,
|
|
3508
3679
|
null,
|
|
3509
|
-
|
|
3680
|
+
selectedHost === void 0 ? React.createElement(
|
|
3510
3681
|
"section",
|
|
3511
|
-
{ className: "
|
|
3682
|
+
{ className: "dshRemoteHosts", "aria-label": t("chooseHost") },
|
|
3512
3683
|
React.createElement(
|
|
3513
3684
|
"div",
|
|
3514
|
-
{ className: "
|
|
3515
|
-
React.createElement(
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3685
|
+
{ className: "dshRemoteSectionHeading" },
|
|
3686
|
+
React.createElement(
|
|
3687
|
+
"div",
|
|
3688
|
+
{ className: "dshRemoteSectionTitle" },
|
|
3689
|
+
React.createElement("strong", null, t("chooseHost")),
|
|
3690
|
+
status?.hostAuthorizationAvailable ? React.createElement(
|
|
3691
|
+
"div",
|
|
3692
|
+
{ className: "dshRemoteHostControlToggle" },
|
|
3693
|
+
React.createElement("span", null, t("allowControlDevice")),
|
|
3694
|
+
React.createElement("input", {
|
|
3695
|
+
type: "checkbox",
|
|
3696
|
+
role: "switch",
|
|
3697
|
+
disabled: busy,
|
|
3698
|
+
"aria-label": t("allowControlDevice"),
|
|
3699
|
+
checked: status.host?.authorized === !0,
|
|
3700
|
+
onChange: (event) => void setCurrentDeviceControl(event.target.checked)
|
|
3701
|
+
})
|
|
3702
|
+
) : null,
|
|
3703
|
+
connectedMenu
|
|
3704
|
+
)
|
|
3532
3705
|
),
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
}
|
|
3539
|
-
}, t("retryLoginProviders")) : null,
|
|
3540
|
-
!providersLoading && !providersFailed && oauthProviders.length === 0 ? React.createElement("p", { role: "status" }, t("noLoginProviders")) : null,
|
|
3541
|
-
loginMethod !== "password" && selectedProvider !== void 0 ? React.createElement(
|
|
3542
|
-
"div",
|
|
3706
|
+
React.createElement("div", {
|
|
3707
|
+
className: `dshRemoteHostList${connectingHost === void 0 ? "" : " isCollapsed"}`,
|
|
3708
|
+
"aria-busy": connectingHost === void 0 ? void 0 : !0
|
|
3709
|
+
}, listedHosts.length === 0 ? React.createElement("p", null, t(busy ? "checkingConnection" : "noRemoteHosts")) : listedHosts.map((device) => React.createElement(
|
|
3710
|
+
"button",
|
|
3543
3711
|
{
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
"aria-
|
|
3712
|
+
type: "button",
|
|
3713
|
+
key: device.deviceId,
|
|
3714
|
+
disabled: busy || !device.online,
|
|
3715
|
+
"aria-current": connectingHost?.deviceId === device.deviceId ? "true" : void 0,
|
|
3716
|
+
onClick: () => void selectHost(device)
|
|
3548
3717
|
},
|
|
3549
|
-
|
|
3550
|
-
"
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
target: "_blank",
|
|
3559
|
-
rel: "noopener noreferrer",
|
|
3560
|
-
"aria-label": t("openInBrowser")
|
|
3561
|
-
},
|
|
3562
|
-
React.createElement("img", {
|
|
3563
|
-
src: qrImage,
|
|
3564
|
-
width: 184,
|
|
3565
|
-
height: 184,
|
|
3566
|
-
alt: scanLabel
|
|
3567
|
-
}),
|
|
3568
|
-
React.createElement("span", null, t("openInBrowser"), " \u2197")
|
|
3569
|
-
) : null,
|
|
3570
|
-
React.createElement("strong", null, scanLabel),
|
|
3571
|
-
React.createElement("p", null, t("scanLoginHint")),
|
|
3572
|
-
status?.serverUrl === void 0 ? null : React.createElement(
|
|
3573
|
-
"p",
|
|
3574
|
-
{ className: "dshRemoteServiceAddress" },
|
|
3575
|
-
t("currentServiceAddress"),
|
|
3576
|
-
" ",
|
|
3577
|
-
React.createElement("a", {
|
|
3578
|
-
href: status.serverUrl,
|
|
3579
|
-
target: "_blank",
|
|
3580
|
-
rel: "noreferrer"
|
|
3581
|
-
}, status.serverUrl)
|
|
3718
|
+
React.createElement(
|
|
3719
|
+
"span",
|
|
3720
|
+
null,
|
|
3721
|
+
React.createElement("strong", null, device.name),
|
|
3722
|
+
React.createElement("small", null, [
|
|
3723
|
+
formatPlatform(device.platform),
|
|
3724
|
+
device.harnessVersion === void 0 ? void 0 : t("harnessVersion", { version: device.harnessVersion }),
|
|
3725
|
+
device.clientVersion === void 0 ? void 0 : t("pluginVersion", { version: device.clientVersion })
|
|
3726
|
+
].filter(Boolean).join(" \xB7 "))
|
|
3582
3727
|
),
|
|
3583
|
-
|
|
3728
|
+
React.createElement("small", null, t(device.online ? "online" : "offline"))
|
|
3729
|
+
)))
|
|
3730
|
+
) : null,
|
|
3731
|
+
React.createElement(RemoteProgressView, { progress, t }),
|
|
3732
|
+
selectedHost === void 0 ? connectingHost === void 0 ? React.createElement(
|
|
3733
|
+
React.Fragment,
|
|
3734
|
+
null,
|
|
3735
|
+
React.createElement("p", { className: "dshRemoteHint" }, t("selectHostHint")),
|
|
3736
|
+
React.createElement(
|
|
3737
|
+
"footer",
|
|
3738
|
+
{ className: "dshRemoteAccountFooter" },
|
|
3739
|
+
React.createElement("span", null, status?.host?.account ?? t("account")),
|
|
3740
|
+
React.createElement("button", {
|
|
3584
3741
|
type: "button",
|
|
3742
|
+
className: "dshRemoteAccountExit",
|
|
3585
3743
|
disabled: busy,
|
|
3586
|
-
onClick: () =>
|
|
3587
|
-
}, t("
|
|
3588
|
-
)
|
|
3744
|
+
onClick: () => void logoutRemote()
|
|
3745
|
+
}, t("exitRemoteAccount"))
|
|
3746
|
+
)
|
|
3747
|
+
) : null : React.createElement(
|
|
3748
|
+
"section",
|
|
3749
|
+
{ className: "dshRemoteBrowser", "aria-label": t("chooseDirectory") },
|
|
3750
|
+
React.createElement(
|
|
3589
3751
|
"div",
|
|
3590
|
-
{
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
},
|
|
3596
|
-
React.createElement("input", {
|
|
3597
|
-
type: "url",
|
|
3598
|
-
value: loginServerUrl,
|
|
3599
|
-
disabled: busy,
|
|
3600
|
-
autoComplete: "url",
|
|
3601
|
-
placeholder: t("serverUrl"),
|
|
3602
|
-
"aria-label": t("serverUrl"),
|
|
3603
|
-
onChange: (event) => setLoginServerUrl(event.target.value)
|
|
3604
|
-
}),
|
|
3605
|
-
React.createElement("input", {
|
|
3606
|
-
type: "email",
|
|
3607
|
-
value: email,
|
|
3752
|
+
{ className: "dshRemoteSectionHeading dshRemoteWorkspaceHeading" },
|
|
3753
|
+
React.createElement("strong", null, t(addingWorkspace ? workspaceBackend === "codex" ? "addCodexWorkspace" : workspaceBackend === "cursor" ? "addCursorWorkspace" : workspaceBackend === "antigravity" ? "addAntigravityWorkspace" : workspaceBackend === "pi" ? "addPiWorkspace" : workspaceBackend === "opencode" ? "addOpencodeWorkspace" : "addRemoteWorkspace" : "existingWorkspaces")),
|
|
3754
|
+
addingWorkspace ? React.createElement("button", {
|
|
3755
|
+
type: "button",
|
|
3756
|
+
className: "dshRemoteCancelWorkspace",
|
|
3608
3757
|
disabled: busy,
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
}),
|
|
3614
|
-
React.createElement("input", {
|
|
3615
|
-
type: "password",
|
|
3616
|
-
value: password,
|
|
3758
|
+
onClick: cancelAddingWorkspace
|
|
3759
|
+
}, t("cancelAddWorkspace")) : React.createElement("button", {
|
|
3760
|
+
type: "button",
|
|
3761
|
+
className: "dshRemoteAddWorkspace",
|
|
3617
3762
|
disabled: busy,
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
"
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
{ className: "dshRemoteSectionHeading" },
|
|
3635
|
-
React.createElement(
|
|
3636
|
-
"div",
|
|
3637
|
-
{ className: "dshRemoteSectionTitle" },
|
|
3638
|
-
React.createElement("strong", null, t("chooseHost")),
|
|
3639
|
-
status?.hostAuthorizationAvailable ? React.createElement(
|
|
3640
|
-
"div",
|
|
3641
|
-
{ className: "dshRemoteHostControlToggle" },
|
|
3642
|
-
React.createElement("span", null, t("allowControlDevice")),
|
|
3643
|
-
React.createElement("input", {
|
|
3644
|
-
type: "checkbox",
|
|
3645
|
-
role: "switch",
|
|
3646
|
-
disabled: busy,
|
|
3647
|
-
"aria-label": t("allowControlDevice"),
|
|
3648
|
-
checked: status.host?.authorized === !0,
|
|
3649
|
-
onChange: (event) => void setCurrentDeviceControl(event.target.checked)
|
|
3650
|
-
})
|
|
3651
|
-
) : null,
|
|
3652
|
-
connectedMenu
|
|
3653
|
-
)
|
|
3654
|
-
),
|
|
3655
|
-
React.createElement("div", {
|
|
3656
|
-
className: `dshRemoteHostList${connectingHost === void 0 ? "" : " isCollapsed"}`,
|
|
3657
|
-
"aria-busy": connectingHost === void 0 ? void 0 : !0
|
|
3658
|
-
}, listedHosts.length === 0 ? React.createElement("p", null, t(busy ? "checkingConnection" : "noRemoteHosts")) : listedHosts.map((device) => React.createElement(
|
|
3659
|
-
"button",
|
|
3660
|
-
{
|
|
3661
|
-
type: "button",
|
|
3662
|
-
key: device.deviceId,
|
|
3663
|
-
disabled: busy || !device.online,
|
|
3664
|
-
"aria-current": connectingHost?.deviceId === device.deviceId ? "true" : void 0,
|
|
3665
|
-
onClick: () => void selectHost(device)
|
|
3666
|
-
},
|
|
3763
|
+
title: t("addRemoteWorkspace"),
|
|
3764
|
+
"aria-label": t("addRemoteWorkspace"),
|
|
3765
|
+
onClick: () => startAddingWorkspace("harness")
|
|
3766
|
+
}, React.createElement("svg", {
|
|
3767
|
+
className: "dshRemoteAddWorkspaceIcon",
|
|
3768
|
+
viewBox: "0 0 16 16",
|
|
3769
|
+
"aria-hidden": !0,
|
|
3770
|
+
focusable: !1
|
|
3771
|
+
}, React.createElement("path", { d: "M8 3v10M3 8h10", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round" })))
|
|
3772
|
+
),
|
|
3773
|
+
addingWorkspace ? React.createElement(
|
|
3774
|
+
"div",
|
|
3775
|
+
{ className: "dshRemoteFolderBrowser" },
|
|
3776
|
+
directory === void 0 ? React.createElement("p", null, t("loadingDirectory")) : React.createElement(
|
|
3777
|
+
React.Fragment,
|
|
3778
|
+
null,
|
|
3667
3779
|
React.createElement(
|
|
3668
|
-
"
|
|
3669
|
-
|
|
3670
|
-
React.createElement("
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3780
|
+
"nav",
|
|
3781
|
+
{ className: "dshRemoteCrumbs", "aria-label": t("currentDirectory") },
|
|
3782
|
+
directory.crumbs.map((crumb) => React.createElement("button", {
|
|
3783
|
+
type: "button",
|
|
3784
|
+
key: crumb.path,
|
|
3785
|
+
disabled: busy || crumb.path === directory.path,
|
|
3786
|
+
onClick: () => void browseDirectory(crumb.path)
|
|
3787
|
+
}, crumb.path === directory.home ? "\u2302" : crumb.name))
|
|
3676
3788
|
),
|
|
3677
|
-
React.createElement("
|
|
3678
|
-
)))
|
|
3679
|
-
) : null,
|
|
3680
|
-
React.createElement(RemoteProgressView, { progress, t }),
|
|
3681
|
-
selectedHost === void 0 ? connectingHost === void 0 ? React.createElement(
|
|
3682
|
-
React.Fragment,
|
|
3683
|
-
null,
|
|
3684
|
-
React.createElement("p", { className: "dshRemoteHint" }, t("selectHostHint")),
|
|
3685
|
-
React.createElement(
|
|
3686
|
-
"footer",
|
|
3687
|
-
{ className: "dshRemoteAccountFooter" },
|
|
3688
|
-
React.createElement("span", null, status?.host?.account ?? t("account")),
|
|
3689
|
-
React.createElement("button", {
|
|
3789
|
+
React.createElement("div", { className: "dshRemoteFolderList" }, directory.entries.filter((entry) => !entry.hidden).length === 0 ? React.createElement("p", null, t("emptyDirectory")) : directory.entries.filter((entry) => !entry.hidden).map((entry) => React.createElement("button", {
|
|
3690
3790
|
type: "button",
|
|
3691
|
-
|
|
3791
|
+
key: entry.path,
|
|
3692
3792
|
disabled: busy,
|
|
3693
|
-
onClick: () => void
|
|
3694
|
-
},
|
|
3793
|
+
onClick: () => void browseDirectory(entry.path)
|
|
3794
|
+
}, React.createElement("span", { "aria-hidden": !0 }, "\u25B1"), React.createElement("span", null, entry.name)))),
|
|
3795
|
+
directory.truncated ? React.createElement("small", null, t("directoryTruncated")) : null
|
|
3695
3796
|
)
|
|
3696
|
-
) :
|
|
3697
|
-
|
|
3698
|
-
|
|
3797
|
+
) : React.createElement(
|
|
3798
|
+
React.Fragment,
|
|
3799
|
+
null,
|
|
3699
3800
|
React.createElement(
|
|
3700
3801
|
"div",
|
|
3701
|
-
{ className: "
|
|
3702
|
-
React.createElement("strong", null, t(addingWorkspace ? workspaceBackend === "codex" ? "addCodexWorkspace" : workspaceBackend === "cursor" ? "addCursorWorkspace" : workspaceBackend === "antigravity" ? "addAntigravityWorkspace" : "addRemoteWorkspace" : "existingWorkspaces")),
|
|
3703
|
-
addingWorkspace ? React.createElement("button", {
|
|
3704
|
-
type: "button",
|
|
3705
|
-
className: "dshRemoteCancelWorkspace",
|
|
3706
|
-
disabled: busy,
|
|
3707
|
-
onClick: cancelAddingWorkspace
|
|
3708
|
-
}, t("cancelAddWorkspace")) : React.createElement("button", {
|
|
3709
|
-
type: "button",
|
|
3710
|
-
className: "dshRemoteAddWorkspace",
|
|
3711
|
-
disabled: busy,
|
|
3712
|
-
title: t("addRemoteWorkspace"),
|
|
3713
|
-
"aria-label": t("addRemoteWorkspace"),
|
|
3714
|
-
onClick: () => startAddingWorkspace("harness")
|
|
3715
|
-
}, React.createElement("svg", {
|
|
3716
|
-
className: "dshRemoteAddWorkspaceIcon",
|
|
3717
|
-
viewBox: "0 0 16 16",
|
|
3718
|
-
"aria-hidden": !0,
|
|
3719
|
-
focusable: !1
|
|
3720
|
-
}, React.createElement("path", { d: "M8 3v10M3 8h10", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round" })))
|
|
3721
|
-
),
|
|
3722
|
-
addingWorkspace ? React.createElement(
|
|
3723
|
-
"div",
|
|
3724
|
-
{ className: "dshRemoteFolderBrowser" },
|
|
3725
|
-
directory === void 0 ? React.createElement("p", null, t("loadingDirectory")) : React.createElement(
|
|
3726
|
-
React.Fragment,
|
|
3727
|
-
null,
|
|
3728
|
-
React.createElement(
|
|
3729
|
-
"nav",
|
|
3730
|
-
{ className: "dshRemoteCrumbs", "aria-label": t("currentDirectory") },
|
|
3731
|
-
directory.crumbs.map((crumb) => React.createElement("button", {
|
|
3732
|
-
type: "button",
|
|
3733
|
-
key: crumb.path,
|
|
3734
|
-
disabled: busy || crumb.path === directory.path,
|
|
3735
|
-
onClick: () => void browseDirectory(crumb.path)
|
|
3736
|
-
}, crumb.path === directory.home ? "\u2302" : crumb.name))
|
|
3737
|
-
),
|
|
3738
|
-
React.createElement("div", { className: "dshRemoteFolderList" }, directory.entries.filter((entry) => !entry.hidden).length === 0 ? React.createElement("p", null, t("emptyDirectory")) : directory.entries.filter((entry) => !entry.hidden).map((entry) => React.createElement("button", {
|
|
3739
|
-
type: "button",
|
|
3740
|
-
key: entry.path,
|
|
3741
|
-
disabled: busy,
|
|
3742
|
-
onClick: () => void browseDirectory(entry.path)
|
|
3743
|
-
}, React.createElement("span", { "aria-hidden": !0 }, "\u25B1"), React.createElement("span", null, entry.name)))),
|
|
3744
|
-
directory.truncated ? React.createElement("small", null, t("directoryTruncated")) : null
|
|
3745
|
-
)
|
|
3746
|
-
) : React.createElement(
|
|
3747
|
-
React.Fragment,
|
|
3748
|
-
null,
|
|
3802
|
+
{ className: "dshRemoteWorkspaceLists" },
|
|
3749
3803
|
React.createElement(
|
|
3750
3804
|
"div",
|
|
3751
|
-
{ className: "
|
|
3752
|
-
React.createElement(
|
|
3753
|
-
"div",
|
|
3754
|
-
{ id: workspaceListId, className: "dshRemoteDirectoryList" },
|
|
3755
|
-
workspaces.length === 0 ? React.createElement("p", null, t("noRemoteWorkspaces")) : visibleWorkspaces.map((workspace) => React.createElement(
|
|
3756
|
-
"button",
|
|
3757
|
-
{
|
|
3758
|
-
type: "button",
|
|
3759
|
-
key: workspace.workspaceId,
|
|
3760
|
-
disabled: busy,
|
|
3761
|
-
className: workspaceBackend === "harness" && path === workspace.path ? "isSelected" : "",
|
|
3762
|
-
"aria-pressed": workspaceBackend === "harness" && path === workspace.path,
|
|
3763
|
-
onClick: () => {
|
|
3764
|
-
setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setCursorWorkspaceId(void 0), setPath(workspace.path);
|
|
3765
|
-
},
|
|
3766
|
-
onDoubleClick: () => void openWorkspace({ backend: "harness", path: workspace.path })
|
|
3767
|
-
},
|
|
3768
|
-
React.createElement("img", { className: "dshRemoteWorkspaceIcon", src: deepSeekWorkspaceIcon, alt: "", "aria-hidden": !0 }),
|
|
3769
|
-
React.createElement("span", null, workspace.title),
|
|
3770
|
-
React.createElement("small", null, workspace.path)
|
|
3771
|
-
)),
|
|
3772
|
-
workspaces.length <= 3 || showAllWorkspaces ? null : React.createElement("button", {
|
|
3773
|
-
type: "button",
|
|
3774
|
-
className: "dshRemoteWorkspaceMore",
|
|
3775
|
-
disabled: busy,
|
|
3776
|
-
"aria-controls": workspaceListId,
|
|
3777
|
-
"aria-label": t("showAllWorkspaces"),
|
|
3778
|
-
onClick: () => setShowAllWorkspaces(!0)
|
|
3779
|
-
}, React.createElement("span", { "aria-hidden": !0 }, "\u2026"))
|
|
3780
|
-
)
|
|
3781
|
-
),
|
|
3782
|
-
codexAvailable ? React.createElement(
|
|
3783
|
-
"section",
|
|
3784
|
-
{ className: "dshRemoteCodexWorkspaceGroup" },
|
|
3785
|
-
React.createElement(
|
|
3786
|
-
"div",
|
|
3787
|
-
{
|
|
3788
|
-
id: codexWorkspaceHeadingId,
|
|
3789
|
-
className: "dshRemoteWorkspaceSourceHeading"
|
|
3790
|
-
},
|
|
3791
|
-
React.createElement(
|
|
3792
|
-
"span",
|
|
3793
|
-
{ className: "dshRemoteWorkspaceSourceText" },
|
|
3794
|
-
React.createElement("strong", null, t("codexVirtualWorkspace"))
|
|
3795
|
-
),
|
|
3796
|
-
codexAvailable ? React.createElement("button", {
|
|
3797
|
-
type: "button",
|
|
3798
|
-
className: "dshRemoteAddWorkspace",
|
|
3799
|
-
disabled: busy,
|
|
3800
|
-
title: t("addCodexWorkspace"),
|
|
3801
|
-
"aria-label": t("addCodexWorkspace"),
|
|
3802
|
-
onClick: () => startAddingWorkspace("codex")
|
|
3803
|
-
}, React.createElement("svg", {
|
|
3804
|
-
className: "dshRemoteAddWorkspaceIcon",
|
|
3805
|
-
viewBox: "0 0 16 16",
|
|
3806
|
-
"aria-hidden": !0,
|
|
3807
|
-
focusable: !1
|
|
3808
|
-
}, React.createElement("path", { d: "M8 3v10M3 8h10", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round" }))) : null
|
|
3809
|
-
),
|
|
3810
|
-
React.createElement("div", {
|
|
3811
|
-
id: codexWorkspaceListId,
|
|
3812
|
-
className: "dshRemoteDirectoryList dshRemoteCodexWorkspaceList",
|
|
3813
|
-
"aria-labelledby": codexWorkspaceHeadingId
|
|
3814
|
-
}, visibleCodexWorkspaces.length === 0 ? React.createElement("p", null, t("noCodexWorkspaces")) : visibleCodexWorkspaces.map((workspace) => React.createElement(
|
|
3805
|
+
{ id: workspaceListId, className: "dshRemoteDirectoryList" },
|
|
3806
|
+
workspaces.length === 0 ? React.createElement("p", null, t("noRemoteWorkspaces")) : visibleWorkspaces.map((workspace) => React.createElement(
|
|
3815
3807
|
"button",
|
|
3816
3808
|
{
|
|
3817
3809
|
type: "button",
|
|
3818
3810
|
key: workspace.workspaceId,
|
|
3819
3811
|
disabled: busy,
|
|
3820
|
-
className: workspaceBackend === "
|
|
3821
|
-
"aria-pressed": workspaceBackend === "
|
|
3812
|
+
className: workspaceBackend === "harness" && path === workspace.path ? "isSelected" : "",
|
|
3813
|
+
"aria-pressed": workspaceBackend === "harness" && path === workspace.path,
|
|
3822
3814
|
onClick: () => {
|
|
3823
|
-
setWorkspaceBackend("
|
|
3815
|
+
setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setCursorWorkspaceId(void 0), setPath(workspace.path);
|
|
3824
3816
|
},
|
|
3825
|
-
onDoubleClick: () => void openWorkspace({
|
|
3826
|
-
backend: "codex",
|
|
3827
|
-
path: workspace.path,
|
|
3828
|
-
workspaceId: workspace.workspaceId
|
|
3829
|
-
})
|
|
3817
|
+
onDoubleClick: () => void openWorkspace({ backend: "harness", path: workspace.path })
|
|
3830
3818
|
},
|
|
3831
|
-
React.createElement("img", { className: "dshRemoteWorkspaceIcon
|
|
3819
|
+
React.createElement("img", { className: "dshRemoteWorkspaceIcon", src: deepSeekWorkspaceIcon, alt: "", "aria-hidden": !0 }),
|
|
3832
3820
|
React.createElement("span", null, workspace.title),
|
|
3833
|
-
React.createElement("small", null,
|
|
3834
|
-
))
|
|
3835
|
-
|
|
3821
|
+
React.createElement("small", null, workspace.path)
|
|
3822
|
+
)),
|
|
3823
|
+
workspaces.length <= 3 || showAllWorkspaces ? null : React.createElement("button", {
|
|
3836
3824
|
type: "button",
|
|
3837
3825
|
className: "dshRemoteWorkspaceMore",
|
|
3838
3826
|
disabled: busy,
|
|
3839
|
-
"aria-controls":
|
|
3840
|
-
"aria-label": t("
|
|
3841
|
-
onClick: () =>
|
|
3827
|
+
"aria-controls": workspaceListId,
|
|
3828
|
+
"aria-label": t("showAllWorkspaces"),
|
|
3829
|
+
onClick: () => setShowAllWorkspaces(!0)
|
|
3842
3830
|
}, React.createElement("span", { "aria-hidden": !0 }, "\u2026"))
|
|
3843
|
-
)
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3831
|
+
)
|
|
3832
|
+
),
|
|
3833
|
+
codexAvailable ? React.createElement(
|
|
3834
|
+
"section",
|
|
3835
|
+
{ className: "dshRemoteCodexWorkspaceGroup" },
|
|
3836
|
+
React.createElement(
|
|
3837
|
+
"div",
|
|
3838
|
+
{
|
|
3839
|
+
id: codexWorkspaceHeadingId,
|
|
3840
|
+
className: "dshRemoteWorkspaceSourceHeading"
|
|
3841
|
+
},
|
|
3847
3842
|
React.createElement(
|
|
3848
|
-
"
|
|
3849
|
-
{
|
|
3850
|
-
|
|
3851
|
-
className: "dshRemoteWorkspaceSourceHeading"
|
|
3852
|
-
},
|
|
3853
|
-
React.createElement(
|
|
3854
|
-
"span",
|
|
3855
|
-
{ className: "dshRemoteWorkspaceSourceText" },
|
|
3856
|
-
React.createElement("strong", null, t("cursorVirtualWorkspace"))
|
|
3857
|
-
),
|
|
3858
|
-
cursorAvailable ? React.createElement("button", {
|
|
3859
|
-
type: "button",
|
|
3860
|
-
className: "dshRemoteAddWorkspace",
|
|
3861
|
-
disabled: busy,
|
|
3862
|
-
title: t("addCursorWorkspace"),
|
|
3863
|
-
"aria-label": t("addCursorWorkspace"),
|
|
3864
|
-
onClick: () => startAddingWorkspace("cursor")
|
|
3865
|
-
}, React.createElement("svg", {
|
|
3866
|
-
className: "dshRemoteAddWorkspaceIcon",
|
|
3867
|
-
viewBox: "0 0 16 16",
|
|
3868
|
-
"aria-hidden": !0,
|
|
3869
|
-
focusable: !1
|
|
3870
|
-
}, React.createElement("path", { d: "M8 3v10M3 8h10", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round" }))) : null
|
|
3843
|
+
"span",
|
|
3844
|
+
{ className: "dshRemoteWorkspaceSourceText" },
|
|
3845
|
+
React.createElement("strong", null, t("codexVirtualWorkspace"))
|
|
3871
3846
|
),
|
|
3872
|
-
React.createElement("
|
|
3873
|
-
|
|
3874
|
-
className: "
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
"
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3847
|
+
codexAvailable ? React.createElement("button", {
|
|
3848
|
+
type: "button",
|
|
3849
|
+
className: "dshRemoteAddWorkspace",
|
|
3850
|
+
disabled: busy,
|
|
3851
|
+
title: t("addCodexWorkspace"),
|
|
3852
|
+
"aria-label": t("addCodexWorkspace"),
|
|
3853
|
+
onClick: () => startAddingWorkspace("codex")
|
|
3854
|
+
}, React.createElement("svg", {
|
|
3855
|
+
className: "dshRemoteAddWorkspaceIcon",
|
|
3856
|
+
viewBox: "0 0 16 16",
|
|
3857
|
+
"aria-hidden": !0,
|
|
3858
|
+
focusable: !1
|
|
3859
|
+
}, React.createElement("path", { d: "M8 3v10M3 8h10", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round" }))) : null
|
|
3860
|
+
),
|
|
3861
|
+
React.createElement("div", {
|
|
3862
|
+
id: codexWorkspaceListId,
|
|
3863
|
+
className: "dshRemoteDirectoryList dshRemoteCodexWorkspaceList",
|
|
3864
|
+
"aria-labelledby": codexWorkspaceHeadingId
|
|
3865
|
+
}, visibleCodexWorkspaces.length === 0 ? React.createElement("p", null, t("noCodexWorkspaces")) : visibleCodexWorkspaces.map((workspace) => React.createElement(
|
|
3866
|
+
"button",
|
|
3867
|
+
{
|
|
3868
|
+
type: "button",
|
|
3869
|
+
key: workspace.workspaceId,
|
|
3870
|
+
disabled: busy,
|
|
3871
|
+
className: workspaceBackend === "codex" && codexWorkspaceId === workspace.workspaceId ? "isSelected" : "",
|
|
3872
|
+
"aria-pressed": workspaceBackend === "codex" && codexWorkspaceId === workspace.workspaceId,
|
|
3873
|
+
onClick: () => {
|
|
3874
|
+
setWorkspaceBackend("codex"), setCodexWorkspaceId(workspace.workspaceId), setCursorWorkspaceId(void 0), setPath(workspace.path);
|
|
3892
3875
|
},
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3876
|
+
onDoubleClick: () => void openWorkspace({
|
|
3877
|
+
backend: "codex",
|
|
3878
|
+
path: workspace.path,
|
|
3879
|
+
workspaceId: workspace.workspaceId
|
|
3880
|
+
})
|
|
3881
|
+
},
|
|
3882
|
+
React.createElement("img", { className: "dshRemoteWorkspaceIcon isGpt", src: gptWorkspaceIcon, alt: "", "aria-hidden": !0 }),
|
|
3883
|
+
React.createElement("span", null, workspace.title),
|
|
3884
|
+
React.createElement("small", null, `${workspace.path} \xB7 ${workspace.sessionCount}`)
|
|
3885
|
+
))),
|
|
3886
|
+
codexWorkspaces.length <= 3 || showAllCodexWorkspaces ? null : React.createElement("button", {
|
|
3887
|
+
type: "button",
|
|
3888
|
+
className: "dshRemoteWorkspaceMore",
|
|
3889
|
+
disabled: busy,
|
|
3890
|
+
"aria-controls": codexWorkspaceListId,
|
|
3891
|
+
"aria-label": t("showAllCodexWorkspaces"),
|
|
3892
|
+
onClick: () => setShowAllCodexWorkspaces(!0)
|
|
3893
|
+
}, React.createElement("span", { "aria-hidden": !0 }, "\u2026"))
|
|
3894
|
+
) : null,
|
|
3895
|
+
cursorAvailable ? React.createElement(
|
|
3896
|
+
"section",
|
|
3897
|
+
{ className: "dshRemoteCodexWorkspaceGroup" },
|
|
3898
|
+
React.createElement(
|
|
3899
|
+
"div",
|
|
3900
|
+
{
|
|
3901
|
+
id: cursorWorkspaceHeadingId,
|
|
3902
|
+
className: "dshRemoteWorkspaceSourceHeading"
|
|
3903
|
+
},
|
|
3904
|
+
React.createElement(
|
|
3905
|
+
"span",
|
|
3906
|
+
{ className: "dshRemoteWorkspaceSourceText" },
|
|
3907
|
+
React.createElement("strong", null, t("cursorVirtualWorkspace"))
|
|
3908
|
+
),
|
|
3909
|
+
cursorAvailable ? React.createElement("button", {
|
|
3898
3910
|
type: "button",
|
|
3899
|
-
className: "
|
|
3911
|
+
className: "dshRemoteAddWorkspace",
|
|
3900
3912
|
disabled: busy,
|
|
3901
|
-
"
|
|
3902
|
-
"aria-label": t("
|
|
3903
|
-
onClick: () =>
|
|
3904
|
-
}, React.createElement("
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3913
|
+
title: t("addCursorWorkspace"),
|
|
3914
|
+
"aria-label": t("addCursorWorkspace"),
|
|
3915
|
+
onClick: () => startAddingWorkspace("cursor")
|
|
3916
|
+
}, React.createElement("svg", {
|
|
3917
|
+
className: "dshRemoteAddWorkspaceIcon",
|
|
3918
|
+
viewBox: "0 0 16 16",
|
|
3919
|
+
"aria-hidden": !0,
|
|
3920
|
+
focusable: !1
|
|
3921
|
+
}, React.createElement("path", { d: "M8 3v10M3 8h10", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round" }))) : null
|
|
3922
|
+
),
|
|
3923
|
+
React.createElement("div", {
|
|
3924
|
+
id: cursorWorkspaceListId,
|
|
3925
|
+
className: "dshRemoteDirectoryList dshRemoteCodexWorkspaceList",
|
|
3926
|
+
"aria-labelledby": cursorWorkspaceHeadingId
|
|
3927
|
+
}, visibleCursorWorkspaces.length === 0 ? React.createElement("p", null, t("noCursorWorkspaces")) : visibleCursorWorkspaces.map((workspace) => React.createElement(
|
|
3928
|
+
"button",
|
|
3929
|
+
{
|
|
3930
|
+
type: "button",
|
|
3931
|
+
key: workspace.workspaceId,
|
|
3932
|
+
disabled: busy,
|
|
3933
|
+
className: workspaceBackend === "cursor" && cursorWorkspaceId === workspace.workspaceId ? "isSelected" : "",
|
|
3934
|
+
"aria-pressed": workspaceBackend === "cursor" && cursorWorkspaceId === workspace.workspaceId,
|
|
3935
|
+
onClick: () => {
|
|
3936
|
+
setWorkspaceBackend("cursor"), setCursorWorkspaceId(workspace.workspaceId), setCodexWorkspaceId(void 0), setAntigravityWorkspaceId(void 0), setPiWorkspaceId(void 0), setPath(workspace.path);
|
|
3937
|
+
},
|
|
3938
|
+
onDoubleClick: () => void openWorkspace({
|
|
3939
|
+
backend: "cursor",
|
|
3940
|
+
path: workspace.path,
|
|
3941
|
+
workspaceId: workspace.workspaceId
|
|
3942
|
+
})
|
|
3943
|
+
},
|
|
3944
|
+
React.createElement("img", { className: "dshRemoteWorkspaceIcon", src: deepSeekWorkspaceIcon, alt: "", "aria-hidden": !0 }),
|
|
3945
|
+
React.createElement("span", null, workspace.title),
|
|
3946
|
+
React.createElement("small", null, `${workspace.path} \xB7 ${workspace.sessionCount}`)
|
|
3947
|
+
))),
|
|
3948
|
+
cursorWorkspaces.length <= 3 || showAllCursorWorkspaces ? null : React.createElement("button", {
|
|
3949
|
+
type: "button",
|
|
3950
|
+
className: "dshRemoteWorkspaceMore",
|
|
3951
|
+
disabled: busy,
|
|
3952
|
+
"aria-controls": cursorWorkspaceListId,
|
|
3953
|
+
"aria-label": t("showAllCursorWorkspaces"),
|
|
3954
|
+
onClick: () => setShowAllCursorWorkspaces(!0)
|
|
3955
|
+
}, React.createElement("span", { "aria-hidden": !0 }, "\u2026"))
|
|
3956
|
+
) : null,
|
|
3957
|
+
antigravityAvailable ? React.createElement(
|
|
3958
|
+
"section",
|
|
3959
|
+
{ className: "dshRemoteCodexWorkspaceGroup" },
|
|
3960
|
+
React.createElement(
|
|
3961
|
+
"div",
|
|
3962
|
+
{
|
|
3963
|
+
id: antigravityWorkspaceHeadingId,
|
|
3964
|
+
className: "dshRemoteWorkspaceSourceHeading"
|
|
3965
|
+
},
|
|
3909
3966
|
React.createElement(
|
|
3910
|
-
"
|
|
3911
|
-
{
|
|
3912
|
-
|
|
3913
|
-
|
|
3967
|
+
"span",
|
|
3968
|
+
{ className: "dshRemoteWorkspaceSourceText" },
|
|
3969
|
+
React.createElement("strong", null, t("antigravityVirtualWorkspace"))
|
|
3970
|
+
),
|
|
3971
|
+
antigravityAvailable ? React.createElement("button", {
|
|
3972
|
+
type: "button",
|
|
3973
|
+
className: "dshRemoteAddWorkspace",
|
|
3974
|
+
disabled: busy,
|
|
3975
|
+
title: t("addAntigravityWorkspace"),
|
|
3976
|
+
"aria-label": t("addAntigravityWorkspace"),
|
|
3977
|
+
onClick: () => startAddingWorkspace("antigravity")
|
|
3978
|
+
}, React.createElement("svg", {
|
|
3979
|
+
className: "dshRemoteAddWorkspaceIcon",
|
|
3980
|
+
viewBox: "0 0 16 16",
|
|
3981
|
+
"aria-hidden": !0,
|
|
3982
|
+
focusable: !1
|
|
3983
|
+
}, React.createElement("path", { d: "M8 3v10M3 8h10", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round" }))) : null
|
|
3984
|
+
),
|
|
3985
|
+
React.createElement("div", {
|
|
3986
|
+
id: antigravityWorkspaceListId,
|
|
3987
|
+
className: "dshRemoteDirectoryList dshRemoteCodexWorkspaceList",
|
|
3988
|
+
"aria-labelledby": antigravityWorkspaceHeadingId
|
|
3989
|
+
}, visibleAntigravityWorkspaces.length === 0 ? React.createElement("p", null, t("noAntigravityWorkspaces")) : visibleAntigravityWorkspaces.map((workspace) => React.createElement(
|
|
3990
|
+
"button",
|
|
3991
|
+
{
|
|
3992
|
+
type: "button",
|
|
3993
|
+
key: workspace.workspaceId,
|
|
3994
|
+
disabled: busy,
|
|
3995
|
+
className: workspaceBackend === "antigravity" && antigravityWorkspaceId === workspace.workspaceId ? "isSelected" : "",
|
|
3996
|
+
"aria-pressed": workspaceBackend === "antigravity" && antigravityWorkspaceId === workspace.workspaceId,
|
|
3997
|
+
onClick: () => {
|
|
3998
|
+
setWorkspaceBackend("antigravity"), setAntigravityWorkspaceId(workspace.workspaceId), setPiWorkspaceId(void 0), setCodexWorkspaceId(void 0), setCursorWorkspaceId(void 0), setPath(workspace.path);
|
|
3914
3999
|
},
|
|
3915
|
-
|
|
3916
|
-
"
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
)
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
4000
|
+
onDoubleClick: () => void openWorkspace({
|
|
4001
|
+
backend: "antigravity",
|
|
4002
|
+
path: workspace.path,
|
|
4003
|
+
workspaceId: workspace.workspaceId
|
|
4004
|
+
})
|
|
4005
|
+
},
|
|
4006
|
+
React.createElement("img", { className: "dshRemoteWorkspaceIcon", src: deepSeekWorkspaceIcon, alt: "", "aria-hidden": !0 }),
|
|
4007
|
+
React.createElement("span", null, workspace.title),
|
|
4008
|
+
React.createElement("small", null, `${workspace.path} \xB7 ${workspace.sessionCount}`)
|
|
4009
|
+
))),
|
|
4010
|
+
antigravityWorkspaces.length <= 3 || showAllAntigravityWorkspaces ? null : React.createElement("button", {
|
|
4011
|
+
type: "button",
|
|
4012
|
+
className: "dshRemoteWorkspaceMore",
|
|
4013
|
+
disabled: busy,
|
|
4014
|
+
"aria-controls": antigravityWorkspaceListId,
|
|
4015
|
+
"aria-label": t("showAllAntigravityWorkspaces"),
|
|
4016
|
+
onClick: () => setShowAllAntigravityWorkspaces(!0)
|
|
4017
|
+
}, React.createElement("span", { "aria-hidden": !0 }, "\u2026"))
|
|
4018
|
+
) : null,
|
|
4019
|
+
piAvailable ? React.createElement(
|
|
4020
|
+
"section",
|
|
4021
|
+
{ className: "dshRemoteCodexWorkspaceGroup" },
|
|
4022
|
+
React.createElement(
|
|
4023
|
+
"div",
|
|
4024
|
+
{
|
|
4025
|
+
id: piWorkspaceHeadingId,
|
|
4026
|
+
className: "dshRemoteWorkspaceSourceHeading"
|
|
4027
|
+
},
|
|
4028
|
+
React.createElement(
|
|
4029
|
+
"span",
|
|
4030
|
+
{ className: "dshRemoteWorkspaceSourceText" },
|
|
4031
|
+
React.createElement("strong", null, t("piVirtualWorkspace"))
|
|
3933
4032
|
),
|
|
3934
|
-
React.createElement("
|
|
3935
|
-
|
|
3936
|
-
className: "
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
"
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
4033
|
+
piAvailable ? React.createElement("button", {
|
|
4034
|
+
type: "button",
|
|
4035
|
+
className: "dshRemoteAddWorkspace",
|
|
4036
|
+
disabled: busy,
|
|
4037
|
+
title: t("addPiWorkspace"),
|
|
4038
|
+
"aria-label": t("addPiWorkspace"),
|
|
4039
|
+
onClick: () => startAddingWorkspace("pi")
|
|
4040
|
+
}, React.createElement("svg", {
|
|
4041
|
+
className: "dshRemoteAddWorkspaceIcon",
|
|
4042
|
+
viewBox: "0 0 16 16",
|
|
4043
|
+
"aria-hidden": !0,
|
|
4044
|
+
focusable: !1
|
|
4045
|
+
}, React.createElement("path", { d: "M8 3v10M3 8h10", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round" }))) : null
|
|
4046
|
+
),
|
|
4047
|
+
React.createElement("div", {
|
|
4048
|
+
id: piWorkspaceListId,
|
|
4049
|
+
className: "dshRemoteDirectoryList dshRemoteCodexWorkspaceList",
|
|
4050
|
+
"aria-labelledby": piWorkspaceHeadingId
|
|
4051
|
+
}, visiblePiWorkspaces.length === 0 ? React.createElement("p", null, t("noPiWorkspaces")) : visiblePiWorkspaces.map((workspace) => React.createElement(
|
|
4052
|
+
"button",
|
|
4053
|
+
{
|
|
4054
|
+
type: "button",
|
|
4055
|
+
key: workspace.workspaceId,
|
|
4056
|
+
disabled: busy,
|
|
4057
|
+
className: workspaceBackend === "pi" && piWorkspaceId === workspace.workspaceId ? "isSelected" : "",
|
|
4058
|
+
"aria-pressed": workspaceBackend === "pi" && piWorkspaceId === workspace.workspaceId,
|
|
4059
|
+
onClick: () => {
|
|
4060
|
+
setWorkspaceBackend("pi"), setPiWorkspaceId(workspace.workspaceId), setAntigravityWorkspaceId(void 0), setCodexWorkspaceId(void 0), setCursorWorkspaceId(void 0), setPath(workspace.path);
|
|
3954
4061
|
},
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
4062
|
+
onDoubleClick: () => void openWorkspace({
|
|
4063
|
+
backend: "pi",
|
|
4064
|
+
path: workspace.path,
|
|
4065
|
+
workspaceId: workspace.workspaceId
|
|
4066
|
+
})
|
|
4067
|
+
},
|
|
4068
|
+
React.createElement("img", { className: "dshRemoteWorkspaceIcon", src: deepSeekWorkspaceIcon, alt: "", "aria-hidden": !0 }),
|
|
4069
|
+
React.createElement("span", null, workspace.title),
|
|
4070
|
+
React.createElement("small", null, `${workspace.path} \xB7 ${workspace.sessionCount}`)
|
|
4071
|
+
))),
|
|
4072
|
+
piWorkspaces.length <= 3 || showAllPiWorkspaces ? null : React.createElement("button", {
|
|
4073
|
+
type: "button",
|
|
4074
|
+
className: "dshRemoteWorkspaceMore",
|
|
4075
|
+
disabled: busy,
|
|
4076
|
+
"aria-controls": piWorkspaceListId,
|
|
4077
|
+
"aria-label": t("showAllPiWorkspaces"),
|
|
4078
|
+
onClick: () => setShowAllPiWorkspaces(!0)
|
|
4079
|
+
}, React.createElement("span", { "aria-hidden": !0 }, "\u2026"))
|
|
4080
|
+
) : null,
|
|
4081
|
+
opencodeAvailable ? React.createElement(
|
|
4082
|
+
"section",
|
|
4083
|
+
{ className: "dshRemoteCodexWorkspaceGroup" },
|
|
4084
|
+
React.createElement(
|
|
4085
|
+
"div",
|
|
4086
|
+
{
|
|
4087
|
+
id: opencodeWorkspaceHeadingId,
|
|
4088
|
+
className: "dshRemoteWorkspaceSourceHeading"
|
|
4089
|
+
},
|
|
4090
|
+
React.createElement("span", { className: "dshRemoteWorkspaceSourceText" }, React.createElement("strong", null, t("opencodeVirtualWorkspace"))),
|
|
4091
|
+
React.createElement("button", {
|
|
3960
4092
|
type: "button",
|
|
3961
|
-
className: "
|
|
4093
|
+
className: "dshRemoteAddWorkspace",
|
|
3962
4094
|
disabled: busy,
|
|
3963
|
-
"
|
|
3964
|
-
"aria-label": t("
|
|
3965
|
-
onClick: () =>
|
|
3966
|
-
}, React.createElement("
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
React.createElement("
|
|
4095
|
+
title: t("addOpencodeWorkspace"),
|
|
4096
|
+
"aria-label": t("addOpencodeWorkspace"),
|
|
4097
|
+
onClick: () => startAddingWorkspace("opencode")
|
|
4098
|
+
}, React.createElement("svg", {
|
|
4099
|
+
className: "dshRemoteAddWorkspaceIcon",
|
|
4100
|
+
viewBox: "0 0 16 16",
|
|
4101
|
+
"aria-hidden": !0,
|
|
4102
|
+
focusable: !1
|
|
4103
|
+
}, React.createElement("path", { d: "M8 3v10M3 8h10", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round" })))
|
|
4104
|
+
),
|
|
4105
|
+
React.createElement("div", {
|
|
4106
|
+
id: opencodeWorkspaceListId,
|
|
4107
|
+
className: "dshRemoteDirectoryList dshRemoteCodexWorkspaceList",
|
|
4108
|
+
"aria-labelledby": opencodeWorkspaceHeadingId
|
|
4109
|
+
}, visibleOpencodeWorkspaces.length === 0 ? React.createElement("p", null, t("noOpencodeWorkspaces")) : visibleOpencodeWorkspaces.map((workspace) => React.createElement(
|
|
4110
|
+
"button",
|
|
4111
|
+
{
|
|
4112
|
+
type: "button",
|
|
4113
|
+
key: workspace.workspaceId,
|
|
4114
|
+
disabled: busy,
|
|
4115
|
+
className: workspaceBackend === "opencode" && opencodeWorkspaceId === workspace.workspaceId ? "isSelected" : "",
|
|
4116
|
+
"aria-pressed": workspaceBackend === "opencode" && opencodeWorkspaceId === workspace.workspaceId,
|
|
4117
|
+
onClick: () => {
|
|
4118
|
+
setWorkspaceBackend("opencode"), setOpencodeWorkspaceId(workspace.workspaceId), setPiWorkspaceId(void 0), setAntigravityWorkspaceId(void 0), setCodexWorkspaceId(void 0), setCursorWorkspaceId(void 0), setPath(workspace.path);
|
|
4119
|
+
},
|
|
4120
|
+
onDoubleClick: () => void openWorkspace({
|
|
4121
|
+
backend: "opencode",
|
|
4122
|
+
path: workspace.path,
|
|
4123
|
+
workspaceId: workspace.workspaceId
|
|
4124
|
+
})
|
|
4125
|
+
},
|
|
4126
|
+
React.createElement("img", { className: "dshRemoteWorkspaceIcon", src: deepSeekWorkspaceIcon, alt: "", "aria-hidden": !0 }),
|
|
4127
|
+
React.createElement("span", null, workspace.title),
|
|
4128
|
+
React.createElement("small", null, `${workspace.path} \xB7 ${workspace.sessionCount}`)
|
|
4129
|
+
))),
|
|
4130
|
+
opencodeWorkspaces.length <= 3 || showAllOpencodeWorkspaces ? null : React.createElement("button", {
|
|
3974
4131
|
type: "button",
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
4132
|
+
className: "dshRemoteWorkspaceMore",
|
|
4133
|
+
disabled: busy,
|
|
4134
|
+
"aria-controls": opencodeWorkspaceListId,
|
|
4135
|
+
"aria-label": t("showAllOpencodeWorkspaces"),
|
|
4136
|
+
onClick: () => setShowAllOpencodeWorkspaces(!0)
|
|
4137
|
+
}, React.createElement("span", { "aria-hidden": !0 }, "\u2026"))
|
|
4138
|
+
) : null
|
|
4139
|
+
),
|
|
4140
|
+
React.createElement(
|
|
4141
|
+
"footer",
|
|
4142
|
+
{ className: "dshRemoteOpenBar" },
|
|
4143
|
+
React.createElement("div", null, React.createElement("span", null, t("currentDirectory")), React.createElement("strong", null, path || "\u2014")),
|
|
4144
|
+
React.createElement("button", {
|
|
4145
|
+
type: "button",
|
|
4146
|
+
disabled: busy || path.trim() === "" || !addingWorkspace && workspaceBackend === "codex" && codexWorkspaceId === void 0 || !addingWorkspace && workspaceBackend === "cursor" && cursorWorkspaceId === void 0 && path === "" || !addingWorkspace && workspaceBackend === "antigravity" && antigravityWorkspaceId === void 0 && path === "" || !addingWorkspace && workspaceBackend === "pi" && piWorkspaceId === void 0 && path === "" || !addingWorkspace && workspaceBackend === "opencode" && opencodeWorkspaceId === void 0 && path === "",
|
|
4147
|
+
onClick: () => void openWorkspace()
|
|
4148
|
+
}, t(busy ? "openingWorkspace" : addingWorkspace ? "confirmAddWorkspace" : "openWorkspace"))
|
|
3979
4149
|
)
|
|
3980
4150
|
)
|
|
3981
|
-
)
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
)
|
|
3985
|
-
)
|
|
3986
|
-
)
|
|
4151
|
+
)
|
|
4152
|
+
),
|
|
4153
|
+
notice === void 0 ? null : React.createElement("p", { className: "dshRemoteNotice", role: "status" }, notice),
|
|
4154
|
+
error === void 0 ? null : React.createElement("p", { className: "dshRemoteError", role: "alert" }, error)
|
|
4155
|
+
)
|
|
4156
|
+
)) : null
|
|
4157
|
+
);
|
|
4158
|
+
}
|
|
4159
|
+
return RemoteWorkspaceAction;
|
|
4160
|
+
}
|
|
4161
|
+
|
|
4162
|
+
// src/control-route.ts
|
|
4163
|
+
var CONTROL_RPC_PREFIX = "/ds-harness-remote", STATUS_STREAM_ENDPOINT = "status.events", STATUS_STREAM_PATH = `${CONTROL_RPC_PREFIX}/${STATUS_STREAM_ENDPOINT}`;
|
|
4164
|
+
|
|
4165
|
+
// src/plugin-route-client.ts
|
|
4166
|
+
var PluginRouteFailure = class extends Error {
|
|
4167
|
+
constructor(code, message) {
|
|
4168
|
+
super(message);
|
|
4169
|
+
this.code = code;
|
|
4170
|
+
}
|
|
4171
|
+
};
|
|
4172
|
+
function createPluginRouteFetch(original, baseUrl, options = {}) {
|
|
4173
|
+
let routeUrl = new URL("api/bot", baseUrl), nextRpcId = 0, control = async (method, payload, signal) => {
|
|
4174
|
+
let rpcId = `plugin-route-${++nextRpcId}`, response = await original(new URL(`${CONTROL_RPC_PREFIX.slice(1)}/${method}`, baseUrl), {
|
|
4175
|
+
method: "POST",
|
|
4176
|
+
credentials: "same-origin",
|
|
4177
|
+
headers: { "content-type": "application/json" },
|
|
4178
|
+
body: JSON.stringify({ type: "client-request", rpcId, method, payload }),
|
|
4179
|
+
signal
|
|
4180
|
+
});
|
|
4181
|
+
if (!response.ok) throw new PluginRouteFailure("remote-plugin/control-unavailable", `The local Remote control request failed (HTTP ${response.status}). Reload the Remote plugin.`);
|
|
4182
|
+
let envelope = await response.json();
|
|
4183
|
+
if (!isRecord(envelope) || envelope.type !== "server-response" || envelope.rpcId !== rpcId || !isRecord(envelope.result))
|
|
4184
|
+
throw new PluginRouteFailure("remote-plugin/control-invalid", "The local Remote control response is invalid. Reload the Remote plugin.");
|
|
4185
|
+
if (envelope.result.ok !== !0) {
|
|
4186
|
+
let error = isRecord(envelope.result.error) ? envelope.result.error : void 0, code = (isRecord(error?.details) ? error.details : void 0)?.remoteCode ?? error?.code;
|
|
4187
|
+
throw code === "FEATURE_NOT_SUPPORTED" || code === "METHOD_NOT_FOUND" ? new PluginRouteFailure("remote-plugin/host-unsupported", "The selected Host does not support plugin route forwarding. Update and reload Remote on the Host, then reconnect.") : code === "REMOTE_NOT_CONNECTED" || code === "TRANSPORT_CLOSED" ? new PluginRouteFailure("remote-plugin/disconnected", "The Remote Host is disconnected. Reconnect to load DS Bot.") : code === "INVALID_MESSAGE" ? new PluginRouteFailure("remote-plugin/operation-not-allowed", "This DS Bot operation is not allowed over Remote. Use the Host locally.") : new PluginRouteFailure("remote-plugin/control-rejected", "The Remote plugin route request was rejected by the control channel.");
|
|
4188
|
+
}
|
|
4189
|
+
return envelope.result.value;
|
|
4190
|
+
};
|
|
4191
|
+
return async (input, init) => {
|
|
4192
|
+
let requestUrl = new URL(input instanceof Request ? input.url : String(input), baseUrl);
|
|
4193
|
+
if ((init?.method ?? (input instanceof Request ? input.method : "GET")).toUpperCase() !== "POST" || requestUrl.href !== routeUrl.href) return original(input, init);
|
|
4194
|
+
let lifetime = (init?.signal !== void 0 ? init.signal ?? void 0 : input instanceof Request ? input.signal : void 0) ?? AbortSignal.timeout(45e3);
|
|
4195
|
+
try {
|
|
4196
|
+
lifetime.throwIfAborted();
|
|
4197
|
+
let status = await control("status", {}, AbortSignal.any([lifetime, AbortSignal.timeout(1e4)]));
|
|
4198
|
+
if (lifetime.throwIfAborted(), !isRecord(status)) throw new PluginRouteFailure("remote-plugin/authority-unavailable", "The Remote plugin route authority is unavailable.");
|
|
4199
|
+
if (status.mode === "local") return original(input, init);
|
|
4200
|
+
if (status.mode !== "remote") throw new PluginRouteFailure("remote-plugin/authority-unavailable", "The Remote plugin route authority is unavailable.");
|
|
4201
|
+
if (status.connected !== !0) throw new PluginRouteFailure("remote-plugin/disconnected", "The Remote Host is disconnected. Reconnect to load DS Bot.");
|
|
4202
|
+
if (!isRecord(status.remoteFeatures) || status.remoteFeatures.pluginRoute !== !0) throw new PluginRouteFailure("remote-plugin/host-unsupported", "The selected Host does not support plugin route forwarding. Update and reload Remote on the Host, then reconnect.");
|
|
4203
|
+
if (status.backend !== void 0 && status.backend !== "harness") throw new PluginRouteFailure("remote-plugin/backend-unsupported", "DS Bot requires the Remote Harness catalog. Select a Harness workspace on this Host.");
|
|
4204
|
+
let body = await (input instanceof Request ? new Request(input, init) : new Request(requestUrl, init)).clone().json();
|
|
4205
|
+
if (!isRecord(body)) throw new Error("The plugin route body must be a JSON object.");
|
|
4206
|
+
let result = await control("plugin.route", { route: "api/bot", body }, lifetime);
|
|
4207
|
+
if (!isRecord(result) || !Number.isInteger(result.status) || result.status < 200 || result.status > 599)
|
|
4208
|
+
throw new Error("The plugin route response is invalid.");
|
|
4209
|
+
let statusCode = result.status;
|
|
4210
|
+
if (statusCode === 404) throw new PluginRouteFailure("remote-plugin/bot-not-loaded", "The Host has no DS Bot route. Enable ds-bot in the same DSH instance/profile as the connected Host.");
|
|
4211
|
+
if (statusCode === 503) throw new PluginRouteFailure("remote-plugin/host-carrier-unavailable", "The Host plugin route carrier is unavailable. Update and reload Remote on the Host.");
|
|
4212
|
+
if (statusCode >= 200 && statusCode < 300 && options.beforeResponse !== void 0)
|
|
4213
|
+
try {
|
|
4214
|
+
await waitWithSignal(options.beforeResponse(status, body, result.json, lifetime), lifetime);
|
|
4215
|
+
} catch {
|
|
4216
|
+
throw lifetime.throwIfAborted(), new PluginRouteFailure("remote-plugin/catalog-unavailable", "The Remote Harness Session catalog is not ready. Reconnect before loading DS Bot.");
|
|
4217
|
+
}
|
|
4218
|
+
return lifetime.throwIfAborted(), new Response([204, 205, 304].includes(statusCode) ? null : JSON.stringify(result.json ?? null), {
|
|
4219
|
+
status: statusCode,
|
|
4220
|
+
headers: { "content-type": "application/json" }
|
|
4221
|
+
});
|
|
4222
|
+
} catch (error) {
|
|
4223
|
+
return lifetime.throwIfAborted(), new Response(JSON.stringify({
|
|
4224
|
+
ok: !1,
|
|
4225
|
+
error: {
|
|
4226
|
+
code: error instanceof PluginRouteFailure ? error.code : "remote-plugin/unavailable",
|
|
4227
|
+
message: error instanceof PluginRouteFailure ? error.message : "The Remote plugin route is unavailable.",
|
|
4228
|
+
details: {}
|
|
4229
|
+
}
|
|
4230
|
+
}), { status: 200, headers: { "content-type": "application/json" } });
|
|
4231
|
+
}
|
|
4232
|
+
};
|
|
4233
|
+
}
|
|
4234
|
+
function createPluginRouteCatalogGuard(readSessions) {
|
|
4235
|
+
return async (_status, body, json, signal) => {
|
|
4236
|
+
if (!isRecord(json) || json.ok !== !0 || !isRecord(json.value)) return;
|
|
4237
|
+
let required = botSessionIds(body.endpoint, json.value);
|
|
4238
|
+
if (required.size === 0) return;
|
|
4239
|
+
let sessions = await readSessions(), containsSessions = () => {
|
|
4240
|
+
let snapshot = sessions.list.getSnapshot(), known = new Set(snapshot.ids);
|
|
4241
|
+
return snapshot.phase === "ready" && [...required].every((id) => known.has(id));
|
|
4242
|
+
};
|
|
4243
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
4244
|
+
if (signal.throwIfAborted(), containsSessions()) return;
|
|
4245
|
+
if (sessions.refresh === void 0) break;
|
|
4246
|
+
await sessions.refresh();
|
|
4247
|
+
}
|
|
4248
|
+
if (signal.throwIfAborted(), !containsSessions()) throw new Error("The Remote Session catalog does not contain the published Sessions.");
|
|
4249
|
+
};
|
|
4250
|
+
}
|
|
4251
|
+
function botSessionIds(endpoint, value) {
|
|
4252
|
+
let ids = /* @__PURE__ */ new Set(), add = (id) => {
|
|
4253
|
+
if (id != null) {
|
|
4254
|
+
if (typeof id != "string" || id.length === 0) throw new Error("Invalid Bot Session identity.");
|
|
4255
|
+
ids.add(id);
|
|
4256
|
+
}
|
|
4257
|
+
}, addArray = (input) => {
|
|
4258
|
+
if (input !== void 0) {
|
|
4259
|
+
if (!Array.isArray(input)) throw new Error("Invalid Bot Session identities.");
|
|
4260
|
+
input.forEach(add);
|
|
4261
|
+
}
|
|
4262
|
+
}, bot = (input) => {
|
|
4263
|
+
if (!isRecord(input)) throw new Error("Invalid Bot catalog entry.");
|
|
4264
|
+
add(input.id), add(input.sessionId), addArray(input.parts), Array.isArray(input.segments) && input.segments.forEach((segment) => {
|
|
4265
|
+
if (!isRecord(segment)) throw new Error("Invalid Bot Session segment.");
|
|
4266
|
+
add(segment.sessionId);
|
|
4267
|
+
});
|
|
4268
|
+
}, room = (input) => {
|
|
4269
|
+
if (!isRecord(input)) throw new Error("Invalid Bot room entry.");
|
|
4270
|
+
add(input.id), addArray(input.parts), isRecord(input.sessions) && Object.values(input.sessions).forEach(add);
|
|
4271
|
+
}, agent = (input) => {
|
|
4272
|
+
if (!isRecord(input)) throw new Error("Invalid Bot agent entry.");
|
|
4273
|
+
addArray(input.sessions);
|
|
4274
|
+
}, roster = () => {
|
|
4275
|
+
for (let [key, visit] of [["bots", bot], ["rooms", room], ["agents", agent]])
|
|
4276
|
+
if (value[key] !== void 0) {
|
|
4277
|
+
if (!Array.isArray(value[key])) throw new Error("Invalid Bot roster.");
|
|
4278
|
+
value[key].forEach(visit);
|
|
4279
|
+
}
|
|
4280
|
+
};
|
|
4281
|
+
switch (endpoint) {
|
|
4282
|
+
case "state":
|
|
4283
|
+
case "delete-bot":
|
|
4284
|
+
case "delete-room":
|
|
4285
|
+
case "set-main":
|
|
4286
|
+
case "remove-agent":
|
|
4287
|
+
roster();
|
|
4288
|
+
break;
|
|
4289
|
+
case "create-bot":
|
|
4290
|
+
case "duplicate-bot":
|
|
4291
|
+
case "update-bot":
|
|
4292
|
+
bot(value);
|
|
4293
|
+
break;
|
|
4294
|
+
case "create-room":
|
|
4295
|
+
room(value);
|
|
4296
|
+
break;
|
|
4297
|
+
case "update-room":
|
|
4298
|
+
room(value.room);
|
|
4299
|
+
break;
|
|
4300
|
+
case "add-agent":
|
|
4301
|
+
agent(value);
|
|
4302
|
+
break;
|
|
4303
|
+
case "agent-session":
|
|
4304
|
+
case "agent-adopt":
|
|
4305
|
+
add(value.sessionId);
|
|
4306
|
+
break;
|
|
4307
|
+
case "set-flags":
|
|
4308
|
+
Array.isArray(value.sessions) ? agent(value) : Array.isArray(value.members) ? room(value) : bot(value);
|
|
4309
|
+
break;
|
|
4310
|
+
}
|
|
4311
|
+
return ids;
|
|
4312
|
+
}
|
|
4313
|
+
function waitWithSignal(pending, signal) {
|
|
4314
|
+
return new Promise((resolve, reject) => {
|
|
4315
|
+
let onAbort = () => reject(signal.reason);
|
|
4316
|
+
signal.addEventListener("abort", onAbort, { once: !0 }), signal.aborted && onAbort(), pending.then(resolve, reject).finally(() => signal.removeEventListener("abort", onAbort));
|
|
4317
|
+
});
|
|
4318
|
+
}
|
|
4319
|
+
function isRecord(value) {
|
|
4320
|
+
return typeof value == "object" && value !== null && !Array.isArray(value);
|
|
4321
|
+
}
|
|
4322
|
+
|
|
4323
|
+
// src/remote-file-content-provider.ts
|
|
4324
|
+
function shouldUseRemoteFileViewer(status) {
|
|
4325
|
+
return status.mode === "remote" && status.remoteFeatures?.fileViewer === !0;
|
|
4326
|
+
}
|
|
4327
|
+
var REMOTE_FILE_SAVE_AS_MAX_BYTES = 100 * 1024 * 1024, REMOTE_FILE_FAST_SAVE_AS_MAX_BYTES = 1024 * 1024 * 1024;
|
|
4328
|
+
function shouldAllowRemoteFileSaveAs(status) {
|
|
4329
|
+
return shouldUseRemoteFileViewer(status) && (status.transport === "LAN" || status.transport === "P2P" || status.transport === "TURN");
|
|
4330
|
+
}
|
|
4331
|
+
function remoteFileSaveAsMaxBytes(status) {
|
|
4332
|
+
return status.transport === "LAN" || status.transport === "P2P" ? REMOTE_FILE_FAST_SAVE_AS_MAX_BYTES : REMOTE_FILE_SAVE_AS_MAX_BYTES;
|
|
4333
|
+
}
|
|
4334
|
+
function createRemoteFileContentProvider(call, options = {}) {
|
|
4335
|
+
return {
|
|
4336
|
+
id: "dsh-remote-files",
|
|
4337
|
+
priority: 1e4,
|
|
4338
|
+
supports: () => !0,
|
|
4339
|
+
saveAsAllowed: () => ({
|
|
4340
|
+
allowed: currentSaveAsAllowed(options.saveAsAllowed),
|
|
4341
|
+
maxBytes: currentSaveAsMaxBytes(options.saveAsMaxBytes)
|
|
4342
|
+
}),
|
|
4343
|
+
async stat(locator, signal) {
|
|
4344
|
+
let value = await call("fileviewer.stat", { path: locator }, signal);
|
|
4345
|
+
if (value.exists)
|
|
4346
|
+
return {
|
|
4347
|
+
name: value.name,
|
|
4348
|
+
size: value.isDirectory ? 0 : value.size,
|
|
4349
|
+
mime: value.mime,
|
|
4350
|
+
mtimeMs: value.mtimeMs,
|
|
4351
|
+
isDirectory: value.isDirectory
|
|
4352
|
+
};
|
|
4353
|
+
},
|
|
4354
|
+
async read(locator, request) {
|
|
4355
|
+
if (!Number.isInteger(request.offset) || request.offset < 0) throw new Error("A non-negative integer offset is required.");
|
|
4356
|
+
if (!Number.isInteger(request.length) || request.length <= 0) throw new Error("A positive integer length is required.");
|
|
4357
|
+
let chunks = [], received = 0;
|
|
4358
|
+
for (; received < request.length; ) {
|
|
4359
|
+
request.signal.throwIfAborted();
|
|
4360
|
+
let length = Math.min(524288, request.length - received), offset = request.offset + received, range = await call("fileviewer.readRange", { path: locator, offset, length }, request.signal);
|
|
4361
|
+
if (range.offset !== offset) throw new Error("The Remote Host returned a mismatched file range.");
|
|
4362
|
+
let bytes = decodeBase64(range.data);
|
|
4363
|
+
if (bytes.byteLength > length) throw new Error("The Remote Host returned more file bytes than requested.");
|
|
4364
|
+
if (chunks.push(bytes), received += bytes.byteLength, range.eof || bytes.byteLength === 0) break;
|
|
4365
|
+
}
|
|
4366
|
+
let merged = new Uint8Array(received), cursor = 0;
|
|
4367
|
+
for (let chunk of chunks)
|
|
4368
|
+
merged.set(chunk, cursor), cursor += chunk.byteLength;
|
|
4369
|
+
return merged;
|
|
4370
|
+
},
|
|
4371
|
+
async list(locator, signal) {
|
|
4372
|
+
return (await call("fileviewer.list", { path: locator }, signal)).entries.map((entry) => ({
|
|
4373
|
+
locator: entry.path,
|
|
4374
|
+
name: entry.name,
|
|
4375
|
+
size: entry.isDirectory ? 0 : entry.size ?? 0,
|
|
4376
|
+
mtimeMs: entry.mtimeMs,
|
|
4377
|
+
isDirectory: entry.isDirectory
|
|
4378
|
+
}));
|
|
4379
|
+
}
|
|
4380
|
+
};
|
|
4381
|
+
}
|
|
4382
|
+
function currentSaveAsAllowed(value) {
|
|
4383
|
+
return typeof value == "function" ? value() : value === !0;
|
|
4384
|
+
}
|
|
4385
|
+
function currentSaveAsMaxBytes(value) {
|
|
4386
|
+
return typeof value == "function" ? value() : value ?? REMOTE_FILE_SAVE_AS_MAX_BYTES;
|
|
4387
|
+
}
|
|
4388
|
+
function decodeBase64(value) {
|
|
4389
|
+
let binary = atob(value), bytes = new Uint8Array(binary.length);
|
|
4390
|
+
for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index);
|
|
4391
|
+
return bytes;
|
|
4392
|
+
}
|
|
4393
|
+
|
|
4394
|
+
// src/status-stream.ts
|
|
4395
|
+
function parseStatus(data) {
|
|
4396
|
+
if (typeof data == "string")
|
|
4397
|
+
try {
|
|
4398
|
+
let parsed = JSON.parse(data);
|
|
4399
|
+
return parsed === null || typeof parsed != "object" ? void 0 : parsed;
|
|
4400
|
+
} catch {
|
|
4401
|
+
return;
|
|
4402
|
+
}
|
|
4403
|
+
}
|
|
4404
|
+
function createStatusFeed(options) {
|
|
4405
|
+
let listeners = /* @__PURE__ */ new Set(), pollIntervalMs = options.pollIntervalMs ?? 1500, openTimeoutMs = options.openTimeoutMs ?? 4e3, createSource = options.createSource ?? ((url) => new EventSource(url)), status, source, openTimer, pollTimer, publish = (next) => {
|
|
4406
|
+
status = next;
|
|
4407
|
+
for (let listener of [...listeners]) listener(next);
|
|
4408
|
+
}, teardown = () => {
|
|
4409
|
+
openTimer !== void 0 && (clearTimeout(openTimer), openTimer = void 0), pollTimer !== void 0 && (clearInterval(pollTimer), pollTimer = void 0), source?.close(), source = void 0;
|
|
4410
|
+
}, poll = () => {
|
|
4411
|
+
options.readStatus().then((next) => {
|
|
4412
|
+
pollTimer !== void 0 && publish(next);
|
|
4413
|
+
}).catch(() => {
|
|
4414
|
+
});
|
|
4415
|
+
}, fallbackToPolling = (reason) => {
|
|
4416
|
+
pollTimer !== void 0 || listeners.size === 0 || (openTimer !== void 0 && (clearTimeout(openTimer), openTimer = void 0), source?.close(), source = void 0, options.onFallback?.(reason), poll(), pollTimer = setInterval(poll, pollIntervalMs));
|
|
4417
|
+
}, openStream = () => {
|
|
4418
|
+
let opened;
|
|
4419
|
+
try {
|
|
4420
|
+
opened = createSource(options.url);
|
|
4421
|
+
} catch {
|
|
4422
|
+
fallbackToPolling("unsupported");
|
|
4423
|
+
return;
|
|
4424
|
+
}
|
|
4425
|
+
source = opened;
|
|
4426
|
+
let received = !1;
|
|
4427
|
+
openTimer = setTimeout(() => {
|
|
4428
|
+
received || fallbackToPolling("silent");
|
|
4429
|
+
}, openTimeoutMs), opened.onmessage = (event) => {
|
|
4430
|
+
received = !0, openTimer !== void 0 && (clearTimeout(openTimer), openTimer = void 0);
|
|
4431
|
+
let next = parseStatus(event.data);
|
|
4432
|
+
next !== void 0 && publish(next);
|
|
4433
|
+
}, opened.onerror = () => {
|
|
4434
|
+
opened.readyState === 2 && fallbackToPolling("unavailable");
|
|
4435
|
+
};
|
|
4436
|
+
};
|
|
4437
|
+
return {
|
|
4438
|
+
getSnapshot: () => status,
|
|
4439
|
+
subscribe: (listener) => (listeners.add(listener), status !== void 0 && listener(status), listeners.size === 1 && openStream(), () => {
|
|
4440
|
+
listeners.delete(listener), listeners.size === 0 && teardown();
|
|
4441
|
+
}),
|
|
4442
|
+
close: () => {
|
|
4443
|
+
listeners.clear(), teardown();
|
|
3987
4444
|
}
|
|
4445
|
+
};
|
|
4446
|
+
}
|
|
4447
|
+
|
|
4448
|
+
// src/client.ts
|
|
4449
|
+
var clientModuleId = "ds-harness-remote", controlRouteBackoffStepsMs = [1e3, 2e3, 5e3, 1e4, 3e4], ControlRouteUnavailableError = class extends Error {
|
|
4450
|
+
constructor(message) {
|
|
4451
|
+
super(message), this.name = "ControlRouteUnavailableError";
|
|
4452
|
+
}
|
|
4453
|
+
}, originalPluginFetch = window.fetch, readyPluginSessions, pluginSessions = new Promise((resolve) => {
|
|
4454
|
+
readyPluginSessions = resolve;
|
|
4455
|
+
}), pluginRouteFetch = typeof originalPluginFetch == "function" && typeof document < "u" ? createPluginRouteFetch(originalPluginFetch.bind(window), document.baseURI, {
|
|
4456
|
+
beforeResponse: createPluginRouteCatalogGuard(() => pluginSessions)
|
|
4457
|
+
}) : void 0;
|
|
4458
|
+
pluginRouteFetch !== void 0 && (window.fetch = pluginRouteFetch);
|
|
4459
|
+
function controlRouteUnavailableStatus() {
|
|
4460
|
+
return {
|
|
4461
|
+
mode: "local",
|
|
4462
|
+
available: !1,
|
|
4463
|
+
controlUnavailable: !0,
|
|
4464
|
+
connected: !1,
|
|
4465
|
+
transport: "Disconnected",
|
|
4466
|
+
remoteFeatures: { commandList: !1, fileViewer: !1, terminal: !1, codex: !1, pluginRoute: !1, cursor: !1, antigravity: !1, pi: !1, opencode: !1 },
|
|
4467
|
+
hostAuthorizationAvailable: !1
|
|
4468
|
+
};
|
|
4469
|
+
}
|
|
4470
|
+
window.__ModuleLoader__.load({
|
|
4471
|
+
id: clientModuleId,
|
|
4472
|
+
factory: (require2) => {
|
|
4473
|
+
let module = { exports: {} }, React = require2("react"), RemotePluginOptions = createRemotePluginOptions(React), RemoteWorkspaceAction = createRemoteWorkspaceAction(React), RemoteProgressView = createRemoteProgressView(React), RemoteSessionHeaderAction = createRemoteSessionHeaderAction(React), inject = [
|
|
4474
|
+
"connection",
|
|
4475
|
+
"slots",
|
|
4476
|
+
"locale",
|
|
4477
|
+
"workspaces",
|
|
4478
|
+
"sessions"
|
|
4479
|
+
];
|
|
3988
4480
|
function RemoteModeAction(props) {
|
|
3989
4481
|
let { t } = props, [open, setOpen] = React.useState(!1), [status, setStatus] = React.useState(void 0), [devices, setDevices] = React.useState([]), [hostRegistrationCode, setHostRegistrationCode] = React.useState(""), [email, setEmail] = React.useState(""), [password, setPassword] = React.useState(""), [busy, setBusy] = React.useState(!1), [progress, setProgress] = React.useState(void 0), progressRun = React.useRef(0), [error, setError] = React.useState(void 0), [supported, setSupported] = React.useState(!0), refresh = async () => {
|
|
3990
4482
|
let [nextStatus, nextDevices] = await Promise.all([
|
|
@@ -4133,278 +4625,6 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
4133
4625
|
) : null
|
|
4134
4626
|
) : null;
|
|
4135
4627
|
}
|
|
4136
|
-
function RemoteSessionHeaderAction(props) {
|
|
4137
|
-
let { t } = props, status = React.useSyncExternalStore(
|
|
4138
|
-
props.statusFeed.subscribe,
|
|
4139
|
-
props.statusFeed.getSnapshot,
|
|
4140
|
-
props.statusFeed.getSnapshot
|
|
4141
|
-
), [busy, setBusy] = React.useState(!1), [routeOpen, setRouteOpen] = React.useState(!1);
|
|
4142
|
-
if (React.useEffect(() => {
|
|
4143
|
-
if (status?.mode === "remote")
|
|
4144
|
-
return hideLocalSessionActions();
|
|
4145
|
-
}, [status?.mode]), React.useEffect(() => (document.documentElement.classList.toggle(
|
|
4146
|
-
"dshRemoteCodexTargetActive",
|
|
4147
|
-
status?.mode === "remote" && status.backend === "codex"
|
|
4148
|
-
), document.documentElement.classList.toggle(
|
|
4149
|
-
"dshRemoteCursorTargetActive",
|
|
4150
|
-
status?.mode === "remote" && status.backend === "cursor"
|
|
4151
|
-
), document.documentElement.classList.toggle(
|
|
4152
|
-
"dshRemoteAntigravityTargetActive",
|
|
4153
|
-
status?.mode === "remote" && status.backend === "antigravity"
|
|
4154
|
-
), () => {
|
|
4155
|
-
document.documentElement.classList.remove("dshRemoteCodexTargetActive"), document.documentElement.classList.remove("dshRemoteCursorTargetActive"), document.documentElement.classList.remove("dshRemoteAntigravityTargetActive");
|
|
4156
|
-
}), [status?.mode, status?.backend]), React.useEffect(() => {
|
|
4157
|
-
if (!routeOpen) return;
|
|
4158
|
-
let closeOnEscape = (event) => {
|
|
4159
|
-
event.key === "Escape" && setRouteOpen(!1);
|
|
4160
|
-
};
|
|
4161
|
-
return document.addEventListener("keydown", closeOnEscape), () => document.removeEventListener("keydown", closeOnEscape);
|
|
4162
|
-
}, [routeOpen]), status?.mode !== "remote") return null;
|
|
4163
|
-
let exit = async () => {
|
|
4164
|
-
setBusy(!0);
|
|
4165
|
-
try {
|
|
4166
|
-
await props.control("mode.set", { mode: "local" }), window.location.reload();
|
|
4167
|
-
} finally {
|
|
4168
|
-
setBusy(!1);
|
|
4169
|
-
}
|
|
4170
|
-
}, transport = status.network?.webRtc?.mode ?? status.transport ?? "Disconnected", networkLabel = t(transport === "P2P" ? "remoteNetworkP2p" : transport === "TURN" ? "remoteNetworkTurn" : transport === "Relay" ? "remoteNetworkRelay" : transport === "LAN" ? "remoteNetworkLan" : "remoteNetworkOffline"), networkOnline = status.connected === !0 && transport !== "Disconnected", routeVia = t(transport === "P2P" ? "connectionRouteP2p" : transport === "TURN" ? "connectionRouteTurn" : transport === "Relay" ? "connectionRouteRelay" : "connectionRouteLan"), routeViaDetail = t(transport === "P2P" ? "connectionRouteP2pDetail" : transport === "TURN" ? "connectionRouteTurnDetail" : transport === "Relay" ? "connectionRouteRelayDetail" : "connectionRouteLanDetail"), network = status.network, webRtc = network?.webRtc, controlStateLabel = network?.controlChannelState === "connecting" ? t("controlStateConnecting") : network?.controlChannelState === "open" ? t("controlStateOpen") : network?.controlChannelState === "closing" ? t("controlStateClosing") : t("controlStateClosed"), detailValue = (value) => value === void 0 || value === "" ? t("notProvided") : String(value), candidateLabel = (value) => value === "host" ? t("candidateHost") : value === "srflx" ? t("candidateSrflx") : value === "prflx" ? t("candidatePrflx") : value === "relay" ? t("candidateRelay") : detailValue(value), fact = (label, value, mono = !1) => React.createElement(
|
|
4171
|
-
"div",
|
|
4172
|
-
null,
|
|
4173
|
-
React.createElement("dt", null, label),
|
|
4174
|
-
React.createElement("dd", { className: mono ? "isMono" : void 0, title: mono ? value : void 0 }, value)
|
|
4175
|
-
);
|
|
4176
|
-
return React.createElement(
|
|
4177
|
-
"div",
|
|
4178
|
-
{ className: "dshRemoteSessionHeader", role: "status" },
|
|
4179
|
-
React.createElement("svg", {
|
|
4180
|
-
viewBox: "0 0 24 24",
|
|
4181
|
-
fill: "none",
|
|
4182
|
-
stroke: "currentColor",
|
|
4183
|
-
strokeWidth: 1.7,
|
|
4184
|
-
strokeLinecap: "round",
|
|
4185
|
-
strokeLinejoin: "round",
|
|
4186
|
-
"aria-hidden": !0
|
|
4187
|
-
}, React.createElement("rect", { x: 3, y: 4, width: 18, height: 13, rx: 2 }), React.createElement("path", { d: "M8 21h8M12 17v4" })),
|
|
4188
|
-
React.createElement("span", { className: "dshRemoteSessionTarget" }, t("remoteModeLabel", { name: status.target?.name ?? t("host") })),
|
|
4189
|
-
React.createElement("button", {
|
|
4190
|
-
type: "button",
|
|
4191
|
-
className: `dshRemoteNetwork${networkOnline ? " isOnline" : " isOffline"}`,
|
|
4192
|
-
title: networkLabel,
|
|
4193
|
-
disabled: !networkOnline,
|
|
4194
|
-
"aria-haspopup": "dialog",
|
|
4195
|
-
"aria-expanded": routeOpen,
|
|
4196
|
-
onClick: () => setRouteOpen((value) => !value)
|
|
4197
|
-
}, React.createElement("i", { "aria-hidden": !0 }), networkLabel),
|
|
4198
|
-
networkOnline ? React.createElement("span", { className: "dshRemoteEncrypted" }, t("remoteLinkEncrypted")) : null,
|
|
4199
|
-
React.createElement("button", { type: "button", className: "dshRemoteHeaderExitLink", disabled: busy, onClick: () => void exit() }, t("exitRemote")),
|
|
4200
|
-
routeOpen ? React.createElement("div", {
|
|
4201
|
-
className: "dshRemoteRouteBackdrop",
|
|
4202
|
-
role: "presentation",
|
|
4203
|
-
onMouseDown: (event) => {
|
|
4204
|
-
event.target === event.currentTarget && setRouteOpen(!1);
|
|
4205
|
-
}
|
|
4206
|
-
}, React.createElement(
|
|
4207
|
-
"section",
|
|
4208
|
-
{
|
|
4209
|
-
className: "dshRemoteRoutePanel",
|
|
4210
|
-
role: "dialog",
|
|
4211
|
-
"aria-label": t("connectionRouteTitle")
|
|
4212
|
-
},
|
|
4213
|
-
React.createElement(
|
|
4214
|
-
"header",
|
|
4215
|
-
null,
|
|
4216
|
-
React.createElement("strong", null, t("connectionRouteTitle")),
|
|
4217
|
-
React.createElement("button", { type: "button", "aria-label": t("close"), onClick: () => setRouteOpen(!1) }, "\xD7")
|
|
4218
|
-
),
|
|
4219
|
-
React.createElement(
|
|
4220
|
-
"ol",
|
|
4221
|
-
null,
|
|
4222
|
-
React.createElement(
|
|
4223
|
-
"li",
|
|
4224
|
-
null,
|
|
4225
|
-
React.createElement("small", null, t("connectionRouteFrom")),
|
|
4226
|
-
React.createElement("strong", null, network?.local.name ?? t("connectionRouteCurrentDevice")),
|
|
4227
|
-
network === void 0 ? null : React.createElement("span", null, `${network.local.platform} \xB7 ${shortDeviceId(network.local.deviceId)}`)
|
|
4228
|
-
),
|
|
4229
|
-
React.createElement(
|
|
4230
|
-
"li",
|
|
4231
|
-
null,
|
|
4232
|
-
React.createElement("small", null, t("connectionRouteVia")),
|
|
4233
|
-
React.createElement("strong", null, routeVia),
|
|
4234
|
-
React.createElement("span", null, routeViaDetail)
|
|
4235
|
-
),
|
|
4236
|
-
React.createElement(
|
|
4237
|
-
"li",
|
|
4238
|
-
null,
|
|
4239
|
-
React.createElement("small", null, t("connectionRouteTo")),
|
|
4240
|
-
React.createElement("strong", null, network?.remote.name ?? status.target?.name ?? t("host")),
|
|
4241
|
-
React.createElement("span", null, network === void 0 ? t("connectionRouteHost") : `${network.remote.platform} \xB7 ${shortDeviceId(network.remote.deviceId)}`)
|
|
4242
|
-
)
|
|
4243
|
-
),
|
|
4244
|
-
network === void 0 ? null : React.createElement(
|
|
4245
|
-
"section",
|
|
4246
|
-
{ className: "dshRemoteRouteSection" },
|
|
4247
|
-
React.createElement("h3", null, t("connectionDetailsConnection")),
|
|
4248
|
-
React.createElement(
|
|
4249
|
-
"dl",
|
|
4250
|
-
null,
|
|
4251
|
-
fact(t("connectionId"), detailValue(network.connectionId), !0),
|
|
4252
|
-
fact(t("connectedAt"), network.connectedAt === void 0 ? t("notProvided") : formatLocalTime(network.connectedAt)),
|
|
4253
|
-
fact(t("preferredTransports"), network.preferredTransports.map((value) => transportLabel(value, t)).join(" \u2192 ")),
|
|
4254
|
-
fact(t("controlChannel"), `WebSocket \xB7 ${controlStateLabel}`),
|
|
4255
|
-
fact(t("controlAddress"), network.controlChannelUrl, !0)
|
|
4256
|
-
)
|
|
4257
|
-
),
|
|
4258
|
-
webRtc === void 0 ? null : React.createElement(
|
|
4259
|
-
"section",
|
|
4260
|
-
{ className: "dshRemoteRouteSection" },
|
|
4261
|
-
React.createElement("h3", null, t("connectionDetailsWebRtc")),
|
|
4262
|
-
React.createElement(
|
|
4263
|
-
"dl",
|
|
4264
|
-
null,
|
|
4265
|
-
fact(t("peerState"), `${webRtc.connectionState} \xB7 ICE ${webRtc.iceConnectionState}`),
|
|
4266
|
-
fact(t("dataChannel"), detailValue(webRtc.dataChannelState)),
|
|
4267
|
-
fact(t("localCandidate"), candidateLabel(webRtc.localCandidateType)),
|
|
4268
|
-
fact(t("remoteCandidate"), candidateLabel(webRtc.remoteCandidateType)),
|
|
4269
|
-
fact(t("localAddress"), detailValue(webRtc.localAddress), !0),
|
|
4270
|
-
fact(t("remoteAddress"), detailValue(webRtc.remoteAddress), !0),
|
|
4271
|
-
fact(t("networkProtocol"), detailValue(webRtc.protocol?.toUpperCase())),
|
|
4272
|
-
fact(t("relayProtocol"), detailValue(webRtc.relayProtocol?.toUpperCase())),
|
|
4273
|
-
fact(t("roundTripTime"), webRtc.currentRoundTripTimeMs === void 0 ? t("notProvided") : `${webRtc.currentRoundTripTimeMs.toLocaleString()} ms`),
|
|
4274
|
-
fact(t("availableBitrate"), webRtc.availableOutgoingBitrate === void 0 ? t("notProvided") : formatBitrate(webRtc.availableOutgoingBitrate)),
|
|
4275
|
-
fact(t("bytesSent"), webRtc.bytesSent === void 0 ? t("notProvided") : formatByteSize(webRtc.bytesSent)),
|
|
4276
|
-
fact(t("bytesReceived"), webRtc.bytesReceived === void 0 ? t("notProvided") : formatByteSize(webRtc.bytesReceived))
|
|
4277
|
-
)
|
|
4278
|
-
),
|
|
4279
|
-
React.createElement("p", null, t("connectionRouteEncrypted"))
|
|
4280
|
-
)) : null
|
|
4281
|
-
);
|
|
4282
|
-
}
|
|
4283
|
-
function hideLocalSessionActions() {
|
|
4284
|
-
let selector = 'button,a,[role="button"]', hiddenAttribute = "data-dsh-remote-hidden-action", localAction = /(?:open|打开).{0,12}vs\s*code|vs\s*code.{0,12}(?:open|打开)|session\s*logs?|download.{0,12}session\s*logs?|会话日志|下载.{0,8}日志/i, inspect = (root) => {
|
|
4285
|
-
let candidates = root instanceof Element && root.matches(selector) ? [root, ...Array.from(root.querySelectorAll(selector))] : Array.from(root.querySelectorAll(selector));
|
|
4286
|
-
for (let candidate of candidates) {
|
|
4287
|
-
if (candidate.closest(".dshRemoteSessionHeader") !== null) continue;
|
|
4288
|
-
let label = [
|
|
4289
|
-
candidate.getAttribute("aria-label"),
|
|
4290
|
-
candidate.getAttribute("title"),
|
|
4291
|
-
candidate.getAttribute("data-tooltip"),
|
|
4292
|
-
candidate.textContent
|
|
4293
|
-
].filter(Boolean).join(" ");
|
|
4294
|
-
localAction.test(label) && candidate.setAttribute(hiddenAttribute, "");
|
|
4295
|
-
}
|
|
4296
|
-
};
|
|
4297
|
-
inspect(document.body);
|
|
4298
|
-
let observer = new MutationObserver((records) => {
|
|
4299
|
-
for (let record of records) {
|
|
4300
|
-
record.type === "attributes" && inspect(record.target);
|
|
4301
|
-
for (let node of Array.from(record.addedNodes))
|
|
4302
|
-
node instanceof Element && inspect(node);
|
|
4303
|
-
}
|
|
4304
|
-
});
|
|
4305
|
-
return observer.observe(document.body, {
|
|
4306
|
-
subtree: !0,
|
|
4307
|
-
childList: !0,
|
|
4308
|
-
attributes: !0,
|
|
4309
|
-
attributeFilter: ["aria-label", "title", "data-tooltip"]
|
|
4310
|
-
}), () => {
|
|
4311
|
-
observer.disconnect(), document.querySelectorAll(`[${hiddenAttribute}]`).forEach((element) => element.removeAttribute(hiddenAttribute));
|
|
4312
|
-
};
|
|
4313
|
-
}
|
|
4314
|
-
function installStyle() {
|
|
4315
|
-
let style = document.createElement("style");
|
|
4316
|
-
return style.dataset.plugin = clientModuleId, style.dataset.pluginCss = "dsh-remote", style.textContent = [
|
|
4317
|
-
'html.dshRemoteTargetActive button[aria-label="\u6DFB\u52A0\u5DE5\u4F5C\u533A"],html.dshRemoteTargetActive button[aria-label="Add workspace"]{display:none!important}',
|
|
4318
|
-
'html.dshRemoteCodexTargetActive [data-composer-card] button[aria-haspopup="listbox"][aria-label="\u6307\u4EE4"],html.dshRemoteCodexTargetActive [data-composer-card] button[aria-haspopup="listbox"][aria-label="Commands"]{display:none!important}',
|
|
4319
|
-
"[data-dsh-remote-hidden-action]{display:none!important}",
|
|
4320
|
-
// The 0.1.6 right sidebar occupies the same shell header area as the
|
|
4321
|
-
// remote status strip. Hide the strip while that sidebar is expanded;
|
|
4322
|
-
// the sidebar itself remains the active context for terminal/files.
|
|
4323
|
-
":has([data-sidebar-right-open]) .dshRemoteSessionHeader{display:none!important}",
|
|
4324
|
-
// TerminalRecovery renders a retry action in the conversation header.
|
|
4325
|
-
// A failed remote terminal is reported when its tab is opened/closed;
|
|
4326
|
-
// keeping this background recovery action out of the top-left header
|
|
4327
|
-
// avoids overlapping the session controls.
|
|
4328
|
-
'[title^="\u6062\u590D\u7EC8\u7AEF\u5931\u8D25"],[title^="Terminal recovery failed"]{display:none!important}',
|
|
4329
|
-
".dshRemoteTerminalUnavailable{box-sizing:border-box;margin:12px;padding:12px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-2);font-size:13px;line-height:1.5}",
|
|
4330
|
-
".dshRemoteModeButton{min-height:36px;border:0;background:transparent;color:var(--dsw-alias-label-primary);display:flex;align-items:center;gap:8px;padding:0 10px;border-radius:8px}.dshRemoteModeButton:is(button){cursor:pointer}",
|
|
4331
|
-
".dshRemoteModeButton:is(button):hover{background:var(--dsw-alias-interactive-bg-hover)}",
|
|
4332
|
-
// Keep additive footer actions in reading order above the Settings seat.
|
|
4333
|
-
'[class*="_footArea"]:has(.dshRemoteSidebarEntry){flex-direction:column!important;align-items:stretch;gap:0}[class*="_footerActions"]:has(.dshRemoteSidebarEntry){display:flex!important;flex-direction:column;align-items:stretch}[class*="_footerActions"]:has(.dshRemoteSidebarEntry.isRail){align-items:center}',
|
|
4334
|
-
'[class*="_footerActions"]:has(.dshRemoteSidebarEntry.isWide) .bt-return{justify-content:flex-start}',
|
|
4335
|
-
// Bot mode seats its account beside Connect plugins. Keep that row intact
|
|
4336
|
-
// and let Remote span a separate row underneath it.
|
|
4337
|
-
'[class*="_footArea"]:has(.bt-connect-wrap):has(.dshRemoteSidebarEntry.isWide){display:grid!important;grid-template-columns:36px minmax(0,1fr);align-items:center;gap:8px 9px}[class*="_footArea"]:has(.bt-connect-wrap):has(.dshRemoteSidebarEntry.isWide)>[class*="_footerActions"]{display:contents!important}[class*="_footArea"]:has(.bt-connect-wrap):has(.dshRemoteSidebarEntry.isWide)>[class*="_footerActions"]>div:not(.dshRemoteSidebarEntry){display:contents!important}',
|
|
4338
|
-
'[class*="_footArea"]:has(.bt-connect-wrap):has(.dshRemoteSidebarEntry.isWide) .bt-connect-wrap{grid-column:2;grid-row:1}[class*="_footArea"]:has(.bt-connect-wrap):has(.dshRemoteSidebarEntry.isWide)>[class*="_settingsArea"]{grid-column:1;grid-row:1;width:36px!important}[class*="_footArea"]:has(.bt-connect-wrap):has(.dshRemoteSidebarEntry.isWide) .dshRemoteSidebarEntry.isWide{display:block!important;grid-column:1/-1;grid-row:2;margin:0}',
|
|
4339
|
-
'[class*="_footArea"]:has(.bt-connect-wrap):has(.bt-foot-account):has(.dshRemoteSidebarEntry.isWide){grid-template-columns:36px minmax(0,1fr) 36px}[class*="_footArea"]:has(.bt-connect-wrap):has(.bt-foot-account):has(.dshRemoteSidebarEntry.isWide) .bt-foot-account{grid-column:1;grid-row:1}[class*="_footArea"]:has(.bt-connect-wrap):has(.bt-foot-account):has(.dshRemoteSidebarEntry.isWide)>[class*="_settingsArea"]{grid-column:3}',
|
|
4340
|
-
".dshRemoteSidebarEntry{box-sizing:border-box;flex:none;width:36px;min-width:36px;display:block}.dshRemoteSidebarEntry .dshRemoteModeButton{box-sizing:border-box;width:36px;height:36px;min-height:36px;justify-content:center;gap:0;padding:0;border-radius:50%}.dshRemoteSidebarEntry.isWide{width:100%;min-width:0;height:36px;margin:4px 0}.dshRemoteSidebarEntry.isWide .dshRemoteModeButton{width:100%;min-width:0;justify-content:flex-start;gap:8px;padding:0 14px;border-radius:8px;font:inherit;font-size:14px;line-height:20px;text-align:start}.dshRemoteSidebarLabel{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dshRemoteSidebarEntry.isRail{height:54px}.dshRemoteSidebarEntry.isRail .dshRemoteModeButton{margin:8px 0 10px}.dshRemoteSidebarEntry.isActive .dshRemoteComputerIcon{color:var(--dsw-alias-brand-primary)}.dshRemoteSidebarEntry .dshRemoteModeButton:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.dshRemoteSidebarEntry .dshRemoteModeButton:disabled{opacity:.45;cursor:default}",
|
|
4341
|
-
".dshRemoteComputerIcon{box-sizing:border-box;width:18px;height:18px;flex:0 0 18px;color:var(--dsw-alias-label-secondary)}",
|
|
4342
|
-
".dshRemoteSidebarEntry.isWide{position:relative}.dshRemoteSidebarEntry.isWide.isActive .dshRemoteModeButton{padding-inline-end:64px}.dshRemoteExitLink{position:absolute;inset-block-start:0;inset-inline-end:8px;min-width:44px;height:36px;border:0;border-radius:8px;background:transparent;color:var(--dsw-alias-label-secondary);padding:0 6px;font:inherit;font-size:12px;line-height:20px;white-space:nowrap;cursor:pointer}.dshRemoteExitLink:hover:not(:disabled){color:var(--dsw-alias-label-primary);text-decoration:underline}.dshRemoteExitLink:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.dshRemoteExitLink:disabled{opacity:.45;cursor:default}",
|
|
4343
|
-
'.dshRemoteSessionHeader{position:fixed;z-index:25;top:12px;left:50%;transform:translateX(-50%);max-width:calc(100vw - 360px);height:28px;display:inline-flex;align-items:center;gap:7px;color:var(--dsw-alias-label-secondary);font-size:12px;white-space:nowrap}.dshRemoteSessionHeader>svg{width:15px;height:15px;flex:0 0 auto}.dshRemoteSessionTarget{min-width:0;max-width:260px;overflow:hidden;text-overflow:ellipsis}.dshRemoteNetwork{flex:0 0 auto;border:0;background:transparent;color:inherit;font:inherit;padding:3px 2px;display:inline-flex;align-items:center;gap:5px;cursor:pointer}.dshRemoteNetwork:hover:not(:disabled){color:var(--dsw-alias-label-primary);text-decoration:underline}.dshRemoteNetwork:disabled{cursor:default}.dshRemoteNetwork>i{width:6px;height:6px;border-radius:50%;background:var(--dsw-alias-label-tertiary)}.dshRemoteNetwork.isOnline>i{background:var(--dsw-alias-state-success-primary)}.dshRemoteNetwork.isOffline{color:var(--dsw-alias-state-error-primary)}.dshRemoteNetwork.isOffline>i{background:currentColor}.dshRemoteEncrypted{flex:0 0 auto;color:var(--dsw-alias-label-tertiary)}.dshRemoteHeaderExitLink{flex:0 0 auto;border:0;background:transparent;color:var(--dsw-alias-label-secondary);padding:3px 2px;font:inherit;text-decoration:none;cursor:pointer}.dshRemoteHeaderExitLink:hover{text-decoration:underline;color:var(--dsw-alias-label-primary)}.dshRemoteHeaderExitLink:disabled{opacity:.45;cursor:default;text-decoration:none}.dshRemoteNetwork:focus-visible,.dshRemoteHeaderExitLink:focus-visible,.dshRemoteRoutePanel>header button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.dshRemoteRouteBackdrop{position:fixed;inset:0;z-index:26}.dshRemoteRoutePanel{box-sizing:border-box;position:absolute;top:48px;right:28px;width:min(680px,calc(100vw - 32px));max-height:calc(100vh - 72px);overflow:auto;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:12px;padding:16px;white-space:normal}.dshRemoteRoutePanel>header{position:sticky;top:-16px;z-index:1;display:flex;align-items:center;justify-content:space-between;margin:-16px -16px 0;padding:16px;background:var(--dsw-alias-bg-layer-1)}.dshRemoteRoutePanel>header strong{font-size:14px}.dshRemoteRoutePanel>header button{width:28px;height:28px;border:0;border-radius:7px;background:transparent;color:inherit;font-size:20px;cursor:pointer}.dshRemoteRoutePanel>header button:hover{background:var(--dsw-alias-interactive-bg-hover)}.dshRemoteRoutePanel ol{display:flex;align-items:stretch;margin:12px 0 0;padding:0 0 16px;border-bottom:1px solid var(--dsw-alias-border-l2);list-style:none}.dshRemoteRoutePanel li{position:relative;min-width:0;flex:1;display:flex;flex-direction:column;gap:4px;padding-right:20px}.dshRemoteRoutePanel li:not(:last-child)::after{content:"\u2192";position:absolute;right:7px;top:21px;color:var(--dsw-alias-label-tertiary)}.dshRemoteRoutePanel li small{color:var(--dsw-alias-label-tertiary)}.dshRemoteRoutePanel li strong,.dshRemoteRoutePanel li span{overflow:hidden;text-overflow:ellipsis}.dshRemoteRoutePanel li strong{font-size:13px}.dshRemoteRoutePanel li span{color:var(--dsw-alias-label-secondary);font-size:11px}.dshRemoteRouteSection{padding-top:16px}.dshRemoteRouteSection h3{margin:0 0 10px;font-size:12px;font-weight:600;color:var(--dsw-alias-label-secondary)}.dshRemoteRouteSection dl{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 24px;margin:0}.dshRemoteRouteSection dl>div{min-width:0;display:grid;grid-template-columns:minmax(104px,auto) minmax(0,1fr);gap:10px;padding:7px 0;border-bottom:1px solid var(--dsw-alias-border-l2);font-size:12px;line-height:1.45}.dshRemoteRouteSection dt{color:var(--dsw-alias-label-tertiary)}.dshRemoteRouteSection dd{min-width:0;margin:0;text-align:right;overflow-wrap:anywhere}.dshRemoteRouteSection dd.isMono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px}.dshRemoteRoutePanel>p{margin:16px 0 0;padding-top:12px;border-top:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5}@media(max-width:620px){.dshRemoteSessionHeader{top:8px;max-width:calc(100vw - 112px)}.dshRemoteSessionHeader>svg{display:none}.dshRemoteSessionTarget{max-width:130px}.dshRemoteEncrypted{display:none}.dshRemoteRoutePanel{top:42px;right:12px;max-height:calc(100vh - 56px)}.dshRemoteRoutePanel ol{flex-direction:column;gap:18px}.dshRemoteRoutePanel li:not(:last-child)::after{content:"\u2193";top:auto;right:auto;bottom:-16px;left:3px}.dshRemoteRouteSection dl{grid-template-columns:1fr}.dshRemoteRouteSection dl>div{grid-template-columns:1fr;gap:2px}.dshRemoteRouteSection dd{text-align:left}}',
|
|
4344
|
-
".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)}}",
|
|
4345
|
-
".dshRemoteModeButton:focus-visible,.dshRemotePage button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}",
|
|
4346
|
-
".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)}",
|
|
4347
|
-
".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}",
|
|
4348
|
-
".dshRemotePageBody{padding:24px;overflow:auto;display:flex;flex-direction:column;gap:24px}.dshRemotePageBody button{font:inherit;color:inherit}",
|
|
4349
|
-
".dshRemotePageTitleRow{display:flex;align-items:center;gap:10px;min-width:0}.dshRemotePageTitleRow>strong{min-width:0;flex:0 1 auto}.dshRemoteStarLink{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:400;text-decoration:none}.dshRemoteStarLink:hover{color:var(--dsw-alias-label-primary);text-decoration:underline;text-underline-offset:3px}.dshRemoteStarLink:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:3px;border-radius:3px}",
|
|
4350
|
-
".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}",
|
|
4351
|
-
".dshRemoteSectionTitle{flex:1}.dshRemoteSectionTitle>.dshRemoteConnectedMenu{margin-left:auto}",
|
|
4352
|
-
'.dshRemoteAcpSetting{display:block!important;width:100%;padding:0}.dshRemoteAcpSetting>summary{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%;cursor:pointer;list-style:none}.dshRemoteAcpSetting>summary::-webkit-details-marker{display:none}.dshRemoteAcpSetting>summary::after{content:"\u2304";color:var(--dsw-alias-label-secondary);transition:transform .18s ease-out}.dshRemoteAcpSetting[open]>summary::after{transform:rotate(180deg)}.dshRemoteAcpSummaryText{min-width:0}.dshRemoteAcpSummaryText strong{display:block}.dshRemoteAcpSummaryText p{margin:4px 0 0;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.4}.dshRemoteAcpCheckLink{grid-column:2;grid-row:1;color:var(--dsw-alias-brand-primary);font-size:12px;text-decoration:underline;text-underline-offset:3px}.dshRemoteAcpCheckLink:hover{color:var(--dsw-alias-label-primary)}.dshRemoteAcpCheckResult{grid-column:3;grid-row:1;font-size:11px;line-height:1.4;white-space:nowrap}.dshRemoteAcpCheckResult.isPassed{color:var(--dsw-alias-state-success-primary)}.dshRemoteAcpCheckResult.isFailed{color:var(--dsw-alias-state-danger-primary)}.dshRemoteAcpList{display:flex;flex-direction:column;gap:0;margin-top:12px;padding-top:0;border-top:0}.dshRemoteAcpList>.dshRemoteAuthorizationSetting{display:grid;width:100%;grid-template-columns:minmax(0,1fr) auto auto auto auto;align-items:center;column-gap:18px;line-height:1.4}.dshRemoteAcpList>.dshRemoteAuthorizationSetting>span:first-child{min-width:0;line-height:1.4}.dshRemoteAcpList>.dshRemoteAuthorizationSetting>input{grid-column:4;grid-row:1}',
|
|
4353
|
-
".dshRemoteAcpAddLink{align-self:flex-start;margin-top:12px;color:var(--dsw-alias-brand-primary);font-size:12px;text-decoration:underline;text-underline-offset:3px}.dshRemoteAcpAddForm{display:grid;grid-template-columns:minmax(100px,.8fr) minmax(140px,1fr) minmax(100px,1fr) auto;gap:8px;margin-top:12px}.dshRemoteAcpAddForm input{min-width:0;height:34px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-2);color:inherit;padding:0 10px}.dshRemoteAcpAddForm button{border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:transparent;color:var(--dsw-alias-label-primary);padding:0 12px;cursor:pointer;font:inherit;font-size:12px}.dshRemoteAcpAddForm button:hover{background:var(--dsw-alias-interactive-bg-hover)}.dshRemoteAcpRemoveLink{grid-column:3;grid-row:1;color:var(--dsw-alias-label-secondary);font-size:12px;text-decoration:underline;text-underline-offset:3px}.dshRemoteAcpRemoveLink:hover{color:var(--dsw-alias-state-danger-primary)}",
|
|
4354
|
-
".dshRemoteAcpCheckResult.isPassed,.dshRemoteAcpCheckResult.isFailed{color:var(--dsw-alias-label-secondary)}",
|
|
4355
|
-
".dshRemoteAcpList>.dshRemoteAuthorizationSetting{grid-template-columns:minmax(0,1fr) 190px 40px 56px;column-gap:18px}.dshRemoteAcpCheckCell{grid-column:2;display:flex;align-items:center;gap:10px;min-width:0}.dshRemoteAcpCheckLink,.dshRemoteAcpRemoveLink{justify-self:start}.dshRemoteAcpCheckResult{position:static}",
|
|
4356
|
-
".dshRemoteAcpCheckLink.isPassed{color:var(--dsw-alias-state-success-primary)}.dshRemoteAcpCheckLink.isFailed{color:var(--dsw-alias-state-danger-primary)}.dshRemoteAcpCheckLink.isChecking{color:var(--dsw-alias-label-secondary)}",
|
|
4357
|
-
".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}",
|
|
4358
|
-
'.dshRemoteHostList{display:flex;flex-direction:column;border-top:1px solid var(--dsw-alias-border-l2);max-height:296px;overflow-y:auto;overscroll-behavior:contain;scrollbar-gutter:stable}.dshRemoteHostList.isCollapsed{max-height:none;overflow-y:visible}.dshRemoteHostList>button{min-height:58px;flex:0 0 auto;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[aria-current="true"]{background:var(--dsw-alias-interactive-bg-hover)}.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}',
|
|
4359
|
-
'.dshRemoteConnectedMenu{position:relative;flex:0 0 auto;margin-right:4px}.dshRemoteConnectedCount{appearance:none;display:inline-flex;align-items:center;justify-content:center;height:22px;border:0;border-radius:999px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);box-shadow:0 1px 2px rgba(0,0,0,.18),0 0 0 1px rgba(255,255,255,.04) inset;padding:0 10px;font:inherit;font-size:11px;font-weight:500;line-height:17px;white-space:nowrap;cursor:default}.dshRemoteConnectedCount.isOnline{color:var(--dsw-alias-state-success-primary)}.dshRemoteConnectedCount.isInteractive{cursor:pointer}.dshRemoteConnectedCount.isInteractive:hover{filter:brightness(1.08)}.dshRemoteConnectedCount:disabled{opacity:1;cursor:default}.dshRemoteConnectedCount:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.dshRemoteConnectedPanel{position:absolute;top:calc(100% + 8px);right:0;z-index:4;width:min(320px,calc(100vw - 48px));max-height:min(280px,40vh);overflow:auto;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-bg-layer-2);box-shadow:0 10px 28px rgba(0,0,0,.28);padding:10px 12px}.dshRemoteConnectedPanelTitle{display:block;margin:0 0 6px;color:var(--dsw-alias-label-primary);font-size:12px;font-weight:600}.dshRemoteClientList{display:flex;flex-direction:column}.dshRemoteClientRow{min-height:44px;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 0;border-bottom:1px solid var(--dsw-alias-border-l2)}.dshRemoteClientRow:last-child{border-bottom:0}.dshRemoteClientRow>span{min-width:0;display:flex;flex-direction:column;gap:2px}.dshRemoteClientRow strong{font-size:13px;font-weight:500}.dshRemoteClientRow small{color:var(--dsw-alias-label-secondary);font-size:11px}.dshRemoteClientOnline{display:inline-flex;align-items:center;gap:6px;color:var(--dsw-alias-state-success-primary)!important}.dshRemoteClientOnline::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor}',
|
|
4360
|
-
".dshRemoteConnectedCount{height:auto;border-radius:0;background:transparent;box-shadow:none;padding:0 4px;text-decoration:underline;text-decoration-color:color-mix(in srgb,currentColor 45%,transparent);text-underline-offset:3px}.dshRemoteConnectedCount.isInteractive:hover{filter:none;text-decoration-color:currentColor}.dshRemoteConnectedCount:focus-visible{outline-offset:3px;border-radius:3px}",
|
|
4361
|
-
'.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}}',
|
|
4362
|
-
'.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}',
|
|
4363
|
-
".dshRemoteWorkspaceLists{overflow:visible}",
|
|
4364
|
-
".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}",
|
|
4365
|
-
".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}",
|
|
4366
|
-
".dshRemotePreviewAction,.dshRemotePreviewForm{display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap}.dshRemotePreviewForm input{width:90px;color:inherit;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);padding:6px}.dshRemotePreviewForm [role=alert]{max-width:360px;white-space:normal}.dshRemoteDevelopmentSettings{width:100%;margin:16px 0}.dshRemoteDevelopmentSettings .dshRemotePathField{display:flex;flex-direction:column;gap:6px;margin:8px 0}.dshRemoteDevelopmentSettings .dshRemotePathField>label{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:1.5}.dshRemoteDevelopmentSettings .dshRemotePortsRow{display:flex;gap:8px;align-items:stretch;width:100%}.dshRemoteDevelopmentSettings .dshRemotePortsRow>input{box-sizing:border-box;width:100%;flex:1;min-width:0;height:34px;border:.5px solid var(--dsw-alias-border-l4);border-radius:8px;background:var(--dsw-alias-bg-layer-3);color:inherit;padding:0 12px;font:inherit;font-size:13px;line-height:1.5}.dshRemoteDevelopmentSettings button{min-height:34px;color:inherit;background:var(--dsw-alias-bg-layer-1);border:.5px solid var(--dsw-alias-border-l2);border-radius:8px;padding:5px 14px;white-space:nowrap;font-size:13px;line-height:1.5}.dshRemoteAcpAddForm>label{display:flex;min-width:0;flex-direction:column;gap:5px;color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:1.5}.dshRemoteAcpAddForm>label>input{box-sizing:border-box;width:100%;height:34px;border:.5px solid var(--dsw-alias-border-l4);border-radius:8px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);padding:0 12px;font:inherit;font-size:13px;line-height:1.5}",
|
|
4367
|
-
".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)}",
|
|
4368
|
-
".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)}",
|
|
4369
|
-
".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}",
|
|
4370
|
-
".dshRemoteEnable{box-sizing:border-box;width:min(440px,100%);max-width:100%;min-height:388px;margin:0 auto;display:flex;flex-direction:column;align-items:stretch;gap:10px}.dshRemoteEnable p{margin:0;color:var(--dsw-alias-label-secondary);line-height:1.5}",
|
|
4371
|
-
'.dshRemoteLoginTabs{width:min(440px,100%);display:flex;border-bottom:1px solid var(--dsw-alias-border-l2)}.dshRemoteLoginTabs>button{position:relative;min-height:38px;border:0;background:transparent;color:var(--dsw-alias-label-secondary);padding:6px 14px;font:inherit;font-size:13px;cursor:pointer}.dshRemoteLoginTabs>button:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.dshRemoteLoginTabs>button.isActive{color:var(--dsw-alias-label-primary);font-weight:600}.dshRemoteLoginTabs>button.isActive::after{content:"";position:absolute;right:12px;bottom:-1px;left:12px;height:2px;border-radius:2px 2px 0 0;background:var(--dsw-alias-brand-primary)}.dshRemoteLoginTabs>button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px;border-radius:6px}',
|
|
4372
|
-
".dshRemoteClientLogin{width:min(440px,100%);display:flex;flex-direction:column;gap:8px}.dshRemoteClientLogin 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}.dshRemoteClientLogin button{align-self:flex-start;min-height:40px;border:0;border-radius:8px;background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-1);padding:8px 16px;cursor:pointer}",
|
|
4373
|
-
".dshRemoteQrLogin{width:min(440px,100%);display:flex;flex-direction:column;align-items:center;gap:8px;padding:6px 0 2px;text-align:center}.dshRemoteQrLogin img,.dshRemoteQrPlaceholder{box-sizing:border-box;width:200px;height:200px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:#fff;padding:8px}.dshRemoteQrOpen{display:flex;flex-direction:column;align-items:center;gap:5px;color:var(--dsw-alias-label-secondary);font-size:12px;text-decoration:none}.dshRemoteQrOpen:hover{color:var(--dsw-alias-label-primary);text-decoration:underline}.dshRemoteQrOpen:hover img{border-color:var(--dsw-alias-label-dimmed)}.dshRemoteQrOpen:focus-visible{border-radius:12px;outline:2px solid var(--dsw-alias-brand-primary);outline-offset:3px}.dshRemoteQrPlaceholder{display:flex;align-items:center;justify-content:center;color:var(--dsw-alias-label-secondary)}.dshRemoteQrLogin>strong{font-size:14px}.dshRemoteQrLogin>p{max-width:48ch;margin:0;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5}.dshRemoteQrLogin>.dshRemoteServiceAddress{margin-top:2px;color:var(--dsw-alias-label-tertiary)}.dshRemoteServiceAddress>a{color:var(--dsw-alias-label-secondary);text-decoration:none}.dshRemoteServiceAddress>a:hover{color:var(--dsw-alias-label-primary);text-decoration:underline}.dshRemoteQrLogin>button,.dshRemoteClientLogin>.dshRemoteLoginSwitch{min-height:32px;border:0;background:transparent;color:var(--dsw-alias-label-secondary);padding:4px 8px;font:inherit;font-size:12px;cursor:pointer}.dshRemoteQrLogin>button:hover,.dshRemoteClientLogin>.dshRemoteLoginSwitch:hover{color:var(--dsw-alias-label-primary);text-decoration:underline}.dshRemoteClientLogin>.dshRemoteLoginSwitch{align-self:flex-start;background:transparent;color:var(--dsw-alias-label-secondary);padding-left:0}",
|
|
4374
|
-
".dshRemoteLoginHeading{box-sizing:border-box;width:100%;display:flex;align-items:baseline;gap:10px;overflow:hidden;white-space:nowrap}.dshRemoteLoginTitle{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dshRemoteLoginHeading>span{flex:0 0 auto;color:var(--dsw-alias-label-secondary);font-size:13px;font-weight:400}.dshRemoteLoginTabs{box-sizing:border-box;width:100%;flex-wrap:wrap}.dshRemoteLoginTabs>button{min-width:120px;flex:1 0 auto;display:flex;align-items:center;justify-content:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:center}.dshRemoteLoginTabs>button.isActive::after{right:0;left:0;border-radius:0}.dshRemoteClientLogin,.dshRemoteQrLogin{box-sizing:border-box;width:100%;height:300px;min-height:300px}.dshRemoteClientLogin{align-items:stretch;padding-top:16px}.dshRemoteClientLogin>button{align-self:stretch;width:100%}.dshRemoteQrLogin{padding-top:12px}",
|
|
4375
|
-
'.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}}',
|
|
4376
|
-
".dshRemoteAccountFooter{display:flex;align-items:center;justify-content:space-between;gap:12px;border-top:1px solid var(--dsw-alias-border-l2);padding-top:14px;color:var(--dsw-alias-label-secondary);font-size:12px}.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}",
|
|
4377
|
-
".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)}",
|
|
4378
|
-
"@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}}",
|
|
4379
|
-
".dshRemoteBackdrop{position:fixed;inset:0;z-index:1000;background:var(--dsw-alias-bg-mask-3);display:grid;place-items:center;padding:20px}",
|
|
4380
|
-
".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)}",
|
|
4381
|
-
".dshRemoteDialog button,.dshRemoteDialog input{font:inherit;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:9px 10px;background:transparent;color:inherit}",
|
|
4382
|
-
".dshRemoteDialog button:not(:disabled){cursor:pointer}.dshRemoteDialog button:disabled{opacity:.5}",
|
|
4383
|
-
".dshRemoteHeader{display:flex;align-items:center;justify-content:space-between}.dshRemoteHeader button{border:0;font-size:22px;padding:0 6px}",
|
|
4384
|
-
".dshRemoteDevices{display:grid;gap:8px}.dshRemoteDevices p{margin:4px 0;color:var(--dsw-alias-label-secondary)}",
|
|
4385
|
-
".dshRemoteError{margin:0;color:var(--dsw-alias-state-error-primary)}",
|
|
4386
|
-
".dshRemoteHostAccount{display:grid;gap:8px;border-top:1px solid var(--dsw-alias-border-l3);padding-top:12px}.dshRemoteHostAccount p{margin:0;color:var(--dsw-alias-label-secondary);font-size:13px}",
|
|
4387
|
-
".dshRemoteLogin{display:grid;grid-template-columns:1fr 1fr;gap:8px}.dshRemoteLogin button{grid-column:1/-1}",
|
|
4388
|
-
// The plugin manager already supplies DSH's detail page chrome and
|
|
4389
|
-
// spacing for `view: page`. Keep the legacy card only for older hosts;
|
|
4390
|
-
// current DSH must not get a second, old-style card inside that page.
|
|
4391
|
-
".dshRemotePluginCard{list-style:none;border:.5px solid var(--dsw-alias-border-l4);background:var(--dsw-alias-bg-layer-3);border-radius:var(--dsw-radius-xl,16px);transition:border-color .16s,background .16s}",
|
|
4392
|
-
".dshRemotePluginModern{box-sizing:border-box;width:100%;max-width:none;box-shadow:none;border:0;background:transparent;border-radius:0}.dshRemotePluginModern>.dshRemotePluginCardHeader{display:none}.dshRemotePluginModern>.dshRemotePluginCardBody{border-top:0;margin:0;padding:0}",
|
|
4393
|
-
".dshRemotePluginCard:hover{border-color:var(--dsw-alias-label-dimmed)}.dshRemotePluginCard.isOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}",
|
|
4394
|
-
".dshRemotePluginCard.dshRemotePluginModern:hover,.dshRemotePluginCard.dshRemotePluginModern.isOpen{border-color:transparent;background:transparent}",
|
|
4395
|
-
".dshRemotePluginCardHeader{display:flex;align-items:center}.dshRemotePluginCardToggle{appearance:none;width:100%;min-width:0;font:inherit;color:inherit;text-align:left;cursor:pointer;background:transparent;border:0;border-radius:12px;display:flex;align-items:center;gap:12px;padding:14px 16px}.dshRemotePluginCardToggle:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}",
|
|
4396
|
-
".dshRemotePluginCardHeading{display:flex;flex-direction:column;gap:4px;min-width:0;flex:1}.dshRemotePluginCardHeading>strong{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.dshRemotePluginCardHeading>span{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.dshRemotePluginCardStatus{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.dshRemotePluginCardStatus.isOnline{color:var(--dsw-alias-state-success-primary)}.dshRemotePluginCardStatus.isReconnecting{color:var(--dsw-alias-state-warn-label)}.dshRemotePluginCardStatus.isOffline{color:var(--dsw-alias-state-error-primary)}.dshRemotePluginCardChevron{color:var(--dsw-alias-label-tertiary);font-size:18px;line-height:14px;transition:transform .16s}.dshRemotePluginCard.isOpen .dshRemotePluginCardChevron{transform:rotate(180deg)}",
|
|
4397
|
-
".dshRemotePluginCardBody{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}.dshRemoteSettings{display:flex;flex-direction:column;max-width:none}.dshRemoteSettingsTop{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;padding:0 0 12px}.dshRemoteSettingsState{margin:0;color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}",
|
|
4398
|
-
".dshRemotePluginModern .dshRemoteField input{border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md,8px);height:40px}.dshRemotePluginModern .dshRemoteSettingsFooter button{border-radius:var(--dsw-radius-md,8px);min-height:32px}",
|
|
4399
|
-
".dshRemoteHostIdentity{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;padding:12px 0;border-top:1px solid var(--dsw-alias-border-l2);border-bottom:1px solid var(--dsw-alias-border-l2)}.dshRemoteHostIdentity>div{min-width:0;display:flex;flex-direction:column;gap:3px}.dshRemoteHostIdentity span{color:var(--dsw-alias-label-tertiary);font-size:12px}.dshRemoteHostIdentity strong,.dshRemoteHostIdentity code{min-width:0;overflow-wrap:anywhere;color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500}.dshRemoteHostIdentity code{font-family:var(--dsw-font-mono,ui-monospace,SFMono-Regular,Menlo,monospace);font-weight:400}",
|
|
4400
|
-
".dshRemoteField{display:flex;flex-direction:column;gap:6px;padding:12px 0}.dshRemoteField+.dshRemoteField{border-top:1px solid var(--dsw-alias-border-l2)}.dshRemoteField label{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;line-height:1.5}.dshRemoteField input{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.dshRemoteField input:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.dshRemoteField input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.dshRemoteField p{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}",
|
|
4401
|
-
'.dshRemoteAuthorizationSetting{border-top:1px solid var(--dsw-alias-border-l2);display:flex;align-items:center;justify-content:space-between;gap:20px;padding:12px 0}.dshRemoteAuthorizationSetting>div{min-width:0}.dshRemoteAuthorizationSetting strong{font-size:13px;font-weight:500}.dshRemoteAuthorizationSetting p{margin:3px 0 0;color:var(--dsw-alias-label-tertiary);font-size:12px}.dshRemoteAuthorizationSetting>input{appearance:none;position:relative;width:38px;height:22px;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}.dshRemoteAuthorizationSetting>input::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--dsw-alias-label-secondary);transition:transform .16s ease-out,background .16s ease-out}.dshRemoteAuthorizationSetting>input:checked{border-color:var(--dsw-alias-state-success-primary);background:var(--dsw-alias-state-success-primary);box-shadow:none}.dshRemoteAuthorizationSetting>input:checked::after{transform:translateX(16px);background:var(--dsw-alias-bg-layer-1)}.dshRemoteAuthorizationSetting>input:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.dshRemoteAuthorizationSetting>input:disabled{opacity:.5;cursor:default}@media(prefers-reduced-motion:reduce){.dshRemoteAuthorizationSetting>input,.dshRemoteAuthorizationSetting>input::after{transition:none}}',
|
|
4402
|
-
".dshRemoteAssociation{min-width:0;flex:1;display:flex;flex-direction:column;gap:4px}.dshRemoteAssociation>span{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}.dshRemoteAssociation strong{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:1.5}.dshRemoteAssociation p{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}",
|
|
4403
|
-
".dshRemoteConnection{border-top:1px solid var(--dsw-alias-border-l2);display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 0}.dshRemoteConnectionSummary{min-width:0;display:flex;flex-direction:column;gap:4px}.dshRemoteConnectionSummary>span{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}.dshRemoteConnectionSummary strong{display:flex;align-items:center;gap:7px;color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:1.5}.dshRemoteConnectionSummary p,.dshRemoteConnectionIssue{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}.dshRemoteConnectionDot{width:8px;height:8px;flex:0 0 auto;border-radius:999px;background:var(--dsw-alias-label-tertiary)}.dshRemoteConnectionDot.isOnline{background:var(--dsw-alias-state-success-primary)}.dshRemoteConnectionDot.isReconnecting{background:var(--dsw-alias-state-warn-primary)}.dshRemoteConnectionDot.isOffline{background:var(--dsw-alias-state-error-primary)}.dshRemoteConnectionIssue{color:var(--dsw-alias-state-error-primary);padding:0 0 12px}.dshRemoteReconnect{appearance:none;flex:0 0 auto;font:inherit;cursor:pointer;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:transparent;color:var(--dsw-alias-label-secondary);min-height:34px;padding:5px 14px;font-size:13px;line-height:1.5}.dshRemoteReconnect:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed);background:var(--dsw-alias-interactive-bg-hover)}.dshRemoteReconnect:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.dshRemoteReconnect:disabled{opacity:.4;cursor:default}",
|
|
4404
|
-
".dshRemoteSettingsFooter{border-top:1px solid var(--dsw-alias-border-l2);display:flex;justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px}.dshRemoteSettingsFooter .dshRemoteError,.dshRemoteNotice{min-width:0;flex:1;margin:0;font-size:12px;line-height:1.5}.dshRemoteNotice{color:var(--dsw-alias-label-tertiary)}.dshRemoteDiscard,.dshRemoteSave{appearance:none;font:inherit;cursor:pointer;border:1px solid transparent;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}.dshRemoteDiscard{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:transparent}.dshRemoteDiscard:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed)}.dshRemoteSave{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}.dshRemoteDiscard:disabled,.dshRemoteSave:disabled{opacity:.4;cursor:default}.dshRemoteDiscard:focus-visible,.dshRemoteSave:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}",
|
|
4405
|
-
"@media(max-width:620px){.dshRemotePluginCardStatus{display:none}.dshRemoteSettingsTop{gap:10px}.dshRemoteConnection{align-items:flex-start}.dshRemoteReconnect{min-height:40px}.dshRemotePortsRow{flex-direction:column}.dshRemoteAcpAddForm{grid-template-columns:1fr}.dshRemoteAcpAddForm button{min-height:40px}}"
|
|
4406
|
-
].join(""), document.head.append(style), () => style.remove();
|
|
4407
|
-
}
|
|
4408
4628
|
function apply(ctx) {
|
|
4409
4629
|
if (window.__DS_HARNESS_REMOTE_CLIENT_ACTIVE__) return;
|
|
4410
4630
|
window.__DS_HARNESS_REMOTE_CLIENT_ACTIVE__ = !0, readyPluginSessions(ctx.sessions), ctx.effect(() => () => {
|
|
@@ -4438,7 +4658,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
4438
4658
|
if (disposed || opening || selection === void 0) return;
|
|
4439
4659
|
let pending = selection, workspaceSnapshot = ctx.workspaces.list.getSnapshot();
|
|
4440
4660
|
if (!workspacesReady(workspaceSnapshot) || !workspaceSnapshot.items.some((workspace) => workspace.workspaceId === pending.workspaceId)) return;
|
|
4441
|
-
let sessionSnapshot = ctx.sessions.list.getSnapshot(), isVirtualBackend = pending.backend === "codex" || pending.backend === "cursor" || pending.backend === "antigravity";
|
|
4661
|
+
let sessionSnapshot = ctx.sessions.list.getSnapshot(), isVirtualBackend = pending.backend === "codex" || pending.backend === "cursor" || pending.backend === "antigravity" || pending.backend === "pi" || pending.backend === "opencode";
|
|
4442
4662
|
if (isVirtualBackend && pending.sessionId !== void 0 && sessionSnapshot.phase !== "ready") return;
|
|
4443
4663
|
opening = !0, unsubscribeWorkspaces?.(), unsubscribeSessions?.(), unsubscribeWorkspaces = void 0, unsubscribeSessions = void 0;
|
|
4444
4664
|
let navigation = ctx.get("uiWorkspace"), connectWorkspace = (workspaceId) => navigation !== void 0 ? navigation.connectWorkspace(workspaceId) : ctx.workspaces.connectWorkspace(workspaceId);
|
|
@@ -4480,7 +4700,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
4480
4700
|
unsubscribe(), unregister?.();
|
|
4481
4701
|
};
|
|
4482
4702
|
}, "ds-harness-remote: remote file viewer provider");
|
|
4483
|
-
}), ctx.effect(() => ctx.locale.register(localeNamespace, { zh, en }), "ds-harness-remote: dictionaries"), ctx.effect(installStyle, "ds-harness-remote: client styles"), ctx.effect(() => installTerminalAvailabilityNotice(statusFeed, t), "ds-harness-remote: terminal availability notice"), ctx.slots.inject("shell.overlay", () => ctx.slots.register({
|
|
4703
|
+
}), ctx.effect(() => ctx.locale.register(localeNamespace, { zh, en }), "ds-harness-remote: dictionaries"), ctx.effect(() => installStyle(clientModuleId), "ds-harness-remote: client styles"), ctx.effect(() => installTerminalAvailabilityNotice(statusFeed, t), "ds-harness-remote: terminal availability notice"), ctx.slots.inject("shell.overlay", () => ctx.slots.register({
|
|
4484
4704
|
name: "shell.overlay",
|
|
4485
4705
|
id: "ds-harness-remote-global-context",
|
|
4486
4706
|
order: 20,
|
|
@@ -4511,31 +4731,6 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
4511
4731
|
function isMissingControlRoute(reason) {
|
|
4512
4732
|
return reason instanceof Error && reason.message.startsWith(`transport failure for ${CONTROL_RPC_PREFIX}/`) && (reason.message.endsWith(": HTTP 404") || reason.message.endsWith(": HTTP 405"));
|
|
4513
4733
|
}
|
|
4514
|
-
function installTerminalAvailabilityNotice(feed, t) {
|
|
4515
|
-
let latest, notice, update = () => {
|
|
4516
|
-
let terminal = document.querySelector("[data-sidebar-terminal]"), unavailable = latest?.mode === "remote" && latest.remoteFeatures?.terminal !== !0;
|
|
4517
|
-
if (!terminal || !unavailable) {
|
|
4518
|
-
notice?.remove(), notice = void 0;
|
|
4519
|
-
return;
|
|
4520
|
-
}
|
|
4521
|
-
notice !== void 0 && notice.isConnected || (notice = document.createElement("div"), notice.className = "dshRemoteTerminalUnavailable", notice.setAttribute("role", "alert"), notice.textContent = t("terminalRemoteUnavailable"), terminal.prepend(notice));
|
|
4522
|
-
}, unsubscribe = feed.subscribe((status) => {
|
|
4523
|
-
latest = status, update();
|
|
4524
|
-
}), observer = new MutationObserver(update);
|
|
4525
|
-
return observer.observe(document.body, { childList: !0, subtree: !0 }), update(), () => {
|
|
4526
|
-
unsubscribe(), observer.disconnect(), notice?.remove();
|
|
4527
|
-
};
|
|
4528
|
-
}
|
|
4529
|
-
function messageOf(reason) {
|
|
4530
|
-
return reason instanceof Error ? reason.message : String(reason);
|
|
4531
|
-
}
|
|
4532
|
-
function formatPlatform(value) {
|
|
4533
|
-
let normalized = value.toLowerCase();
|
|
4534
|
-
return normalized === "darwin" || normalized === "macos" ? "macOS" : normalized === "win32" || normalized === "windows" ? "Windows" : normalized === "linux" ? "Linux" : normalized === "android" ? "Android" : value;
|
|
4535
|
-
}
|
|
4536
|
-
function connectedClientModeLabel(mode, t) {
|
|
4537
|
-
return t(mode === "LAN" ? "remoteNetworkLan" : mode === "P2P" ? "remoteNetworkP2p" : mode === "TURN" ? "remoteNetworkTurn" : mode === "Relay" ? "remoteNetworkRelay" : "connected");
|
|
4538
|
-
}
|
|
4539
4734
|
return module.exports.apply = apply, module.exports.inject = inject, module.exports;
|
|
4540
4735
|
}
|
|
4541
4736
|
});
|