@blue-soda/dsh-remote 0.4.29 → 0.4.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client-runtime.d.ts +137 -1
- package/dist/client-runtime.d.ts.map +1 -1
- package/dist/client-runtime.js +399 -22
- package/dist/client-runtime.js.map +1 -1
- package/dist/client-secure-transport.d.ts.map +1 -1
- package/dist/client-secure-transport.js +2 -1
- package/dist/client-secure-transport.js.map +1 -1
- package/dist/client-target-store.d.ts +40 -0
- package/dist/client-target-store.d.ts.map +1 -0
- package/dist/client-target-store.js +79 -0
- package/dist/client-target-store.js.map +1 -0
- package/dist/client.github.js +63 -15
- package/dist/client.js +63 -15
- package/dist/codex/domain.d.ts +9 -0
- package/dist/codex/domain.d.ts.map +1 -1
- package/dist/codex/domain.js +48 -7
- package/dist/codex/domain.js.map +1 -1
- package/dist/codex/virtual-harness.d.ts.map +1 -1
- package/dist/codex/virtual-harness.js +35 -1
- package/dist/codex/virtual-harness.js.map +1 -1
- package/dist/harness-api-bridge.d.ts +2 -0
- package/dist/harness-api-bridge.d.ts.map +1 -1
- package/dist/harness-api-bridge.js +10 -0
- package/dist/harness-api-bridge.js.map +1 -1
- package/dist/harness-remote-bridge.d.ts +8 -0
- package/dist/harness-remote-bridge.d.ts.map +1 -1
- package/dist/harness-remote-bridge.js +12 -1
- package/dist/harness-remote-bridge.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +795 -184
- package/dist/index.js.map +4 -4
- package/dist/remote-api-proxy.d.ts.map +1 -1
- package/dist/remote-api-proxy.js +52 -1
- package/dist/remote-api-proxy.js.map +1 -1
- package/dist/remote-typert-gateway.d.ts.map +1 -1
- package/dist/remote-typert-gateway.js +5 -3
- package/dist/remote-typert-gateway.js.map +1 -1
- package/dist/rpc-binary-attachments.d.ts +33 -0
- package/dist/rpc-binary-attachments.d.ts.map +1 -0
- package/dist/rpc-binary-attachments.js +142 -0
- package/dist/rpc-binary-attachments.js.map +1 -0
- package/dist/service.d.ts +10 -0
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +17 -1
- package/dist/service.js.map +1 -1
- package/dist/tui-command.js +7 -5
- package/dist/tui-command.js.map +1 -1
- package/dist/typert-gateway-switch.d.ts.map +1 -1
- package/dist/typert-gateway-switch.js +148 -15
- package/dist/typert-gateway-switch.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dsh-plugin.json +1 -1
- package/package.json +1 -1
package/dist/client.github.js
CHANGED
|
@@ -1933,6 +1933,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
1933
1933
|
noRemoteWorkspaces: "No remote workspaces yet. Use + to add one.",
|
|
1934
1934
|
activeRemote: "{name}",
|
|
1935
1935
|
exitRemote: "Exit",
|
|
1936
|
+
stopReconnecting: "Stop reconnecting",
|
|
1936
1937
|
addRemoteWorkspace: "Add remote workspace",
|
|
1937
1938
|
addCodexWorkspace: "Add CodeX workspace",
|
|
1938
1939
|
noCodexWorkspaces: "No CodeX workspaces yet.",
|
|
@@ -2188,6 +2189,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2188
2189
|
noRemoteWorkspaces: "\u8FD9\u53F0\u4E3B\u673A\u8FD8\u6CA1\u6709\u5DE5\u4F5C\u533A\uFF0C\u70B9\u51FB + \u6DFB\u52A0\u3002",
|
|
2189
2190
|
activeRemote: "{name}",
|
|
2190
2191
|
exitRemote: "\u9000\u51FA",
|
|
2192
|
+
stopReconnecting: "\u505C\u6B62\u91CD\u8FDE",
|
|
2191
2193
|
addRemoteWorkspace: "\u6DFB\u52A0\u8FDC\u7A0B\u5DE5\u4F5C\u533A",
|
|
2192
2194
|
addCodexWorkspace: "\u6DFB\u52A0 CodeX \u5DE5\u4F5C\u533A",
|
|
2193
2195
|
noCodexWorkspaces: "\u8FD8\u6CA1\u6709 CodeX \u5DE5\u4F5C\u533A\u3002",
|
|
@@ -3017,6 +3019,14 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
3017
3019
|
}, [status?.host?.connectedClients?.length]), React.useEffect(() => {
|
|
3018
3020
|
props.control("status").then(setStatus).catch(() => {
|
|
3019
3021
|
});
|
|
3022
|
+
}, []), React.useEffect(() => {
|
|
3023
|
+
let verify = () => {
|
|
3024
|
+
document.visibilityState === "visible" && props.control("client.connection.verify").then(setStatus).catch(() => {
|
|
3025
|
+
});
|
|
3026
|
+
};
|
|
3027
|
+
return document.addEventListener("visibilitychange", verify), window.addEventListener("focus", verify), () => {
|
|
3028
|
+
document.removeEventListener("visibilitychange", verify), window.removeEventListener("focus", verify);
|
|
3029
|
+
};
|
|
3020
3030
|
}, []), React.useEffect(() => {
|
|
3021
3031
|
status?.serverUrl !== void 0 && loginServerUrl === DEFAULT_REMOTE_SERVER_URL && setLoginServerUrl(status.serverUrl);
|
|
3022
3032
|
}, [status?.serverUrl]), React.useEffect(() => {
|
|
@@ -3337,7 +3347,11 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
3337
3347
|
},
|
|
3338
3348
|
React.createElement("rect", { x: 3, y: 4, width: 18, height: 13, rx: 2 }),
|
|
3339
3349
|
React.createElement("path", { d: "M8 21h8M12 17v4" })
|
|
3340
|
-
), props.wide ? React.createElement(
|
|
3350
|
+
), props.wide ? React.createElement(
|
|
3351
|
+
"span",
|
|
3352
|
+
{ className: "dshRemoteSidebarLabel" },
|
|
3353
|
+
remoteLabel
|
|
3354
|
+
) : null),
|
|
3341
3355
|
(status?.mode === "remote" || status?.fellBackToLocal === !0) && props.wide ? React.createElement("button", {
|
|
3342
3356
|
type: "button",
|
|
3343
3357
|
className: "dshRemoteExitLink",
|
|
@@ -3883,8 +3897,8 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
3883
3897
|
event.key === "Escape" && setRouteOpen(!1);
|
|
3884
3898
|
};
|
|
3885
3899
|
return document.addEventListener("keydown", closeOnEscape), () => document.removeEventListener("keydown", closeOnEscape);
|
|
3886
|
-
}, [routeOpen]), status?.mode !== "remote") return null;
|
|
3887
|
-
let 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(
|
|
3900
|
+
}, [routeOpen]), status?.mode !== "remote" && status?.reconnecting === void 0) return null;
|
|
3901
|
+
let 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", reconnecting = status.reconnecting !== void 0, 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(
|
|
3888
3902
|
"div",
|
|
3889
3903
|
null,
|
|
3890
3904
|
React.createElement("dt", null, label),
|
|
@@ -3903,17 +3917,32 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
3903
3917
|
"aria-hidden": !0
|
|
3904
3918
|
}, React.createElement("rect", { x: 3, y: 4, width: 18, height: 13, rx: 2 }), React.createElement("path", { d: "M8 21h8M12 17v4" })),
|
|
3905
3919
|
React.createElement("span", { className: "dshRemoteModePrefix" }, t("remoteModePrefix")),
|
|
3906
|
-
React.createElement(
|
|
3920
|
+
React.createElement(
|
|
3921
|
+
"span",
|
|
3922
|
+
{ className: "dshRemoteSessionTarget" },
|
|
3923
|
+
// While reconnecting the carriers may already describe the local shell, so its name must not
|
|
3924
|
+
// stand in for the target: name the Host the reconnect is about, or its short id.
|
|
3925
|
+
status.reconnecting === void 0 ? status.target?.name ?? t("host") : status.reconnecting.targetName ?? shortDeviceId(status.reconnecting.targetDeviceId)
|
|
3926
|
+
),
|
|
3907
3927
|
React.createElement("button", {
|
|
3908
3928
|
type: "button",
|
|
3909
|
-
className: `dshRemoteNetwork${networkOnline ? " isOnline" : " isOffline"}`,
|
|
3910
|
-
title: networkLabel,
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
"aria-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3929
|
+
className: `dshRemoteNetwork${reconnecting ? " isReconnecting" : networkOnline ? " isOnline" : " isOffline"}`,
|
|
3930
|
+
title: reconnecting ? t("stopReconnecting") : networkLabel,
|
|
3931
|
+
// Cancelling has to stay clickable: a reconnecting session is offline by definition.
|
|
3932
|
+
disabled: reconnecting ? !1 : !networkOnline,
|
|
3933
|
+
"aria-haspopup": reconnecting ? void 0 : "dialog",
|
|
3934
|
+
"aria-expanded": reconnecting ? void 0 : routeOpen,
|
|
3935
|
+
"aria-label": reconnecting ? t("stopReconnecting") : void 0,
|
|
3936
|
+
onClick: () => {
|
|
3937
|
+
if (!reconnecting) {
|
|
3938
|
+
setRouteOpen((value) => !value);
|
|
3939
|
+
return;
|
|
3940
|
+
}
|
|
3941
|
+
setRouteOpen(!1), props.control("mode.set", { mode: "local" }).catch(() => {
|
|
3942
|
+
});
|
|
3943
|
+
}
|
|
3944
|
+
}, React.createElement("i", { "aria-hidden": !0 }), reconnecting ? t("reconnecting") : networkLabel),
|
|
3945
|
+
networkOnline && !reconnecting ? React.createElement("span", { className: "dshRemoteEncrypted" }, t("remoteLinkEncrypted")) : null,
|
|
3917
3946
|
routeOpen ? React.createElement("div", {
|
|
3918
3947
|
className: "dshRemoteRouteBackdrop",
|
|
3919
3948
|
role: "presentation",
|
|
@@ -4048,7 +4077,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
4048
4077
|
".dshRemoteModeButton:is(button):hover{background:var(--dsw-alias-interactive-bg-hover)}",
|
|
4049
4078
|
".dshRemoteSidebarEntry{box-sizing:border-box;position:relative;min-width:0;display:block;overflow:hidden}.dshRemoteSidebarEntry .dshRemoteModeButton{box-sizing:border-box;width:100%;min-width:0}.dshRemoteSidebarEntry.isWide{width:calc(100% + 8px);height:34px;margin:4px -4px}.dshRemoteSidebarEntry.isWide .dshRemoteModeButton{height:34px;min-height:34px;padding:6px 48px 6px 10px;border-radius:12px}.dshRemoteSidebarEntry.isRail{width:36px;height:54px}.dshRemoteSidebarEntry.isRail .dshRemoteModeButton{width:36px;height:36px;min-height:36px;justify-content:center;gap:0;margin:8px 0 10px;padding:0;border-radius:50%}.dshRemoteSidebarEntry.isActive .dshRemoteModeButton{color:var(--dsw-alias-label-secondary);background:transparent}.dshRemoteSidebarLabel{display:block;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dshRemoteExitLink{position:absolute;top:50%;right:10px;transform:translateY(-50%);white-space:nowrap;border:0;background:transparent;color:var(--dsw-alias-label-secondary);padding:0;font:inherit;font-size:12px;line-height:20px;cursor:pointer}.dshRemoteExitLink:hover{color:var(--dsw-alias-label-primary);text-decoration:underline}.dshRemoteExitLink:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px;border-radius:2px}.dshRemoteExitLink:disabled{opacity:.45;cursor:default;text-decoration:none}",
|
|
4050
4079
|
".dshRemoteComputerIcon{box-sizing:border-box;width:18px;height:18px;flex:0 0 18px;color:var(--dsw-alias-label-secondary)}",
|
|
4051
|
-
'.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;overflow:hidden}.dshRemoteSessionHeader>svg{width:15px;height:15px;flex:0 0 auto}.dshRemoteModePrefix{flex:0 0 auto}.dshRemoteSessionTarget{flex:0 1 auto;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)}.dshRemoteNetwork: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}}',
|
|
4080
|
+
'.dshRemoteNetwork.isReconnecting{color:#f0a020;border-color:rgba(240,160,32,.55);cursor:pointer}.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;overflow:hidden}.dshRemoteSessionHeader>svg{width:15px;height:15px;flex:0 0 auto}.dshRemoteModePrefix{flex:0 0 auto}.dshRemoteSessionTarget{flex:0 1 auto;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)}.dshRemoteNetwork: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}}',
|
|
4052
4081
|
".dshRemoteSessionHeader{left:auto;right:148px;transform:none;max-width:calc(100vw - 420px)}@media(max-width:760px){.dshRemoteSessionHeader{left:auto;right:88px;transform:none;max-width:calc(100vw - 104px);padding:3px 8px;border:1px solid var(--dsw-alias-border-l1);border-radius:8px;background:var(--dsw-alias-bg-layer-1)}.dshRemoteModePrefix,.dshRemoteEncrypted{display:none}.dshRemoteSessionTarget{max-width:min(30vw,150px)}}",
|
|
4053
4082
|
".dshRemoteModeButton:focus-visible,.dshRemotePage button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}",
|
|
4054
4083
|
".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)}",
|
|
@@ -4134,7 +4163,26 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
4134
4163
|
console.warn("ds-harness-remote: status event stream unavailable, polling status instead:", reason);
|
|
4135
4164
|
}
|
|
4136
4165
|
});
|
|
4137
|
-
ctx.effect(() => () => statusFeed.close(), "ds-harness-remote: status stream")
|
|
4166
|
+
ctx.effect(() => () => statusFeed.close(), "ds-harness-remote: status stream");
|
|
4167
|
+
let firstSnapshot = !0, wasRemoteView = !1, wasFallenBack = !1, sawFallback = !1, wasReconnecting = !1, lastFallbackReloadAt = 0, lastRecoveryReloadAt = 0, unsubscribeReconnectRefresh = statusFeed.subscribe(() => {
|
|
4168
|
+
let current = statusFeed.getSnapshot();
|
|
4169
|
+
if (current === void 0) return;
|
|
4170
|
+
if (firstSnapshot) {
|
|
4171
|
+
firstSnapshot = !1, wasRemoteView = current.mode === "remote", wasFallenBack = current.fellBackToLocal === !0, sawFallback = wasFallenBack, wasReconnecting = current.reconnecting !== void 0;
|
|
4172
|
+
return;
|
|
4173
|
+
}
|
|
4174
|
+
let sawRemoteViewBefore = wasRemoteView;
|
|
4175
|
+
if (current.mode === "remote" && (wasRemoteView = !0), current.fellBackToLocal === !0 && (sawFallback = !0), current.fellBackToLocal === !0 ? wasFallenBack || (wasFallenBack = !0, wasRemoteView && Date.now() - lastFallbackReloadAt > 2e4 && (lastFallbackReloadAt = Date.now(), window.location.reload())) : wasFallenBack = !1, current.reconnecting !== void 0) {
|
|
4176
|
+
wasReconnecting = !0;
|
|
4177
|
+
return;
|
|
4178
|
+
}
|
|
4179
|
+
wasReconnecting && (wasReconnecting = !1, current.connected === !0 && (ctx.sessions.refresh().catch(() => {
|
|
4180
|
+
}), (!sawRemoteViewBefore || sawFallback) && Date.now() - lastRecoveryReloadAt > 5e3 && (lastRecoveryReloadAt = Date.now(), window.location.reload())));
|
|
4181
|
+
});
|
|
4182
|
+
ctx.effect(
|
|
4183
|
+
() => () => unsubscribeReconnectRefresh(),
|
|
4184
|
+
"ds-harness-remote: refresh the Session list after a reconnect"
|
|
4185
|
+
), ctx.effect(() => {
|
|
4138
4186
|
let disposed = !1, unsubscribeWorkspaces, unsubscribeSessions, selection, opening = !1, reconcile = () => {
|
|
4139
4187
|
if (disposed || opening || selection === void 0) return;
|
|
4140
4188
|
let pending = selection, workspaceSnapshot = ctx.workspaces.list.getSnapshot();
|
|
@@ -4142,7 +4190,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
4142
4190
|
let sessionSnapshot = ctx.sessions.list.getSnapshot();
|
|
4143
4191
|
if (pending.backend === "codex" && pending.sessionId !== void 0 && sessionSnapshot.phase !== "ready") return;
|
|
4144
4192
|
opening = !0, unsubscribeWorkspaces?.(), unsubscribeSessions?.(), unsubscribeWorkspaces = void 0, unsubscribeSessions = void 0, (pending.backend === "codex" && pending.sessionId !== void 0 && sessionSnapshot.ids.includes(pending.sessionId) ? Promise.resolve(pending.sessionId) : ctx.uiWorkspace.connectWorkspace(pending.workspaceId)).then(async (sessionId) => {
|
|
4145
|
-
disposed || (ctx.sessions.open(sessionId),
|
|
4193
|
+
disposed || (ctx.sessions.open(sessionId), await control("workspace.selection.consume", pending).catch(() => {
|
|
4146
4194
|
}));
|
|
4147
4195
|
}).catch((reason) => {
|
|
4148
4196
|
disposed || console.warn("remote workspace selection failed:", reason);
|
package/dist/client.js
CHANGED
|
@@ -1933,6 +1933,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
1933
1933
|
noRemoteWorkspaces: "No remote workspaces yet. Use + to add one.",
|
|
1934
1934
|
activeRemote: "{name}",
|
|
1935
1935
|
exitRemote: "Exit",
|
|
1936
|
+
stopReconnecting: "Stop reconnecting",
|
|
1936
1937
|
addRemoteWorkspace: "Add remote workspace",
|
|
1937
1938
|
addCodexWorkspace: "Add CodeX workspace",
|
|
1938
1939
|
noCodexWorkspaces: "No CodeX workspaces yet.",
|
|
@@ -2188,6 +2189,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2188
2189
|
noRemoteWorkspaces: "\u8FD9\u53F0\u4E3B\u673A\u8FD8\u6CA1\u6709\u5DE5\u4F5C\u533A\uFF0C\u70B9\u51FB + \u6DFB\u52A0\u3002",
|
|
2189
2190
|
activeRemote: "{name}",
|
|
2190
2191
|
exitRemote: "\u9000\u51FA",
|
|
2192
|
+
stopReconnecting: "\u505C\u6B62\u91CD\u8FDE",
|
|
2191
2193
|
addRemoteWorkspace: "\u6DFB\u52A0\u8FDC\u7A0B\u5DE5\u4F5C\u533A",
|
|
2192
2194
|
addCodexWorkspace: "\u6DFB\u52A0 CodeX \u5DE5\u4F5C\u533A",
|
|
2193
2195
|
noCodexWorkspaces: "\u8FD8\u6CA1\u6709 CodeX \u5DE5\u4F5C\u533A\u3002",
|
|
@@ -3017,6 +3019,14 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
3017
3019
|
}, [status?.host?.connectedClients?.length]), React.useEffect(() => {
|
|
3018
3020
|
props.control("status").then(setStatus).catch(() => {
|
|
3019
3021
|
});
|
|
3022
|
+
}, []), React.useEffect(() => {
|
|
3023
|
+
let verify = () => {
|
|
3024
|
+
document.visibilityState === "visible" && props.control("client.connection.verify").then(setStatus).catch(() => {
|
|
3025
|
+
});
|
|
3026
|
+
};
|
|
3027
|
+
return document.addEventListener("visibilitychange", verify), window.addEventListener("focus", verify), () => {
|
|
3028
|
+
document.removeEventListener("visibilitychange", verify), window.removeEventListener("focus", verify);
|
|
3029
|
+
};
|
|
3020
3030
|
}, []), React.useEffect(() => {
|
|
3021
3031
|
status?.serverUrl !== void 0 && loginServerUrl === DEFAULT_REMOTE_SERVER_URL && setLoginServerUrl(status.serverUrl);
|
|
3022
3032
|
}, [status?.serverUrl]), React.useEffect(() => {
|
|
@@ -3337,7 +3347,11 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
3337
3347
|
},
|
|
3338
3348
|
React.createElement("rect", { x: 3, y: 4, width: 18, height: 13, rx: 2 }),
|
|
3339
3349
|
React.createElement("path", { d: "M8 21h8M12 17v4" })
|
|
3340
|
-
), props.wide ? React.createElement(
|
|
3350
|
+
), props.wide ? React.createElement(
|
|
3351
|
+
"span",
|
|
3352
|
+
{ className: "dshRemoteSidebarLabel" },
|
|
3353
|
+
remoteLabel
|
|
3354
|
+
) : null),
|
|
3341
3355
|
(status?.mode === "remote" || status?.fellBackToLocal === !0) && props.wide ? React.createElement("button", {
|
|
3342
3356
|
type: "button",
|
|
3343
3357
|
className: "dshRemoteExitLink",
|
|
@@ -3883,8 +3897,8 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
3883
3897
|
event.key === "Escape" && setRouteOpen(!1);
|
|
3884
3898
|
};
|
|
3885
3899
|
return document.addEventListener("keydown", closeOnEscape), () => document.removeEventListener("keydown", closeOnEscape);
|
|
3886
|
-
}, [routeOpen]), status?.mode !== "remote") return null;
|
|
3887
|
-
let 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(
|
|
3900
|
+
}, [routeOpen]), status?.mode !== "remote" && status?.reconnecting === void 0) return null;
|
|
3901
|
+
let 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", reconnecting = status.reconnecting !== void 0, 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(
|
|
3888
3902
|
"div",
|
|
3889
3903
|
null,
|
|
3890
3904
|
React.createElement("dt", null, label),
|
|
@@ -3903,17 +3917,32 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
3903
3917
|
"aria-hidden": !0
|
|
3904
3918
|
}, React.createElement("rect", { x: 3, y: 4, width: 18, height: 13, rx: 2 }), React.createElement("path", { d: "M8 21h8M12 17v4" })),
|
|
3905
3919
|
React.createElement("span", { className: "dshRemoteModePrefix" }, t("remoteModePrefix")),
|
|
3906
|
-
React.createElement(
|
|
3920
|
+
React.createElement(
|
|
3921
|
+
"span",
|
|
3922
|
+
{ className: "dshRemoteSessionTarget" },
|
|
3923
|
+
// While reconnecting the carriers may already describe the local shell, so its name must not
|
|
3924
|
+
// stand in for the target: name the Host the reconnect is about, or its short id.
|
|
3925
|
+
status.reconnecting === void 0 ? status.target?.name ?? t("host") : status.reconnecting.targetName ?? shortDeviceId(status.reconnecting.targetDeviceId)
|
|
3926
|
+
),
|
|
3907
3927
|
React.createElement("button", {
|
|
3908
3928
|
type: "button",
|
|
3909
|
-
className: `dshRemoteNetwork${networkOnline ? " isOnline" : " isOffline"}`,
|
|
3910
|
-
title: networkLabel,
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
"aria-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3929
|
+
className: `dshRemoteNetwork${reconnecting ? " isReconnecting" : networkOnline ? " isOnline" : " isOffline"}`,
|
|
3930
|
+
title: reconnecting ? t("stopReconnecting") : networkLabel,
|
|
3931
|
+
// Cancelling has to stay clickable: a reconnecting session is offline by definition.
|
|
3932
|
+
disabled: reconnecting ? !1 : !networkOnline,
|
|
3933
|
+
"aria-haspopup": reconnecting ? void 0 : "dialog",
|
|
3934
|
+
"aria-expanded": reconnecting ? void 0 : routeOpen,
|
|
3935
|
+
"aria-label": reconnecting ? t("stopReconnecting") : void 0,
|
|
3936
|
+
onClick: () => {
|
|
3937
|
+
if (!reconnecting) {
|
|
3938
|
+
setRouteOpen((value) => !value);
|
|
3939
|
+
return;
|
|
3940
|
+
}
|
|
3941
|
+
setRouteOpen(!1), props.control("mode.set", { mode: "local" }).catch(() => {
|
|
3942
|
+
});
|
|
3943
|
+
}
|
|
3944
|
+
}, React.createElement("i", { "aria-hidden": !0 }), reconnecting ? t("reconnecting") : networkLabel),
|
|
3945
|
+
networkOnline && !reconnecting ? React.createElement("span", { className: "dshRemoteEncrypted" }, t("remoteLinkEncrypted")) : null,
|
|
3917
3946
|
routeOpen ? React.createElement("div", {
|
|
3918
3947
|
className: "dshRemoteRouteBackdrop",
|
|
3919
3948
|
role: "presentation",
|
|
@@ -4048,7 +4077,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
4048
4077
|
".dshRemoteModeButton:is(button):hover{background:var(--dsw-alias-interactive-bg-hover)}",
|
|
4049
4078
|
".dshRemoteSidebarEntry{box-sizing:border-box;position:relative;min-width:0;display:block;overflow:hidden}.dshRemoteSidebarEntry .dshRemoteModeButton{box-sizing:border-box;width:100%;min-width:0}.dshRemoteSidebarEntry.isWide{width:calc(100% + 8px);height:34px;margin:4px -4px}.dshRemoteSidebarEntry.isWide .dshRemoteModeButton{height:34px;min-height:34px;padding:6px 48px 6px 10px;border-radius:12px}.dshRemoteSidebarEntry.isRail{width:36px;height:54px}.dshRemoteSidebarEntry.isRail .dshRemoteModeButton{width:36px;height:36px;min-height:36px;justify-content:center;gap:0;margin:8px 0 10px;padding:0;border-radius:50%}.dshRemoteSidebarEntry.isActive .dshRemoteModeButton{color:var(--dsw-alias-label-secondary);background:transparent}.dshRemoteSidebarLabel{display:block;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dshRemoteExitLink{position:absolute;top:50%;right:10px;transform:translateY(-50%);white-space:nowrap;border:0;background:transparent;color:var(--dsw-alias-label-secondary);padding:0;font:inherit;font-size:12px;line-height:20px;cursor:pointer}.dshRemoteExitLink:hover{color:var(--dsw-alias-label-primary);text-decoration:underline}.dshRemoteExitLink:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px;border-radius:2px}.dshRemoteExitLink:disabled{opacity:.45;cursor:default;text-decoration:none}",
|
|
4050
4079
|
".dshRemoteComputerIcon{box-sizing:border-box;width:18px;height:18px;flex:0 0 18px;color:var(--dsw-alias-label-secondary)}",
|
|
4051
|
-
'.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;overflow:hidden}.dshRemoteSessionHeader>svg{width:15px;height:15px;flex:0 0 auto}.dshRemoteModePrefix{flex:0 0 auto}.dshRemoteSessionTarget{flex:0 1 auto;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)}.dshRemoteNetwork: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}}',
|
|
4080
|
+
'.dshRemoteNetwork.isReconnecting{color:#f0a020;border-color:rgba(240,160,32,.55);cursor:pointer}.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;overflow:hidden}.dshRemoteSessionHeader>svg{width:15px;height:15px;flex:0 0 auto}.dshRemoteModePrefix{flex:0 0 auto}.dshRemoteSessionTarget{flex:0 1 auto;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)}.dshRemoteNetwork: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}}',
|
|
4052
4081
|
".dshRemoteSessionHeader{left:auto;right:148px;transform:none;max-width:calc(100vw - 420px)}@media(max-width:760px){.dshRemoteSessionHeader{left:auto;right:88px;transform:none;max-width:calc(100vw - 104px);padding:3px 8px;border:1px solid var(--dsw-alias-border-l1);border-radius:8px;background:var(--dsw-alias-bg-layer-1)}.dshRemoteModePrefix,.dshRemoteEncrypted{display:none}.dshRemoteSessionTarget{max-width:min(30vw,150px)}}",
|
|
4053
4082
|
".dshRemoteModeButton:focus-visible,.dshRemotePage button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}",
|
|
4054
4083
|
".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)}",
|
|
@@ -4134,7 +4163,26 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
4134
4163
|
console.warn("ds-harness-remote: status event stream unavailable, polling status instead:", reason);
|
|
4135
4164
|
}
|
|
4136
4165
|
});
|
|
4137
|
-
ctx.effect(() => () => statusFeed.close(), "ds-harness-remote: status stream")
|
|
4166
|
+
ctx.effect(() => () => statusFeed.close(), "ds-harness-remote: status stream");
|
|
4167
|
+
let firstSnapshot = !0, wasRemoteView = !1, wasFallenBack = !1, sawFallback = !1, wasReconnecting = !1, lastFallbackReloadAt = 0, lastRecoveryReloadAt = 0, unsubscribeReconnectRefresh = statusFeed.subscribe(() => {
|
|
4168
|
+
let current = statusFeed.getSnapshot();
|
|
4169
|
+
if (current === void 0) return;
|
|
4170
|
+
if (firstSnapshot) {
|
|
4171
|
+
firstSnapshot = !1, wasRemoteView = current.mode === "remote", wasFallenBack = current.fellBackToLocal === !0, sawFallback = wasFallenBack, wasReconnecting = current.reconnecting !== void 0;
|
|
4172
|
+
return;
|
|
4173
|
+
}
|
|
4174
|
+
let sawRemoteViewBefore = wasRemoteView;
|
|
4175
|
+
if (current.mode === "remote" && (wasRemoteView = !0), current.fellBackToLocal === !0 && (sawFallback = !0), current.fellBackToLocal === !0 ? wasFallenBack || (wasFallenBack = !0, wasRemoteView && Date.now() - lastFallbackReloadAt > 2e4 && (lastFallbackReloadAt = Date.now(), window.location.reload())) : wasFallenBack = !1, current.reconnecting !== void 0) {
|
|
4176
|
+
wasReconnecting = !0;
|
|
4177
|
+
return;
|
|
4178
|
+
}
|
|
4179
|
+
wasReconnecting && (wasReconnecting = !1, current.connected === !0 && (ctx.sessions.refresh().catch(() => {
|
|
4180
|
+
}), (!sawRemoteViewBefore || sawFallback) && Date.now() - lastRecoveryReloadAt > 5e3 && (lastRecoveryReloadAt = Date.now(), window.location.reload())));
|
|
4181
|
+
});
|
|
4182
|
+
ctx.effect(
|
|
4183
|
+
() => () => unsubscribeReconnectRefresh(),
|
|
4184
|
+
"ds-harness-remote: refresh the Session list after a reconnect"
|
|
4185
|
+
), ctx.effect(() => {
|
|
4138
4186
|
let disposed = !1, unsubscribeWorkspaces, unsubscribeSessions, selection, opening = !1, reconcile = () => {
|
|
4139
4187
|
if (disposed || opening || selection === void 0) return;
|
|
4140
4188
|
let pending = selection, workspaceSnapshot = ctx.workspaces.list.getSnapshot();
|
|
@@ -4142,7 +4190,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
4142
4190
|
let sessionSnapshot = ctx.sessions.list.getSnapshot();
|
|
4143
4191
|
if (pending.backend === "codex" && pending.sessionId !== void 0 && sessionSnapshot.phase !== "ready") return;
|
|
4144
4192
|
opening = !0, unsubscribeWorkspaces?.(), unsubscribeSessions?.(), unsubscribeWorkspaces = void 0, unsubscribeSessions = void 0, (pending.backend === "codex" && pending.sessionId !== void 0 && sessionSnapshot.ids.includes(pending.sessionId) ? Promise.resolve(pending.sessionId) : ctx.uiWorkspace.connectWorkspace(pending.workspaceId)).then(async (sessionId) => {
|
|
4145
|
-
disposed || (ctx.sessions.open(sessionId),
|
|
4193
|
+
disposed || (ctx.sessions.open(sessionId), await control("workspace.selection.consume", pending).catch(() => {
|
|
4146
4194
|
}));
|
|
4147
4195
|
}).catch((reason) => {
|
|
4148
4196
|
disposed || console.warn("remote workspace selection failed:", reason);
|
package/dist/codex/domain.d.ts
CHANGED
|
@@ -49,6 +49,15 @@ export declare class CodexRemoteDomain {
|
|
|
49
49
|
}>;
|
|
50
50
|
detachPeer(connectionId: string): Promise<void>;
|
|
51
51
|
close(): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Launch the App Server within {@link CODEX_START_BUDGET_MS}.
|
|
54
|
+
*
|
|
55
|
+
* The losing side of the race keeps running until the disposal in start()'s catch stops it, so
|
|
56
|
+
* it needs its own handler: an unhandled rejection here would surface as a process-level error
|
|
57
|
+
* for what is only an optional feature being unavailable.
|
|
58
|
+
* @returns nothing once a candidate is ready.
|
|
59
|
+
*/
|
|
60
|
+
private launchWithinBudget;
|
|
52
61
|
private launchAppServer;
|
|
53
62
|
private launchAppServerCandidate;
|
|
54
63
|
private handleAppServerUnavailable;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"domain.d.ts","sourceRoot":"","sources":["../../src/codex/domain.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAE,wBAAwB,EAAyB,MAAM,sBAAsB,CAAA;AAC9G,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AACvD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAA;AACxE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAE/C,OAAO,EAIL,KAAK,kBAAkB,EACxB,MAAM,iBAAiB,CAAA;AAOxB,OAAO,EAAE,eAAe,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"domain.d.ts","sourceRoot":"","sources":["../../src/codex/domain.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAE,wBAAwB,EAAyB,MAAM,sBAAsB,CAAA;AAC9G,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AACvD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAA;AACxE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAE/C,OAAO,EAIL,KAAK,kBAAkB,EACxB,MAAM,iBAAiB,CAAA;AAOxB,OAAO,EAAE,eAAe,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAuD1E,KAAK,gBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,KAAK,kBAAkB,CAAA;AAElF;;;;GAIG;AACH,qBAAa,iBAAiB;IAkB1B,QAAQ,CAAC,MAAM,EAAE,mBAAmB;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,eAAe;IApBlC,OAAO,CAAC,SAAS,CAAC,CAAoB;IACtC,OAAO,CAAC,kBAAkB,CAAC,CAAY;IACvC,OAAO,CAAC,sBAAsB,CAAC,CAAY;IAC3C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqC;IAC3D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA4B;IAC1D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqC;IAChE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqC;IAC/D,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA2C;IAC7E,OAAO,CAAC,mBAAmB,CAAC,CAA+B;IAC3D,OAAO,CAAC,YAAY,CAAC,CAA+B;IACpD,OAAO,CAAC,cAAc,CAAI;IAC1B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,KAAK,CAA+E;IAC5F,OAAO,CAAC,eAAe,CAAC,CAAQ;gBAGrB,MAAM,EAAE,mBAAmB,EACnB,MAAM,EAAE,UAAU,EAClB,eAAe,GAAE,gBAA2F,EAC5G,eAAe,GAAE,SAAS,MAAM,EAA8B;IAG3E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAe5B,WAAW,IAAI,OAAO;IAEtB,MAAM,IAAI;QACR,OAAO,EAAE,OAAO,CAAA;QAChB,SAAS,EAAE,OAAO,CAAA;QAClB,KAAK,EAAE,UAAU,GAAG,UAAU,GAAG,OAAO,GAAG,YAAY,GAAG,aAAa,CAAA;QACvE,cAAc,EAAE,MAAM,CAAA;QACtB,KAAK,CAAC,EAAE,MAAM,CAAA;KACf;IAUD,uEAAuE;IACjE,sBAAsB,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAajG,UAAU,CAAC,OAAO,EAAE,qBAAqB,EAAE,OAAO,EAAE,iBAAiB,GAAG,eAAe,GAAG,SAAS;IAQ7F,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAwK5D,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,IAAI,CAAA;KAAE,CAAC;IAa1E,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB/C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB5B;;;;;;;OAOG;YACW,kBAAkB;YAmBlB,eAAe;YAcf,wBAAwB;YAkCxB,0BAA0B;IAexC,OAAO,CAAC,eAAe;YAkBT,mBAAmB;YAgBnB,gBAAgB;YAUhB,aAAa;IA2B3B,OAAO,CAAC,kBAAkB;YAMZ,sBAAsB;YAiCtB,iBAAiB;YAMjB,mBAAmB;YAqCnB,eAAe;YAoBf,oBAAoB;YA4BpB,eAAe;YAgCf,eAAe;IAkC7B,OAAO,CAAC,kBAAkB;YAQZ,yBAAyB;IAUvC,OAAO,CAAC,SAAS;IAmCjB,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,uBAAuB;YAOjB,eAAe;IAW7B,OAAO,CAAC,sBAAsB;IAc9B,OAAO,CAAC,gBAAgB;YAOV,YAAY;YAQZ,sBAAsB;YAgDtB,qBAAqB;YAuBrB,yBAAyB;YAyBzB,0BAA0B;YAa1B,kBAAkB;YAqClB,qBAAqB;YA4BrB,uBAAuB;CAMtC;AAED,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,GAAG,wBAAwB,CAAA;AAE3E;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,EAClB,YAAY,GAAE,MAAM,CAAC,QAA2B,EAChD,QAAQ,GAAE,MAAkB,GAC3B,MAAM,EAAE,CAiCV"}
|
package/dist/codex/domain.js
CHANGED
|
@@ -2,7 +2,7 @@ import { randomUUID } from 'node:crypto';
|
|
|
2
2
|
import { accessSync, constants, existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
3
3
|
import { readdir, realpath, stat } from 'node:fs/promises';
|
|
4
4
|
import { homedir } from 'node:os';
|
|
5
|
-
import { basename, isAbsolute, join, relative, resolve } from 'node:path';
|
|
5
|
+
import { basename, isAbsolute, join, posix, relative, resolve } from 'node:path';
|
|
6
6
|
import { deriveCodexCwdWorkspaces } from '@dsh-remote/client-core';
|
|
7
7
|
import { RpcError } from '../safe-error.js';
|
|
8
8
|
import { CodexAppServerClient, CodexAppServerError, } from './app-server.js';
|
|
@@ -12,6 +12,16 @@ import { codexPermissionPresetFromResponse } from './permissions.js';
|
|
|
12
12
|
import { paginateCodexNativeHistory, projectCodexNativeHistory } from './virtual-harness.js';
|
|
13
13
|
const APPROVAL_TTL_MS = 5 * 60_000;
|
|
14
14
|
const DEFAULT_RESTART_DELAYS_MS = [1_000, 2_000, 4_000, 8_000, 15_000];
|
|
15
|
+
/**
|
|
16
|
+
* How long the whole App Server launch may take.
|
|
17
|
+
*
|
|
18
|
+
* `launchAppServer` tries several binary candidates and each attempt can spend a full request
|
|
19
|
+
* timeout waiting for a binary that will never answer, so a missing or broken install used to
|
|
20
|
+
* cost that timeout several times over. One budget for all candidates keeps the domain's own
|
|
21
|
+
* status honest ('unavailable' in seconds, not tens of seconds) while the existing restart
|
|
22
|
+
* backoff keeps trying in the background.
|
|
23
|
+
*/
|
|
24
|
+
const CODEX_START_BUDGET_MS = 5_000;
|
|
15
25
|
const CODEX_PAGE_LIMIT = 100;
|
|
16
26
|
const MAX_CODEX_PAGES = 32;
|
|
17
27
|
const CODEX_HISTORY_PAGE_LIMIT = 25;
|
|
@@ -55,7 +65,7 @@ export class CodexRemoteDomain {
|
|
|
55
65
|
return;
|
|
56
66
|
try {
|
|
57
67
|
this.state = 'starting';
|
|
58
|
-
await this.
|
|
68
|
+
await this.launchWithinBudget();
|
|
59
69
|
}
|
|
60
70
|
catch (error) {
|
|
61
71
|
this.available = false;
|
|
@@ -306,6 +316,34 @@ export class CodexRemoteDomain {
|
|
|
306
316
|
await this.appServer?.close();
|
|
307
317
|
this.appServer = undefined;
|
|
308
318
|
}
|
|
319
|
+
/**
|
|
320
|
+
* Launch the App Server within {@link CODEX_START_BUDGET_MS}.
|
|
321
|
+
*
|
|
322
|
+
* The losing side of the race keeps running until the disposal in start()'s catch stops it, so
|
|
323
|
+
* it needs its own handler: an unhandled rejection here would surface as a process-level error
|
|
324
|
+
* for what is only an optional feature being unavailable.
|
|
325
|
+
* @returns nothing once a candidate is ready.
|
|
326
|
+
*/
|
|
327
|
+
async launchWithinBudget() {
|
|
328
|
+
let timer;
|
|
329
|
+
const attempt = this.launchAppServer();
|
|
330
|
+
attempt.catch(() => undefined);
|
|
331
|
+
try {
|
|
332
|
+
await Promise.race([
|
|
333
|
+
attempt,
|
|
334
|
+
new Promise((_resolve, reject) => {
|
|
335
|
+
timer = setTimeout(() => {
|
|
336
|
+
reject(new RpcError('CODEX_START_TIMEOUT', `Codex App Server did not start within ${CODEX_START_BUDGET_MS}ms.`));
|
|
337
|
+
}, CODEX_START_BUDGET_MS);
|
|
338
|
+
timer.unref?.();
|
|
339
|
+
}),
|
|
340
|
+
]);
|
|
341
|
+
}
|
|
342
|
+
finally {
|
|
343
|
+
if (timer !== undefined)
|
|
344
|
+
clearTimeout(timer);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
309
347
|
async launchAppServer() {
|
|
310
348
|
let lastError;
|
|
311
349
|
for (const binary of codexBinaryCandidates(this.config.binary)) {
|
|
@@ -951,17 +989,20 @@ export function codexBinaryCandidates(configured, hostPlatform = process.platfor
|
|
|
951
989
|
return [...bundledWindowsCodex(userHome), configured];
|
|
952
990
|
if (hostPlatform !== 'darwin')
|
|
953
991
|
return [configured];
|
|
992
|
+
// The platform is a parameter, not necessarily this host: joining with the host flavour would
|
|
993
|
+
// return Windows separators for a macOS home and make the darwin branch unreachable from a test
|
|
994
|
+
// or tool running elsewhere.
|
|
954
995
|
const bundledCandidates = [
|
|
955
996
|
'/Applications/ChatGPT.app',
|
|
956
|
-
join(userHome, 'Applications', 'ChatGPT.app'),
|
|
997
|
+
posix.join(userHome, 'Applications', 'ChatGPT.app'),
|
|
957
998
|
].flatMap(chatGptApp => {
|
|
958
|
-
const codexCli = join(chatGptApp, 'Contents', 'Resources', 'codex-cli');
|
|
999
|
+
const codexCli = posix.join(chatGptApp, 'Contents', 'Resources', 'codex-cli');
|
|
959
1000
|
try {
|
|
960
|
-
const manifest = JSON.parse(readFileSync(join(codexCli, 'codex-package.json'), 'utf8'));
|
|
1001
|
+
const manifest = JSON.parse(readFileSync(posix.join(codexCli, 'codex-package.json'), 'utf8'));
|
|
961
1002
|
if (!isRecord(manifest) || typeof manifest.entrypoint !== 'string' || manifest.entrypoint.length === 0) {
|
|
962
1003
|
return [];
|
|
963
1004
|
}
|
|
964
|
-
const candidate = join(codexCli, manifest.entrypoint);
|
|
1005
|
+
const candidate = posix.join(codexCli, manifest.entrypoint);
|
|
965
1006
|
if (!existsSync(candidate))
|
|
966
1007
|
return [];
|
|
967
1008
|
accessSync(candidate, constants.X_OK);
|
|
@@ -974,7 +1015,7 @@ export function codexBinaryCandidates(configured, hostPlatform = process.platfor
|
|
|
974
1015
|
return [...new Set([
|
|
975
1016
|
...bundledCandidates,
|
|
976
1017
|
'/Applications/ChatGPT.app/Contents/Resources/codex',
|
|
977
|
-
join(userHome, 'Applications', 'ChatGPT.app', 'Contents', 'Resources', 'codex'),
|
|
1018
|
+
posix.join(userHome, 'Applications', 'ChatGPT.app', 'Contents', 'Resources', 'codex'),
|
|
978
1019
|
configured,
|
|
979
1020
|
])];
|
|
980
1021
|
}
|