chatroom-cli 1.38.5 → 1.38.6
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/dist/index.js +116 -97
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -75858,6 +75858,9 @@ function evictStalePendingStops() {
|
|
|
75858
75858
|
pendingStops.delete(runId);
|
|
75859
75859
|
}
|
|
75860
75860
|
}
|
|
75861
|
+
function buildCommandKey(machineId, workingDir, commandName) {
|
|
75862
|
+
return `${machineId}|${workingDir}|${commandName}`;
|
|
75863
|
+
}
|
|
75861
75864
|
async function reportRunFailed(ctx, runId, reason) {
|
|
75862
75865
|
try {
|
|
75863
75866
|
await ctx.deps.backend.mutation(api.commands.updateRunStatus, {
|
|
@@ -75895,9 +75898,42 @@ function appendToBuffer(ctx, tracked, data) {
|
|
|
75895
75898
|
flushOutput(ctx, tracked).catch(() => {});
|
|
75896
75899
|
}
|
|
75897
75900
|
}
|
|
75901
|
+
function killProcess(child, signal) {
|
|
75902
|
+
try {
|
|
75903
|
+
child.kill(signal);
|
|
75904
|
+
} catch {}
|
|
75905
|
+
}
|
|
75906
|
+
function waitForExit(runIdStr, ms) {
|
|
75907
|
+
return new Promise((resolve5) => {
|
|
75908
|
+
const interval = 100;
|
|
75909
|
+
let elapsed3 = 0;
|
|
75910
|
+
const timer = setInterval(() => {
|
|
75911
|
+
if (!runningProcesses.has(runIdStr)) {
|
|
75912
|
+
clearInterval(timer);
|
|
75913
|
+
resolve5(true);
|
|
75914
|
+
return;
|
|
75915
|
+
}
|
|
75916
|
+
elapsed3 += interval;
|
|
75917
|
+
if (elapsed3 >= ms) {
|
|
75918
|
+
clearInterval(timer);
|
|
75919
|
+
resolve5(false);
|
|
75920
|
+
}
|
|
75921
|
+
}, interval);
|
|
75922
|
+
});
|
|
75923
|
+
}
|
|
75924
|
+
async function killTrackedProcess(tracked) {
|
|
75925
|
+
killProcess(tracked.process, "SIGTERM");
|
|
75926
|
+
const exited = await waitForExit(tracked.runId, SIGTERM_GRACE_PERIOD_MS);
|
|
75927
|
+
if (!exited) {
|
|
75928
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDD2A Force-killing process: ${tracked.runId}`);
|
|
75929
|
+
killProcess(tracked.process, "SIGKILL");
|
|
75930
|
+
await waitForExit(tracked.runId, 1000);
|
|
75931
|
+
}
|
|
75932
|
+
}
|
|
75898
75933
|
async function onCommandRun(ctx, event) {
|
|
75899
75934
|
const { workingDir, commandName, script, runId } = event;
|
|
75900
75935
|
const runIdStr = runId.toString();
|
|
75936
|
+
const commandKey = buildCommandKey(ctx.machineId, workingDir, commandName);
|
|
75901
75937
|
if (runningProcesses.has(runIdStr)) {
|
|
75902
75938
|
console.log(`[${formatTimestamp()}] ⚠️ Command already running: ${runIdStr}`);
|
|
75903
75939
|
return;
|
|
@@ -75917,6 +75953,19 @@ async function onCommandRun(ctx, event) {
|
|
|
75917
75953
|
}
|
|
75918
75954
|
return;
|
|
75919
75955
|
}
|
|
75956
|
+
const priorRunId = runningProcessesByCommand.get(commandKey);
|
|
75957
|
+
if (priorRunId) {
|
|
75958
|
+
const priorTracked = runningProcesses.get(priorRunId);
|
|
75959
|
+
if (priorTracked) {
|
|
75960
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDD04 Replacing prior run ${priorRunId} with ${runIdStr} for ${commandName}`);
|
|
75961
|
+
clearInterval(priorTracked.flushTimer);
|
|
75962
|
+
if (priorTracked.softTimeoutTimer)
|
|
75963
|
+
clearTimeout(priorTracked.softTimeoutTimer);
|
|
75964
|
+
await killTrackedProcess(priorTracked);
|
|
75965
|
+
runningProcesses.delete(priorRunId);
|
|
75966
|
+
runningProcessesByCommand.delete(commandKey);
|
|
75967
|
+
}
|
|
75968
|
+
}
|
|
75920
75969
|
console.log(`[${formatTimestamp()}] \uD83D\uDE80 Running command: ${commandName} → ${script}`);
|
|
75921
75970
|
if (!workingDir.startsWith("/")) {
|
|
75922
75971
|
console.error(`[${formatTimestamp()}] ❌ Rejected command: workingDir is not absolute: ${workingDir}`);
|
|
@@ -75933,49 +75982,48 @@ async function onCommandRun(ctx, event) {
|
|
|
75933
75982
|
const child = spawn4("sh", ["-c", script], {
|
|
75934
75983
|
cwd: workingDir,
|
|
75935
75984
|
env: { ...process.env },
|
|
75936
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
75937
|
-
detached: true
|
|
75985
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
75938
75986
|
});
|
|
75939
|
-
const timeoutTimer = setTimeout(() => {
|
|
75940
|
-
console.log(`[${formatTimestamp()}] ⏰ Command timed out after ${DEFAULT_COMMAND_TIMEOUT_MS / 60000} minutes: ${commandName} (runId: ${runIdStr})`);
|
|
75941
|
-
const pid = child.pid;
|
|
75942
|
-
if (pid) {
|
|
75943
|
-
try {
|
|
75944
|
-
process.kill(-pid, "SIGTERM");
|
|
75945
|
-
} catch {
|
|
75946
|
-
child.kill("SIGTERM");
|
|
75947
|
-
}
|
|
75948
|
-
} else {
|
|
75949
|
-
child.kill("SIGTERM");
|
|
75950
|
-
}
|
|
75951
|
-
setTimeout(() => {
|
|
75952
|
-
if (!runningProcesses.has(runIdStr))
|
|
75953
|
-
return;
|
|
75954
|
-
console.log(`[${formatTimestamp()}] \uD83D\uDD2A Force-killing timed-out process: ${runIdStr}`);
|
|
75955
|
-
if (pid) {
|
|
75956
|
-
try {
|
|
75957
|
-
process.kill(-pid, "SIGKILL");
|
|
75958
|
-
} catch {
|
|
75959
|
-
child.kill("SIGKILL");
|
|
75960
|
-
}
|
|
75961
|
-
} else {
|
|
75962
|
-
child.kill("SIGKILL");
|
|
75963
|
-
}
|
|
75964
|
-
}, SIGTERM_GRACE_PERIOD_MS);
|
|
75965
|
-
}, DEFAULT_COMMAND_TIMEOUT_MS);
|
|
75966
|
-
timeoutTimer.unref?.();
|
|
75967
75987
|
const tracked = {
|
|
75968
75988
|
process: child,
|
|
75969
75989
|
runId: runIdStr,
|
|
75990
|
+
commandKey,
|
|
75970
75991
|
outputBuffer: "",
|
|
75971
75992
|
chunkIndex: 0,
|
|
75972
75993
|
flushTimer: setInterval(() => {
|
|
75973
75994
|
flushOutput(ctx, tracked).catch(() => {});
|
|
75974
75995
|
}, OUTPUT_FLUSH_INTERVAL_MS),
|
|
75975
|
-
|
|
75996
|
+
softTimeoutTimer: null
|
|
75976
75997
|
};
|
|
75977
75998
|
tracked.flushTimer.unref?.();
|
|
75978
75999
|
runningProcesses.set(runIdStr, tracked);
|
|
76000
|
+
runningProcessesByCommand.set(commandKey, runIdStr);
|
|
76001
|
+
const softTimeoutTimer = setTimeout(async () => {
|
|
76002
|
+
console.log(`[${formatTimestamp()}] ⏰ Command soft timeout (24h): ${commandName} (runId: ${runIdStr})`);
|
|
76003
|
+
const currentTracked = runningProcesses.get(runIdStr);
|
|
76004
|
+
if (!currentTracked)
|
|
76005
|
+
return;
|
|
76006
|
+
try {
|
|
76007
|
+
await ctx.deps.backend.mutation(api.commands.updateRunStatus, {
|
|
76008
|
+
sessionId: ctx.sessionId,
|
|
76009
|
+
machineId: ctx.machineId,
|
|
76010
|
+
runId,
|
|
76011
|
+
status: "killed",
|
|
76012
|
+
terminationReason: "timeout-24h"
|
|
76013
|
+
});
|
|
76014
|
+
} catch (err) {
|
|
76015
|
+
console.warn(`[${formatTimestamp()}] ⚠️ Failed to mark run as killed (timeout): ${getErrorMessage(err)}`);
|
|
76016
|
+
}
|
|
76017
|
+
killProcess(child, "SIGTERM");
|
|
76018
|
+
setTimeout(() => {
|
|
76019
|
+
if (!runningProcesses.has(runIdStr))
|
|
76020
|
+
return;
|
|
76021
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDD2A Force-killing timed-out process: ${runIdStr}`);
|
|
76022
|
+
killProcess(child, "SIGKILL");
|
|
76023
|
+
}, SIGTERM_GRACE_PERIOD_MS);
|
|
76024
|
+
}, SOFT_TIMEOUT_MS);
|
|
76025
|
+
softTimeoutTimer.unref?.();
|
|
76026
|
+
tracked.softTimeoutTimer = softTimeoutTimer;
|
|
75979
76027
|
try {
|
|
75980
76028
|
await ctx.deps.backend.mutation(api.commands.updateRunStatus, {
|
|
75981
76029
|
sessionId: ctx.sessionId,
|
|
@@ -75997,9 +76045,12 @@ async function onCommandRun(ctx, event) {
|
|
|
75997
76045
|
console.log(`[${formatTimestamp()}] \uD83C\uDFC1 Command exited: ${commandName} (code=${code2}, signal=${signal})`);
|
|
75998
76046
|
await flushOutput(ctx, tracked).catch(() => {});
|
|
75999
76047
|
clearInterval(tracked.flushTimer);
|
|
76000
|
-
if (tracked.
|
|
76001
|
-
clearTimeout(tracked.
|
|
76048
|
+
if (tracked.softTimeoutTimer)
|
|
76049
|
+
clearTimeout(tracked.softTimeoutTimer);
|
|
76002
76050
|
runningProcesses.delete(runIdStr);
|
|
76051
|
+
if (runningProcessesByCommand.get(commandKey) === runIdStr) {
|
|
76052
|
+
runningProcessesByCommand.delete(commandKey);
|
|
76053
|
+
}
|
|
76003
76054
|
const status3 = code2 === 0 ? "completed" : signal ? "stopped" : "failed";
|
|
76004
76055
|
try {
|
|
76005
76056
|
await ctx.deps.backend.mutation(api.commands.updateRunStatus, {
|
|
@@ -76016,9 +76067,12 @@ async function onCommandRun(ctx, event) {
|
|
|
76016
76067
|
child.on("error", async (err) => {
|
|
76017
76068
|
console.error(`[${formatTimestamp()}] ❌ Command spawn failed: ${commandName}: ${err.message}`);
|
|
76018
76069
|
clearInterval(tracked.flushTimer);
|
|
76019
|
-
if (tracked.
|
|
76020
|
-
clearTimeout(tracked.
|
|
76070
|
+
if (tracked.softTimeoutTimer)
|
|
76071
|
+
clearTimeout(tracked.softTimeoutTimer);
|
|
76021
76072
|
runningProcesses.delete(runIdStr);
|
|
76073
|
+
if (runningProcessesByCommand.get(commandKey) === runIdStr) {
|
|
76074
|
+
runningProcessesByCommand.delete(commandKey);
|
|
76075
|
+
}
|
|
76022
76076
|
try {
|
|
76023
76077
|
await ctx.deps.backend.mutation(api.commands.updateRunStatus, {
|
|
76024
76078
|
sessionId: ctx.sessionId,
|
|
@@ -76031,36 +76085,6 @@ async function onCommandRun(ctx, event) {
|
|
|
76031
76085
|
}
|
|
76032
76086
|
});
|
|
76033
76087
|
}
|
|
76034
|
-
function killProcess(child, signal) {
|
|
76035
|
-
const pid = child.pid;
|
|
76036
|
-
if (pid) {
|
|
76037
|
-
try {
|
|
76038
|
-
process.kill(-pid, signal);
|
|
76039
|
-
return;
|
|
76040
|
-
} catch {}
|
|
76041
|
-
}
|
|
76042
|
-
try {
|
|
76043
|
-
child.kill(signal);
|
|
76044
|
-
} catch {}
|
|
76045
|
-
}
|
|
76046
|
-
function waitForExit(runIdStr, ms) {
|
|
76047
|
-
return new Promise((resolve5) => {
|
|
76048
|
-
const interval = 100;
|
|
76049
|
-
let elapsed3 = 0;
|
|
76050
|
-
const timer = setInterval(() => {
|
|
76051
|
-
if (!runningProcesses.has(runIdStr)) {
|
|
76052
|
-
clearInterval(timer);
|
|
76053
|
-
resolve5(true);
|
|
76054
|
-
return;
|
|
76055
|
-
}
|
|
76056
|
-
elapsed3 += interval;
|
|
76057
|
-
if (elapsed3 >= ms) {
|
|
76058
|
-
clearInterval(timer);
|
|
76059
|
-
resolve5(false);
|
|
76060
|
-
}
|
|
76061
|
-
}, interval);
|
|
76062
|
-
});
|
|
76063
|
-
}
|
|
76064
76088
|
async function onCommandStop(ctx, event) {
|
|
76065
76089
|
const runIdStr = event.runId.toString();
|
|
76066
76090
|
const tracked = runningProcesses.get(runIdStr);
|
|
@@ -76081,19 +76105,16 @@ async function onCommandStop(ctx, event) {
|
|
|
76081
76105
|
return;
|
|
76082
76106
|
}
|
|
76083
76107
|
console.log(`[${formatTimestamp()}] \uD83D\uDED1 Stopping command run: ${runIdStr}`);
|
|
76084
|
-
if (tracked.
|
|
76085
|
-
clearTimeout(tracked.
|
|
76086
|
-
tracked.
|
|
76108
|
+
if (tracked.softTimeoutTimer) {
|
|
76109
|
+
clearTimeout(tracked.softTimeoutTimer);
|
|
76110
|
+
tracked.softTimeoutTimer = null;
|
|
76087
76111
|
}
|
|
76088
76112
|
killProcess(tracked.process, "SIGTERM");
|
|
76089
76113
|
const exitedAfterSigterm = await waitForExit(runIdStr, SIGTERM_GRACE_PERIOD_MS);
|
|
76090
76114
|
if (!exitedAfterSigterm) {
|
|
76091
76115
|
console.log(`[${formatTimestamp()}] \uD83D\uDD2A Force-killing process: ${runIdStr}`);
|
|
76092
76116
|
killProcess(tracked.process, "SIGKILL");
|
|
76093
|
-
|
|
76094
|
-
if (!exitedAfterSigkill) {
|
|
76095
|
-
console.error(`[${formatTimestamp()}] ❌ Failed to stop process for run: ${runIdStr} — process did not exit after SIGKILL`);
|
|
76096
|
-
}
|
|
76117
|
+
await waitForExit(runIdStr, 1000);
|
|
76097
76118
|
}
|
|
76098
76119
|
try {
|
|
76099
76120
|
await ctx.deps.backend.mutation(api.commands.updateRunStatus, {
|
|
@@ -76110,49 +76131,47 @@ async function shutdownAllCommands(ctx) {
|
|
|
76110
76131
|
if (runningProcesses.size === 0)
|
|
76111
76132
|
return;
|
|
76112
76133
|
console.log(`[${formatTimestamp()}] Shutting down ${runningProcesses.size} running command(s)...`);
|
|
76113
|
-
|
|
76134
|
+
const trackedEntries = [...runningProcesses.entries()];
|
|
76135
|
+
for (const [, tracked] of trackedEntries) {
|
|
76114
76136
|
clearInterval(tracked.flushTimer);
|
|
76115
|
-
if (tracked.
|
|
76116
|
-
clearTimeout(tracked.
|
|
76137
|
+
if (tracked.softTimeoutTimer)
|
|
76138
|
+
clearTimeout(tracked.softTimeoutTimer);
|
|
76117
76139
|
await flushOutput(ctx, tracked).catch(() => {});
|
|
76118
|
-
|
|
76119
|
-
|
|
76120
|
-
|
|
76121
|
-
|
|
76122
|
-
|
|
76123
|
-
|
|
76124
|
-
|
|
76125
|
-
|
|
76126
|
-
|
|
76140
|
+
try {
|
|
76141
|
+
await ctx.deps.backend.mutation(api.commands.updateRunStatus, {
|
|
76142
|
+
sessionId: ctx.sessionId,
|
|
76143
|
+
machineId: ctx.machineId,
|
|
76144
|
+
runId: tracked.runId,
|
|
76145
|
+
status: "killed",
|
|
76146
|
+
terminationReason: "daemon-shutdown"
|
|
76147
|
+
});
|
|
76148
|
+
} catch (err) {
|
|
76149
|
+
console.warn(`[${formatTimestamp()}] ⚠️ Failed to mark run as killed on shutdown: ${getErrorMessage(err)}`);
|
|
76127
76150
|
}
|
|
76151
|
+
killProcess(tracked.process, "SIGTERM");
|
|
76128
76152
|
}
|
|
76129
76153
|
await new Promise((resolve5) => {
|
|
76130
76154
|
const t = setTimeout(resolve5, 3000);
|
|
76131
76155
|
t.unref?.();
|
|
76132
76156
|
});
|
|
76133
|
-
for (const [, tracked] of
|
|
76134
|
-
|
|
76135
|
-
|
|
76136
|
-
try {
|
|
76137
|
-
process.kill(-pid, "SIGKILL");
|
|
76138
|
-
} catch {}
|
|
76139
|
-
} else {
|
|
76140
|
-
try {
|
|
76141
|
-
tracked.process.kill("SIGKILL");
|
|
76142
|
-
} catch {}
|
|
76157
|
+
for (const [, tracked] of trackedEntries) {
|
|
76158
|
+
if (runningProcesses.has(tracked.runId)) {
|
|
76159
|
+
killProcess(tracked.process, "SIGKILL");
|
|
76143
76160
|
}
|
|
76144
76161
|
}
|
|
76145
76162
|
runningProcesses.clear();
|
|
76163
|
+
runningProcessesByCommand.clear();
|
|
76146
76164
|
console.log(`[${formatTimestamp()}] All commands stopped`);
|
|
76147
76165
|
}
|
|
76148
|
-
var runningProcesses, pendingStops, PENDING_STOP_TTL_MS = 60000, OUTPUT_FLUSH_INTERVAL_MS = 3000, MAX_BUFFER_SIZE,
|
|
76166
|
+
var runningProcesses, runningProcessesByCommand, pendingStops, PENDING_STOP_TTL_MS = 60000, OUTPUT_FLUSH_INTERVAL_MS = 3000, MAX_BUFFER_SIZE, SOFT_TIMEOUT_MS, SIGTERM_GRACE_PERIOD_MS = 5000;
|
|
76149
76167
|
var init_command_runner = __esm(() => {
|
|
76150
76168
|
init_api3();
|
|
76151
76169
|
init_convex_error();
|
|
76152
76170
|
runningProcesses = new Map;
|
|
76171
|
+
runningProcessesByCommand = new Map;
|
|
76153
76172
|
pendingStops = new Map;
|
|
76154
76173
|
MAX_BUFFER_SIZE = 100 * 1024;
|
|
76155
|
-
|
|
76174
|
+
SOFT_TIMEOUT_MS = 24 * 60 * 60 * 1000;
|
|
76156
76175
|
});
|
|
76157
76176
|
|
|
76158
76177
|
// src/commands/machine/daemon-start/handlers/ping.ts
|
|
@@ -79289,5 +79308,5 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
|
79289
79308
|
});
|
|
79290
79309
|
program2.parse();
|
|
79291
79310
|
|
|
79292
|
-
//# debugId=
|
|
79311
|
+
//# debugId=1884CBA22481288264756E2164756E21
|
|
79293
79312
|
//# sourceMappingURL=index.js.map
|