dsh-remote-local-plugin 0.8.8 → 0.8.9
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 +1 -1
- package/assets/goldenpigeon-dsh-remote-agent-0.2.9.tgz +0 -0
- package/lib/client.js +34 -11
- package/lib/client.js.map +2 -2
- package/lib/index.js +187 -29
- package/lib/types/host-api/contract.d.ts +2 -0
- package/lib/types/mirror/service.d.ts +19 -2
- package/lib/types/service.d.ts +1 -1
- package/package.json +1 -1
- package/assets/goldenpigeon-dsh-remote-agent-0.2.5.tgz +0 -0
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* dsh-remote-local-plugin@0.8.
|
|
1
|
+
/* dsh-remote-local-plugin@0.8.9 — bundled host entry */
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { credentialRef } from "@deepseek-ai/dsh-credentials";
|
|
@@ -269,7 +269,7 @@ async function handleHostApi(ctx, service, mirrors, request) {
|
|
|
269
269
|
async function dispatch(ctx, service, mirrors, endpoint, payload, signal) {
|
|
270
270
|
switch (endpoint) {
|
|
271
271
|
case "state":
|
|
272
|
-
return service.state();
|
|
272
|
+
return { ...service.state(), mirroredWorkspaceIds: mirrors?.localWorkspaceIds() ?? [] };
|
|
273
273
|
case "target/validate":
|
|
274
274
|
return service.validateTarget(requireStringField(payload, "sshTarget"));
|
|
275
275
|
case "host/add": {
|
|
@@ -504,12 +504,83 @@ var SURFACE_TYPES = /* @__PURE__ */ new Set([
|
|
|
504
504
|
"assistant/message",
|
|
505
505
|
"tool/result"
|
|
506
506
|
]);
|
|
507
|
+
function messageIdentity(message) {
|
|
508
|
+
return typeof message === "object" && message !== null ? message.id : void 0;
|
|
509
|
+
}
|
|
510
|
+
function createMirrorInbox(session) {
|
|
511
|
+
const nextTurn = [];
|
|
512
|
+
const nextStep = [];
|
|
513
|
+
const locate = (id) => {
|
|
514
|
+
for (const target of ["next-turn", "next-step"]) {
|
|
515
|
+
const list = target === "next-turn" ? nextTurn : nextStep;
|
|
516
|
+
const index = list.findIndex((message) => messageIdentity(message) === id);
|
|
517
|
+
if (index >= 0) return { target, index };
|
|
518
|
+
}
|
|
519
|
+
return void 0;
|
|
520
|
+
};
|
|
521
|
+
const append = (target, start, inserted, removedCount = 0) => {
|
|
522
|
+
try {
|
|
523
|
+
;
|
|
524
|
+
session.append("agent/inbox/spliced", {
|
|
525
|
+
target,
|
|
526
|
+
start,
|
|
527
|
+
...removedCount === 0 ? {} : { removedCount },
|
|
528
|
+
inserted
|
|
529
|
+
});
|
|
530
|
+
} catch {
|
|
531
|
+
}
|
|
532
|
+
};
|
|
533
|
+
const inbox = {
|
|
534
|
+
"next-turn": nextTurn,
|
|
535
|
+
"next-step": nextStep,
|
|
536
|
+
nextTurn,
|
|
537
|
+
nextStep,
|
|
538
|
+
get hasPending() {
|
|
539
|
+
return nextTurn.length > 0 || nextStep.length > 0;
|
|
540
|
+
},
|
|
541
|
+
remove(id) {
|
|
542
|
+
const found = locate(id);
|
|
543
|
+
if (found === void 0) return false;
|
|
544
|
+
const list = found.target === "next-turn" ? nextTurn : nextStep;
|
|
545
|
+
list.splice(found.index, 1);
|
|
546
|
+
append(found.target, found.index, [], 1);
|
|
547
|
+
return true;
|
|
548
|
+
},
|
|
549
|
+
replace(id, message) {
|
|
550
|
+
const found = locate(id);
|
|
551
|
+
if (found === void 0) return false;
|
|
552
|
+
const list = found.target === "next-turn" ? nextTurn : nextStep;
|
|
553
|
+
list.splice(found.index, 1, message);
|
|
554
|
+
append(found.target, found.index, [message], 1);
|
|
555
|
+
return true;
|
|
556
|
+
},
|
|
557
|
+
splice(target, start, deleteCount, inserted) {
|
|
558
|
+
const list = target === "next-turn" ? nextTurn : nextStep;
|
|
559
|
+
const removed = list.splice(start, deleteCount, ...inserted);
|
|
560
|
+
append(target === "next-turn" ? "next-turn" : "next-step", start, inserted, removed.length);
|
|
561
|
+
return removed;
|
|
562
|
+
},
|
|
563
|
+
clear() {
|
|
564
|
+
if (nextStep.length > 0) {
|
|
565
|
+
const count = nextStep.length;
|
|
566
|
+
nextStep.length = 0;
|
|
567
|
+
append("next-step", 0, [], count);
|
|
568
|
+
}
|
|
569
|
+
if (nextTurn.length > 0) {
|
|
570
|
+
const count = nextTurn.length;
|
|
571
|
+
nextTurn.length = 0;
|
|
572
|
+
append("next-turn", 0, [], count);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
};
|
|
576
|
+
return inbox;
|
|
577
|
+
}
|
|
507
578
|
var RemoteMirrorAgent = class {
|
|
508
579
|
id;
|
|
509
580
|
session;
|
|
510
581
|
options;
|
|
511
582
|
ctx;
|
|
512
|
-
inbox
|
|
583
|
+
inbox;
|
|
513
584
|
#runtime;
|
|
514
585
|
#mirror;
|
|
515
586
|
constructor(mirror, runtime, ctx, options) {
|
|
@@ -519,11 +590,13 @@ var RemoteMirrorAgent = class {
|
|
|
519
590
|
this.session = runtime.session;
|
|
520
591
|
this.ctx = ctx;
|
|
521
592
|
this.options = options;
|
|
593
|
+
this.inbox = createMirrorInbox(runtime.session);
|
|
522
594
|
}
|
|
523
595
|
get status() {
|
|
524
596
|
return this.#runtime.running ? "running" : "idle";
|
|
525
597
|
}
|
|
526
598
|
cancel() {
|
|
599
|
+
this.inbox.clear();
|
|
527
600
|
this.#mirror.cancel(this.#runtime);
|
|
528
601
|
}
|
|
529
602
|
whenIdle() {
|
|
@@ -536,10 +609,14 @@ var RemoteMirrorAgent = class {
|
|
|
536
609
|
return task(new AbortController().signal);
|
|
537
610
|
}
|
|
538
611
|
send(message, _target, wakeup = false) {
|
|
539
|
-
if (wakeup) this.followup(message);
|
|
612
|
+
if (wakeup || this.#runtime.running) this.followup(message);
|
|
540
613
|
else this.#mirror.prompt(this.#runtime, message, "queue");
|
|
541
614
|
}
|
|
542
615
|
followup(message) {
|
|
616
|
+
if (this.#runtime.running) {
|
|
617
|
+
this.inbox.splice("next-turn", this.inbox.nextTurn.length, 0, [message]);
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
543
620
|
this.#mirror.prompt(this.#runtime, message, "queue");
|
|
544
621
|
}
|
|
545
622
|
steer(message) {
|
|
@@ -643,6 +720,10 @@ var RemoteMirrorService = class {
|
|
|
643
720
|
}
|
|
644
721
|
return void 0;
|
|
645
722
|
}
|
|
723
|
+
/** Local workspace ids that represent remote workspaces. */
|
|
724
|
+
localWorkspaceIds() {
|
|
725
|
+
return Object.values(this.#state.workspaces).map((workspace) => workspace.localWorkspaceId).filter((id) => typeof id === "string" && id !== "");
|
|
726
|
+
}
|
|
646
727
|
/** Whether the test-only manifest excludes this remote workspace from UI listings. */
|
|
647
728
|
isTestHidden(remoteWorkspaceId, remotePath) {
|
|
648
729
|
return isTestHidden(remotePath, remoteWorkspaceId, this.#testVisibility);
|
|
@@ -680,9 +761,10 @@ var RemoteMirrorService = class {
|
|
|
680
761
|
}
|
|
681
762
|
/** Route one prompt from the local Agent façade to the remote session. */
|
|
682
763
|
prompt(runtime, message, mode) {
|
|
683
|
-
const
|
|
684
|
-
if (
|
|
685
|
-
|
|
764
|
+
const parts = promptParts(message);
|
|
765
|
+
if (parts.length === 0) return;
|
|
766
|
+
const pending = { message, localSeq: -1 };
|
|
767
|
+
runtime.pendingUsers.push(pending);
|
|
686
768
|
if (!runtime.running) {
|
|
687
769
|
runtime.awaitingTurn = runtime.latestTurn + 1;
|
|
688
770
|
runtime.awaitingStarted = false;
|
|
@@ -697,19 +779,63 @@ var RemoteMirrorService = class {
|
|
|
697
779
|
}
|
|
698
780
|
const selection = this.#selectionFor(runtime);
|
|
699
781
|
if (selection !== void 0) Object.assign(runtime.agent.options, selection);
|
|
700
|
-
void this.#hosts.promptSession(
|
|
782
|
+
void this.#promptContent(message).then(({ text, content }) => this.#hosts.promptSession(
|
|
701
783
|
runtime.record.hostId,
|
|
702
784
|
runtime.record.remoteSessionId,
|
|
703
785
|
text,
|
|
704
786
|
mode,
|
|
705
|
-
selection
|
|
706
|
-
|
|
787
|
+
selection,
|
|
788
|
+
content
|
|
789
|
+
)).then(() => {
|
|
790
|
+
if (!runtime.pendingUsers.includes(pending)) return;
|
|
791
|
+
const before = runtime.session.seq;
|
|
792
|
+
try {
|
|
793
|
+
runtime.session.append("user/message", messageData(message), { surfaceOp: "append" });
|
|
794
|
+
pending.localSeq = runtime.session.seq > before ? runtime.session.seq - 1 : -1;
|
|
795
|
+
} catch (error) {
|
|
796
|
+
this.#ctx.logger.warn("dsh-remote-local: could not append accepted user message: %s", String(error));
|
|
797
|
+
}
|
|
798
|
+
}).catch((error) => {
|
|
707
799
|
runtime.lastError = error instanceof Error ? error.message : String(error);
|
|
708
|
-
runtime.pendingUsers.
|
|
800
|
+
const index = runtime.pendingUsers.indexOf(pending);
|
|
801
|
+
if (index >= 0) runtime.pendingUsers.splice(index, 1);
|
|
709
802
|
this.#ctx.logger.warn("dsh-remote-local: remote prompt failed: %s", runtime.lastError);
|
|
803
|
+
try {
|
|
804
|
+
const emit = this.#ctx.emit;
|
|
805
|
+
emit.call(this.#ctx, "agent/error", {
|
|
806
|
+
agent: runtime.agent,
|
|
807
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
808
|
+
});
|
|
809
|
+
} catch (emitError) {
|
|
810
|
+
this.#ctx.logger.warn("dsh-remote-local: prompt error notification failed: %s", String(emitError));
|
|
811
|
+
}
|
|
710
812
|
this.#setRunning(runtime, false);
|
|
711
813
|
});
|
|
712
814
|
}
|
|
815
|
+
async #promptContent(message) {
|
|
816
|
+
const content = [];
|
|
817
|
+
for (const part of promptParts(message)) {
|
|
818
|
+
if (part.type === "text") {
|
|
819
|
+
content.push({ type: "text", text: part.text });
|
|
820
|
+
continue;
|
|
821
|
+
}
|
|
822
|
+
const attachments = this.#ctx.get("attachments");
|
|
823
|
+
if (attachments === void 0) throw new Error("\u672C\u5730\u9644\u4EF6\u670D\u52A1\u4E0D\u53EF\u7528");
|
|
824
|
+
const stored = await attachments.readImage(part.attachment);
|
|
825
|
+
const mediaType = typeof stored.mediaType === "string" ? stored.mediaType : typeof stored.ref?.mediaType === "string" ? stored.ref.mediaType : void 0;
|
|
826
|
+
if (mediaType === void 0) throw new Error("\u56FE\u7247\u7F3A\u5C11 mediaType");
|
|
827
|
+
const name2 = part.name ?? (typeof stored.ref?.name === "string" ? stored.ref.name : void 0);
|
|
828
|
+
content.push({
|
|
829
|
+
type: "image",
|
|
830
|
+
data: Buffer.from(stored.data).toString("base64"),
|
|
831
|
+
mediaType,
|
|
832
|
+
...name2 === void 0 ? {} : { name: name2 }
|
|
833
|
+
});
|
|
834
|
+
}
|
|
835
|
+
const text = content.filter((part) => part.type === "text").map((part) => part.text).join("\n").trim();
|
|
836
|
+
if (content.length === 0) throw new Error("\u6D88\u606F\u5185\u5BB9\u4E3A\u7A7A");
|
|
837
|
+
return { text, content };
|
|
838
|
+
}
|
|
713
839
|
/** Route cancellation to the remote session only after the remote accepts it. */
|
|
714
840
|
cancel(runtime) {
|
|
715
841
|
void this.#hosts.cancelSession(runtime.record.hostId, runtime.record.remoteSessionId).then(() => {
|
|
@@ -1044,9 +1170,13 @@ var RemoteMirrorService = class {
|
|
|
1044
1170
|
let session;
|
|
1045
1171
|
try {
|
|
1046
1172
|
const seed = filtered.map((event, index) => toSeedEvent(event, index, seqMap));
|
|
1173
|
+
const remoteCreatedAt = Date.parse(remote.createdAt);
|
|
1047
1174
|
session = this.#sessions.create(localId, {
|
|
1048
1175
|
...seed.length === 0 ? {} : { seed },
|
|
1049
|
-
meta: {
|
|
1176
|
+
meta: {
|
|
1177
|
+
cwd: anchor,
|
|
1178
|
+
...Number.isFinite(remoteCreatedAt) ? { createdAt: remoteCreatedAt } : {}
|
|
1179
|
+
}
|
|
1050
1180
|
});
|
|
1051
1181
|
} catch (error) {
|
|
1052
1182
|
this.#ctx.logger.warn("dsh-remote-local: could not seed mirror for %s: %s", remote.sessionId, String(error));
|
|
@@ -1221,15 +1351,19 @@ var RemoteMirrorService = class {
|
|
|
1221
1351
|
#appendEvent(runtime, event) {
|
|
1222
1352
|
const before = runtime.session.seq;
|
|
1223
1353
|
runtime.applyingRemote = true;
|
|
1354
|
+
let mappedSeq;
|
|
1224
1355
|
try {
|
|
1225
1356
|
if (!isMirrorNoise(event.type)) {
|
|
1226
|
-
appendRemoteEvent(runtime.session, remapRemoteEvent(event, runtime.remoteToLocalSeq), runtime);
|
|
1357
|
+
mappedSeq = appendRemoteEvent(runtime.session, remapRemoteEvent(event, runtime.remoteToLocalSeq), runtime);
|
|
1227
1358
|
}
|
|
1228
1359
|
} finally {
|
|
1229
1360
|
runtime.applyingRemote = false;
|
|
1230
1361
|
}
|
|
1231
1362
|
const after = runtime.session.seq;
|
|
1232
|
-
if (
|
|
1363
|
+
if (mappedSeq !== void 0) {
|
|
1364
|
+
runtime.remoteToLocalSeq.set(event.seq, mappedSeq);
|
|
1365
|
+
this.#flushAssistantEnd(runtime, event.seq);
|
|
1366
|
+
} else if (after > before) {
|
|
1233
1367
|
runtime.remoteToLocalSeq.set(event.seq, after - 1);
|
|
1234
1368
|
this.#flushAssistantEnd(runtime, event.seq);
|
|
1235
1369
|
}
|
|
@@ -1237,6 +1371,7 @@ var RemoteMirrorService = class {
|
|
|
1237
1371
|
if (typeof turn !== "number") return;
|
|
1238
1372
|
if (event.type === "turn/start") {
|
|
1239
1373
|
runtime.latestTurn = Math.max(runtime.latestTurn, turn);
|
|
1374
|
+
this.#setRunning(runtime, true);
|
|
1240
1375
|
return;
|
|
1241
1376
|
}
|
|
1242
1377
|
if (event.type !== "turn/end") return;
|
|
@@ -1245,6 +1380,16 @@ var RemoteMirrorService = class {
|
|
|
1245
1380
|
runtime.awaitingTurn = null;
|
|
1246
1381
|
runtime.awaitingStarted = false;
|
|
1247
1382
|
this.#setRunning(runtime, false);
|
|
1383
|
+
const reason = typeof event.data === "object" && event.data !== null ? event.data.reason?.kind : void 0;
|
|
1384
|
+
if (reason === "aborted") {
|
|
1385
|
+
runtime.agent.inbox.clear();
|
|
1386
|
+
} else if (runtime.agent.inbox.hasPending) {
|
|
1387
|
+
const next = runtime.agent.inbox.nextTurn[0];
|
|
1388
|
+
if (next !== void 0) {
|
|
1389
|
+
runtime.agent.inbox.remove(messageIdentity(next));
|
|
1390
|
+
this.prompt(runtime, next, "queue");
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1248
1393
|
}
|
|
1249
1394
|
}
|
|
1250
1395
|
#onLocalSessionEvent(session, event) {
|
|
@@ -1459,11 +1604,8 @@ function appendRemoteEvent(session, event, runtime) {
|
|
|
1459
1604
|
if (event.type === "user/message" && runtime.pendingUsers.length > 0) {
|
|
1460
1605
|
const source = event.data.source;
|
|
1461
1606
|
if (source?.kind === "user") {
|
|
1462
|
-
const
|
|
1463
|
-
if (
|
|
1464
|
-
session.append("user/message", messageData(message), { surfaceOp: "append" });
|
|
1465
|
-
return;
|
|
1466
|
-
}
|
|
1607
|
+
const pending = runtime.pendingUsers.shift();
|
|
1608
|
+
if (pending !== void 0 && pending.localSeq >= 0) return pending.localSeq;
|
|
1467
1609
|
}
|
|
1468
1610
|
}
|
|
1469
1611
|
const append = session.append.bind(session);
|
|
@@ -1476,6 +1618,7 @@ function appendRemoteEvent(session, event, runtime) {
|
|
|
1476
1618
|
} else {
|
|
1477
1619
|
append(event.type, event.data);
|
|
1478
1620
|
}
|
|
1621
|
+
return void 0;
|
|
1479
1622
|
}
|
|
1480
1623
|
function messageData(message) {
|
|
1481
1624
|
if (typeof message !== "object" || message === null) return message;
|
|
@@ -1544,20 +1687,25 @@ function latestRemoteSandboxMode(events) {
|
|
|
1544
1687
|
}
|
|
1545
1688
|
return void 0;
|
|
1546
1689
|
}
|
|
1547
|
-
function
|
|
1548
|
-
if (typeof message
|
|
1549
|
-
if (typeof message !== "object" || message === null) return "";
|
|
1690
|
+
function promptParts(message) {
|
|
1691
|
+
if (typeof message !== "object" || message === null) return [];
|
|
1550
1692
|
const content = message.content;
|
|
1551
|
-
if (!Array.isArray(content)) return
|
|
1552
|
-
const
|
|
1693
|
+
if (!Array.isArray(content)) return [];
|
|
1694
|
+
const parts = [];
|
|
1553
1695
|
for (const part of content) {
|
|
1554
|
-
if (typeof part === "
|
|
1555
|
-
else if (typeof part === "object" && part !== null && part.type === "text") {
|
|
1696
|
+
if (typeof part === "object" && part !== null && part.type === "text") {
|
|
1556
1697
|
const text = part.text;
|
|
1557
|
-
if (typeof text === "string")
|
|
1698
|
+
if (typeof text === "string" && text.trim() !== "") parts.push({ type: "text", text });
|
|
1699
|
+
continue;
|
|
1700
|
+
}
|
|
1701
|
+
if (typeof part === "object" && part !== null && part.type === "image") {
|
|
1702
|
+
const attachment = part.attachment;
|
|
1703
|
+
if (attachment === void 0) continue;
|
|
1704
|
+
const name2 = attachment.name;
|
|
1705
|
+
parts.push({ type: "image", attachment, ...typeof name2 === "string" ? { name: name2 } : {} });
|
|
1558
1706
|
}
|
|
1559
1707
|
}
|
|
1560
|
-
return
|
|
1708
|
+
return parts;
|
|
1561
1709
|
}
|
|
1562
1710
|
function canonicalPath(path) {
|
|
1563
1711
|
try {
|
|
@@ -1762,6 +1910,15 @@ function targetOf(mirrors, workspaceRoot, path) {
|
|
|
1762
1910
|
workspaceRoot: anchor
|
|
1763
1911
|
};
|
|
1764
1912
|
}
|
|
1913
|
+
if (isAbsolute2(path)) {
|
|
1914
|
+
return {
|
|
1915
|
+
hostId: context.hostId,
|
|
1916
|
+
localPath: path,
|
|
1917
|
+
remotePath: path,
|
|
1918
|
+
relativePath: path,
|
|
1919
|
+
workspaceRoot: anchor
|
|
1920
|
+
};
|
|
1921
|
+
}
|
|
1765
1922
|
throw Object.assign(
|
|
1766
1923
|
new Error(`remote file path is outside the mirrored workspace: ${path}`),
|
|
1767
1924
|
{ code: "workspace-file/not-found" }
|
|
@@ -4601,12 +4758,13 @@ var RemoteHostsService = class {
|
|
|
4601
4758
|
}
|
|
4602
4759
|
}
|
|
4603
4760
|
/** Send a prompt to a remote session. */
|
|
4604
|
-
async promptSession(id, sessionId, text, mode, selection) {
|
|
4761
|
+
async promptSession(id, sessionId, text, mode, selection, content) {
|
|
4605
4762
|
const client = this.#requireClient(id);
|
|
4606
4763
|
try {
|
|
4607
4764
|
await client.promptSession(sessionId, {
|
|
4608
4765
|
text,
|
|
4609
4766
|
...mode === void 0 ? {} : { mode },
|
|
4767
|
+
...content === void 0 ? {} : { content },
|
|
4610
4768
|
...selection === void 0 ? {} : selection
|
|
4611
4769
|
});
|
|
4612
4770
|
return { accepted: true };
|
|
@@ -17,6 +17,8 @@ export type HostApiEndpoint = 'state' | 'target/validate' | 'host/add' | 'host/r
|
|
|
17
17
|
export interface RemoteHostsState {
|
|
18
18
|
readonly protocolVersion: number;
|
|
19
19
|
readonly hosts: readonly HostView[];
|
|
20
|
+
/** Local workspace ids whose Session creation is owned by a remote host. */
|
|
21
|
+
readonly mirroredWorkspaceIds: readonly string[];
|
|
20
22
|
}
|
|
21
23
|
/** Result of parsing a destination. */
|
|
22
24
|
export interface ValidatedTarget {
|
|
@@ -25,6 +25,10 @@ interface MirrorRecord {
|
|
|
25
25
|
lastSeq: number;
|
|
26
26
|
updatedAt: string;
|
|
27
27
|
}
|
|
28
|
+
interface PendingUser {
|
|
29
|
+
readonly message: unknown;
|
|
30
|
+
localSeq: number;
|
|
31
|
+
}
|
|
28
32
|
interface MirrorRuntime {
|
|
29
33
|
readonly record: MirrorRecord;
|
|
30
34
|
readonly agent: MirrorAgent;
|
|
@@ -41,7 +45,7 @@ interface MirrorRuntime {
|
|
|
41
45
|
running: boolean;
|
|
42
46
|
stopped: boolean;
|
|
43
47
|
lastError: string | null;
|
|
44
|
-
pendingUsers:
|
|
48
|
+
pendingUsers: PendingUser[];
|
|
45
49
|
waiters: Array<() => void>;
|
|
46
50
|
}
|
|
47
51
|
interface MirrorAgent {
|
|
@@ -53,7 +57,7 @@ interface MirrorAgent {
|
|
|
53
57
|
reasoningEffort?: string;
|
|
54
58
|
};
|
|
55
59
|
readonly ctx: Context;
|
|
56
|
-
readonly inbox:
|
|
60
|
+
readonly inbox: MirrorInbox;
|
|
57
61
|
readonly status: 'idle' | 'running';
|
|
58
62
|
cancel(cause?: unknown): void;
|
|
59
63
|
whenIdle(): Promise<void>;
|
|
@@ -63,6 +67,17 @@ interface MirrorAgent {
|
|
|
63
67
|
steer(message: unknown): void;
|
|
64
68
|
inject(message: unknown): void;
|
|
65
69
|
}
|
|
70
|
+
interface MirrorInbox {
|
|
71
|
+
readonly 'next-turn': unknown[];
|
|
72
|
+
readonly 'next-step': unknown[];
|
|
73
|
+
readonly nextTurn: unknown[];
|
|
74
|
+
readonly nextStep: unknown[];
|
|
75
|
+
readonly hasPending: boolean;
|
|
76
|
+
remove(id: unknown): boolean;
|
|
77
|
+
replace(id: unknown, message: unknown): boolean;
|
|
78
|
+
splice(target: string, start: number, deleteCount: number, inserted: unknown[]): unknown[];
|
|
79
|
+
clear(): void;
|
|
80
|
+
}
|
|
66
81
|
/** Mirror remote sessions into local Sessions and custom Agents. */
|
|
67
82
|
export declare class RemoteMirrorService {
|
|
68
83
|
#private;
|
|
@@ -79,6 +94,8 @@ export declare class RemoteMirrorService {
|
|
|
79
94
|
remoteRoot: string;
|
|
80
95
|
anchor: string;
|
|
81
96
|
} | undefined;
|
|
97
|
+
/** Local workspace ids that represent remote workspaces. */
|
|
98
|
+
localWorkspaceIds(): string[];
|
|
82
99
|
/** Whether the test-only manifest excludes this remote workspace from UI listings. */
|
|
83
100
|
isTestHidden(remoteWorkspaceId: string, remotePath: string): boolean;
|
|
84
101
|
/** Find the local mirror workspace for one remote workspace. */
|
package/lib/types/service.d.ts
CHANGED
|
@@ -84,7 +84,7 @@ export declare class RemoteHostsService {
|
|
|
84
84
|
provider: string;
|
|
85
85
|
model: string;
|
|
86
86
|
reasoningEffort?: string;
|
|
87
|
-
}): Promise<AcceptedResult>;
|
|
87
|
+
}, content?: readonly import('@dsh-remote/protocol').PromptContentPart[]): Promise<AcceptedResult>;
|
|
88
88
|
/** Cancel a remote session's active turn. */
|
|
89
89
|
cancelSession(id: string, sessionId: string): Promise<AcceptedResult>;
|
|
90
90
|
/** SSH invocation facts for auxiliary remote file/terminal adapters. */
|
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.9",
|
|
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
|