@blue-soda/dsh-remote 0.5.4 → 0.5.6
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/README.md +2 -2
- package/dist/client.github.js +46 -15
- package/dist/client.js +46 -15
- package/dist/index.js +119 -29
- package/dist/index.js.map +4 -4
- package/dsh-plugin.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ Continue DeepSeek Harness sessions and experimental Codex workspaces from anothe
|
|
|
23
23
|
Add the current package version to the `web` profile, then restart Harness:
|
|
24
24
|
|
|
25
25
|
```sh
|
|
26
|
-
dsh plugin --profile web add -w @blue-soda/dsh-remote@0.5.
|
|
26
|
+
dsh plugin --profile web add -w @blue-soda/dsh-remote@0.5.6
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
### dsh-TUI Host
|
|
@@ -31,7 +31,7 @@ dsh plugin --profile web add -w @blue-soda/dsh-remote@0.5.4
|
|
|
31
31
|
Remote can also run as a Host in a terminal-only [dsh-TUI](https://github.com/ccch1mneyyy/dsh-TUI) profile:
|
|
32
32
|
|
|
33
33
|
```sh
|
|
34
|
-
dsh plugin --profile dsh-tui add -w @blue-soda/dsh-remote@0.5.
|
|
34
|
+
dsh plugin --profile dsh-tui add -w @blue-soda/dsh-remote@0.5.6
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
After starting dsh-TUI, manage Remote with `/remote`, `/remote login`, `/remote status`, and `/remote logout`.
|
package/dist/client.github.js
CHANGED
|
@@ -1410,7 +1410,12 @@
|
|
|
1410
1410
|
);
|
|
1411
1411
|
}
|
|
1412
1412
|
function RemoteWorkspaceAction(props) {
|
|
1413
|
-
let { t } = props, [open, setOpen] = React.useState(!1)
|
|
1413
|
+
let { t } = props, [open, setOpen] = React.useState(!1);
|
|
1414
|
+
React.useEffect(() => {
|
|
1415
|
+
open && props.control("settings.get").catch(() => {
|
|
1416
|
+
});
|
|
1417
|
+
}, [open]);
|
|
1418
|
+
let [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([]), [codexNotice, setCodexNotice] = React.useState(void 0), [codexAvailable, setCodexAvailable] = React.useState(!1), codexProbeAvailable = React.useRef(!1), [codexOpen, setCodexOpen] = React.useState(!1), [workspaceBackend, setWorkspaceBackend] = React.useState("harness"), [codexWorkspaceId, setCodexWorkspaceId] = React.useState(void 0), [directory, setDirectory] = React.useState(void 0), [path, setPath] = React.useState(""), [addingWorkspace, setAddingWorkspace] = React.useState(!1), [showAllWorkspaces, setShowAllWorkspaces] = React.useState(!1), [showAllCodexWorkspaces, setShowAllCodexWorkspaces] = React.useState(!1), [devicesOpen, setDevicesOpen] = React.useState(!1), workspaceListId = "dsh-remote-workspace-list", codexWorkspaceHeadingId = "dsh-remote-codex-workspace-heading", codexWorkspaceListId = "dsh-remote-codex-workspace-list", [busy, setBusy] = React.useState(!1), [needsAuthorization, setNeedsAuthorization] = React.useState(!1), authorizedOnce = React.useRef(!1), [authorizationResolved, setAuthorizationResolved] = React.useState(!1), [loginServerUrl, setLoginServerUrl] = React.useState(DEFAULT_REMOTE_SERVER_URL), [editingServerUrl, setEditingServerUrl] = React.useState(!1), [awaitingDeepSeek, setAwaitingDeepSeek] = React.useState(!1), [pendingAuthorizeUrl, setPendingAuthorizeUrl] = React.useState(void 0), [loginMethod] = React.useState(
|
|
1414
1419
|
isEnabledQrProvider(props.preferredQrProvider) ? props.preferredQrProvider : defaultQrProvider
|
|
1415
1420
|
), [qrSession, setQrSession] = 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), [confirmingSignOut, setConfirmingSignOut] = React.useState(!1), [confirmingRevoke, setConfirmingRevoke] = React.useState(!1), [error, setError] = React.useState(void 0);
|
|
1416
1421
|
React.useEffect(() => {
|
|
@@ -1476,7 +1481,7 @@
|
|
|
1476
1481
|
polling || settled || (polling = !0, props.control("client.account.qr.poll", { qrId: qrSession.qrId }).then(async (result) => {
|
|
1477
1482
|
if (!(!active || settled || run !== qrFlowRun.current))
|
|
1478
1483
|
if (result.status === "complete") {
|
|
1479
|
-
settled = !0, timer !== void 0 && window.clearInterval(timer), setBusy(!0), setError(void 0), setQrExpired(!1), setNeedsAuthorization(!1);
|
|
1484
|
+
settled = !0, timer !== void 0 && window.clearInterval(timer), setBusy(!0), setError(void 0), setQrExpired(!1), authorizedOnce.current = !0, setNeedsAuthorization(!1);
|
|
1480
1485
|
try {
|
|
1481
1486
|
let [nextDevices, nextStatus] = await Promise.all([
|
|
1482
1487
|
props.control("devices"),
|
|
@@ -1575,25 +1580,25 @@
|
|
|
1575
1580
|
try {
|
|
1576
1581
|
let nextStatus = await props.control("status");
|
|
1577
1582
|
if (setStatus(nextStatus), !nextStatus.available) {
|
|
1578
|
-
setDevices([]), setNeedsAuthorization(!1), setAuthorizationResolved(!0), setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
|
|
1583
|
+
setDevices([]), authorizedOnce.current = !0, setNeedsAuthorization(!1), setAuthorizationResolved(!0), setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
|
|
1579
1584
|
return;
|
|
1580
1585
|
}
|
|
1581
1586
|
let storedLocally;
|
|
1582
1587
|
try {
|
|
1583
1588
|
storedLocally = (await props.control("authorization.local"))?.stored === !0, setNeedsAuthorization(!storedLocally);
|
|
1584
1589
|
} catch {
|
|
1585
|
-
setNeedsAuthorization(!1);
|
|
1590
|
+
authorizedOnce.current = !0, setNeedsAuthorization(!1);
|
|
1586
1591
|
} finally {
|
|
1587
1592
|
setAuthorizationResolved(!0);
|
|
1588
1593
|
}
|
|
1589
1594
|
try {
|
|
1590
1595
|
let nextDevices = await props.control("devices");
|
|
1591
|
-
if (setDevices(nextDevices), storedLocally !== void 0 && setNeedsAuthorization(authorizationStillNeeded(storedLocally, nextDevices.length)), selectedHost !== void 0) {
|
|
1596
|
+
if (setDevices(nextDevices), !authorizedOnce.current && storedLocally !== void 0 && setNeedsAuthorization(authorizationStillNeeded(storedLocally, nextDevices.length)), selectedHost !== void 0) {
|
|
1592
1597
|
let nextSelectedHost = nextDevices.find((device) => device.deviceId === selectedHost.deviceId);
|
|
1593
1598
|
nextSelectedHost === void 0 ? (setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0)) : setSelectedHost(nextSelectedHost);
|
|
1594
1599
|
}
|
|
1595
1600
|
} catch {
|
|
1596
|
-
setDevices([]), setNeedsAuthorization(!0), setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
|
|
1601
|
+
setDevices([]), authorizedOnce.current = !1, setNeedsAuthorization(!0), setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
|
|
1597
1602
|
}
|
|
1598
1603
|
selectedHost !== void 0 && (await props.control("remote.session.recover").then((next) => setStatus(next)).catch(() => {
|
|
1599
1604
|
}), await Promise.all([loadHarnessWorkspaces(selectedHost), loadCodexWorkspaces(selectedHost)]));
|
|
@@ -1604,6 +1609,17 @@
|
|
|
1604
1609
|
}
|
|
1605
1610
|
}, show = async () => {
|
|
1606
1611
|
setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setOpen(!0), await refreshRemote();
|
|
1612
|
+
for (let attempt = 0; attempt < 10; attempt++) {
|
|
1613
|
+
let list = await props.control("devices").catch(() => {
|
|
1614
|
+
});
|
|
1615
|
+
if (list !== void 0) {
|
|
1616
|
+
setDevices(list), authorizedOnce.current = !0, setNeedsAuthorization(!1), setAuthorizationResolved(!0), await refreshRemote();
|
|
1617
|
+
return;
|
|
1618
|
+
}
|
|
1619
|
+
await new Promise((resolve) => {
|
|
1620
|
+
setTimeout(resolve, 1e3);
|
|
1621
|
+
});
|
|
1622
|
+
}
|
|
1607
1623
|
};
|
|
1608
1624
|
React.useEffect(() => {
|
|
1609
1625
|
if (!(!open || selectedHost !== void 0))
|
|
@@ -1629,7 +1645,22 @@
|
|
|
1629
1645
|
}, [open, selectedHost]);
|
|
1630
1646
|
let chooseAnotherHost = () => {
|
|
1631
1647
|
setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setCodexNotice(void 0), setCodexAvailable(!1), codexProbeAvailable.current = !1, setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setDirectory(void 0), setPath(""), setAddingWorkspace(!1), setError(void 0);
|
|
1632
|
-
},
|
|
1648
|
+
}, signingIn = busy || status?.authorizing === !0 || needsAuthorization && status?.hasDeepSeekSession === !0;
|
|
1649
|
+
React.useEffect(() => {
|
|
1650
|
+
if (!signingIn) return;
|
|
1651
|
+
let tries = 0, timer = window.setInterval(() => {
|
|
1652
|
+
tries += 1, (async () => {
|
|
1653
|
+
let next = await props.control("status").catch(() => {
|
|
1654
|
+
});
|
|
1655
|
+
next !== void 0 && setStatus(next);
|
|
1656
|
+
let list = await props.control("devices").catch(() => {
|
|
1657
|
+
});
|
|
1658
|
+
list !== void 0 && (setDevices(list), authorizedOnce.current = !0, setNeedsAuthorization(!1), setAuthorizationResolved(!0));
|
|
1659
|
+
})(), tries >= 5 && window.clearInterval(timer);
|
|
1660
|
+
}, 1e3);
|
|
1661
|
+
return () => window.clearInterval(timer);
|
|
1662
|
+
}, [signingIn]);
|
|
1663
|
+
let requestDeepSeekSignIn = async () => {
|
|
1633
1664
|
let transport = globalThis.__DSH_TRANSPORT__, callbackOrigin = transport?.streamBaseUrl !== void 0 ? new URL(transport.streamBaseUrl).origin : window.location.origin, result = await props.control("settings.configure", {
|
|
1634
1665
|
// No `role`: a device has one identity, and the control writes only the Server address plus this
|
|
1635
1666
|
// sign-in. Sending a role here was the last thing that made one look like a runtime switch.
|
|
@@ -1667,7 +1698,7 @@
|
|
|
1667
1698
|
if (state.pending) throw new Error(t("deepseekSignInTimeout"));
|
|
1668
1699
|
} else
|
|
1669
1700
|
tab?.close();
|
|
1670
|
-
setDevices(await props.control("devices")), setStatus(await props.control("status")), setNeedsAuthorization(!1), setAuthorizationResolved(!0), setNotice(void 0);
|
|
1701
|
+
setDevices(await props.control("devices")), setStatus(await props.control("status")), authorizedOnce.current = !0, setNeedsAuthorization(!1), setAuthorizationResolved(!0), setNotice(void 0);
|
|
1671
1702
|
} catch (reason) {
|
|
1672
1703
|
setError(remoteErrorMessage(reason, t));
|
|
1673
1704
|
} finally {
|
|
@@ -1692,7 +1723,7 @@
|
|
|
1692
1723
|
}, revokeRemote = async () => {
|
|
1693
1724
|
setBusy(!0), setError(void 0), setNotice(void 0);
|
|
1694
1725
|
try {
|
|
1695
|
-
await props.control("client.device.revoke"), setDevices([]), setNeedsAuthorization(!0), setStatus(await props.control("status"));
|
|
1726
|
+
await props.control("client.device.revoke"), setDevices([]), authorizedOnce.current = !1, setNeedsAuthorization(!0), setStatus(await props.control("status"));
|
|
1696
1727
|
} catch (reason) {
|
|
1697
1728
|
setError(remoteErrorMessage(reason, t));
|
|
1698
1729
|
} finally {
|
|
@@ -1701,7 +1732,7 @@
|
|
|
1701
1732
|
}, logoutRemote = async () => {
|
|
1702
1733
|
setBusy(!0), setError(void 0), setNotice(void 0);
|
|
1703
1734
|
try {
|
|
1704
|
-
await props.control("settings.logout"), setDevices([]), setNeedsAuthorization(!0), setQrSession(void 0), setQrExpired(!1), setStatus(await props.control("status"));
|
|
1735
|
+
await props.control("settings.logout"), setDevices([]), authorizedOnce.current = !1, setNeedsAuthorization(!0), setQrSession(void 0), setQrExpired(!1), setStatus(await props.control("status"));
|
|
1705
1736
|
} catch (reason) {
|
|
1706
1737
|
setError(remoteErrorMessage(reason, t));
|
|
1707
1738
|
} finally {
|
|
@@ -1909,11 +1940,11 @@
|
|
|
1909
1940
|
onClick: () => setEditingServerUrl(!0)
|
|
1910
1941
|
}, loginServerUrl)
|
|
1911
1942
|
),
|
|
1912
|
-
React.createElement(
|
|
1913
|
-
"button",
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
),
|
|
1943
|
+
React.createElement("button", {
|
|
1944
|
+
type: "button",
|
|
1945
|
+
disabled: busy || signingIn || loginServerUrl.trim() === "",
|
|
1946
|
+
onClick: () => void signInClient()
|
|
1947
|
+
}, t(signingIn ? "signingIn" : "deepseekSignIn")),
|
|
1917
1948
|
awaitingDeepSeek ? React.createElement(
|
|
1918
1949
|
"p",
|
|
1919
1950
|
{ className: "dshRemoteServiceAddress" },
|
package/dist/client.js
CHANGED
|
@@ -1410,7 +1410,12 @@
|
|
|
1410
1410
|
);
|
|
1411
1411
|
}
|
|
1412
1412
|
function RemoteWorkspaceAction(props) {
|
|
1413
|
-
let { t } = props, [open, setOpen] = React.useState(!1)
|
|
1413
|
+
let { t } = props, [open, setOpen] = React.useState(!1);
|
|
1414
|
+
React.useEffect(() => {
|
|
1415
|
+
open && props.control("settings.get").catch(() => {
|
|
1416
|
+
});
|
|
1417
|
+
}, [open]);
|
|
1418
|
+
let [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([]), [codexNotice, setCodexNotice] = React.useState(void 0), [codexAvailable, setCodexAvailable] = React.useState(!1), codexProbeAvailable = React.useRef(!1), [codexOpen, setCodexOpen] = React.useState(!1), [workspaceBackend, setWorkspaceBackend] = React.useState("harness"), [codexWorkspaceId, setCodexWorkspaceId] = React.useState(void 0), [directory, setDirectory] = React.useState(void 0), [path, setPath] = React.useState(""), [addingWorkspace, setAddingWorkspace] = React.useState(!1), [showAllWorkspaces, setShowAllWorkspaces] = React.useState(!1), [showAllCodexWorkspaces, setShowAllCodexWorkspaces] = React.useState(!1), [devicesOpen, setDevicesOpen] = React.useState(!1), workspaceListId = "dsh-remote-workspace-list", codexWorkspaceHeadingId = "dsh-remote-codex-workspace-heading", codexWorkspaceListId = "dsh-remote-codex-workspace-list", [busy, setBusy] = React.useState(!1), [needsAuthorization, setNeedsAuthorization] = React.useState(!1), authorizedOnce = React.useRef(!1), [authorizationResolved, setAuthorizationResolved] = React.useState(!1), [loginServerUrl, setLoginServerUrl] = React.useState(DEFAULT_REMOTE_SERVER_URL), [editingServerUrl, setEditingServerUrl] = React.useState(!1), [awaitingDeepSeek, setAwaitingDeepSeek] = React.useState(!1), [pendingAuthorizeUrl, setPendingAuthorizeUrl] = React.useState(void 0), [loginMethod] = React.useState(
|
|
1414
1419
|
isEnabledQrProvider(props.preferredQrProvider) ? props.preferredQrProvider : defaultQrProvider
|
|
1415
1420
|
), [qrSession, setQrSession] = 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), [confirmingSignOut, setConfirmingSignOut] = React.useState(!1), [confirmingRevoke, setConfirmingRevoke] = React.useState(!1), [error, setError] = React.useState(void 0);
|
|
1416
1421
|
React.useEffect(() => {
|
|
@@ -1476,7 +1481,7 @@
|
|
|
1476
1481
|
polling || settled || (polling = !0, props.control("client.account.qr.poll", { qrId: qrSession.qrId }).then(async (result) => {
|
|
1477
1482
|
if (!(!active || settled || run !== qrFlowRun.current))
|
|
1478
1483
|
if (result.status === "complete") {
|
|
1479
|
-
settled = !0, timer !== void 0 && window.clearInterval(timer), setBusy(!0), setError(void 0), setQrExpired(!1), setNeedsAuthorization(!1);
|
|
1484
|
+
settled = !0, timer !== void 0 && window.clearInterval(timer), setBusy(!0), setError(void 0), setQrExpired(!1), authorizedOnce.current = !0, setNeedsAuthorization(!1);
|
|
1480
1485
|
try {
|
|
1481
1486
|
let [nextDevices, nextStatus] = await Promise.all([
|
|
1482
1487
|
props.control("devices"),
|
|
@@ -1575,25 +1580,25 @@
|
|
|
1575
1580
|
try {
|
|
1576
1581
|
let nextStatus = await props.control("status");
|
|
1577
1582
|
if (setStatus(nextStatus), !nextStatus.available) {
|
|
1578
|
-
setDevices([]), setNeedsAuthorization(!1), setAuthorizationResolved(!0), setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
|
|
1583
|
+
setDevices([]), authorizedOnce.current = !0, setNeedsAuthorization(!1), setAuthorizationResolved(!0), setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
|
|
1579
1584
|
return;
|
|
1580
1585
|
}
|
|
1581
1586
|
let storedLocally;
|
|
1582
1587
|
try {
|
|
1583
1588
|
storedLocally = (await props.control("authorization.local"))?.stored === !0, setNeedsAuthorization(!storedLocally);
|
|
1584
1589
|
} catch {
|
|
1585
|
-
setNeedsAuthorization(!1);
|
|
1590
|
+
authorizedOnce.current = !0, setNeedsAuthorization(!1);
|
|
1586
1591
|
} finally {
|
|
1587
1592
|
setAuthorizationResolved(!0);
|
|
1588
1593
|
}
|
|
1589
1594
|
try {
|
|
1590
1595
|
let nextDevices = await props.control("devices");
|
|
1591
|
-
if (setDevices(nextDevices), storedLocally !== void 0 && setNeedsAuthorization(authorizationStillNeeded(storedLocally, nextDevices.length)), selectedHost !== void 0) {
|
|
1596
|
+
if (setDevices(nextDevices), !authorizedOnce.current && storedLocally !== void 0 && setNeedsAuthorization(authorizationStillNeeded(storedLocally, nextDevices.length)), selectedHost !== void 0) {
|
|
1592
1597
|
let nextSelectedHost = nextDevices.find((device) => device.deviceId === selectedHost.deviceId);
|
|
1593
1598
|
nextSelectedHost === void 0 ? (setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0)) : setSelectedHost(nextSelectedHost);
|
|
1594
1599
|
}
|
|
1595
1600
|
} catch {
|
|
1596
|
-
setDevices([]), setNeedsAuthorization(!0), setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
|
|
1601
|
+
setDevices([]), authorizedOnce.current = !1, setNeedsAuthorization(!0), setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
|
|
1597
1602
|
}
|
|
1598
1603
|
selectedHost !== void 0 && (await props.control("remote.session.recover").then((next) => setStatus(next)).catch(() => {
|
|
1599
1604
|
}), await Promise.all([loadHarnessWorkspaces(selectedHost), loadCodexWorkspaces(selectedHost)]));
|
|
@@ -1604,6 +1609,17 @@
|
|
|
1604
1609
|
}
|
|
1605
1610
|
}, show = async () => {
|
|
1606
1611
|
setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setOpen(!0), await refreshRemote();
|
|
1612
|
+
for (let attempt = 0; attempt < 10; attempt++) {
|
|
1613
|
+
let list = await props.control("devices").catch(() => {
|
|
1614
|
+
});
|
|
1615
|
+
if (list !== void 0) {
|
|
1616
|
+
setDevices(list), authorizedOnce.current = !0, setNeedsAuthorization(!1), setAuthorizationResolved(!0), await refreshRemote();
|
|
1617
|
+
return;
|
|
1618
|
+
}
|
|
1619
|
+
await new Promise((resolve) => {
|
|
1620
|
+
setTimeout(resolve, 1e3);
|
|
1621
|
+
});
|
|
1622
|
+
}
|
|
1607
1623
|
};
|
|
1608
1624
|
React.useEffect(() => {
|
|
1609
1625
|
if (!(!open || selectedHost !== void 0))
|
|
@@ -1629,7 +1645,22 @@
|
|
|
1629
1645
|
}, [open, selectedHost]);
|
|
1630
1646
|
let chooseAnotherHost = () => {
|
|
1631
1647
|
setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setCodexNotice(void 0), setCodexAvailable(!1), codexProbeAvailable.current = !1, setShowAllWorkspaces(!1), setShowAllCodexWorkspaces(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setDirectory(void 0), setPath(""), setAddingWorkspace(!1), setError(void 0);
|
|
1632
|
-
},
|
|
1648
|
+
}, signingIn = busy || status?.authorizing === !0 || needsAuthorization && status?.hasDeepSeekSession === !0;
|
|
1649
|
+
React.useEffect(() => {
|
|
1650
|
+
if (!signingIn) return;
|
|
1651
|
+
let tries = 0, timer = window.setInterval(() => {
|
|
1652
|
+
tries += 1, (async () => {
|
|
1653
|
+
let next = await props.control("status").catch(() => {
|
|
1654
|
+
});
|
|
1655
|
+
next !== void 0 && setStatus(next);
|
|
1656
|
+
let list = await props.control("devices").catch(() => {
|
|
1657
|
+
});
|
|
1658
|
+
list !== void 0 && (setDevices(list), authorizedOnce.current = !0, setNeedsAuthorization(!1), setAuthorizationResolved(!0));
|
|
1659
|
+
})(), tries >= 5 && window.clearInterval(timer);
|
|
1660
|
+
}, 1e3);
|
|
1661
|
+
return () => window.clearInterval(timer);
|
|
1662
|
+
}, [signingIn]);
|
|
1663
|
+
let requestDeepSeekSignIn = async () => {
|
|
1633
1664
|
let transport = globalThis.__DSH_TRANSPORT__, callbackOrigin = transport?.streamBaseUrl !== void 0 ? new URL(transport.streamBaseUrl).origin : window.location.origin, result = await props.control("settings.configure", {
|
|
1634
1665
|
// No `role`: a device has one identity, and the control writes only the Server address plus this
|
|
1635
1666
|
// sign-in. Sending a role here was the last thing that made one look like a runtime switch.
|
|
@@ -1667,7 +1698,7 @@
|
|
|
1667
1698
|
if (state.pending) throw new Error(t("deepseekSignInTimeout"));
|
|
1668
1699
|
} else
|
|
1669
1700
|
tab?.close();
|
|
1670
|
-
setDevices(await props.control("devices")), setStatus(await props.control("status")), setNeedsAuthorization(!1), setAuthorizationResolved(!0), setNotice(void 0);
|
|
1701
|
+
setDevices(await props.control("devices")), setStatus(await props.control("status")), authorizedOnce.current = !0, setNeedsAuthorization(!1), setAuthorizationResolved(!0), setNotice(void 0);
|
|
1671
1702
|
} catch (reason) {
|
|
1672
1703
|
setError(remoteErrorMessage(reason, t));
|
|
1673
1704
|
} finally {
|
|
@@ -1692,7 +1723,7 @@
|
|
|
1692
1723
|
}, revokeRemote = async () => {
|
|
1693
1724
|
setBusy(!0), setError(void 0), setNotice(void 0);
|
|
1694
1725
|
try {
|
|
1695
|
-
await props.control("client.device.revoke"), setDevices([]), setNeedsAuthorization(!0), setStatus(await props.control("status"));
|
|
1726
|
+
await props.control("client.device.revoke"), setDevices([]), authorizedOnce.current = !1, setNeedsAuthorization(!0), setStatus(await props.control("status"));
|
|
1696
1727
|
} catch (reason) {
|
|
1697
1728
|
setError(remoteErrorMessage(reason, t));
|
|
1698
1729
|
} finally {
|
|
@@ -1701,7 +1732,7 @@
|
|
|
1701
1732
|
}, logoutRemote = async () => {
|
|
1702
1733
|
setBusy(!0), setError(void 0), setNotice(void 0);
|
|
1703
1734
|
try {
|
|
1704
|
-
await props.control("settings.logout"), setDevices([]), setNeedsAuthorization(!0), setQrSession(void 0), setQrExpired(!1), setStatus(await props.control("status"));
|
|
1735
|
+
await props.control("settings.logout"), setDevices([]), authorizedOnce.current = !1, setNeedsAuthorization(!0), setQrSession(void 0), setQrExpired(!1), setStatus(await props.control("status"));
|
|
1705
1736
|
} catch (reason) {
|
|
1706
1737
|
setError(remoteErrorMessage(reason, t));
|
|
1707
1738
|
} finally {
|
|
@@ -1909,11 +1940,11 @@
|
|
|
1909
1940
|
onClick: () => setEditingServerUrl(!0)
|
|
1910
1941
|
}, loginServerUrl)
|
|
1911
1942
|
),
|
|
1912
|
-
React.createElement(
|
|
1913
|
-
"button",
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
),
|
|
1943
|
+
React.createElement("button", {
|
|
1944
|
+
type: "button",
|
|
1945
|
+
disabled: busy || signingIn || loginServerUrl.trim() === "",
|
|
1946
|
+
onClick: () => void signInClient()
|
|
1947
|
+
}, t(signingIn ? "signingIn" : "deepseekSignIn")),
|
|
1917
1948
|
awaitingDeepSeek ? React.createElement(
|
|
1918
1949
|
"p",
|
|
1919
1950
|
{ className: "dshRemoteServiceAddress" },
|
package/dist/index.js
CHANGED
|
@@ -13521,7 +13521,7 @@ function normalizeServerUrl(value) {
|
|
|
13521
13521
|
}
|
|
13522
13522
|
|
|
13523
13523
|
// src/version.ts
|
|
13524
|
-
var PLUGIN_VERSION = "0.5.
|
|
13524
|
+
var PLUGIN_VERSION = "0.5.6";
|
|
13525
13525
|
|
|
13526
13526
|
// src/server-api.ts
|
|
13527
13527
|
var ENABLED_QR_PROVIDERS = ["github"];
|
|
@@ -14109,7 +14109,7 @@ var HostServerConnection = class {
|
|
|
14109
14109
|
if (TERMINAL_AUTH_ERRORS.has(code)) {
|
|
14110
14110
|
this.logger.warn(code === "CONNECTION_REPLACED" ? "Another instance is using this Host identity. Standing by: retrying in five minutes, and taking over as soon as it leaves." : code === "SERVER_CREDENTIALS_BUSY" ? "Credential refresh is locked. Stop other instances; after a crash, stop all instances before removing server-credentials.json.refresh-lock and authorizing again." : "Host authorization failed. Run /remote login or authorize this Host again in Remote settings.");
|
|
14111
14111
|
}
|
|
14112
|
-
if (code === "DEVICE_REVOKED") {
|
|
14112
|
+
if (code === "DEVICE_REVOKED" || code === "AUTH_INVALID") {
|
|
14113
14113
|
try {
|
|
14114
14114
|
await this.api.clearAuthorization();
|
|
14115
14115
|
} catch (clearError) {
|
|
@@ -15512,7 +15512,7 @@ var CodexRemoteClient = class {
|
|
|
15512
15512
|
if (!isRecord(result) || !Array.isArray(result.data))
|
|
15513
15513
|
throw invalidResponse("thread list");
|
|
15514
15514
|
return {
|
|
15515
|
-
sessions: result.data.map(projectCodexThread).filter((value) => value !== void 0),
|
|
15515
|
+
sessions: uniqueCodexThreadRows(result.data).map(projectCodexThread).filter((value) => value !== void 0),
|
|
15516
15516
|
...typeof result.nextCursor === "string" ? { nextCursor: result.nextCursor } : {}
|
|
15517
15517
|
};
|
|
15518
15518
|
}
|
|
@@ -15666,6 +15666,33 @@ function projectCodexThread(value) {
|
|
|
15666
15666
|
...typeof value.isPinned === "boolean" ? { pinned: value.isPinned } : {}
|
|
15667
15667
|
};
|
|
15668
15668
|
}
|
|
15669
|
+
var THREAD_ID_KEY = /^[A-Za-z0-9][A-Za-z0-9._-]{0,255}$/u;
|
|
15670
|
+
var LEGACY_ROW_KEY = /^([A-Za-z0-9][A-Za-z0-9._-]{0,255})~[^~]{0,64}~[0-9]{1,9}$/u;
|
|
15671
|
+
function codexThreadIdFromKey(key) {
|
|
15672
|
+
if (THREAD_ID_KEY.test(key))
|
|
15673
|
+
return key;
|
|
15674
|
+
return LEGACY_ROW_KEY.exec(key)?.[1];
|
|
15675
|
+
}
|
|
15676
|
+
function rowFreshness(row) {
|
|
15677
|
+
for (const field of ["updatedAt", "createdAt"]) {
|
|
15678
|
+
const value = row[field];
|
|
15679
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
15680
|
+
return value;
|
|
15681
|
+
}
|
|
15682
|
+
return 0;
|
|
15683
|
+
}
|
|
15684
|
+
function uniqueCodexThreadRows(values) {
|
|
15685
|
+
const byThread = /* @__PURE__ */ new Map();
|
|
15686
|
+
for (const value of values) {
|
|
15687
|
+
if (!isRecord(value) || typeof value.id !== "string" || value.id.length === 0)
|
|
15688
|
+
continue;
|
|
15689
|
+
const threadId = codexThreadIdFromKey(value.id) ?? value.id;
|
|
15690
|
+
const current = byThread.get(threadId);
|
|
15691
|
+
if (current === void 0 || rowFreshness(value) > rowFreshness(current))
|
|
15692
|
+
byThread.set(threadId, value);
|
|
15693
|
+
}
|
|
15694
|
+
return [...byThread.values()];
|
|
15695
|
+
}
|
|
15669
15696
|
function deriveCodexCwdWorkspaces(values) {
|
|
15670
15697
|
const byPath = /* @__PURE__ */ new Map();
|
|
15671
15698
|
const usedIds = /* @__PURE__ */ new Set();
|
|
@@ -17540,6 +17567,17 @@ function record(value) {
|
|
|
17540
17567
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
17541
17568
|
}
|
|
17542
17569
|
|
|
17570
|
+
// src/codex/session-id.ts
|
|
17571
|
+
var SESSION_PREFIX = "codex:";
|
|
17572
|
+
function parseCodexSessionId(value) {
|
|
17573
|
+
if (typeof value !== "string" || !value.startsWith(SESSION_PREFIX)) return void 0;
|
|
17574
|
+
const threadId = codexThreadIdFromKey(value.slice(SESSION_PREFIX.length));
|
|
17575
|
+
return threadId === void 0 ? void 0 : { sessionId: value, threadId };
|
|
17576
|
+
}
|
|
17577
|
+
function resolveCodexThreadKey(key) {
|
|
17578
|
+
return codexThreadIdFromKey(key) ?? key;
|
|
17579
|
+
}
|
|
17580
|
+
|
|
17543
17581
|
// src/codex/method-policy.ts
|
|
17544
17582
|
var id2 = external_exports.string().min(1).max(256);
|
|
17545
17583
|
var cursor = external_exports.string().min(1).max(4096).nullable().optional();
|
|
@@ -19411,7 +19449,7 @@ async function loadCatalog(client, signal, pendingThreads) {
|
|
|
19411
19449
|
updatedAt: workspace.updatedAt
|
|
19412
19450
|
}));
|
|
19413
19451
|
}
|
|
19414
|
-
const projected = threads.map((thread) => {
|
|
19452
|
+
const projected = uniqueCodexThreadRows(threads).map((thread) => {
|
|
19415
19453
|
const session = projectCodexThread(thread);
|
|
19416
19454
|
return session === void 0 ? void 0 : { thread, session };
|
|
19417
19455
|
}).filter((value) => value !== void 0);
|
|
@@ -20121,10 +20159,9 @@ function sessionIdFromAddress(address) {
|
|
|
20121
20159
|
return requiredString(address.childSessionId, "childSessionId");
|
|
20122
20160
|
}
|
|
20123
20161
|
function nativeThreadId(sessionId) {
|
|
20124
|
-
|
|
20125
|
-
|
|
20126
|
-
|
|
20127
|
-
return sessionId.slice(CODEX_SESSION_PREFIX.length);
|
|
20162
|
+
const parsed = parseCodexSessionId(sessionId);
|
|
20163
|
+
if (parsed === void 0) throw new Error("The selected Session does not belong to CodeX.");
|
|
20164
|
+
return parsed.threadId;
|
|
20128
20165
|
}
|
|
20129
20166
|
function activeTurnId(value) {
|
|
20130
20167
|
if (!Array.isArray(value)) return void 0;
|
|
@@ -21920,10 +21957,16 @@ var ClientModeRuntime = class {
|
|
|
21920
21957
|
registerControl(connection, webServer) {
|
|
21921
21958
|
return registerControlRoute(connection, (endpoint, payload, signal) => this.handleControl(endpoint, payload, signal), webServer);
|
|
21922
21959
|
}
|
|
21960
|
+
/** True while the plugin is exchanging DSH's DeepSeek credential for this device's Server credentials. */
|
|
21961
|
+
authorizingWithDeepSeek = false;
|
|
21962
|
+
/** Whether DSH held a DeepSeek session at the last reconciliation. */
|
|
21963
|
+
hasDeepSeekSession = false;
|
|
21923
21964
|
status() {
|
|
21924
21965
|
const targetStatus = this.gatewaySwitch.supportsCarrier() ? this.gatewaySwitch.status() : this.proxySwitch?.status() ?? this.gatewaySwitch.status();
|
|
21925
21966
|
return {
|
|
21926
21967
|
available: this.config.serverUrl !== void 0,
|
|
21968
|
+
authorizing: this.authorizingWithDeepSeek,
|
|
21969
|
+
hasDeepSeekSession: this.hasDeepSeekSession,
|
|
21927
21970
|
identityReady: this.identity !== void 0,
|
|
21928
21971
|
deviceId: this.identity?.deviceId,
|
|
21929
21972
|
deviceName: this.identity?.name,
|
|
@@ -22086,6 +22129,11 @@ var ClientModeRuntime = class {
|
|
|
22086
22129
|
reloadCredentials() {
|
|
22087
22130
|
this.server.reloadCredentials();
|
|
22088
22131
|
}
|
|
22132
|
+
/** Whether this device holds Server credentials, i.e. the panel shows it as signed in. */
|
|
22133
|
+
async hasServerAuthorization() {
|
|
22134
|
+
if (this.server.hasStoredAuthorization === void 0) return false;
|
|
22135
|
+
return await this.server.hasStoredAuthorization().catch(() => false);
|
|
22136
|
+
}
|
|
22089
22137
|
async setHostAuthorization(enabled) {
|
|
22090
22138
|
if (this.host === void 0) throw new ClientModeError("METHOD_NOT_ALLOWED", "This plugin is not running as a Host.");
|
|
22091
22139
|
if (!enabled) {
|
|
@@ -24668,8 +24716,9 @@ var CodexPeerBridge = class {
|
|
|
24668
24716
|
method: "thread/read",
|
|
24669
24717
|
params: { threadId: params.threadId, includeTurns: false }
|
|
24670
24718
|
});
|
|
24671
|
-
|
|
24672
|
-
|
|
24719
|
+
const threadId = resolveCodexThreadKey(params.threadId);
|
|
24720
|
+
this.streams.set(params.streamId, threadId);
|
|
24721
|
+
return { opened: true, streamId: params.streamId, threadId };
|
|
24673
24722
|
}
|
|
24674
24723
|
closeStream(input2) {
|
|
24675
24724
|
const params = streamCloseSchema.parse(input2);
|
|
@@ -25014,12 +25063,19 @@ var CodexRemoteDomain = class {
|
|
|
25014
25063
|
idempotencyKey: call.params.idempotencyKey
|
|
25015
25064
|
}));
|
|
25016
25065
|
}
|
|
25066
|
+
if (isRecord12(call.params) && typeof call.params.threadId === "string") {
|
|
25067
|
+
call.params.threadId = resolveCodexThreadKey(call.params.threadId);
|
|
25068
|
+
}
|
|
25017
25069
|
if (call.method === "thread/list") {
|
|
25018
25070
|
const result = sanitizeThreadList(await this.callUpstream(call.method, call.params));
|
|
25019
|
-
|
|
25071
|
+
const authorized = filterThreadListByWorkspaceAuthority(
|
|
25020
25072
|
result,
|
|
25021
25073
|
await this.readWorkspaceAuthority(result.data)
|
|
25022
25074
|
);
|
|
25075
|
+
return {
|
|
25076
|
+
...authorized,
|
|
25077
|
+
data: uniqueCodexThreadRows(authorized.data)
|
|
25078
|
+
};
|
|
25023
25079
|
}
|
|
25024
25080
|
if (call.method === "thread/start") {
|
|
25025
25081
|
const cwd = await this.requireCodexWorkspacePath(call.params.cwd);
|
|
@@ -26228,7 +26284,6 @@ var PluginControlRuntime = class {
|
|
|
26228
26284
|
*
|
|
26229
26285
|
* `undefined` means no sign-in is in flight, which is also the state after a completed authorization.
|
|
26230
26286
|
*/
|
|
26231
|
-
deepSeekSignIn;
|
|
26232
26287
|
register(connection, webServer) {
|
|
26233
26288
|
const statusStream = new ControlStatusStream(() => this.streamStatus());
|
|
26234
26289
|
return registerControlRoute(
|
|
@@ -26337,15 +26392,13 @@ var PluginControlRuntime = class {
|
|
|
26337
26392
|
throw new ClientModeError("METHOD_NOT_ALLOWED", "DeepSeek account sign-in is unavailable in this profile.");
|
|
26338
26393
|
}
|
|
26339
26394
|
const session = await this.deepseekSession.read();
|
|
26340
|
-
|
|
26341
|
-
if (!counted) {
|
|
26395
|
+
if (session === void 0) {
|
|
26342
26396
|
const started = await this.deepseekSession.startSignIn({
|
|
26343
26397
|
callbackOrigin: typeof value.callbackOrigin === "string" ? value.callbackOrigin : "",
|
|
26344
26398
|
loginSource: value.loginSource === "desktop" ? "desktop" : "web",
|
|
26345
26399
|
locale: typeof value.locale === "string" ? value.locale : "en",
|
|
26346
26400
|
timezoneOffsetSeconds: typeof value.timezoneOffsetSeconds === "number" ? value.timezoneOffsetSeconds : 0
|
|
26347
26401
|
});
|
|
26348
|
-
this.deepSeekSignIn = true;
|
|
26349
26402
|
return {
|
|
26350
26403
|
status: "deepseek-sign-in-required",
|
|
26351
26404
|
...started.authorizeUrl === void 0 ? {} : { authorizeUrl: started.authorizeUrl }
|
|
@@ -26358,7 +26411,6 @@ var PluginControlRuntime = class {
|
|
|
26358
26411
|
this.verifiedDeepSeekToken = session.token;
|
|
26359
26412
|
this.verifiedDeepSeekAuthorization = authorization;
|
|
26360
26413
|
}
|
|
26361
|
-
this.deepSeekSignIn = void 0;
|
|
26362
26414
|
} else {
|
|
26363
26415
|
if (typeof value.email !== "string" || typeof value.password !== "string") {
|
|
26364
26416
|
throw new ClientModeError("INVALID_MESSAGE", "Email and password are required for account authorization.");
|
|
@@ -26371,7 +26423,8 @@ var PluginControlRuntime = class {
|
|
|
26371
26423
|
if (this.host !== void 0 && !hostPaused) {
|
|
26372
26424
|
try {
|
|
26373
26425
|
this.host.reconnectHost?.();
|
|
26374
|
-
} catch {
|
|
26426
|
+
} catch (error) {
|
|
26427
|
+
console.error(`[dsh-remote] reconcile failed ${JSON.stringify({ code: String(error?.code ?? "") })}`);
|
|
26375
26428
|
}
|
|
26376
26429
|
}
|
|
26377
26430
|
await this.settings.replace(editableConfig(next));
|
|
@@ -26471,14 +26524,13 @@ var PluginControlRuntime = class {
|
|
|
26471
26524
|
await this.settings.replace(editableConfig({ ...current, acp: { enabled: current.acp?.enabled ?? true, backends } }));
|
|
26472
26525
|
return this.settingsView();
|
|
26473
26526
|
}
|
|
26474
|
-
async logout() {
|
|
26527
|
+
async logout(options = {}) {
|
|
26475
26528
|
if (this.settings === void 0) {
|
|
26476
26529
|
throw new ClientModeError("SETTINGS_UNAVAILABLE", "DSH user settings are unavailable in this profile.");
|
|
26477
26530
|
}
|
|
26478
26531
|
const config = resolveConfig(this.settings.get());
|
|
26479
26532
|
this.verifiedDeepSeekToken = void 0;
|
|
26480
26533
|
this.verifiedDeepSeekAuthorization = void 0;
|
|
26481
|
-
this.deepSeekSignIn = void 0;
|
|
26482
26534
|
if (config.serverUrl !== void 0) {
|
|
26483
26535
|
await Promise.all([
|
|
26484
26536
|
this.client?.clearClientAuthorization(),
|
|
@@ -26487,11 +26539,13 @@ var PluginControlRuntime = class {
|
|
|
26487
26539
|
const directory = await ensureDeviceDirectory(this.identityDirectory, config.serverUrl);
|
|
26488
26540
|
await new ServerCredentialStore(directory).clear();
|
|
26489
26541
|
}
|
|
26542
|
+
if (this.client !== void 0) this.client.hasDeepSeekSession = false;
|
|
26490
26543
|
let deepseekSignedOut = false;
|
|
26491
26544
|
if (this.deepseekSession !== void 0) {
|
|
26492
26545
|
try {
|
|
26493
|
-
deepseekSignedOut = await this.deepseekSession.signOut();
|
|
26494
|
-
} catch {
|
|
26546
|
+
deepseekSignedOut = options.releaseDeepSeek === false ? false : await this.deepseekSession.signOut();
|
|
26547
|
+
} catch (error) {
|
|
26548
|
+
console.error(`[dsh-remote] reconcile failed ${JSON.stringify({ code: String(error?.code ?? "") })}`);
|
|
26495
26549
|
deepseekSignedOut = false;
|
|
26496
26550
|
}
|
|
26497
26551
|
}
|
|
@@ -26522,7 +26576,49 @@ var PluginControlRuntime = class {
|
|
|
26522
26576
|
}
|
|
26523
26577
|
return this.client === void 0 ? this.hostOnlyStatus() : await this.client.status();
|
|
26524
26578
|
}
|
|
26579
|
+
/** Consecutive reconciliations without a DSH session: DSH refreshes its grant, so one empty read is not a sign-out. */
|
|
26580
|
+
/** Guards against re-entry through configure(), which reads the settings view back. */
|
|
26581
|
+
reconcilingWithDeepSeek = false;
|
|
26582
|
+
/**
|
|
26583
|
+
* Keep this device's Server credentials in step with DSH's DeepSeek session - that session is the credential, and
|
|
26584
|
+
* the Server verifies it before issuing this device its own tokens.
|
|
26585
|
+
*
|
|
26586
|
+
* Three cases: DSH signed in and this device not authorized -> authorize; DSH signed out and this device authorized
|
|
26587
|
+
* -> sign out; otherwise nothing. At most once per ten seconds, from the settings poll the panel already makes.
|
|
26588
|
+
*/
|
|
26589
|
+
async reconcileWithDeepSeek() {
|
|
26590
|
+
if (this.deepseekSession === void 0 || this.reconcilingWithDeepSeek) return;
|
|
26591
|
+
this.reconcilingWithDeepSeek = true;
|
|
26592
|
+
try {
|
|
26593
|
+
const session = await this.deepseekSession.read();
|
|
26594
|
+
if (this.client !== void 0) this.client.hasDeepSeekSession = session !== void 0;
|
|
26595
|
+
const authorized = this.client === void 0 ? false : await this.client.hasServerAuthorization();
|
|
26596
|
+
console.error(`[dsh-remote] reconcile ${JSON.stringify({ hasSession: session !== void 0, authorized })}`);
|
|
26597
|
+
if (session === void 0 && authorized) {
|
|
26598
|
+
await this.logout({ releaseDeepSeek: false });
|
|
26599
|
+
return;
|
|
26600
|
+
}
|
|
26601
|
+
if (session === void 0 || authorized) return;
|
|
26602
|
+
if (this.client !== void 0) this.client.authorizingWithDeepSeek = true;
|
|
26603
|
+
void (async () => {
|
|
26604
|
+
try {
|
|
26605
|
+
await this.configure({ provider: "deepseek", serverUrl: this.config.serverUrl });
|
|
26606
|
+
} catch (error) {
|
|
26607
|
+
console.error(`[dsh-remote] reconcile failed ${JSON.stringify({ code: String(error?.code ?? "") })}`);
|
|
26608
|
+
} finally {
|
|
26609
|
+
if (this.client !== void 0) this.client.authorizingWithDeepSeek = false;
|
|
26610
|
+
}
|
|
26611
|
+
})();
|
|
26612
|
+
} finally {
|
|
26613
|
+
this.reconcilingWithDeepSeek = false;
|
|
26614
|
+
}
|
|
26615
|
+
}
|
|
26616
|
+
/**
|
|
26617
|
+
* Keeps the reconciliation alive without the panel: DSH can be signed in or out while the card is closed, and the
|
|
26618
|
+
* plugin has to follow. Only local reads - the exchange itself is throttled to one per ten seconds.
|
|
26619
|
+
*/
|
|
26525
26620
|
async settingsView() {
|
|
26621
|
+
await this.reconcileWithDeepSeek();
|
|
26526
26622
|
const config = this.settings === void 0 ? editableConfig(this.config) : editableConfig(resolveConfig(this.settings.get()));
|
|
26527
26623
|
const associations = await this.associations(config);
|
|
26528
26624
|
const association = associations.host;
|
|
@@ -26661,13 +26757,6 @@ function redact(value, key = "") {
|
|
|
26661
26757
|
return Object.fromEntries(Object.entries(value).map(([childKey, child]) => [childKey, redact(child, childKey)]));
|
|
26662
26758
|
}
|
|
26663
26759
|
|
|
26664
|
-
// src/codex/session-id.ts
|
|
26665
|
-
function parseCodexSessionId(value) {
|
|
26666
|
-
if (typeof value !== "string") return void 0;
|
|
26667
|
-
const match = /^codex:([A-Za-z0-9][A-Za-z0-9._-]{0,255})$/.exec(value);
|
|
26668
|
-
return match === null ? void 0 : { sessionId: value, threadId: match[1] };
|
|
26669
|
-
}
|
|
26670
|
-
|
|
26671
26760
|
// src/terminal-policy.ts
|
|
26672
26761
|
var TERMINAL_CALLS = /* @__PURE__ */ new Set([
|
|
26673
26762
|
"terminal/environment",
|
|
@@ -26681,6 +26770,7 @@ var TERMINAL_CALLS = /* @__PURE__ */ new Set([
|
|
|
26681
26770
|
]);
|
|
26682
26771
|
var TERMINAL_STREAMS = /* @__PURE__ */ new Set(["terminal/follow", "terminal/retain"]);
|
|
26683
26772
|
var id3 = external_exports.string().regex(/^[A-Za-z0-9_:-]{1,256}$/);
|
|
26773
|
+
var sessionKey = external_exports.string().regex(/^[A-Za-z0-9_:~-]{1,512}$/);
|
|
26684
26774
|
var TerminalPolicy = class {
|
|
26685
26775
|
constructor(enabled, deviceId, owners) {
|
|
26686
26776
|
this.enabled = enabled;
|
|
@@ -26695,7 +26785,7 @@ var TerminalPolicy = class {
|
|
|
26695
26785
|
);
|
|
26696
26786
|
const args = external_exports.object({ args: external_exports.record(external_exports.unknown()) }).strict().parse(payload).args;
|
|
26697
26787
|
const rawSessionId = args.agentId ?? args.sessionId;
|
|
26698
|
-
const sessionId =
|
|
26788
|
+
const sessionId = sessionKey.parse(rawSessionId);
|
|
26699
26789
|
const codexSession = parseCodexSessionId(sessionId);
|
|
26700
26790
|
void codexSession;
|
|
26701
26791
|
if (endpoint === "terminal/environment" || endpoint === "terminal/shells" || endpoint === "terminal/list") return {};
|