dsh-wechat-remote 1.7.8 → 1.7.10
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 +10 -8
- package/assets/plugin.tgz +0 -0
- package/assets/release.json +28 -11
- package/bin/dsh-discovery.mjs +18 -18
- package/bin/native-recovery.mjs +44 -44
- package/bin/release-selection.mjs +2 -2
- package/bin/setup.mjs +117 -94
- package/lib/install-control.js +172 -50
- package/lib/install-profile.js +2 -1
- package/lib/native-recovery.js +145 -145
- package/lib/update-download.js +162 -36
- package/lib/update-policy.js +9 -1
- package/lib/update-worker.js +13 -4
- package/package.json +1 -1
package/lib/install-control.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/* Generated from the shared plugin installation sources. */
|
|
2
2
|
|
|
3
3
|
// src/install-control.ts
|
|
4
|
-
import
|
|
5
|
-
import
|
|
4
|
+
import fs3 from "node:fs";
|
|
5
|
+
import path6 from "node:path";
|
|
6
6
|
import http from "node:http";
|
|
7
7
|
|
|
8
8
|
// src/dsh-runtime.ts
|
|
@@ -617,6 +617,84 @@ function withPresentationProjections(block) {
|
|
|
617
617
|
return { ...source, values };
|
|
618
618
|
}
|
|
619
619
|
|
|
620
|
+
// src/dsh-host-contract.ts
|
|
621
|
+
import fs from "node:fs";
|
|
622
|
+
import path4 from "node:path";
|
|
623
|
+
var contracts = /* @__PURE__ */ new WeakMap();
|
|
624
|
+
function runningDshVersion(entry = process.argv[1]) {
|
|
625
|
+
if (!entry) return;
|
|
626
|
+
let directory;
|
|
627
|
+
try {
|
|
628
|
+
directory = path4.dirname(fs.realpathSync(entry));
|
|
629
|
+
} catch {
|
|
630
|
+
return;
|
|
631
|
+
}
|
|
632
|
+
for (let depth = 0; depth < 8; depth++) {
|
|
633
|
+
try {
|
|
634
|
+
const manifest = JSON.parse(fs.readFileSync(path4.join(directory, "package.json"), "utf8"));
|
|
635
|
+
if (manifest.name === "@deepseek-ai/dsh") return manifest.version;
|
|
636
|
+
} catch {
|
|
637
|
+
}
|
|
638
|
+
const parent = path4.dirname(directory);
|
|
639
|
+
if (parent === directory) break;
|
|
640
|
+
directory = parent;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
function usesDuplexEvents(version) {
|
|
644
|
+
if (!version) return false;
|
|
645
|
+
const match = /^(\d+)\.(\d+)\.(\d+)(?:-[\w.-]+)?$/.exec(version);
|
|
646
|
+
if (!match) throw new Error("\u65E0\u6CD5\u8BC6\u522B\u5F53\u524D DSH \u4E8B\u4EF6\u534F\u8BAE\u7248\u672C");
|
|
647
|
+
const [, major, minor, patch] = match.map(Number);
|
|
648
|
+
return major > 0 || minor > 1 || minor === 1 && patch >= 7;
|
|
649
|
+
}
|
|
650
|
+
function openHostEvents(gateway, endpoint, payload, signal) {
|
|
651
|
+
let contract = contracts.get(gateway);
|
|
652
|
+
if (!contract) {
|
|
653
|
+
contract = { duplex: usesDuplexEvents(runningDshVersion()) };
|
|
654
|
+
contracts.set(gateway, contract);
|
|
655
|
+
}
|
|
656
|
+
signal.throwIfAborted();
|
|
657
|
+
const empty = { async *[Symbol.asyncIterator]() {
|
|
658
|
+
} };
|
|
659
|
+
return contract.duplex ? gateway.wireStream.open(endpoint, payload, empty, void 0, signal) : gateway.wireStream.open(endpoint, payload, signal);
|
|
660
|
+
}
|
|
661
|
+
function projectedSubagentCatalog(parent, projection, rows) {
|
|
662
|
+
const entries = projection?.values?.subagentCatalog;
|
|
663
|
+
if (!Array.isArray(entries) || !Array.isArray(rows)) throw new Error("DSH \u5B50\u4EE3\u7406\u76EE\u5F55\u6682\u4E0D\u53EF\u8BFB\u53D6");
|
|
664
|
+
const byId = new Map(rows.map((row) => [row.sessionId, row]));
|
|
665
|
+
const parents = new Set(rows.filter((row) => row.origin === "subagent").map((row) => row.parentSessionId));
|
|
666
|
+
const ids = /* @__PURE__ */ new Set();
|
|
667
|
+
return { parentAvailable: byId.get(parent)?.agentAvailable === true, entries: entries.map((entry) => {
|
|
668
|
+
if (typeof entry.id !== "string" || !entry.id || ids.has(entry.id)) throw new Error("DSH \u5B50\u4EE3\u7406\u76EE\u5F55\u4E0D\u5B8C\u6574");
|
|
669
|
+
ids.add(entry.id);
|
|
670
|
+
if (entry.mode !== "one-shot" && entry.mode !== "continuable") return { id: entry.id, kind: "diagnostic", reason: "unsupported" };
|
|
671
|
+
const row = byId.get(entry.id);
|
|
672
|
+
if (row && (row.origin !== "subagent" || row.parentSessionId !== parent)) throw new Error("DSH \u5B50\u4EE3\u7406\u5F52\u5C5E\u4E0D\u4E00\u81F4");
|
|
673
|
+
return {
|
|
674
|
+
id: entry.id,
|
|
675
|
+
kind: "child",
|
|
676
|
+
mode: entry.mode,
|
|
677
|
+
...typeof entry.label === "string" ? { label: entry.label } : {},
|
|
678
|
+
activity: row?.running === true ? "running" : "inactive",
|
|
679
|
+
hasChildren: parents.has(entry.id)
|
|
680
|
+
};
|
|
681
|
+
}) };
|
|
682
|
+
}
|
|
683
|
+
async function invokeHostRemote(ctx, gateway, request) {
|
|
684
|
+
if (request.namespace !== "subagents" || request.method !== "list") return gateway.invoke(request);
|
|
685
|
+
const registry = ctx.get("typert")?.local;
|
|
686
|
+
if (registry?.get("subagents/list") || registry?.hasSeen?.("subagents/list") || !usesDuplexEvents(runningDshVersion())) return gateway.invoke(request);
|
|
687
|
+
const parent = request.args.parentSessionId;
|
|
688
|
+
if (typeof parent !== "string" || !parent || parent.length > 256) throw new Error("\u7236\u4F1A\u8BDD\u6807\u8BC6\u65E0\u6548");
|
|
689
|
+
request.signal?.throwIfAborted();
|
|
690
|
+
const [projection, listing] = await Promise.all([
|
|
691
|
+
gateway.invoke({ namespace: "session", method: "projections", args: { request: { sessionId: parent } }, signal: request.signal }),
|
|
692
|
+
gateway.invoke({ namespace: "session", method: "list", args: { _request: {} }, signal: request.signal })
|
|
693
|
+
]);
|
|
694
|
+
request.signal?.throwIfAborted();
|
|
695
|
+
return projectedSubagentCatalog(parent, projection, listing?.items);
|
|
696
|
+
}
|
|
697
|
+
|
|
620
698
|
// src/dsh-protocol-compat.ts
|
|
621
699
|
var SINGLE_REQUEST_METHODS = /* @__PURE__ */ new Set([
|
|
622
700
|
"session.attachment",
|
|
@@ -817,8 +895,8 @@ function resolveTypertGateway(ctx) {
|
|
|
817
895
|
const candidate = ctx.get("typertGateway");
|
|
818
896
|
if (!candidate || typeof candidate.invoke !== "function" || typeof candidate.stream !== "function") return null;
|
|
819
897
|
return {
|
|
820
|
-
wireStream: candidate.wireStream,
|
|
821
|
-
invoke: (request) => candidate
|
|
898
|
+
wireStream: candidate.wireStream ? { open: (endpoint, payload, signal) => openHostEvents(candidate, endpoint, payload, signal) } : void 0,
|
|
899
|
+
invoke: (request) => invokeHostRemote(ctx, candidate, request),
|
|
822
900
|
stream: (request) => candidate.stream(request),
|
|
823
901
|
commandAttachmentField: () => {
|
|
824
902
|
const registry = ctx.get("typert");
|
|
@@ -912,41 +990,65 @@ async function historyValue(gateway, request, signal) {
|
|
|
912
990
|
const sessionId = typeof request.sessionId === "string" ? request.sessionId : "";
|
|
913
991
|
if (!sessionId) throw new Error("session.history requires sessionId");
|
|
914
992
|
const maxMessages = Number.isSafeInteger(request.maxMessages) ? Math.max(1, Math.min(30, Number(request.maxMessages))) : 8;
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
if (Number.isSafeInteger(request.beforeSeq)) {
|
|
993
|
+
return createHistoryPageReader(gateway, sessionId, signal)({
|
|
994
|
+
maxMessages,
|
|
995
|
+
...Number.isSafeInteger(request.beforeSeq) ? { beforeSeq: Number(request.beforeSeq) } : {}
|
|
996
|
+
});
|
|
997
|
+
}
|
|
998
|
+
function createHistoryPageReader(gateway, sessionId, signal) {
|
|
999
|
+
let address;
|
|
1000
|
+
let opening;
|
|
1001
|
+
const readPage = async (request, throughSeq) => {
|
|
1002
|
+
const resolved = await (address ??= resolveDshSessionAddress(gateway, sessionId, signal));
|
|
1003
|
+
signal.throwIfAborted();
|
|
927
1004
|
const page = recordOf(await gateway.invoke({
|
|
928
1005
|
namespace: "session",
|
|
929
1006
|
method: "page",
|
|
930
|
-
args: {
|
|
931
|
-
request: {
|
|
932
|
-
address,
|
|
933
|
-
throughSeq: first.cursor,
|
|
934
|
-
beforeSeq: request.beforeSeq,
|
|
935
|
-
maxMessages
|
|
936
|
-
}
|
|
937
|
-
},
|
|
1007
|
+
args: { request: { address: resolved, throughSeq, beforeSeq: request.beforeSeq, maxMessages: request.maxMessages } },
|
|
938
1008
|
signal
|
|
939
1009
|
})) ?? {};
|
|
1010
|
+
signal.throwIfAborted();
|
|
1011
|
+
return { events: historyEvents(page.records), hasMore: page.hasMore === true };
|
|
1012
|
+
};
|
|
1013
|
+
return async (request) => {
|
|
1014
|
+
signal.throwIfAborted();
|
|
1015
|
+
if (!opening && request.beforeSeq !== void 0) {
|
|
1016
|
+
return readPage(request, request.beforeSeq - 1);
|
|
1017
|
+
}
|
|
1018
|
+
if (!opening) {
|
|
1019
|
+
opening = (async () => {
|
|
1020
|
+
const resolved = await (address ??= resolveDshSessionAddress(gateway, sessionId, signal));
|
|
1021
|
+
signal.throwIfAborted();
|
|
1022
|
+
const maxMessages2 = request.maxMessages;
|
|
1023
|
+
const first2 = recordOf(await firstStreamFrame(gateway, "session", "follow", {
|
|
1024
|
+
request: { address: resolved, maxMessages: maxMessages2 }
|
|
1025
|
+
}, signal));
|
|
1026
|
+
signal.throwIfAborted();
|
|
1027
|
+
if (first2?.type !== "snapshot" || !Number.isSafeInteger(first2.cursor) || Number(first2.cursor) < -1) {
|
|
1028
|
+
throw new Error("session/follow returned an invalid opening snapshot");
|
|
1029
|
+
}
|
|
1030
|
+
return { first: first2, maxMessages: maxMessages2 };
|
|
1031
|
+
})();
|
|
1032
|
+
}
|
|
1033
|
+
const { first, maxMessages } = await opening;
|
|
1034
|
+
signal.throwIfAborted();
|
|
1035
|
+
const latest = request.beforeSeq === void 0;
|
|
1036
|
+
if (latest && request.maxMessages === maxMessages) {
|
|
1037
|
+
return {
|
|
1038
|
+
events: historyEvents(first.records),
|
|
1039
|
+
hasMore: first.hasMore === true,
|
|
1040
|
+
projections: withPresentationProjections(first.projections),
|
|
1041
|
+
historyEndSeq: first.cursor
|
|
1042
|
+
};
|
|
1043
|
+
}
|
|
1044
|
+
const page = await readPage(request, Number(first.cursor));
|
|
940
1045
|
return {
|
|
941
|
-
|
|
942
|
-
|
|
1046
|
+
...page,
|
|
1047
|
+
...latest ? {
|
|
1048
|
+
projections: withPresentationProjections(first.projections),
|
|
1049
|
+
historyEndSeq: first.cursor
|
|
1050
|
+
} : {}
|
|
943
1051
|
};
|
|
944
|
-
}
|
|
945
|
-
return {
|
|
946
|
-
events: historyEvents(first.records),
|
|
947
|
-
hasMore: first.hasMore === true,
|
|
948
|
-
projections: withPresentationProjections(first.projections),
|
|
949
|
-
historyEndSeq: first.cursor
|
|
950
1052
|
};
|
|
951
1053
|
}
|
|
952
1054
|
async function workspaceValue(gateway, signal) {
|
|
@@ -1050,8 +1152,8 @@ async function invokeLegacyRpc(gateway, request, options) {
|
|
|
1050
1152
|
}
|
|
1051
1153
|
|
|
1052
1154
|
// src/install-lifecycle.ts
|
|
1053
|
-
import
|
|
1054
|
-
import
|
|
1155
|
+
import fs2 from "node:fs";
|
|
1156
|
+
import path5 from "node:path";
|
|
1055
1157
|
import { execFileSync as execFileSync2, spawn } from "node:child_process";
|
|
1056
1158
|
var serviceName = (s) => /^[A-Za-z0-9_.@-]{1,180}$/.test(s);
|
|
1057
1159
|
function run(command, args) {
|
|
@@ -1060,13 +1162,13 @@ function run(command, args) {
|
|
|
1060
1162
|
function validateManager(value) {
|
|
1061
1163
|
if (value.kind === "process") return;
|
|
1062
1164
|
if (value.kind === "systemd" && process.platform === "linux" && serviceName(value.unit) && value.unit.endsWith(".service")) return;
|
|
1063
|
-
if (value.kind === "launchd" && process.platform === "darwin" && serviceName(value.label) && /^gui\/\d+$/.test(value.domain) && value.domain === `gui/${process.getuid?.()}` &&
|
|
1165
|
+
if (value.kind === "launchd" && process.platform === "darwin" && serviceName(value.label) && /^gui\/\d+$/.test(value.domain) && value.domain === `gui/${process.getuid?.()}` && path5.isAbsolute(value.plist) && fs2.statSync(value.plist).isFile()) return;
|
|
1064
1166
|
throw new Error("\u65E0\u6CD5\u786E\u8BA4\u539F\u540E\u53F0\u670D\u52A1\uFF0C\u672A\u505C\u6B62 DSH\u3002");
|
|
1065
1167
|
}
|
|
1066
1168
|
function currentHostManager() {
|
|
1067
1169
|
if (process.env.PM2_HOME || process.env.NODE_APP_INSTANCE || process.env.KUBERNETES_SERVICE_HOST || process.env.container) throw new Error("\u6B64\u540E\u53F0\u7BA1\u7406\u65B9\u5F0F\u5C1A\u4E0D\u652F\u6301\u81EA\u52A8\u91CD\u542F\u3002");
|
|
1068
1170
|
if (process.platform === "linux") {
|
|
1069
|
-
const group =
|
|
1171
|
+
const group = fs2.readFileSync("/proc/self/cgroup", "utf8");
|
|
1070
1172
|
const units = group.split(/[\n/]/).filter((s) => serviceName(s) && s.endsWith(".service"));
|
|
1071
1173
|
const unit = units.at(-1);
|
|
1072
1174
|
if (unit && !/^user@\d+\.service$/.test(unit)) {
|
|
@@ -1095,17 +1197,17 @@ function currentHostManager() {
|
|
|
1095
1197
|
}
|
|
1096
1198
|
function startUpdateWorker(manager, directory, executable) {
|
|
1097
1199
|
validateManager(manager);
|
|
1098
|
-
const id =
|
|
1200
|
+
const id = path5.basename(directory);
|
|
1099
1201
|
if (!/^[a-f0-9]{32}$/.test(id)) throw new Error("\u65E0\u6548\u7684\u66F4\u65B0\u4EFB\u52A1");
|
|
1100
|
-
const args = [
|
|
1202
|
+
const args = [path5.join(directory, "update-worker.js"), path5.join(directory, "job.json")];
|
|
1101
1203
|
if (manager.kind === "systemd") {
|
|
1102
1204
|
run("systemd-run", ["--user", "--quiet", "--collect", `--unit=dsh-wechat-update-${id}`, "--property=Type=exec", `--working-directory=${directory}`, executable, ...args]);
|
|
1103
1205
|
} else if (manager.kind === "launchd") {
|
|
1104
|
-
run("/bin/launchctl", ["submit", "-l", `dsh.wechat.update.${id}`, "-o",
|
|
1206
|
+
run("/bin/launchctl", ["submit", "-l", `dsh.wechat.update.${id}`, "-o", path5.join(directory, "worker.log"), "-e", path5.join(directory, "worker.log"), "--", executable, ...args]);
|
|
1105
1207
|
} else {
|
|
1106
|
-
const log =
|
|
1208
|
+
const log = fs2.openSync(path5.join(directory, "worker.log"), "a", 384);
|
|
1107
1209
|
const child = spawn(executable, args, { cwd: directory, env: process.env, windowsHide: true, detached: true, stdio: ["ignore", log, log] });
|
|
1108
|
-
|
|
1210
|
+
fs2.closeSync(log);
|
|
1109
1211
|
child.unref();
|
|
1110
1212
|
child.on("error", () => {
|
|
1111
1213
|
});
|
|
@@ -1133,6 +1235,17 @@ function assertNativeUpdateCapabilities(context) {
|
|
|
1133
1235
|
}
|
|
1134
1236
|
|
|
1135
1237
|
// src/install-control.ts
|
|
1238
|
+
async function nativeInstallSessions(ctx, signal) {
|
|
1239
|
+
const controller = ctx.get("sessionController");
|
|
1240
|
+
if (typeof controller?.list !== "function") throw new Error("DSH \u539F\u751F\u4F1A\u8BDD\u68C0\u67E5\u4E0D\u53EF\u7528\uFF0C\u672A\u505C\u6B62\u8282\u70B9\u3002");
|
|
1241
|
+
signal.throwIfAborted();
|
|
1242
|
+
const value = await controller.list({}, signal);
|
|
1243
|
+
signal.throwIfAborted();
|
|
1244
|
+
if (!Array.isArray(value?.items) || value.items.some((s) => typeof s.sessionId !== "string" || !s.sessionId || typeof s.running !== "boolean") || new Set(value.items.map((s) => s.sessionId)).size !== value.items.length) {
|
|
1245
|
+
throw new Error("DSH \u539F\u751F\u4F1A\u8BDD\u72B6\u6001\u4E0D\u5B8C\u6574\uFF0C\u672A\u505C\u6B62\u8282\u70B9\u3002");
|
|
1246
|
+
}
|
|
1247
|
+
return value;
|
|
1248
|
+
}
|
|
1136
1249
|
async function quiesceNativeHost(ctx, read, disposing) {
|
|
1137
1250
|
const items = (await read("session.list")).items;
|
|
1138
1251
|
if (!Array.isArray(items) || items.some((s) => s.running !== false)) throw new Error("\u8BF7\u7B49\u5F85\u8FD0\u884C\u4E2D\u7684\u4F1A\u8BDD\u7ED3\u675F\u540E\u518D\u66F4\u65B0\u3002");
|
|
@@ -1146,11 +1259,11 @@ async function quiesceNativeHost(ctx, read, disposing) {
|
|
|
1146
1259
|
async function createInstallControl(context, config) {
|
|
1147
1260
|
const ctx = context.root;
|
|
1148
1261
|
assertNativeUpdateCapabilities(ctx);
|
|
1149
|
-
const home = adapterDshHome(), id =
|
|
1150
|
-
if (!/^[a-f0-9]{32}$/.test(id) || !/^[a-f0-9]{48}$/.test(config.token) ||
|
|
1151
|
-
const scope = resolveAgentProfileScope("", process.argv, home), profile =
|
|
1152
|
-
const cli =
|
|
1153
|
-
const manifest = JSON.parse(
|
|
1262
|
+
const home = adapterDshHome(), id = path6.basename(config.directory);
|
|
1263
|
+
if (!/^[a-f0-9]{32}$/.test(id) || !/^[a-f0-9]{48}$/.test(config.token) || path6.dirname(config.directory) !== path6.join(home, "harness-remote-updates") || fs3.realpathSync(config.directory) !== config.directory) throw new Error("\u5B89\u88C5\u63A7\u5236\u8BF7\u6C42\u4E0D\u5C5E\u4E8E\u5F53\u524D DSH\u3002");
|
|
1264
|
+
const scope = resolveAgentProfileScope("", process.argv, home), profile = path6.join(home, "profiles", scope);
|
|
1265
|
+
const cli = fs3.realpathSync(process.argv[1]);
|
|
1266
|
+
const manifest = JSON.parse(fs3.readFileSync(path6.resolve(cli, "../../package.json"), "utf8"));
|
|
1154
1267
|
if (manifest.name !== "@deepseek-ai/dsh" || process.execArgv.length) throw new Error("\u6B64 DSH \u542F\u52A8\u65B9\u5F0F\u5C1A\u4E0D\u652F\u6301\u81EA\u52A8\u66F4\u65B0\u3002");
|
|
1155
1268
|
const manager = currentHostManager(), webPort = resolveDshWebRuntime(ctx, process.env).port;
|
|
1156
1269
|
const ports = deriveGatePorts(scope, loadAgentDescriptor().agentInstanceId);
|
|
@@ -1159,6 +1272,9 @@ async function createInstallControl(context, config) {
|
|
|
1159
1272
|
let launched = false, quiesced = false;
|
|
1160
1273
|
const read = async (method, payload = {}) => {
|
|
1161
1274
|
if (!["session.list", "session.history"].includes(method)) throw new Error("\u4E0D\u652F\u6301\u7684\u5B89\u88C5\u68C0\u67E5");
|
|
1275
|
+
if (method === "session.list" && typeof ctx.get("sessionController")?.list === "function") {
|
|
1276
|
+
return nativeInstallSessions(ctx, AbortSignal.timeout(1e4));
|
|
1277
|
+
}
|
|
1162
1278
|
const request = { type: "client-request", rpcId: "installer-read", method, payload };
|
|
1163
1279
|
const response = gateway ? await invokeLegacyRpc(gateway, request, { signal: AbortSignal.timeout(1e4), describeHost: () => ({}) }) : await (await fetch(`http://127.0.0.1:${webPort}/api/${method}`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(request), signal: AbortSignal.timeout(1e4), redirect: "error" })).json();
|
|
1164
1280
|
if (!response.result?.ok) throw new Error("\u65E0\u6CD5\u9A8C\u8BC1 DSH \u4F1A\u8BDD\u72B6\u6001\uFF0C\u672A\u505C\u6B62\u8282\u70B9\u3002");
|
|
@@ -1166,7 +1282,7 @@ async function createInstallControl(context, config) {
|
|
|
1166
1282
|
};
|
|
1167
1283
|
const version = () => {
|
|
1168
1284
|
try {
|
|
1169
|
-
return JSON.parse(
|
|
1285
|
+
return JSON.parse(fs3.readFileSync(path6.join(profile, "node_modules/@harness-remote/dsh-wechat-remote/package.json"), "utf8")).version;
|
|
1170
1286
|
} catch {
|
|
1171
1287
|
return "0.0.0";
|
|
1172
1288
|
}
|
|
@@ -1206,9 +1322,14 @@ async function createInstallControl(context, config) {
|
|
|
1206
1322
|
quiesced
|
|
1207
1323
|
});
|
|
1208
1324
|
if (req.url === "/read" && !quiesced) return json(200, await read(input.method, input.payload));
|
|
1325
|
+
if (req.url === "/health" && !quiesced) {
|
|
1326
|
+
if (!gateway) throw new Error("DSH \u4E1A\u52A1\u63A5\u53E3\u5C1A\u672A\u5C31\u7EEA");
|
|
1327
|
+
await gateway.invoke({ namespace: "session", method: "list", args: { _request: {} }, signal: AbortSignal.timeout(1e4) });
|
|
1328
|
+
return json(200, { ready: true });
|
|
1329
|
+
}
|
|
1209
1330
|
if (req.url === "/launch" && !launched && !quiesced) {
|
|
1210
|
-
const filename =
|
|
1211
|
-
const job = JSON.parse(
|
|
1331
|
+
const filename = path6.join(config.directory, "job.json");
|
|
1332
|
+
const job = JSON.parse(fs3.readFileSync(filename, "utf8"));
|
|
1212
1333
|
if (job.id !== id || job.controlOrigin !== origin || job.statusToken !== config.token || job.parentPid !== process.pid || job.home !== home || job.profile !== profile || job.cli !== cli || job.pnpm !== config.pnpm) throw new Error("\u5B89\u88C5\u76EE\u6807\u53D1\u751F\u53D8\u5316");
|
|
1213
1334
|
startUpdateWorker(manager, config.directory, process.execPath);
|
|
1214
1335
|
launched = true;
|
|
@@ -1253,7 +1374,7 @@ async function createInstallControl(context, config) {
|
|
|
1253
1374
|
server.closeAllConnections();
|
|
1254
1375
|
server.close();
|
|
1255
1376
|
}
|
|
1256
|
-
writePrivateJsonAtomic(
|
|
1377
|
+
writePrivateJsonAtomic(path6.join(config.directory, "control-ready.json"), { origin, pid: process.pid });
|
|
1257
1378
|
return { origin, close };
|
|
1258
1379
|
}
|
|
1259
1380
|
var apply = async (ctx, config) => {
|
|
@@ -1264,5 +1385,6 @@ export {
|
|
|
1264
1385
|
apply,
|
|
1265
1386
|
createInstallControl,
|
|
1266
1387
|
inject,
|
|
1388
|
+
nativeInstallSessions,
|
|
1267
1389
|
quiesceNativeHost
|
|
1268
1390
|
};
|
package/lib/install-profile.js
CHANGED
|
@@ -19,7 +19,8 @@ function backupProfile(profile, backup) {
|
|
|
19
19
|
filter(source, target) {
|
|
20
20
|
if (!fs.lstatSync(source).isSymbolicLink()) return true;
|
|
21
21
|
const type = process.platform === "win32" ? fs.statSync(source, { throwIfNoEntry: false })?.isDirectory() ? "junction" : "file" : void 0;
|
|
22
|
-
fs.
|
|
22
|
+
const link = fs.readlinkSync(source);
|
|
23
|
+
fs.symlinkSync(type === "junction" ? path.resolve(path.dirname(source), link) : link, target, type);
|
|
23
24
|
return false;
|
|
24
25
|
}
|
|
25
26
|
});
|