@runweave/server-linux-x64 0.1.11 → 0.1.13
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/manifest.json +12 -12
- package/native.tar.gz +0 -0
- package/package.json +1 -1
- package/payload/app-server/build-info.json +3 -3
- package/payload/app-server/index.cjs +1 -1
- package/payload/backend/build-info.json +4 -4
- package/payload/backend/index.cjs +255 -130
- package/payload/frontend/dist/build-info.json +3 -3
- package/payload/frontend/dist/companion.html +1 -1
- package/payload/frontend/dist/index.html +1 -1
- package/payload/pty-host/index.cjs +21 -3
package/manifest.json
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
"protocolVersion": 1,
|
|
7
7
|
"entry": "pty-host/index.cjs"
|
|
8
8
|
},
|
|
9
|
-
"version": "0.1.
|
|
10
|
-
"sourceRevision": "
|
|
9
|
+
"version": "0.1.13",
|
|
10
|
+
"sourceRevision": "da67d523de925abb4f2b958f949fd50a3ac2b5bb",
|
|
11
11
|
"platform": "linux",
|
|
12
12
|
"arch": "x64",
|
|
13
13
|
"nodeModuleAbi": "127",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
{
|
|
31
31
|
"path": "app-server/build-info.json",
|
|
32
32
|
"size": 286,
|
|
33
|
-
"sha256": "
|
|
33
|
+
"sha256": "9c7c169c3553261b2cc8b7d83bc7d2fb7f7e16d75e8d3ae8bd8b0fa0ffc28307"
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
36
|
"path": "app-server/configuration-compatibility.json",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
{
|
|
41
41
|
"path": "app-server/index.cjs",
|
|
42
42
|
"size": 1991601,
|
|
43
|
-
"sha256": "
|
|
43
|
+
"sha256": "d99ba7fb4934b29a6cc499e8212fb1f098d01127b499b1b1d241b0ea20f28211"
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
"path": "app-server/index.cjs.map",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
{
|
|
56
56
|
"path": "backend/build-info.json",
|
|
57
57
|
"size": 286,
|
|
58
|
-
"sha256": "
|
|
58
|
+
"sha256": "bd960ff86288c8d4553d3d0444a66ae4dec7d3f902d34b53810f00f4be4f931b"
|
|
59
59
|
},
|
|
60
60
|
{
|
|
61
61
|
"path": "backend/dev-resources/control.cjs",
|
|
@@ -69,8 +69,8 @@
|
|
|
69
69
|
},
|
|
70
70
|
{
|
|
71
71
|
"path": "backend/index.cjs",
|
|
72
|
-
"size":
|
|
73
|
-
"sha256": "
|
|
72
|
+
"size": 5753065,
|
|
73
|
+
"sha256": "55247579573e991db66d087db63c29a17a3147ea2fb43560c1ef61eed54f23e7"
|
|
74
74
|
},
|
|
75
75
|
{
|
|
76
76
|
"path": "backend/ios-simulators/device_shutdown.py",
|
|
@@ -505,12 +505,12 @@
|
|
|
505
505
|
{
|
|
506
506
|
"path": "frontend/dist/build-info.json",
|
|
507
507
|
"size": 286,
|
|
508
|
-
"sha256": "
|
|
508
|
+
"sha256": "77cffa6df1475be5a25363546a40125d700ae5736c04a33b80312ce440dbaca7"
|
|
509
509
|
},
|
|
510
510
|
{
|
|
511
511
|
"path": "frontend/dist/companion.html",
|
|
512
512
|
"size": 822,
|
|
513
|
-
"sha256": "
|
|
513
|
+
"sha256": "724bf62ecacd1f23e651185eb112ff0f1d6f180076a31c4c61cd6801b69f7ba1"
|
|
514
514
|
},
|
|
515
515
|
{
|
|
516
516
|
"path": "frontend/dist/icons/apple-touch-icon.png",
|
|
@@ -535,7 +535,7 @@
|
|
|
535
535
|
{
|
|
536
536
|
"path": "frontend/dist/index.html",
|
|
537
537
|
"size": 1028,
|
|
538
|
-
"sha256": "
|
|
538
|
+
"sha256": "468e70be64ca45305732605cbc4f3c7e5338661a523783be8a705525c58a6c1c"
|
|
539
539
|
},
|
|
540
540
|
{
|
|
541
541
|
"path": "frontend/dist/manifest.webmanifest",
|
|
@@ -1859,8 +1859,8 @@
|
|
|
1859
1859
|
},
|
|
1860
1860
|
{
|
|
1861
1861
|
"path": "pty-host/index.cjs",
|
|
1862
|
-
"size":
|
|
1863
|
-
"sha256": "
|
|
1862
|
+
"size": 918936,
|
|
1863
|
+
"sha256": "764642ecafe1b4e3f28ef9a84451e17d469257878e9730e73e6953eb060e2125"
|
|
1864
1864
|
},
|
|
1865
1865
|
{
|
|
1866
1866
|
"path": "scripts/toolkit/codex-state.mjs",
|
package/native.tar.gz
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "0.1.0",
|
|
3
|
-
"buildId": "
|
|
4
|
-
"sourceRevision": "
|
|
3
|
+
"buildId": "20261109T123037865Z-da67d523",
|
|
4
|
+
"sourceRevision": "da67d523de925abb4f2b958f949fd50a3ac2b5bb",
|
|
5
5
|
"sourceDirty": false,
|
|
6
|
-
"builtAt": "2026-11-
|
|
6
|
+
"builtAt": "2026-11-09T12:30:37.865Z",
|
|
7
7
|
"contentSha256": "ee24c2adfe7a38b0f7698d68d8493b560042b699baba92c63e79961518d9a9af"
|
|
8
8
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* runweave:build-info */var __RUNWEAVE_BUILD_INFO__={"version":"0.1.0","buildId":"
|
|
1
|
+
/* runweave:build-info */var __RUNWEAVE_BUILD_INFO__={"version":"0.1.0","buildId":"20261109T123037865Z-da67d523","sourceRevision":"da67d523de925abb4f2b958f949fd50a3ac2b5bb","sourceDirty":false,"builtAt":"2026-11-09T12:30:37.865Z","contentSha256":"ee24c2adfe7a38b0f7698d68d8493b560042b699baba92c63e79961518d9a9af"};
|
|
2
2
|
const __IMPORT_META_URL__ = require('url').pathToFileURL(__filename).href;
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "0.1.0",
|
|
3
|
-
"buildId": "
|
|
4
|
-
"sourceRevision": "
|
|
3
|
+
"buildId": "20261109T123037121Z-da67d523",
|
|
4
|
+
"sourceRevision": "da67d523de925abb4f2b958f949fd50a3ac2b5bb",
|
|
5
5
|
"sourceDirty": false,
|
|
6
|
-
"builtAt": "2026-11-
|
|
7
|
-
"contentSha256": "
|
|
6
|
+
"builtAt": "2026-11-09T12:30:37.121Z",
|
|
7
|
+
"contentSha256": "fd2cc32d5678e48707cff4a53f44897eb73eb0eff1b7584fc1da101e402cb2a2"
|
|
8
8
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* runweave:build-info */var __RUNWEAVE_BUILD_INFO__={"version":"0.1.0","buildId":"
|
|
1
|
+
/* runweave:build-info */var __RUNWEAVE_BUILD_INFO__={"version":"0.1.0","buildId":"20261109T123037121Z-da67d523","sourceRevision":"da67d523de925abb4f2b958f949fd50a3ac2b5bb","sourceDirty":false,"builtAt":"2026-11-09T12:30:37.121Z","contentSha256":"fd2cc32d5678e48707cff4a53f44897eb73eb0eff1b7584fc1da101e402cb2a2"};
|
|
2
2
|
const __IMPORT_META_URL__ = require('url').pathToFileURL(__filename).href;
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -71434,6 +71434,21 @@ function buildAgentResumeArgs(agent, thread) {
|
|
|
71434
71434
|
return [resumeFlags[agent] ?? "resume", thread];
|
|
71435
71435
|
}
|
|
71436
71436
|
|
|
71437
|
+
// packages/shared/src/terminal/shell.ts
|
|
71438
|
+
function terminalShellName(command) {
|
|
71439
|
+
return (command.split(/[\\/]/).at(-1) ?? command).toLowerCase().replace(/\.exe$/, "");
|
|
71440
|
+
}
|
|
71441
|
+
function isInteractiveShellLaunch(launch) {
|
|
71442
|
+
const name = terminalShellName(launch.command);
|
|
71443
|
+
if (!["sh", "bash", "zsh", "dash", "ksh", "fish", "powershell", "pwsh", "cmd"].includes(name)) return false;
|
|
71444
|
+
return !(launch.args ?? []).some((arg) => {
|
|
71445
|
+
const value = arg.toLowerCase();
|
|
71446
|
+
if (name === "cmd") return !/^\/(?:d|q|a|u|e:(?:on|off)|f:(?:on|off)|v:(?:on|off))$/.test(value);
|
|
71447
|
+
if (name === "powershell" || name === "pwsh") return !["-nologo", "-noprofile", "-noexit", "-login", "-l"].includes(value);
|
|
71448
|
+
return ["--help", "--version"].includes(value) || !value.startsWith("-") || value === "--" || /^-[^-]*[cs]/.test(value) || /^--(?:command|init-command)(?:=|$)/.test(value);
|
|
71449
|
+
});
|
|
71450
|
+
}
|
|
71451
|
+
|
|
71437
71452
|
// backend/src/terminal/runtime/pi-editor.ts
|
|
71438
71453
|
var import_node_crypto12 = require("node:crypto");
|
|
71439
71454
|
var import_node_http = require("node:http");
|
|
@@ -71575,7 +71590,19 @@ function buildAgentResumeCommand(thread) {
|
|
|
71575
71590
|
thread.sessionFile ?? thread.threadId
|
|
71576
71591
|
)
|
|
71577
71592
|
];
|
|
71578
|
-
|
|
71593
|
+
const configured = thread.provider === "codex" ? settingText("agents.codex.binary")?.trim() : ["trae", "traex", "traecli"].includes(thread.provider) ? settingText("agents.traex.binary")?.trim() : void 0;
|
|
71594
|
+
const executable = thread.executable ?? configured ?? thread.provider;
|
|
71595
|
+
const shell = terminalShellName(thread.shell ?? "sh");
|
|
71596
|
+
if (["powershell", "pwsh", "cmd"].includes(shell)) {
|
|
71597
|
+
const parts = [executable, ...args];
|
|
71598
|
+
if (parts.some((part) => [...part].some((character) => character.charCodeAt(0) < 32 || character.charCodeAt(0) === 127)))
|
|
71599
|
+
throw new Error("Agent resume arguments contain terminal control characters");
|
|
71600
|
+
const command = `& ${parts.map((part) => `'${part.replaceAll("'", "''")}'`).join(" ")}`;
|
|
71601
|
+
return shell === "cmd" ? `powershell.exe -NoProfile -EncodedCommand ${Buffer.from(command, "utf16le").toString("base64")}
|
|
71602
|
+
` : `${command}
|
|
71603
|
+
`;
|
|
71604
|
+
}
|
|
71605
|
+
return `${shellQuote(executable)} ${args.map(shellQuote).join(" ")}
|
|
71579
71606
|
`;
|
|
71580
71607
|
}
|
|
71581
71608
|
function shellQuote(value) {
|
|
@@ -71878,21 +71905,6 @@ var aiDiagnosticLog = createAiDiagnosticLog({
|
|
|
71878
71905
|
source: "backend"
|
|
71879
71906
|
});
|
|
71880
71907
|
|
|
71881
|
-
// packages/shared/src/terminal/shell.ts
|
|
71882
|
-
function terminalShellName(command) {
|
|
71883
|
-
return (command.split(/[\\/]/).at(-1) ?? command).toLowerCase().replace(/\.exe$/, "");
|
|
71884
|
-
}
|
|
71885
|
-
function isInteractiveShellLaunch(launch) {
|
|
71886
|
-
const name = terminalShellName(launch.command);
|
|
71887
|
-
if (!["sh", "bash", "zsh", "dash", "ksh", "fish", "powershell", "pwsh", "cmd"].includes(name)) return false;
|
|
71888
|
-
return !(launch.args ?? []).some((arg) => {
|
|
71889
|
-
const value = arg.toLowerCase();
|
|
71890
|
-
if (name === "cmd") return !/^\/(?:d|q|a|u|e:(?:on|off)|f:(?:on|off)|v:(?:on|off))$/.test(value);
|
|
71891
|
-
if (name === "powershell" || name === "pwsh") return !["-nologo", "-noprofile", "-noexit", "-login", "-l"].includes(value);
|
|
71892
|
-
return ["--help", "--version"].includes(value) || !value.startsWith("-") || value === "--" || /^-[^-]*[cs]/.test(value) || /^--(?:command|init-command)(?:=|$)/.test(value);
|
|
71893
|
-
});
|
|
71894
|
-
}
|
|
71895
|
-
|
|
71896
71908
|
// backend/src/terminal/runtime/pty-host-client.ts
|
|
71897
71909
|
var import_node_crypto15 = require("node:crypto");
|
|
71898
71910
|
|
|
@@ -71985,10 +71997,7 @@ var PtyHostClient = class _PtyHostClient {
|
|
|
71985
71997
|
});
|
|
71986
71998
|
this.socket.on("close", () => {
|
|
71987
71999
|
this.connected = false;
|
|
71988
|
-
for (const request2 of this.pending.values())
|
|
71989
|
-
clearTimeout(request2.timer);
|
|
71990
|
-
request2.reject(new Error("HOST_CONNECTION_LOST"));
|
|
71991
|
-
}
|
|
72000
|
+
for (const request2 of this.pending.values()) request2.reject(new Error("HOST_CONNECTION_LOST"));
|
|
71992
72001
|
this.pending.clear();
|
|
71993
72002
|
for (const listener of this.disconnected) listener();
|
|
71994
72003
|
});
|
|
@@ -71997,8 +72006,6 @@ var PtyHostClient = class _PtyHostClient {
|
|
|
71997
72006
|
if (message2.requestId) {
|
|
71998
72007
|
const request2 = this.pending.get(message2.requestId);
|
|
71999
72008
|
if (!request2) return;
|
|
72000
|
-
clearTimeout(request2.timer);
|
|
72001
|
-
this.pending.delete(message2.requestId);
|
|
72002
72009
|
if (message2.error) request2.reject(new Error(message2.error));
|
|
72003
72010
|
else request2.resolve(message2.result);
|
|
72004
72011
|
} else if (message2.type) for (const listener of this.events) listener(value);
|
|
@@ -72030,16 +72037,38 @@ var PtyHostClient = class _PtyHostClient {
|
|
|
72030
72037
|
throw error2;
|
|
72031
72038
|
}
|
|
72032
72039
|
}
|
|
72033
|
-
|
|
72040
|
+
/** Aborting only releases this caller's wait; it does not cancel or replay Host operations. */
|
|
72041
|
+
request(action, body2 = {}, signal) {
|
|
72042
|
+
if (signal?.aborted) return Promise.reject(new Error("HOST_REQUEST_ABORTED"));
|
|
72034
72043
|
if (!this.connected) return Promise.reject(new Error("HOST_CONNECTION_LOST"));
|
|
72035
72044
|
const requestId = (0, import_node_crypto14.randomUUID)();
|
|
72036
72045
|
return new Promise((resolve, reject) => {
|
|
72037
|
-
const
|
|
72046
|
+
const cleanup = () => {
|
|
72047
|
+
clearTimeout(timer);
|
|
72048
|
+
signal?.removeEventListener("abort", abort);
|
|
72038
72049
|
this.pending.delete(requestId);
|
|
72039
|
-
|
|
72040
|
-
|
|
72041
|
-
|
|
72042
|
-
|
|
72050
|
+
};
|
|
72051
|
+
const request2 = {
|
|
72052
|
+
resolve: (value) => {
|
|
72053
|
+
cleanup();
|
|
72054
|
+
resolve(value);
|
|
72055
|
+
},
|
|
72056
|
+
reject: (error2) => {
|
|
72057
|
+
cleanup();
|
|
72058
|
+
reject(error2);
|
|
72059
|
+
}
|
|
72060
|
+
};
|
|
72061
|
+
const abort = () => request2.reject(new Error("HOST_REQUEST_ABORTED"));
|
|
72062
|
+
const timer = setTimeout(() => request2.reject(new Error("HOST_REQUEST_UNCERTAIN")), 15e3);
|
|
72063
|
+
this.pending.set(requestId, request2);
|
|
72064
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
72065
|
+
try {
|
|
72066
|
+
if (!sendJson(this.socket, { requestId, token: this.token, hostInstanceId: this.descriptor.hostInstanceId, action, body: body2 })) {
|
|
72067
|
+
request2.reject(new Error("HOST_CONNECTION_LOST"));
|
|
72068
|
+
}
|
|
72069
|
+
} catch (error2) {
|
|
72070
|
+
request2.reject(error2);
|
|
72071
|
+
}
|
|
72043
72072
|
});
|
|
72044
72073
|
}
|
|
72045
72074
|
close() {
|
|
@@ -72052,27 +72081,37 @@ var ownerId = (0, import_node_crypto15.randomUUID)();
|
|
|
72052
72081
|
var connection;
|
|
72053
72082
|
var generation;
|
|
72054
72083
|
var hostInstanceId;
|
|
72084
|
+
var upstreams;
|
|
72055
72085
|
var stopped = false;
|
|
72056
72086
|
function usesPtyHost() {
|
|
72057
72087
|
return process.platform === "win32" && Boolean(process.env.RUNWEAVE_RUNTIME_RELEASE_ID);
|
|
72058
72088
|
}
|
|
72059
72089
|
async function getPtyHost() {
|
|
72060
72090
|
if (stopped) throw new Error("HOST_CLIENT_STOPPED");
|
|
72061
|
-
connection ??= PtyHostClient.connect(configuration().context, ownerId, generation, hostInstanceId).then((client) => {
|
|
72091
|
+
connection ??= PtyHostClient.connect(configuration().context, ownerId, generation, hostInstanceId).then(async (client) => {
|
|
72062
72092
|
generation = client.generation;
|
|
72063
72093
|
hostInstanceId = client.descriptor.hostInstanceId;
|
|
72064
72094
|
client.disconnected.add(() => {
|
|
72065
72095
|
connection = void 0;
|
|
72066
72096
|
});
|
|
72067
|
-
|
|
72097
|
+
try {
|
|
72098
|
+
if (upstreams) await client.request("setUpstreams", upstreams);
|
|
72099
|
+
return client;
|
|
72100
|
+
} catch (error2) {
|
|
72101
|
+
client.close();
|
|
72102
|
+
throw error2;
|
|
72103
|
+
}
|
|
72068
72104
|
}).catch((error2) => {
|
|
72069
72105
|
connection = void 0;
|
|
72070
72106
|
throw error2;
|
|
72071
72107
|
});
|
|
72072
72108
|
return connection;
|
|
72073
72109
|
}
|
|
72074
|
-
async function syncPtyHostUpstreams(
|
|
72075
|
-
if (usesPtyHost())
|
|
72110
|
+
async function syncPtyHostUpstreams(value) {
|
|
72111
|
+
if (usesPtyHost()) {
|
|
72112
|
+
upstreams = { ...value };
|
|
72113
|
+
await (await getPtyHost()).request("setUpstreams", value);
|
|
72114
|
+
}
|
|
72076
72115
|
}
|
|
72077
72116
|
async function createHostedPty(options) {
|
|
72078
72117
|
const client = await getPtyHost();
|
|
@@ -73169,63 +73208,139 @@ function createTerminalRuntimeRecorder(terminalSessionManager, terminalSessionId
|
|
|
73169
73208
|
};
|
|
73170
73209
|
}
|
|
73171
73210
|
|
|
73211
|
+
// backend/src/terminal/runtime/recovery-policy.ts
|
|
73212
|
+
var RebuildWindowMs = 6e4;
|
|
73213
|
+
var MaxRebuildAttempts = 3;
|
|
73214
|
+
var TerminalRebuildLimitError = class extends Error {
|
|
73215
|
+
constructor(terminalSessionId, count, windowMs, maxAttempts, runtime = "terminal") {
|
|
73216
|
+
super(`${runtime} session rebuild exceeded ${maxAttempts} attempts in ${windowMs} ms for ${terminalSessionId}`);
|
|
73217
|
+
this.terminalSessionId = terminalSessionId;
|
|
73218
|
+
this.count = count;
|
|
73219
|
+
this.windowMs = windowMs;
|
|
73220
|
+
this.maxAttempts = maxAttempts;
|
|
73221
|
+
this.name = "TerminalRebuildLimitError";
|
|
73222
|
+
}
|
|
73223
|
+
};
|
|
73224
|
+
function recordTerminalRebuildAttempt(history, terminalSessionId, now2 = Date.now()) {
|
|
73225
|
+
const attempts = (history.get(terminalSessionId) ?? []).filter((timestamp3) => timestamp3 >= now2 - RebuildWindowMs);
|
|
73226
|
+
history.set(terminalSessionId, attempts);
|
|
73227
|
+
if (attempts.length >= MaxRebuildAttempts)
|
|
73228
|
+
throw new TerminalRebuildLimitError(terminalSessionId, attempts.length + 1, RebuildWindowMs, MaxRebuildAttempts);
|
|
73229
|
+
attempts.push(now2);
|
|
73230
|
+
return { allowed: true, count: attempts.length, windowMs: RebuildWindowMs, maxAttempts: MaxRebuildAttempts };
|
|
73231
|
+
}
|
|
73232
|
+
function resolveAgentThreadToResume(session) {
|
|
73233
|
+
const activeProvider = getAgentForCommand(session.activeCommand) ?? (session.terminalState?.state.startsWith("agent_") ? session.terminalState.agent : null);
|
|
73234
|
+
if (!activeProvider) return null;
|
|
73235
|
+
const currentThreadId = session.threadId?.trim();
|
|
73236
|
+
const currentProvider = session.threadProvider ?? (currentThreadId ? "codex" : void 0);
|
|
73237
|
+
if (currentThreadId && currentProvider === activeProvider)
|
|
73238
|
+
return { provider: activeProvider, threadId: currentThreadId };
|
|
73239
|
+
const recentThreadId = session.lastThreadId?.trim();
|
|
73240
|
+
return recentThreadId && session.lastThreadProvider === activeProvider ? { provider: activeProvider, threadId: recentThreadId } : null;
|
|
73241
|
+
}
|
|
73242
|
+
|
|
73172
73243
|
// backend/src/terminal/runtime/pty-host-runtime.ts
|
|
73173
73244
|
var launches = /* @__PURE__ */ new Map();
|
|
73245
|
+
var rebuildAttempts = /* @__PURE__ */ new Map();
|
|
73174
73246
|
function ensureHostedTerminal(options) {
|
|
73175
73247
|
const previous = launches.get(options.session.id);
|
|
73176
73248
|
if (previous) return previous;
|
|
73177
|
-
const launch = (
|
|
73178
|
-
const { session, terminalSessionManager, runtimeRegistry } = options;
|
|
73179
|
-
const existing = runtimeRegistry.getSessionRuntime(session.id);
|
|
73180
|
-
if (existing) return existing;
|
|
73181
|
-
let binding = session.ptyHost;
|
|
73182
|
-
const creating = !binding;
|
|
73183
|
-
if (!binding) {
|
|
73184
|
-
binding = { hostInstanceId: (await getPtyHost()).descriptor.hostInstanceId, sessionInstanceId: (0, import_node_crypto16.randomUUID)() };
|
|
73185
|
-
await terminalSessionManager.updateRuntimeMetadata(session.id, { runtimeKind: "pty", ptyHost: binding, recoverable: true });
|
|
73186
|
-
}
|
|
73187
|
-
const fallback = creating ? resolveTerminalFallbackLaunchConfig(session) : null;
|
|
73188
|
-
const terminalEnv = buildTerminalRuntimeEnvironment({ terminalSessionId: session.id, projectId: session.projectId, source: session.source });
|
|
73189
|
-
const runtime = await createHostedPty({
|
|
73190
|
-
terminalSessionId: session.id,
|
|
73191
|
-
binding,
|
|
73192
|
-
onLaunch: async (launch2) => {
|
|
73193
|
-
if (launch2.fallbackReason) logger.warn("terminal.pty-host.fallback.activated", { terminalSessionId: session.id, command: launch2.command, reason: launch2.fallbackReason });
|
|
73194
|
-
await terminalSessionManager.updateSessionLaunch(session.id, { command: launch2.command, args: launch2.args });
|
|
73195
|
-
},
|
|
73196
|
-
create: creating ? {
|
|
73197
|
-
sessionInstanceId: binding.sessionInstanceId,
|
|
73198
|
-
terminalSessionId: session.id,
|
|
73199
|
-
projectId: session.projectId,
|
|
73200
|
-
command: session.command,
|
|
73201
|
-
args: session.args,
|
|
73202
|
-
cwd: session.cwd,
|
|
73203
|
-
cols: 80,
|
|
73204
|
-
rows: 24,
|
|
73205
|
-
env: buildPtyEnv(process.env, terminalEnv, session.command),
|
|
73206
|
-
...fallback ? { fallback: { ...fallback, env: buildPtyEnv(process.env, terminalEnv, fallback.command) } } : {}
|
|
73207
|
-
} : void 0
|
|
73208
|
-
});
|
|
73209
|
-
runtimeRegistry.createRuntime(session.id, runtime);
|
|
73210
|
-
runtimeRegistry.ensureRecorder(session.id, createTerminalRuntimeRecorder(terminalSessionManager, session.id));
|
|
73211
|
-
return runtime;
|
|
73212
|
-
})().catch((error2) => {
|
|
73213
|
-
if (error2 instanceof Error && error2.message === "HOST_SESSION_GONE") {
|
|
73214
|
-
options.terminalSessionManager.markExited(options.session.id);
|
|
73215
|
-
}
|
|
73216
|
-
throw error2;
|
|
73217
|
-
}).finally(() => {
|
|
73249
|
+
const launch = attachOrRebuild(options).finally(() => {
|
|
73218
73250
|
launches.delete(options.session.id);
|
|
73219
73251
|
});
|
|
73220
73252
|
launches.set(options.session.id, launch);
|
|
73221
73253
|
return launch;
|
|
73222
73254
|
}
|
|
73255
|
+
async function attachOrRebuild(options) {
|
|
73256
|
+
const { session, terminalSessionManager, runtimeRegistry } = options;
|
|
73257
|
+
const existing = runtimeRegistry.getSessionRuntime(session.id);
|
|
73258
|
+
if (existing) return { runtime: existing };
|
|
73259
|
+
let runtime;
|
|
73260
|
+
let warning;
|
|
73261
|
+
try {
|
|
73262
|
+
runtime = await launchHostedTerminal(options, !session.ptyHost);
|
|
73263
|
+
} catch (error2) {
|
|
73264
|
+
if (!(error2 instanceof Error) || error2.message !== "HOST_SESSION_GONE" || session.status !== "running") throw error2;
|
|
73265
|
+
({ runtime, warning } = await rebuildHostedTerminal(options));
|
|
73266
|
+
}
|
|
73267
|
+
runtimeRegistry.createRuntime(session.id, runtime);
|
|
73268
|
+
runtimeRegistry.ensureRecorder(session.id, createTerminalRuntimeRecorder(terminalSessionManager, session.id));
|
|
73269
|
+
return { runtime, warning };
|
|
73270
|
+
}
|
|
73271
|
+
async function launchHostedTerminal(options, creating) {
|
|
73272
|
+
const { session, terminalSessionManager } = options;
|
|
73273
|
+
let binding = session.ptyHost;
|
|
73274
|
+
if (creating) {
|
|
73275
|
+
binding = { hostInstanceId: (await getPtyHost()).descriptor.hostInstanceId, sessionInstanceId: (0, import_node_crypto16.randomUUID)() };
|
|
73276
|
+
await terminalSessionManager.updateRuntimeMetadata(session.id, { runtimeKind: "pty", ptyHost: binding, recoverable: true });
|
|
73277
|
+
}
|
|
73278
|
+
if (!binding) throw new Error("HOST_SESSION_GONE");
|
|
73279
|
+
const fallback = creating ? resolveTerminalFallbackLaunchConfig(session) : null;
|
|
73280
|
+
const terminalEnv = buildTerminalRuntimeEnvironment({ terminalSessionId: session.id, projectId: session.projectId, source: session.source });
|
|
73281
|
+
return createHostedPty({
|
|
73282
|
+
terminalSessionId: session.id,
|
|
73283
|
+
binding,
|
|
73284
|
+
onLaunch: async (launch) => {
|
|
73285
|
+
if (launch.fallbackReason) logger.warn("terminal.pty-host.fallback.activated", { terminalSessionId: session.id, command: launch.command, reason: launch.fallbackReason });
|
|
73286
|
+
await terminalSessionManager.updateSessionLaunch(session.id, { command: launch.command, args: launch.args });
|
|
73287
|
+
},
|
|
73288
|
+
create: creating ? {
|
|
73289
|
+
sessionInstanceId: binding.sessionInstanceId,
|
|
73290
|
+
terminalSessionId: session.id,
|
|
73291
|
+
projectId: session.projectId,
|
|
73292
|
+
command: session.command,
|
|
73293
|
+
args: session.args,
|
|
73294
|
+
cwd: session.cwd,
|
|
73295
|
+
cols: 80,
|
|
73296
|
+
rows: 24,
|
|
73297
|
+
env: buildPtyEnv(process.env, terminalEnv, session.command),
|
|
73298
|
+
...fallback ? { fallback: { ...fallback, env: buildPtyEnv(process.env, terminalEnv, fallback.command) } } : {}
|
|
73299
|
+
} : void 0
|
|
73300
|
+
});
|
|
73301
|
+
}
|
|
73302
|
+
async function rebuildHostedTerminal(options) {
|
|
73303
|
+
const { session, terminalSessionManager } = options;
|
|
73304
|
+
const interactive = isInteractiveShellLaunch(session);
|
|
73305
|
+
const thread = interactive ? resolveAgentThreadToResume(session) : null;
|
|
73306
|
+
let warning = "Command exited; returned to a shell.";
|
|
73307
|
+
if (interactive) {
|
|
73308
|
+
try {
|
|
73309
|
+
const attempt = recordTerminalRebuildAttempt(rebuildAttempts, session.id);
|
|
73310
|
+
warning = thread ? `Original PTY Host session was lost; starting ${thread.provider} resume from saved threadId (${attempt.count}/${attempt.maxAttempts}).` : `Original PTY Host session was lost; created a fresh terminal session (${attempt.count}/${attempt.maxAttempts}).`;
|
|
73311
|
+
} catch (error2) {
|
|
73312
|
+
if (error2 instanceof TerminalRebuildLimitError) {
|
|
73313
|
+
await terminalSessionManager.updateRuntimeMetadata(session.id, { runtimeKind: "pty", ptyHost: session.ptyHost, recoverable: false });
|
|
73314
|
+
terminalSessionManager.markExited(session.id, 1);
|
|
73315
|
+
}
|
|
73316
|
+
throw error2;
|
|
73317
|
+
}
|
|
73318
|
+
} else {
|
|
73319
|
+
await terminalSessionManager.updateSessionLaunch(session.id, resolveDefaultTerminalLaunchConfig());
|
|
73320
|
+
await terminalSessionManager.updateSessionMetadata(session.id, { cwd: session.cwd, activeCommand: null });
|
|
73321
|
+
terminalSessionManager.markRunning(session.id);
|
|
73322
|
+
}
|
|
73323
|
+
const sessionFile = thread ? await getAgentAdapter(thread.provider).resolveResumeTarget(thread.threadId, session.pi) : void 0;
|
|
73324
|
+
const runtime = await launchHostedTerminal(options, true);
|
|
73325
|
+
try {
|
|
73326
|
+
if (thread) {
|
|
73327
|
+
const command = buildAgentResumeCommand({ ...thread, sessionFile, shell: session.command });
|
|
73328
|
+
await runtime.hosted.writeSteps([{ type: "text", data: command.replace(/\n$/, "") }, { type: "delay", ms: 200 }, { type: "text", data: "\r" }], `recovery:${session.ptyHost.sessionInstanceId}`);
|
|
73329
|
+
await terminalSessionManager.updateSessionThreadId(session.id, thread.threadId, thread.provider);
|
|
73330
|
+
}
|
|
73331
|
+
} catch (error2) {
|
|
73332
|
+
runtime.dispose();
|
|
73333
|
+
throw error2;
|
|
73334
|
+
}
|
|
73335
|
+
logger.warn("terminal.pty-host.session-missing.rebuild", { terminalSessionId: session.id, warning });
|
|
73336
|
+
return { runtime, warning };
|
|
73337
|
+
}
|
|
73223
73338
|
async function reconcileHostedTerminals(manager, registry2) {
|
|
73224
73339
|
if (!usesPtyHost()) return;
|
|
73225
73340
|
for (const session of manager.listSessions()) {
|
|
73226
73341
|
if (session.runtimeKind !== "pty" || session.status !== "running") continue;
|
|
73227
73342
|
if (!session.ptyHost) {
|
|
73228
|
-
|
|
73343
|
+
manager.markExited(session.id);
|
|
73229
73344
|
continue;
|
|
73230
73345
|
}
|
|
73231
73346
|
try {
|
|
@@ -73279,8 +73394,6 @@ var import_node_fs16 = require("node:fs");
|
|
|
73279
73394
|
var import_node_path25 = __toESM(require("node:path"), 1);
|
|
73280
73395
|
var RUNWEAVE_TMUX_PREFIX = "runweave-";
|
|
73281
73396
|
var TmuxCommandTimeoutMs = 5e3;
|
|
73282
|
-
var RebuildWindowMs = 6e4;
|
|
73283
|
-
var MaxRebuildAttempts = 3;
|
|
73284
73397
|
var CaptureHistoryLines = 5e3;
|
|
73285
73398
|
var InteractivePaneReadyMinWaitMs = 1e3;
|
|
73286
73399
|
var InteractivePaneReadyStableMs = 200;
|
|
@@ -74033,28 +74146,13 @@ var TmuxSessionService = class extends TmuxProcess {
|
|
|
74033
74146
|
return orphanedSessions;
|
|
74034
74147
|
}
|
|
74035
74148
|
recordRebuildAttempt(terminalSessionId) {
|
|
74036
|
-
|
|
74037
|
-
|
|
74038
|
-
|
|
74039
|
-
(
|
|
74040
|
-
|
|
74041
|
-
|
|
74042
|
-
this.rebuildAttempts.set(terminalSessionId, attempts);
|
|
74043
|
-
throw new TmuxRebuildLimitError(
|
|
74044
|
-
terminalSessionId,
|
|
74045
|
-
attempts.length + 1,
|
|
74046
|
-
RebuildWindowMs,
|
|
74047
|
-
MaxRebuildAttempts
|
|
74048
|
-
);
|
|
74149
|
+
try {
|
|
74150
|
+
return recordTerminalRebuildAttempt(this.rebuildAttempts, terminalSessionId, this.now());
|
|
74151
|
+
} catch (error2) {
|
|
74152
|
+
if (error2 instanceof TerminalRebuildLimitError)
|
|
74153
|
+
throw new TmuxRebuildLimitError(error2.terminalSessionId, error2.count, error2.windowMs, error2.maxAttempts);
|
|
74154
|
+
throw error2;
|
|
74049
74155
|
}
|
|
74050
|
-
attempts.push(now2);
|
|
74051
|
-
this.rebuildAttempts.set(terminalSessionId, attempts);
|
|
74052
|
-
return {
|
|
74053
|
-
allowed: true,
|
|
74054
|
-
count: attempts.length,
|
|
74055
|
-
windowMs: RebuildWindowMs,
|
|
74056
|
-
maxAttempts: MaxRebuildAttempts
|
|
74057
|
-
};
|
|
74058
74156
|
}
|
|
74059
74157
|
};
|
|
74060
74158
|
|
|
@@ -74795,7 +74893,7 @@ async function ensureTerminalRuntime(options) {
|
|
|
74795
74893
|
};
|
|
74796
74894
|
});
|
|
74797
74895
|
}
|
|
74798
|
-
if (options.session.ptyHost || usesPtyHost()) return
|
|
74896
|
+
if (options.session.ptyHost || usesPtyHost()) return ensureHostedTerminal(options);
|
|
74799
74897
|
const runtime = options.ptyService.spawnSession({
|
|
74800
74898
|
command: options.session.command,
|
|
74801
74899
|
args: options.session.args,
|
|
@@ -74835,19 +74933,6 @@ async function ensureTerminalRuntime(options) {
|
|
|
74835
74933
|
function isInteractiveShellLaunch2(command, args) {
|
|
74836
74934
|
return isInteractiveShellLaunch({ command, args });
|
|
74837
74935
|
}
|
|
74838
|
-
function resolveAgentThreadToResume(session) {
|
|
74839
|
-
const activeProvider = getAgentForCommand(session.activeCommand);
|
|
74840
|
-
if (!activeProvider) {
|
|
74841
|
-
return null;
|
|
74842
|
-
}
|
|
74843
|
-
const currentThreadId = session.threadId?.trim();
|
|
74844
|
-
const currentProvider = session.threadProvider ?? (currentThreadId ? "codex" : void 0);
|
|
74845
|
-
if (currentThreadId && currentProvider === activeProvider) {
|
|
74846
|
-
return { provider: activeProvider, threadId: currentThreadId };
|
|
74847
|
-
}
|
|
74848
|
-
const recentThreadId = session.lastThreadId?.trim();
|
|
74849
|
-
return recentThreadId && session.lastThreadProvider === activeProvider ? { provider: activeProvider, threadId: recentThreadId } : null;
|
|
74850
|
-
}
|
|
74851
74936
|
function createTmuxInputPacedRuntime(runtime) {
|
|
74852
74937
|
const queuedInput = [];
|
|
74853
74938
|
let holdInputUntil = 0;
|
|
@@ -112240,9 +112325,6 @@ function registerDesktopNetworkRoutes(app, requireAuth) {
|
|
|
112240
112325
|
});
|
|
112241
112326
|
}
|
|
112242
112327
|
|
|
112243
|
-
// backend/src/remote/routes.ts
|
|
112244
|
-
var import_node_crypto57 = require("node:crypto");
|
|
112245
|
-
|
|
112246
112328
|
// packages/shared/src/remote/index.ts
|
|
112247
112329
|
function isRemoteBrowserProfileState(value) {
|
|
112248
112330
|
if (!value || typeof value !== "object") return false;
|
|
@@ -112569,13 +112651,63 @@ function registerRemoteCapabilitiesRoute(app, requireTunnelAuth, requireAuth, br
|
|
|
112569
112651
|
});
|
|
112570
112652
|
}
|
|
112571
112653
|
|
|
112572
|
-
// backend/src/remote/
|
|
112573
|
-
|
|
112574
|
-
|
|
112654
|
+
// backend/src/remote/terminal-hook-auth.ts
|
|
112655
|
+
var import_node_crypto57 = require("node:crypto");
|
|
112656
|
+
function matchesToken2(value, expected) {
|
|
112657
|
+
if (!expected) return false;
|
|
112575
112658
|
const supplied = Buffer.from(value);
|
|
112576
112659
|
const actual = Buffer.from(expected);
|
|
112577
112660
|
return supplied.length === actual.length && (0, import_node_crypto57.timingSafeEqual)(supplied, actual);
|
|
112578
112661
|
}
|
|
112662
|
+
async function authenticatesTerminal(value, terminalId, sessions, signal) {
|
|
112663
|
+
signal.throwIfAborted();
|
|
112664
|
+
if (typeof value !== "string" || !value) return false;
|
|
112665
|
+
if (matchesToken2(value, process.env.RUNWEAVE_HOOK_TOKEN)) return true;
|
|
112666
|
+
if (!usesPtyHost()) return false;
|
|
112667
|
+
const session = sessions.getSession(terminalId);
|
|
112668
|
+
const binding = session?.ptyHost;
|
|
112669
|
+
if (!binding || session.status !== "running") return false;
|
|
112670
|
+
const host = await getPtyHost();
|
|
112671
|
+
signal.throwIfAborted();
|
|
112672
|
+
if (host.descriptor.hostInstanceId !== binding.hostInstanceId) return false;
|
|
112673
|
+
const hosted = (await host.request("listSessions", {}, signal)).find(
|
|
112674
|
+
(item) => item.terminalSessionId === terminalId && item.hostInstanceId === binding.hostInstanceId && item.sessionInstanceId === binding.sessionInstanceId
|
|
112675
|
+
);
|
|
112676
|
+
return hosted?.status === "running" && matchesToken2(value, hosted.gatewayToken);
|
|
112677
|
+
}
|
|
112678
|
+
function createRequireTerminalHook(sessions) {
|
|
112679
|
+
return async (req, res, next) => {
|
|
112680
|
+
if (res.destroyed) return;
|
|
112681
|
+
const controller = new AbortController();
|
|
112682
|
+
const cancel = () => controller.abort();
|
|
112683
|
+
const aborted2 = new Promise((_resolve, reject) => {
|
|
112684
|
+
controller.signal.onabort = () => reject(new Error("Terminal authentication aborted"));
|
|
112685
|
+
});
|
|
112686
|
+
const timeout = setTimeout(cancel, 4e3);
|
|
112687
|
+
res.once("close", cancel);
|
|
112688
|
+
try {
|
|
112689
|
+
const authenticated = await Promise.race([
|
|
112690
|
+
authenticatesTerminal(req.headers["x-runweave-hook-token"], String(req.params.id), sessions, controller.signal),
|
|
112691
|
+
aborted2
|
|
112692
|
+
]);
|
|
112693
|
+
controller.signal.throwIfAborted();
|
|
112694
|
+
if (res.destroyed) return;
|
|
112695
|
+
if (!authenticated) {
|
|
112696
|
+
res.sendStatus(401);
|
|
112697
|
+
return;
|
|
112698
|
+
}
|
|
112699
|
+
next();
|
|
112700
|
+
} catch {
|
|
112701
|
+
if (!res.destroyed) res.status(503).json({ code: "DESKTOP_UNAVAILABLE", message: "Terminal runtime authentication is unavailable" });
|
|
112702
|
+
} finally {
|
|
112703
|
+
clearTimeout(timeout);
|
|
112704
|
+
res.off("close", cancel);
|
|
112705
|
+
controller.signal.onabort = null;
|
|
112706
|
+
}
|
|
112707
|
+
};
|
|
112708
|
+
}
|
|
112709
|
+
|
|
112710
|
+
// backend/src/remote/routes.ts
|
|
112579
112711
|
function sendError(res, error2) {
|
|
112580
112712
|
if (error2 instanceof RemoteBrowserError) {
|
|
112581
112713
|
res.status(error2.status).json({ code: error2.code, message: error2.message });
|
|
@@ -112586,14 +112718,11 @@ function sendError(res, error2) {
|
|
|
112586
112718
|
function registerRemoteBrowserRoutes(app, auth, sessions, requireTunnelAuth, browserProfileDir, backendId) {
|
|
112587
112719
|
const bindings = new DesktopBrowserBindings(sessions);
|
|
112588
112720
|
const requireAuth = createRequireAuth(auth);
|
|
112721
|
+
const requireTerminalHook = createRequireTerminalHook(sessions);
|
|
112589
112722
|
registerDesktopNetworkRoutes(app, requireAuth);
|
|
112590
112723
|
registerRemoteCapabilitiesRoute(app, requireTunnelAuth, requireAuth, browserProfileDir, backendId);
|
|
112591
|
-
app.get("/api/terminal/session/:id/runtime-identity", (req, res) => {
|
|
112592
|
-
|
|
112593
|
-
res.sendStatus(401);
|
|
112594
|
-
return;
|
|
112595
|
-
}
|
|
112596
|
-
const session = sessions.getSession(req.params.id);
|
|
112724
|
+
app.get("/api/terminal/session/:id/runtime-identity", requireTerminalHook, (req, res) => {
|
|
112725
|
+
const session = sessions.getSession(String(req.params.id));
|
|
112597
112726
|
if (!session) {
|
|
112598
112727
|
res.status(404).json({ code: "terminal_session_not_found" });
|
|
112599
112728
|
return;
|
|
@@ -112650,18 +112779,14 @@ function registerRemoteBrowserRoutes(app, auth, sessions, requireTunnelAuth, bro
|
|
|
112650
112779
|
sendError(res, error2);
|
|
112651
112780
|
}
|
|
112652
112781
|
});
|
|
112653
|
-
app.post("/api/terminal/session/:id/browser/capability", (req, res) => {
|
|
112654
|
-
if (!matchesHookToken(req.headers["x-runweave-hook-token"], process.env.RUNWEAVE_HOOK_TOKEN)) {
|
|
112655
|
-
res.sendStatus(401);
|
|
112656
|
-
return;
|
|
112657
|
-
}
|
|
112782
|
+
app.post("/api/terminal/session/:id/browser/capability", requireTerminalHook, (req, res) => {
|
|
112658
112783
|
const projectId = req.body?.projectId;
|
|
112659
112784
|
if (typeof projectId !== "string") {
|
|
112660
112785
|
res.sendStatus(400);
|
|
112661
112786
|
return;
|
|
112662
112787
|
}
|
|
112663
112788
|
try {
|
|
112664
|
-
res.json({ capability: bindings.issueCapability(req.params.id, projectId), expiresIn: 3600 });
|
|
112789
|
+
res.json({ capability: bindings.issueCapability(String(req.params.id), projectId), expiresIn: 3600 });
|
|
112665
112790
|
} catch (error2) {
|
|
112666
112791
|
sendError(res, error2);
|
|
112667
112792
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "0.1.0",
|
|
3
|
-
"buildId": "
|
|
4
|
-
"sourceRevision": "
|
|
3
|
+
"buildId": "20261109T123036078Z-da67d523",
|
|
4
|
+
"sourceRevision": "da67d523de925abb4f2b958f949fd50a3ac2b5bb",
|
|
5
5
|
"sourceDirty": false,
|
|
6
|
-
"builtAt": "2026-11-
|
|
6
|
+
"builtAt": "2026-11-09T12:30:36.078Z",
|
|
7
7
|
"contentSha256": "d88edba1ac622f799a43f96f04cacdfb2052f2b959dae733f3feb164b615427b"
|
|
8
8
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<!doctype html>
|
|
2
2
|
<html lang="zh-CN">
|
|
3
|
-
<head><script data-runweave-build-info>var __RUNWEAVE_BUILD_INFO__={"version":"0.1.0","buildId":"
|
|
3
|
+
<head><script data-runweave-build-info>var __RUNWEAVE_BUILD_INFO__={"version":"0.1.0","buildId":"20261109T123036078Z-da67d523","sourceRevision":"da67d523de925abb4f2b958f949fd50a3ac2b5bb","sourceDirty":false,"builtAt":"2026-11-09T12:30:36.078Z","contentSha256":"d88edba1ac622f799a43f96f04cacdfb2052f2b959dae733f3feb164b615427b"};</script>
|
|
4
4
|
|
|
5
5
|
<meta charset="UTF-8" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<!doctype html>
|
|
2
2
|
<html lang="en">
|
|
3
|
-
<head><script data-runweave-build-info>var __RUNWEAVE_BUILD_INFO__={"version":"0.1.0","buildId":"
|
|
3
|
+
<head><script data-runweave-build-info>var __RUNWEAVE_BUILD_INFO__={"version":"0.1.0","buildId":"20261109T123036078Z-da67d523","sourceRevision":"da67d523de925abb4f2b958f949fd50a3ac2b5bb","sourceDirty":false,"builtAt":"2026-11-09T12:30:36.078Z","contentSha256":"d88edba1ac622f799a43f96f04cacdfb2052f2b959dae733f3feb164b615427b"};</script>
|
|
4
4
|
|
|
5
5
|
<meta charset="UTF-8" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
@@ -18953,6 +18953,7 @@ var NEVER = INVALID;
|
|
|
18953
18953
|
// packages/pty-host/src/discovery.ts
|
|
18954
18954
|
var import_node_crypto = require("node:crypto");
|
|
18955
18955
|
var import_node_fs4 = require("node:fs");
|
|
18956
|
+
var import_promises = require("node:fs/promises");
|
|
18956
18957
|
var import_node_path2 = __toESM(require("node:path"), 1);
|
|
18957
18958
|
var import_node_os = __toESM(require("node:os"), 1);
|
|
18958
18959
|
function hostPaths(scope) {
|
|
@@ -18982,10 +18983,27 @@ function prepareHostDirectory(scope) {
|
|
|
18982
18983
|
readPrivateFile(paths.token, 256);
|
|
18983
18984
|
return paths;
|
|
18984
18985
|
}
|
|
18985
|
-
function writeHostJson(file, data) {
|
|
18986
|
+
async function writeHostJson(file, data) {
|
|
18986
18987
|
const temporary = `${file}.${(0, import_node_crypto.randomUUID)()}.tmp`;
|
|
18987
18988
|
(0, import_node_fs4.writeFileSync)(temporary, JSON.stringify(data) + "\n", { mode: 384, flag: "wx" });
|
|
18988
|
-
|
|
18989
|
+
const deadline = Date.now() + 5e3;
|
|
18990
|
+
try {
|
|
18991
|
+
for (; ; ) {
|
|
18992
|
+
try {
|
|
18993
|
+
await (0, import_promises.rename)(temporary, file);
|
|
18994
|
+
return;
|
|
18995
|
+
} catch (error) {
|
|
18996
|
+
if (process.platform !== "win32" || !["EPERM", "EACCES", "EBUSY"].includes(error.code ?? "") || Date.now() >= deadline) throw error;
|
|
18997
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
18998
|
+
}
|
|
18999
|
+
}
|
|
19000
|
+
} catch (error) {
|
|
19001
|
+
try {
|
|
19002
|
+
(0, import_node_fs4.rmSync)(temporary, { force: true });
|
|
19003
|
+
} catch {
|
|
19004
|
+
}
|
|
19005
|
+
throw error;
|
|
19006
|
+
}
|
|
18989
19007
|
}
|
|
18990
19008
|
|
|
18991
19009
|
// packages/pty-host/src/gateway.ts
|
|
@@ -20181,7 +20199,7 @@ async function startHost(scope, release) {
|
|
|
20181
20199
|
gatewayUrl: gateway.url,
|
|
20182
20200
|
release
|
|
20183
20201
|
};
|
|
20184
|
-
writeHostJson(paths.descriptor, descriptor);
|
|
20202
|
+
await writeHostJson(paths.descriptor, descriptor);
|
|
20185
20203
|
process.once("SIGTERM", () => {
|
|
20186
20204
|
void shutdown();
|
|
20187
20205
|
});
|