dsh-remote-local-plugin 0.8.7 → 0.8.8
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
CHANGED
|
@@ -7,7 +7,7 @@ Remote development that appears as ordinary local sessions.
|
|
|
7
7
|
This plugin targets the official **DSH Desktop** application. Tested/supported versions:
|
|
8
8
|
|
|
9
9
|
- [DSH Desktop](https://github.com/deepseek-ai/deepseek-harness) [`0.2.1-rc.2`](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.2.1-rc.2)
|
|
10
|
-
- Plugin [`0.8.
|
|
10
|
+
- Plugin [`0.8.8`](https://www.npmjs.com/package/dsh-remote-local-plugin)
|
|
11
11
|
- Remote DSH [`0.2.1-rc.2`](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.2.1-rc.2)
|
|
12
12
|
- Remote [Node.js `22.19+`](https://nodejs.org/en/download) on Linux/macOS
|
|
13
13
|
|
|
Binary file
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* dsh-remote-local-plugin@0.8.
|
|
1
|
+
/* dsh-remote-local-plugin@0.8.8 — bundled host entry */
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { credentialRef } from "@deepseek-ai/dsh-credentials";
|
|
@@ -1107,6 +1107,13 @@ var RemoteMirrorService = class {
|
|
|
1107
1107
|
runtime.agent = agent;
|
|
1108
1108
|
this.#runtimes.set(record.localSessionId, runtime);
|
|
1109
1109
|
this.#registrations.set(record.localSessionId, this.#agents.enter(agent, void 0));
|
|
1110
|
+
const localMode = this.#localSandboxMode(session);
|
|
1111
|
+
const remoteMode = latestRemoteSandboxMode(snapshot.events);
|
|
1112
|
+
if (localMode !== void 0 && remoteMode !== void 0 && localMode !== remoteMode) {
|
|
1113
|
+
void this.#hosts.setSandboxMode(record.hostId, record.remoteSessionId, localMode).catch((error) => {
|
|
1114
|
+
this.#ctx.logger.warn("dsh-remote-local: initial sandbox mode failed: %s", String(error));
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
1110
1117
|
await this.#save();
|
|
1111
1118
|
this.#schedule(runtime);
|
|
1112
1119
|
if (live) {
|
|
@@ -1242,9 +1249,18 @@ var RemoteMirrorService = class {
|
|
|
1242
1249
|
}
|
|
1243
1250
|
#onLocalSessionEvent(session, event) {
|
|
1244
1251
|
const candidate = event;
|
|
1245
|
-
if (candidate.type !== "model/selection") return;
|
|
1252
|
+
if (candidate.type !== "model/selection" && candidate.type !== "sandbox/mode") return;
|
|
1246
1253
|
const runtime = [...this.#runtimes.values()].find((item) => item.session.id === session.id);
|
|
1247
1254
|
if (runtime === void 0 || runtime.stopped || runtime.applyingRemote) return;
|
|
1255
|
+
if (candidate.type === "sandbox/mode") {
|
|
1256
|
+
const mode = candidate.data.mode;
|
|
1257
|
+
if (mode !== "read-only" && mode !== "workspace-write" && mode !== "danger-full-access") return;
|
|
1258
|
+
void this.#hosts.setSandboxMode(runtime.record.hostId, runtime.record.remoteSessionId, mode).catch((error) => {
|
|
1259
|
+
runtime.lastError = error instanceof Error ? error.message : String(error);
|
|
1260
|
+
this.#ctx.logger.warn("dsh-remote-local: remote sandbox mode failed: %s", runtime.lastError);
|
|
1261
|
+
});
|
|
1262
|
+
return;
|
|
1263
|
+
}
|
|
1248
1264
|
const record = candidate.data;
|
|
1249
1265
|
if (typeof record.provider !== "string" || typeof record.model !== "string") return;
|
|
1250
1266
|
const selection = {
|
|
@@ -1258,6 +1274,11 @@ var RemoteMirrorService = class {
|
|
|
1258
1274
|
this.#ctx.logger.warn("dsh-remote-local: remote model selection failed: %s", runtime.lastError);
|
|
1259
1275
|
});
|
|
1260
1276
|
}
|
|
1277
|
+
#localSandboxMode(session) {
|
|
1278
|
+
const projections = this.#ctx.get("sessionProjections");
|
|
1279
|
+
const mode = projections?.stateOf?.(session, "sandboxMode");
|
|
1280
|
+
return mode === "read-only" || mode === "workspace-write" || mode === "danger-full-access" ? mode : void 0;
|
|
1281
|
+
}
|
|
1261
1282
|
#defaultSelection() {
|
|
1262
1283
|
const defaults = this.#ctx.get("agentDefaultModel");
|
|
1263
1284
|
const candidate = defaults?.currentSelection?.();
|
|
@@ -1514,6 +1535,15 @@ function latestSelection(session) {
|
|
|
1514
1535
|
}
|
|
1515
1536
|
return void 0;
|
|
1516
1537
|
}
|
|
1538
|
+
function latestRemoteSandboxMode(events) {
|
|
1539
|
+
for (let index = events.length - 1; index >= 0; index -= 1) {
|
|
1540
|
+
const event = events[index];
|
|
1541
|
+
if (event === void 0 || event.type !== "sandbox/mode") continue;
|
|
1542
|
+
const mode = event.data.mode;
|
|
1543
|
+
if (mode === "read-only" || mode === "workspace-write" || mode === "danger-full-access") return mode;
|
|
1544
|
+
}
|
|
1545
|
+
return void 0;
|
|
1546
|
+
}
|
|
1517
1547
|
function contentText(message) {
|
|
1518
1548
|
if (typeof message === "string") return message;
|
|
1519
1549
|
if (typeof message !== "object" || message === null) return "";
|
|
@@ -2271,6 +2301,9 @@ function sessionPath(sessionId) {
|
|
|
2271
2301
|
function sessionModelPath(sessionId) {
|
|
2272
2302
|
return `${sessionPath(sessionId)}/model`;
|
|
2273
2303
|
}
|
|
2304
|
+
function sessionSandboxModePath(sessionId) {
|
|
2305
|
+
return `${sessionPath(sessionId)}/sandbox`;
|
|
2306
|
+
}
|
|
2274
2307
|
function sessionPromptPath(sessionId) {
|
|
2275
2308
|
return `${sessionPath(sessionId)}/prompt`;
|
|
2276
2309
|
}
|
|
@@ -2533,6 +2566,13 @@ var RemoteAgentClient = class {
|
|
|
2533
2566
|
body: request
|
|
2534
2567
|
});
|
|
2535
2568
|
}
|
|
2569
|
+
/** Set the file-effect sandbox mode for one remote session. */
|
|
2570
|
+
async setSandboxMode(sessionId, request) {
|
|
2571
|
+
await this.#request(sessionSandboxModePath(sessionId), isAcceptedResult, {
|
|
2572
|
+
method: "POST",
|
|
2573
|
+
body: request
|
|
2574
|
+
});
|
|
2575
|
+
}
|
|
2536
2576
|
/** Send a text prompt to a remote session. */
|
|
2537
2577
|
async promptSession(sessionId, request) {
|
|
2538
2578
|
await this.#request(sessionPromptPath(sessionId), isAcceptedResult, {
|
|
@@ -4493,6 +4533,15 @@ var RemoteHostsService = class {
|
|
|
4493
4533
|
throw this.#remoteFailure(id, error);
|
|
4494
4534
|
}
|
|
4495
4535
|
}
|
|
4536
|
+
/** Set the file-effect sandbox mode for one remote session. */
|
|
4537
|
+
async setSandboxMode(id, sessionId, mode) {
|
|
4538
|
+
const client = this.#requireClient(id);
|
|
4539
|
+
try {
|
|
4540
|
+
await client.setSandboxMode(sessionId, { mode });
|
|
4541
|
+
} catch (error) {
|
|
4542
|
+
throw this.#remoteFailure(id, error);
|
|
4543
|
+
}
|
|
4544
|
+
}
|
|
4496
4545
|
/** Follow a live remote session from a cursor as an SSE-backed stream. */
|
|
4497
4546
|
async *followSessionEvents(id, sessionId, cursor, signal) {
|
|
4498
4547
|
const client = this.#requireClient(id);
|
package/lib/types/service.d.ts
CHANGED
|
@@ -61,6 +61,8 @@ export declare class RemoteHostsService {
|
|
|
61
61
|
workspaces(id: string): Promise<readonly RemoteWorkspace[]>;
|
|
62
62
|
/** List remote sessions, optionally within one workspace. */
|
|
63
63
|
sessions(id: string, workspaceId?: string, includeSubagents?: boolean): Promise<ListSessionsResult>;
|
|
64
|
+
/** Set the file-effect sandbox mode for one remote session. */
|
|
65
|
+
setSandboxMode(id: string, sessionId: string, mode: 'read-only' | 'workspace-write' | 'danger-full-access'): Promise<void>;
|
|
64
66
|
/** Follow a live remote session from a cursor as an SSE-backed stream. */
|
|
65
67
|
followSessionEvents(id: string, sessionId: string, cursor: number, signal: AbortSignal): AsyncGenerator<SessionStreamFrame>;
|
|
66
68
|
/** Read one session snapshot. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-remote-local-plugin",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.8",
|
|
4
4
|
"description": "DSH remote-development local plugin: host registry, SSH tunnels, remote workspace/session discovery, an authenticated Connection RPC surface, agent tools, and a Settings page.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|
|
Binary file
|