ds-harness-remote 0.4.1 → 0.4.3
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 +35 -11
- package/cordis.patch.yml +3 -0
- package/dist/client-runtime.d.ts +28 -0
- package/dist/client-runtime.d.ts.map +1 -1
- package/dist/client-runtime.js +327 -5
- package/dist/client-runtime.js.map +1 -1
- package/dist/client-secure-transport.d.ts.map +1 -1
- package/dist/client-secure-transport.js +9 -2
- package/dist/client-secure-transport.js.map +1 -1
- package/dist/client.github.js +167 -48
- package/dist/client.js +167 -48
- package/dist/client.js.map +1 -1
- package/dist/codex/app-server.d.ts +71 -0
- package/dist/codex/app-server.d.ts.map +1 -0
- package/dist/codex/app-server.js +268 -0
- package/dist/codex/app-server.js.map +1 -0
- package/dist/codex/domain.d.ts +82 -0
- package/dist/codex/domain.d.ts.map +1 -0
- package/dist/codex/domain.js +893 -0
- package/dist/codex/domain.js.map +1 -0
- package/dist/codex/method-policy.d.ts +297 -0
- package/dist/codex/method-policy.d.ts.map +1 -0
- package/dist/codex/method-policy.js +103 -0
- package/dist/codex/method-policy.js.map +1 -0
- package/dist/codex/peer-bridge.d.ts +57 -0
- package/dist/codex/peer-bridge.d.ts.map +1 -0
- package/dist/codex/peer-bridge.js +300 -0
- package/dist/codex/peer-bridge.js.map +1 -0
- package/dist/codex/virtual-harness.d.ts +178 -0
- package/dist/codex/virtual-harness.d.ts.map +1 -0
- package/dist/codex/virtual-harness.js +2515 -0
- package/dist/codex/virtual-harness.js.map +1 -0
- package/dist/config.d.ts +10 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +12 -0
- package/dist/config.js.map +1 -1
- package/dist/control-runtime.d.ts +1 -0
- package/dist/control-runtime.d.ts.map +1 -1
- package/dist/control-runtime.js +22 -0
- package/dist/control-runtime.js.map +1 -1
- package/dist/harness-remote-bridge.d.ts +2 -2
- package/dist/harness-remote-bridge.d.ts.map +1 -1
- package/dist/harness-remote-bridge.js +2 -2
- package/dist/harness-remote-bridge.js.map +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8550 -3884
- package/dist/index.js.map +4 -4
- package/dist/remote-typert-gateway.d.ts +1 -1
- package/dist/remote-typert-gateway.d.ts.map +1 -1
- package/dist/remote-typert-gateway.js +9 -2
- package/dist/remote-typert-gateway.js.map +1 -1
- package/dist/rpc-router.d.ts +5 -2
- package/dist/rpc-router.d.ts.map +1 -1
- package/dist/rpc-router.js +30 -1
- package/dist/rpc-router.js.map +1 -1
- package/dist/server-connection.d.ts +1 -0
- package/dist/server-connection.d.ts.map +1 -1
- package/dist/server-connection.js +69 -22
- package/dist/server-connection.js.map +1 -1
- package/dist/service.d.ts +20 -0
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +58 -2
- package/dist/service.js.map +1 -1
- package/dist/typert-gateway-contract.d.ts +2 -2
- package/dist/typert-gateway-contract.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +19 -23
- package/public.d.ts +4 -0
package/dist/client.github.js
CHANGED
|
@@ -1697,7 +1697,25 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
1697
1697
|
var CONTROL_RPC_PREFIX = "/ds-harness-remote";
|
|
1698
1698
|
|
|
1699
1699
|
// src/client.ts
|
|
1700
|
-
var clientModuleId = "ds-harness-remote",
|
|
1700
|
+
var clientModuleId = "ds-harness-remote", pendingWorkspaceSelectionKey = "dsh-remote:pending-workspace-selection";
|
|
1701
|
+
function storedWorkspaceSelection() {
|
|
1702
|
+
let raw = window.sessionStorage.getItem(pendingWorkspaceSelectionKey);
|
|
1703
|
+
if (raw !== null)
|
|
1704
|
+
try {
|
|
1705
|
+
let value = JSON.parse(raw);
|
|
1706
|
+
if (typeof value.targetDeviceId != "string" || typeof value.workspaceId != "string") throw new Error("invalid");
|
|
1707
|
+
if (value.backend !== void 0 && value.backend !== "harness" && value.backend !== "codex") throw new Error("invalid");
|
|
1708
|
+
if (value.sessionId !== void 0 && typeof value.sessionId != "string") throw new Error("invalid");
|
|
1709
|
+
return value;
|
|
1710
|
+
} catch {
|
|
1711
|
+
window.sessionStorage.removeItem(pendingWorkspaceSelectionKey);
|
|
1712
|
+
return;
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
function workspacesReady(snapshot) {
|
|
1716
|
+
return snapshot.baselinesReady === !0 || snapshot.phase === "ready";
|
|
1717
|
+
}
|
|
1718
|
+
var localeNamespace = "ds-harness-remote", en = {
|
|
1701
1719
|
pluginTitle: "DeepSeek Remote",
|
|
1702
1720
|
pluginDescription: "Connect once. Available anytime.",
|
|
1703
1721
|
expandSettings: "Show settings: {name}",
|
|
@@ -1724,6 +1742,9 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
1724
1742
|
serverUrl: "Server URL",
|
|
1725
1743
|
serverUrlHint: "HTTPS origin used for account authorization and encrypted relay.",
|
|
1726
1744
|
serverSaved: "Server address saved. Restart DSH to apply it.",
|
|
1745
|
+
codexRemote: "Codex Remote",
|
|
1746
|
+
codexRemoteHint: "Expose Codex projects through this Host. Restart DSH after changing this setting.",
|
|
1747
|
+
codexSaved: "Codex Remote setting saved. Restart DSH to apply it.",
|
|
1727
1748
|
authorizeFromRemote: "Sign in from the Remote entry in the sidebar, then return here to manage this device.",
|
|
1728
1749
|
authorizationMethod: "Authorization method",
|
|
1729
1750
|
accountPassword: "Account password",
|
|
@@ -1893,7 +1914,9 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
1893
1914
|
currentServiceAddress: "Current service address:",
|
|
1894
1915
|
accountPasswordLogin: "Password",
|
|
1895
1916
|
qrLoginExpired: "This QR code expired. Refresh it to continue.",
|
|
1896
|
-
refreshQrCode: "Refresh QR code"
|
|
1917
|
+
refreshQrCode: "Refresh QR code",
|
|
1918
|
+
codexVirtualWorkspace: "CodeX virtual workspace",
|
|
1919
|
+
codexVirtualSessions: "Sessions"
|
|
1897
1920
|
}, zh = {
|
|
1898
1921
|
pluginTitle: "DeepSeek \u8FDC\u7A0B\u8FDE\u63A5",
|
|
1899
1922
|
pluginDescription: "\u4E00\u6B21\u8FDE\u63A5\uFF0C\u968F\u65F6\u53EF\u7528\u3002",
|
|
@@ -1921,6 +1944,9 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
1921
1944
|
serverUrl: "Server \u5730\u5740",
|
|
1922
1945
|
serverUrlHint: "\u7528\u4E8E\u8D26\u53F7\u6388\u6743\u548C\u52A0\u5BC6\u4E2D\u7EE7\u7684 HTTPS \u5730\u5740\u3002",
|
|
1923
1946
|
serverSaved: "Server \u5730\u5740\u5DF2\u4FDD\u5B58\uFF0C\u91CD\u542F DSH \u540E\u751F\u6548\u3002",
|
|
1947
|
+
codexRemote: "Codex Remote",
|
|
1948
|
+
codexRemoteHint: "\u901A\u8FC7\u8FD9\u53F0 Host \u63D0\u4F9B Codex \u9879\u76EE\uFF1B\u4FEE\u6539\u540E\u9700\u91CD\u542F DSH \u751F\u6548\u3002",
|
|
1949
|
+
codexSaved: "Codex Remote \u8BBE\u7F6E\u5DF2\u4FDD\u5B58\uFF0C\u91CD\u542F DSH \u540E\u751F\u6548\u3002",
|
|
1924
1950
|
authorizeFromRemote: "\u8BF7\u4ECE\u4FA7\u680F Remote \u5165\u53E3\u767B\u5F55\uFF0C\u767B\u5F55\u540E\u53EF\u5728\u8FD9\u91CC\u7BA1\u7406\u5F53\u524D\u8BBE\u5907\u3002",
|
|
1925
1951
|
authorizationMethod: "\u6388\u6743\u65B9\u5F0F",
|
|
1926
1952
|
accountPassword: "\u8D26\u53F7\u5BC6\u7801",
|
|
@@ -2090,7 +2116,9 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2090
2116
|
currentServiceAddress: "\u5F53\u524D\u670D\u52A1\u5730\u5740\uFF1A",
|
|
2091
2117
|
accountPasswordLogin: "\u8D26\u53F7\u5BC6\u7801",
|
|
2092
2118
|
qrLoginExpired: "\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5\u3002",
|
|
2093
|
-
refreshQrCode: "\u5237\u65B0\u4E8C\u7EF4\u7801"
|
|
2119
|
+
refreshQrCode: "\u5237\u65B0\u4E8C\u7EF4\u7801",
|
|
2120
|
+
codexVirtualWorkspace: "CodeX \u5DE5\u4F5C\u533A",
|
|
2121
|
+
codexVirtualSessions: "Sessions"
|
|
2094
2122
|
}, defaultPreferredTransports = ["lan", "p2p", "turn", "relay"];
|
|
2095
2123
|
function normalizedPreferredTransports(value) {
|
|
2096
2124
|
return value === void 0 || value.length === 0 ? [...defaultPreferredTransports] : [...value];
|
|
@@ -2176,7 +2204,13 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2176
2204
|
window.__ModuleLoader__.load({
|
|
2177
2205
|
id: clientModuleId,
|
|
2178
2206
|
factory: (require2) => {
|
|
2179
|
-
let module = { exports: {} }, React = require2("react"), inject = [
|
|
2207
|
+
let module = { exports: {} }, React = require2("react"), inject = [
|
|
2208
|
+
"connection",
|
|
2209
|
+
"slots",
|
|
2210
|
+
"locale",
|
|
2211
|
+
"workspaces",
|
|
2212
|
+
"sessions"
|
|
2213
|
+
];
|
|
2180
2214
|
function RemoteProgressView(props) {
|
|
2181
2215
|
let progress = props.progress;
|
|
2182
2216
|
if (progress === void 0) return null;
|
|
@@ -2214,7 +2248,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2214
2248
|
"aria-valuemax": 100,
|
|
2215
2249
|
"aria-valuenow": percent,
|
|
2216
2250
|
"aria-label": props.t(progress.label)
|
|
2217
|
-
}, React.createElement("span", { style: {
|
|
2251
|
+
}, React.createElement("span", { style: { transform: `scaleX(${percent / 100})` } }))
|
|
2218
2252
|
);
|
|
2219
2253
|
}
|
|
2220
2254
|
async function runRemoteProgress(steps, setProgress, progressRun, action, readyProgress) {
|
|
@@ -2237,8 +2271,8 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2237
2271
|
{ label: "remoteProgressSwitchingWorkspace", detail: "remoteProgressSwitchingWorkspaceDetail", percent: 74, delayMs: 520 }
|
|
2238
2272
|
];
|
|
2239
2273
|
function RemotePluginOptions(props) {
|
|
2240
|
-
let { t } = props, [open, setOpen] = React.useState(!1), [serverUrl, setServerUrl] = React.useState(""), role = "host", [registrationCode, setRegistrationCode] = React.useState(""), [associations, setAssociations] = React.useState({}), [loaded, setLoaded] = React.useState(!1), [writable, setWritable] = React.useState(!1), [busy, setBusy] = React.useState(!1), [reconnectBusy, setReconnectBusy] = React.useState(!1), [hostStatus, setHostStatus] = React.useState(void 0), [notice, setNotice] = React.useState(void 0), [error, setError] = React.useState(void 0), [settingsView, setSettingsView] = React.useState(void 0), persistedServerUrl = settingsView?.config.serverUrl ?? "https://dsh.r2049.cn", association = associations.client ?? associations.host, serverDirty = settingsView !== void 0 && serverUrl !== persistedServerUrl, draftDirty = serverDirty, applyView = (view) => {
|
|
2241
|
-
setSettingsView(view), setServerUrl(view.config.serverUrl ?? "https://dsh.r2049.cn"), setAssociations(view.associations ?? (view.association === void 0 ? {} : { host: view.association })), setWritable(view.writable), setLoaded(!0);
|
|
2274
|
+
let { t } = props, [open, setOpen] = React.useState(!1), [serverUrl, setServerUrl] = React.useState(""), [codexEnabled, setCodexEnabled] = React.useState(!0), role = "host", [registrationCode, setRegistrationCode] = React.useState(""), [associations, setAssociations] = React.useState({}), [loaded, setLoaded] = React.useState(!1), [writable, setWritable] = React.useState(!1), [busy, setBusy] = React.useState(!1), [codexBusy, setCodexBusy] = React.useState(!1), [reconnectBusy, setReconnectBusy] = React.useState(!1), [hostStatus, setHostStatus] = React.useState(void 0), [notice, setNotice] = React.useState(void 0), [error, setError] = React.useState(void 0), [settingsView, setSettingsView] = React.useState(void 0), persistedServerUrl = settingsView?.config.serverUrl ?? "https://dsh.r2049.cn", association = associations.client ?? associations.host, serverDirty = settingsView !== void 0 && serverUrl !== persistedServerUrl, draftDirty = serverDirty, applyView = (view) => {
|
|
2275
|
+
setSettingsView(view), setServerUrl(view.config.serverUrl ?? "https://dsh.r2049.cn"), setCodexEnabled(view.config.codex?.enabled ?? !0), setAssociations(view.associations ?? (view.association === void 0 ? {} : { host: view.association })), setWritable(view.writable), setLoaded(!0);
|
|
2242
2276
|
}, load = async () => {
|
|
2243
2277
|
let [view, status] = await Promise.all([
|
|
2244
2278
|
props.control("settings.get"),
|
|
@@ -2305,9 +2339,37 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2305
2339
|
} finally {
|
|
2306
2340
|
setBusy(!1);
|
|
2307
2341
|
}
|
|
2342
|
+
}, setCodexRemote = async (enabled) => {
|
|
2343
|
+
let previous = codexEnabled;
|
|
2344
|
+
setCodexEnabled(enabled), setCodexBusy(!0), setError(void 0), setNotice(void 0);
|
|
2345
|
+
try {
|
|
2346
|
+
let view = await props.control("settings.codex.set", { enabled });
|
|
2347
|
+
applyView(view), setNotice({ key: "codexSaved" });
|
|
2348
|
+
} catch (reason) {
|
|
2349
|
+
setCodexEnabled(previous), setError(messageOf(reason));
|
|
2350
|
+
} finally {
|
|
2351
|
+
setCodexBusy(!1);
|
|
2352
|
+
}
|
|
2308
2353
|
}, discard = () => {
|
|
2309
2354
|
settingsView !== void 0 && applyView(settingsView), setRegistrationCode(""), setNotice(void 0), setError(void 0);
|
|
2310
|
-
}
|
|
2355
|
+
}, codexSetting = React.createElement(
|
|
2356
|
+
"div",
|
|
2357
|
+
{ className: "dshRemoteAuthorizationSetting" },
|
|
2358
|
+
React.createElement(
|
|
2359
|
+
"div",
|
|
2360
|
+
null,
|
|
2361
|
+
React.createElement("strong", null, t("codexRemote")),
|
|
2362
|
+
React.createElement("p", null, t("codexRemoteHint"))
|
|
2363
|
+
),
|
|
2364
|
+
React.createElement("input", {
|
|
2365
|
+
type: "checkbox",
|
|
2366
|
+
role: "switch",
|
|
2367
|
+
disabled: busy || codexBusy || !writable,
|
|
2368
|
+
"aria-label": t("codexRemote"),
|
|
2369
|
+
checked: codexEnabled,
|
|
2370
|
+
onChange: (event) => void setCodexRemote(event.target.checked)
|
|
2371
|
+
})
|
|
2372
|
+
);
|
|
2311
2373
|
return React.createElement(
|
|
2312
2374
|
"li",
|
|
2313
2375
|
{ className: `dshRemotePluginCard${open ? " isOpen" : ""}` },
|
|
@@ -2369,6 +2431,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2369
2431
|
}),
|
|
2370
2432
|
React.createElement("p", null, t("serverUrlHint"))
|
|
2371
2433
|
),
|
|
2434
|
+
codexSetting,
|
|
2372
2435
|
React.createElement(
|
|
2373
2436
|
"div",
|
|
2374
2437
|
{ className: "dshRemoteAuthorizationSetting" },
|
|
@@ -2450,6 +2513,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2450
2513
|
}),
|
|
2451
2514
|
React.createElement("p", null, t("serverUrlHint"))
|
|
2452
2515
|
),
|
|
2516
|
+
codexSetting,
|
|
2453
2517
|
React.createElement("p", { className: "dshRemoteSettingsState" }, t("authorizeFromRemote")),
|
|
2454
2518
|
writable ? null : React.createElement("p", { className: "dshRemoteError" }, t("readOnly")),
|
|
2455
2519
|
React.createElement(
|
|
@@ -2464,7 +2528,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2464
2528
|
);
|
|
2465
2529
|
}
|
|
2466
2530
|
function RemoteWorkspaceAction(props) {
|
|
2467
|
-
let { t } = props, [open, setOpen] = React.useState(!1), [status, setStatus] = React.useState(void 0), [devices, setDevices] = React.useState([]), [selectedHost, setSelectedHost] = React.useState(void 0), [workspaces, setWorkspaces] = React.useState([]), [directory, setDirectory] = React.useState(void 0), [path, setPath] = React.useState(""), [addingWorkspace, setAddingWorkspace] = React.useState(!1), [busy, setBusy] = React.useState(!1), [needsAuthorization, setNeedsAuthorization] = React.useState(!1), [email, setEmail] = React.useState(""), [password, setPassword] = React.useState(""), [loginMethod, setLoginMethod] = React.useState(props.preferredQrProvider), [loginMethodManuallySelected, setLoginMethodManuallySelected] = React.useState(!1), [qrSession, setQrSession] = React.useState(void 0), [qrImage, setQrImage] = React.useState(void 0), [qrExpired, setQrExpired] = React.useState(!1), [progress, setProgress] = React.useState(void 0), progressRun = React.useRef(0), qrFlowRun = React.useRef(0), [notice, setNotice] = React.useState(void 0), [error, setError] = React.useState(void 0);
|
|
2531
|
+
let { t } = props, [open, setOpen] = React.useState(!1), [status, setStatus] = React.useState(void 0), [devices, setDevices] = React.useState([]), [selectedHost, setSelectedHost] = React.useState(void 0), [workspaces, setWorkspaces] = React.useState([]), [codexWorkspaces, setCodexWorkspaces] = React.useState([]), [workspaceBackend, setWorkspaceBackend] = React.useState("harness"), [codexWorkspaceId, setCodexWorkspaceId] = React.useState(void 0), [directory, setDirectory] = React.useState(void 0), [path, setPath] = React.useState(""), [addingWorkspace, setAddingWorkspace] = React.useState(!1), [busy, setBusy] = React.useState(!1), [needsAuthorization, setNeedsAuthorization] = React.useState(!1), [email, setEmail] = React.useState(""), [password, setPassword] = React.useState(""), [loginMethod, setLoginMethod] = React.useState(props.preferredQrProvider), [loginMethodManuallySelected, setLoginMethodManuallySelected] = React.useState(!1), [qrSession, setQrSession] = React.useState(void 0), [qrImage, setQrImage] = React.useState(void 0), [qrExpired, setQrExpired] = React.useState(!1), [progress, setProgress] = React.useState(void 0), progressRun = React.useRef(0), qrFlowRun = React.useRef(0), [notice, setNotice] = React.useState(void 0), [error, setError] = React.useState(void 0);
|
|
2468
2532
|
React.useEffect(() => {
|
|
2469
2533
|
if (!open) return;
|
|
2470
2534
|
let closeOnEscape = (event) => {
|
|
@@ -2543,20 +2607,24 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2543
2607
|
disabled: busy,
|
|
2544
2608
|
onClick: () => selectLoginMethod(provider)
|
|
2545
2609
|
}, t(provider === "github" ? "githubLogin" : "zhihuLogin")), selectHost = async (host) => {
|
|
2546
|
-
setBusy(!0), setError(void 0);
|
|
2610
|
+
setBusy(!0), setError(void 0), setCodexWorkspaces([]);
|
|
2547
2611
|
try {
|
|
2548
2612
|
let result = await runRemoteProgress(
|
|
2549
2613
|
connectHostProgressSteps(status?.preferredTransports),
|
|
2550
2614
|
setProgress,
|
|
2551
2615
|
progressRun,
|
|
2552
2616
|
async () => {
|
|
2553
|
-
let nextWorkspaces = await props.control("workspaces.list", {
|
|
2617
|
+
let nextWorkspaces = await props.control("workspaces.list", {
|
|
2618
|
+
targetDeviceId: host.deviceId
|
|
2619
|
+
}), nextCodexWorkspaces = await props.control("codex.workspaces.list", {
|
|
2620
|
+
targetDeviceId: host.deviceId
|
|
2621
|
+
}).catch(() => []), nextStatus = await props.control("status").catch(() => {
|
|
2554
2622
|
});
|
|
2555
|
-
return nextStatus !== void 0 && setStatus(nextStatus), { workspaces: nextWorkspaces, status: nextStatus };
|
|
2623
|
+
return nextStatus !== void 0 && setStatus(nextStatus), { workspaces: nextWorkspaces, codexWorkspaces: nextCodexWorkspaces, status: nextStatus };
|
|
2556
2624
|
},
|
|
2557
2625
|
(result2) => connectedProgress(result2.status)
|
|
2558
2626
|
);
|
|
2559
|
-
setWorkspaces(result.workspaces), setSelectedHost(host), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
|
|
2627
|
+
setWorkspaces(result.workspaces), setCodexWorkspaces(result.codexWorkspaces), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setSelectedHost(host), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
|
|
2560
2628
|
} catch (reason) {
|
|
2561
2629
|
setError(messageOf(reason));
|
|
2562
2630
|
} finally {
|
|
@@ -2570,7 +2638,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2570
2638
|
targetDeviceId: selectedHost.deviceId,
|
|
2571
2639
|
...nextPath === void 0 ? {} : { path: nextPath }
|
|
2572
2640
|
});
|
|
2573
|
-
setDirectory(listing), setPath(listing.path);
|
|
2641
|
+
setDirectory(listing), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(listing.path);
|
|
2574
2642
|
} catch (reason) {
|
|
2575
2643
|
setError(messageOf(reason));
|
|
2576
2644
|
} finally {
|
|
@@ -2582,17 +2650,17 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2582
2650
|
try {
|
|
2583
2651
|
let nextStatus = await props.control("status");
|
|
2584
2652
|
if (setStatus(nextStatus), !nextStatus.available) {
|
|
2585
|
-
setDevices([]), setNeedsAuthorization(!1), setSelectedHost(void 0), setWorkspaces([]), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
|
|
2653
|
+
setDevices([]), setNeedsAuthorization(!1), setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
|
|
2586
2654
|
return;
|
|
2587
2655
|
}
|
|
2588
2656
|
try {
|
|
2589
2657
|
let nextDevices = await props.control("devices");
|
|
2590
2658
|
if (setDevices(nextDevices), setNeedsAuthorization(!1), selectedHost !== void 0) {
|
|
2591
2659
|
let nextSelectedHost = nextDevices.find((device) => device.deviceId === selectedHost.deviceId);
|
|
2592
|
-
nextSelectedHost === void 0 ? (setSelectedHost(void 0), setWorkspaces([]), setPath(""), setAddingWorkspace(!1), setDirectory(void 0)) : setSelectedHost(nextSelectedHost);
|
|
2660
|
+
nextSelectedHost === void 0 ? (setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0)) : setSelectedHost(nextSelectedHost);
|
|
2593
2661
|
}
|
|
2594
2662
|
} catch {
|
|
2595
|
-
setDevices([]), setNeedsAuthorization(!0), setSelectedHost(void 0), setWorkspaces([]), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
|
|
2663
|
+
setDevices([]), setNeedsAuthorization(!0), setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(""), setAddingWorkspace(!1), setDirectory(void 0);
|
|
2596
2664
|
}
|
|
2597
2665
|
} catch (reason) {
|
|
2598
2666
|
setError(messageOf(reason));
|
|
@@ -2638,20 +2706,23 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2638
2706
|
setBusy(!1);
|
|
2639
2707
|
}
|
|
2640
2708
|
}, openWorkspace = async () => {
|
|
2641
|
-
if (!(selectedHost === void 0 || path.trim() === "")) {
|
|
2709
|
+
if (!(selectedHost === void 0 || workspaceBackend === "harness" && path.trim() === "" || workspaceBackend === "codex" && codexWorkspaceId === void 0)) {
|
|
2642
2710
|
setBusy(!0), setError(void 0);
|
|
2643
2711
|
try {
|
|
2644
2712
|
let nextStatus = await runRemoteProgress(
|
|
2645
2713
|
openWorkspaceProgressSteps,
|
|
2646
2714
|
setProgress,
|
|
2647
2715
|
progressRun,
|
|
2648
|
-
() => props.control("workspace.open", {
|
|
2716
|
+
() => workspaceBackend === "codex" ? props.control("codex.workspace.open", {
|
|
2717
|
+
targetDeviceId: selectedHost.deviceId,
|
|
2718
|
+
workspaceId: codexWorkspaceId
|
|
2719
|
+
}) : props.control("workspace.open", {
|
|
2649
2720
|
targetDeviceId: selectedHost.deviceId,
|
|
2650
2721
|
path: path.trim()
|
|
2651
2722
|
}),
|
|
2652
2723
|
connectedProgress
|
|
2653
2724
|
);
|
|
2654
|
-
setStatus(nextStatus), window.location.reload();
|
|
2725
|
+
setStatus(nextStatus), nextStatus.workspaceSelection !== void 0 && window.sessionStorage.setItem(pendingWorkspaceSelectionKey, JSON.stringify(nextStatus.workspaceSelection)), window.location.reload();
|
|
2655
2726
|
} catch (reason) {
|
|
2656
2727
|
setError(messageOf(reason)), setBusy(!1);
|
|
2657
2728
|
}
|
|
@@ -2873,7 +2944,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2873
2944
|
React.createElement("button", {
|
|
2874
2945
|
type: "button",
|
|
2875
2946
|
onClick: () => {
|
|
2876
|
-
setSelectedHost(void 0), setWorkspaces([]), setDirectory(void 0), setPath(""), setAddingWorkspace(!1), setError(void 0);
|
|
2947
|
+
setSelectedHost(void 0), setWorkspaces([]), setCodexWorkspaces([]), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setDirectory(void 0), setPath(""), setAddingWorkspace(!1), setError(void 0);
|
|
2877
2948
|
}
|
|
2878
2949
|
}, t("backToHosts"))
|
|
2879
2950
|
)
|
|
@@ -2927,22 +2998,56 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2927
2998
|
}
|
|
2928
2999
|
}, "+")
|
|
2929
3000
|
),
|
|
2930
|
-
React.createElement(
|
|
2931
|
-
"
|
|
2932
|
-
{
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
3001
|
+
React.createElement(
|
|
3002
|
+
"div",
|
|
3003
|
+
{ className: "dshRemoteWorkspaceLists" },
|
|
3004
|
+
React.createElement("div", { className: "dshRemoteDirectoryList" }, workspaces.length === 0 ? React.createElement("p", null, t("noRemoteWorkspaces")) : workspaces.map((workspace) => React.createElement(
|
|
3005
|
+
"button",
|
|
3006
|
+
{
|
|
3007
|
+
type: "button",
|
|
3008
|
+
key: workspace.workspaceId,
|
|
3009
|
+
disabled: busy,
|
|
3010
|
+
className: workspaceBackend === "harness" && !addingWorkspace && path === workspace.path ? "isSelected" : "",
|
|
3011
|
+
"aria-pressed": workspaceBackend === "harness" && !addingWorkspace && path === workspace.path,
|
|
3012
|
+
onClick: () => {
|
|
3013
|
+
setAddingWorkspace(!1), setWorkspaceBackend("harness"), setCodexWorkspaceId(void 0), setPath(workspace.path);
|
|
3014
|
+
}
|
|
3015
|
+
},
|
|
3016
|
+
React.createElement("span", { "aria-hidden": !0 }, "\u25B1"),
|
|
3017
|
+
React.createElement("span", null, workspace.title),
|
|
3018
|
+
React.createElement("small", null, workspace.path)
|
|
3019
|
+
))),
|
|
3020
|
+
codexWorkspaces.length === 0 ? null : React.createElement(
|
|
3021
|
+
React.Fragment,
|
|
3022
|
+
null,
|
|
3023
|
+
React.createElement(
|
|
3024
|
+
"div",
|
|
3025
|
+
{ className: "dshRemoteWorkspaceSourceHeading" },
|
|
3026
|
+
React.createElement("strong", null, t("codexVirtualWorkspace")),
|
|
3027
|
+
React.createElement("small", null, t("codexVirtualSessions"))
|
|
3028
|
+
),
|
|
3029
|
+
React.createElement(
|
|
3030
|
+
"div",
|
|
3031
|
+
{ className: "dshRemoteDirectoryList dshRemoteCodexWorkspaceList" },
|
|
3032
|
+
codexWorkspaces.map((workspace) => React.createElement(
|
|
3033
|
+
"button",
|
|
3034
|
+
{
|
|
3035
|
+
type: "button",
|
|
3036
|
+
key: workspace.workspaceId,
|
|
3037
|
+
disabled: busy,
|
|
3038
|
+
className: workspaceBackend === "codex" && codexWorkspaceId === workspace.workspaceId ? "isSelected" : "",
|
|
3039
|
+
"aria-pressed": workspaceBackend === "codex" && codexWorkspaceId === workspace.workspaceId,
|
|
3040
|
+
onClick: () => {
|
|
3041
|
+
setAddingWorkspace(!1), setWorkspaceBackend("codex"), setCodexWorkspaceId(workspace.workspaceId), setPath(workspace.path);
|
|
3042
|
+
}
|
|
3043
|
+
},
|
|
3044
|
+
React.createElement("span", { className: "dshRemoteCodexMark", "aria-hidden": !0 }, "C"),
|
|
3045
|
+
React.createElement("span", null, workspace.title),
|
|
3046
|
+
React.createElement("small", null, `${workspace.path} \xB7 ${workspace.sessionCount}`)
|
|
3047
|
+
))
|
|
3048
|
+
)
|
|
3049
|
+
)
|
|
3050
|
+
),
|
|
2946
3051
|
addingWorkspace ? React.createElement(
|
|
2947
3052
|
"div",
|
|
2948
3053
|
{ className: "dshRemoteFolderBrowser" },
|
|
@@ -2972,7 +3077,11 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
2972
3077
|
"footer",
|
|
2973
3078
|
{ className: "dshRemoteOpenBar" },
|
|
2974
3079
|
React.createElement("div", null, React.createElement("span", null, t("currentDirectory")), React.createElement("strong", null, path || "\u2014")),
|
|
2975
|
-
React.createElement("button", {
|
|
3080
|
+
React.createElement("button", {
|
|
3081
|
+
type: "button",
|
|
3082
|
+
disabled: busy || workspaceBackend === "harness" && path.trim() === "" || workspaceBackend === "codex" && codexWorkspaceId === void 0,
|
|
3083
|
+
onClick: () => void openWorkspace()
|
|
3084
|
+
}, t(busy ? "openingWorkspace" : "openWorkspace"))
|
|
2976
3085
|
)
|
|
2977
3086
|
)
|
|
2978
3087
|
)
|
|
@@ -3149,7 +3258,10 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
3149
3258
|
}, []), React.useEffect(() => {
|
|
3150
3259
|
if (status?.mode === "remote")
|
|
3151
3260
|
return hideLocalSessionActions();
|
|
3152
|
-
}, [status?.mode]), React.useEffect(() =>
|
|
3261
|
+
}, [status?.mode]), React.useEffect(() => (document.documentElement.classList.toggle(
|
|
3262
|
+
"dshRemoteCodexTargetActive",
|
|
3263
|
+
status?.mode === "remote" && status.backend === "codex"
|
|
3264
|
+
), () => document.documentElement.classList.remove("dshRemoteCodexTargetActive")), [status?.mode, status?.backend]), React.useEffect(() => {
|
|
3153
3265
|
if (!routeOpen) return;
|
|
3154
3266
|
let closeOnEscape = (event) => {
|
|
3155
3267
|
event.key === "Escape" && setRouteOpen(!1);
|
|
@@ -3311,6 +3423,7 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
3311
3423
|
let style = document.createElement("style");
|
|
3312
3424
|
return style.dataset.pluginCss = "dsh-remote", style.textContent = [
|
|
3313
3425
|
'html.dshRemoteTargetActive button[aria-label="\u6DFB\u52A0\u5DE5\u4F5C\u533A"],html.dshRemoteTargetActive button[aria-label="Add workspace"]{display:none!important}',
|
|
3426
|
+
'html.dshRemoteCodexTargetActive [data-composer-card] button[aria-haspopup="listbox"][aria-label="\u6307\u4EE4"],html.dshRemoteCodexTargetActive [data-composer-card] button[aria-haspopup="listbox"][aria-label="Commands"]{display:none!important}',
|
|
3314
3427
|
"[data-dsh-remote-hidden-action]{display:none!important}",
|
|
3315
3428
|
".dshRemoteModeButton{min-height:36px;border:0;background:transparent;color:var(--dsw-alias-label-primary);display:flex;align-items:center;gap:8px;padding:0 10px;border-radius:8px}.dshRemoteModeButton:is(button){cursor:pointer}",
|
|
3316
3429
|
".dshRemoteModeButton:is(button):hover{background:var(--dsw-alias-interactive-bg-hover)}",
|
|
@@ -3326,9 +3439,11 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
3326
3439
|
".dshRemoteSectionHeading>.dshRemoteAddWorkspace{width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;padding:0;border-radius:50%;font-size:20px;line-height:1}.dshRemoteSectionHeading>.dshRemoteAddWorkspace:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}",
|
|
3327
3440
|
".dshRemoteHostList{display:flex;flex-direction:column;border-top:1px solid var(--dsw-alias-border-l2)}.dshRemoteHostList>button{min-height:58px;display:flex;align-items:center;justify-content:space-between;gap:16px;text-align:left;border:0;border-bottom:1px solid var(--dsw-alias-border-l2);background:transparent;padding:10px 4px;cursor:pointer}.dshRemoteHostList>button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.dshRemoteHostList>button:disabled{opacity:.5;cursor:default}.dshRemoteHostList>button>span{min-width:0;display:flex;flex-direction:column;gap:3px}.dshRemoteHostList>button strong{font-size:14px;font-weight:500}.dshRemoteHostList small,.dshRemoteSelectedHost small{color:var(--dsw-alias-label-secondary);font-size:12px}",
|
|
3328
3441
|
".dshRemoteSelectedHost{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 14px;border-radius:10px;background:var(--dsw-alias-bg-layer-2)}",
|
|
3329
|
-
|
|
3442
|
+
'.dshRemoteProgress{display:flex;flex-direction:column;gap:8px;margin:12px 0;padding:12px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-layer-2)}.dshRemoteProgressHeader{display:flex;align-items:center;justify-content:space-between;gap:12px}.dshRemoteProgressHeader strong{font-size:13px;font-weight:600}.dshRemoteProgressHeader span{color:var(--dsw-alias-label-secondary);font-size:12px}.dshRemoteProgressBar{height:6px;overflow:hidden;border-radius:999px;background:var(--dsw-alias-bg-layer-3)}.dshRemoteProgressBar>span{display:block;width:100%;height:100%;border-radius:inherit;background:var(--dsw-alias-brand-primary);transform-origin:left center;transition:transform .22s ease-out}[dir="rtl"] .dshRemoteProgressBar>span{transform-origin:right center}.dshRemoteProgress p{margin:0;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.45}.dshRemoteProgressRoute{font-weight:500}.dshRemoteProgressRoute .isActive{color:var(--dsw-alias-state-success-primary);font-weight:700}.dshRemoteProgressRouteArrow{color:var(--dsw-alias-label-tertiary)}@media(prefers-reduced-motion:reduce){.dshRemoteProgressBar>span{transition:none}}',
|
|
3330
3443
|
'.dshRemoteBrowser{display:flex;flex-direction:column}.dshRemoteCrumbs{display:flex;align-items:center;gap:4px;overflow:auto;padding:2px 0 10px}.dshRemoteCrumbs>button{flex:0 0 auto;border:0;background:transparent;color:var(--dsw-alias-label-secondary);padding:5px 7px;border-radius:6px;cursor:pointer}.dshRemoteCrumbs>button:not(:last-child)::after{content:" /";color:var(--dsw-alias-label-tertiary)}.dshRemoteCrumbs>button:disabled{color:var(--dsw-alias-label-primary);font-weight:600}',
|
|
3331
|
-
".
|
|
3444
|
+
".dshRemoteWorkspaceLists{max-height:min(360px,42vh);overflow-y:auto;overscroll-behavior:contain;scrollbar-gutter:stable;scrollbar-width:thin;scrollbar-color:var(--dsw-alias-label-tertiary) transparent}.dshRemoteWorkspaceLists::-webkit-scrollbar{width:8px}.dshRemoteWorkspaceLists::-webkit-scrollbar-thumb{border:2px solid transparent;border-radius:8px;background:var(--dsw-alias-label-tertiary);background-clip:padding-box}.dshRemoteWorkspaceLists::-webkit-scrollbar-track{background:transparent}",
|
|
3445
|
+
".dshRemoteDirectoryList{min-height:72px;display:flex;flex-direction:column;border-top:1px solid var(--dsw-alias-border-l2)}.dshRemoteDirectoryList>button{min-height:52px;display:grid;grid-template-columns:auto minmax(0,1fr);column-gap:10px;text-align:left;border:0;border-bottom:1px solid var(--dsw-alias-border-l2);background:transparent;padding:8px 4px;cursor:pointer}.dshRemoteDirectoryList>button:hover,.dshRemoteDirectoryList>button.isSelected{background:var(--dsw-alias-interactive-bg-hover)}.dshRemoteDirectoryList>button.isSelected{color:var(--dsw-alias-label-primary)}.dshRemoteDirectoryList>button>span:first-child{grid-row:1/3}.dshRemoteDirectoryList>button>span:not(:first-child),.dshRemoteDirectoryList>button>small{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dshRemoteDirectoryList>button>small{grid-column:2;color:var(--dsw-alias-label-secondary)}.dshRemoteDirectoryList>p,.dshRemoteHint{margin:12px 0;color:var(--dsw-alias-label-secondary);font-size:13px}",
|
|
3446
|
+
".dshRemoteWorkspaceSourceHeading{position:sticky;top:0;z-index:1;display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:16px;padding:8px 4px 7px;background:var(--dsw-alias-bg-layer-1)}.dshRemoteWorkspaceSourceHeading>strong{font-size:13px}.dshRemoteWorkspaceSourceHeading>small{color:var(--dsw-alias-label-secondary);font-size:11px}.dshRemoteCodexWorkspaceList{min-height:0}.dshRemoteCodexMark{box-sizing:border-box;width:22px;height:22px;display:grid;place-items:center;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;color:var(--dsw-alias-label-primary);font-size:11px;font-weight:650}",
|
|
3332
3447
|
".dshRemoteFolderBrowser{margin-top:14px}.dshRemoteFolderBrowser>p,.dshRemoteFolderList>p{margin:12px 0;color:var(--dsw-alias-label-secondary);font-size:13px}.dshRemoteFolderList{max-height:260px;overflow:auto;border-block:1px solid var(--dsw-alias-border-l2)}.dshRemoteFolderList>button{width:100%;min-height:42px;display:flex;align-items:center;gap:9px;border:0;border-bottom:1px solid var(--dsw-alias-border-l2);background:transparent;padding:7px 6px;text-align:left;cursor:pointer}.dshRemoteFolderList>button:hover{background:var(--dsw-alias-interactive-bg-hover)}.dshRemoteFolderBrowser>small{display:block;margin-top:8px;color:var(--dsw-alias-state-warn-label)}",
|
|
3333
3448
|
".dshRemotePathField{display:flex;flex-direction:column;gap:6px;margin-top:20px}.dshRemotePathField>span{font-size:13px;font-weight:600}.dshRemotePathField>input{min-height:40px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-3);color:inherit;padding:0 12px;font:inherit}.dshRemotePathField>small{color:var(--dsw-alias-label-secondary)}",
|
|
3334
3449
|
".dshRemoteOpenBar{position:sticky;bottom:-96px;display:flex;align-items:center;justify-content:space-between;gap:20px;margin-top:20px;padding:14px 0;background:var(--dsw-alias-bg-layer-1);border-top:1px solid var(--dsw-alias-border-l2)}.dshRemoteOpenBar>div{min-width:0;display:flex;flex-direction:column;gap:3px}.dshRemoteOpenBar span{color:var(--dsw-alias-label-secondary);font-size:12px}.dshRemoteOpenBar strong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:13px}.dshRemoteOpenBar>button,.dshRemoteEnable>button{min-height:40px;flex:0 0 auto;border:0;border-radius:8px;background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-1);padding:8px 16px;cursor:pointer}.dshRemoteOpenBar>button:disabled,.dshRemoteEnable>button:disabled{opacity:.5;cursor:default}",
|
|
@@ -3382,21 +3497,25 @@ Minimum version required to store current data is: ` + bestVersion + `.
|
|
|
3382
3497
|
return result.value;
|
|
3383
3498
|
};
|
|
3384
3499
|
ctx.effect(() => {
|
|
3385
|
-
let disposed = !1,
|
|
3500
|
+
let disposed = !1, unsubscribeWorkspaces, unsubscribeSessions, selection, opening = !1, reconcile = () => {
|
|
3386
3501
|
if (disposed || opening || selection === void 0) return;
|
|
3387
|
-
let pending = selection,
|
|
3388
|
-
!
|
|
3389
|
-
|
|
3502
|
+
let pending = selection, workspaceSnapshot = ctx.workspaces.list.getSnapshot();
|
|
3503
|
+
if (!workspacesReady(workspaceSnapshot) || !workspaceSnapshot.items.some((workspace) => workspace.workspaceId === pending.workspaceId)) return;
|
|
3504
|
+
let sessionSnapshot = ctx.sessions.list.getSnapshot();
|
|
3505
|
+
if (pending.backend === "codex" && pending.sessionId !== void 0 && sessionSnapshot.phase !== "ready") return;
|
|
3506
|
+
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.workspaces.connectWorkspace(pending.workspaceId)).then(async (sessionId) => {
|
|
3507
|
+
disposed || (ctx.sessions.open(sessionId), window.sessionStorage.removeItem(pendingWorkspaceSelectionKey), await control("workspace.selection.consume", pending).catch(() => {
|
|
3390
3508
|
}));
|
|
3391
3509
|
}).catch((reason) => {
|
|
3392
3510
|
disposed || console.warn("remote workspace selection failed:", reason);
|
|
3393
|
-
})
|
|
3511
|
+
});
|
|
3394
3512
|
};
|
|
3395
3513
|
return control("status").then((status) => {
|
|
3396
|
-
|
|
3514
|
+
let pending = status.workspaceSelection ?? storedWorkspaceSelection();
|
|
3515
|
+
disposed || status.mode !== "remote" || pending === void 0 || status.target?.deviceId !== pending.targetDeviceId || (selection = pending, unsubscribeWorkspaces = ctx.workspaces.list.subscribe(reconcile), unsubscribeSessions = ctx.sessions.list.subscribe(reconcile), reconcile());
|
|
3397
3516
|
}).catch(() => {
|
|
3398
3517
|
}), () => {
|
|
3399
|
-
disposed = !0,
|
|
3518
|
+
disposed = !0, unsubscribeWorkspaces?.(), unsubscribeSessions?.();
|
|
3400
3519
|
};
|
|
3401
3520
|
}, "ds-harness-remote: resume selected workspace"), ctx.inject(["fileViewer"], (fileViewerContext) => {
|
|
3402
3521
|
let viewer = fileViewerContext.get("fileViewer");
|