chatroom-cli 1.0.79 → 1.0.81
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 +93 -13
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10263,7 +10263,12 @@ class ProcessDriver {
|
|
|
10263
10263
|
return {
|
|
10264
10264
|
success: true,
|
|
10265
10265
|
message: "Agent spawned successfully",
|
|
10266
|
-
handle
|
|
10266
|
+
handle,
|
|
10267
|
+
onExit: (callback) => {
|
|
10268
|
+
childProcess.on("exit", (code2, signal) => {
|
|
10269
|
+
callback(code2, signal);
|
|
10270
|
+
});
|
|
10271
|
+
}
|
|
10267
10272
|
};
|
|
10268
10273
|
} catch (error) {
|
|
10269
10274
|
return {
|
|
@@ -10276,7 +10281,26 @@ class ProcessDriver {
|
|
|
10276
10281
|
if (handle.type !== "process" || !handle.pid) {
|
|
10277
10282
|
throw new Error(`Cannot stop: handle has no PID (type=${handle.type})`);
|
|
10278
10283
|
}
|
|
10279
|
-
|
|
10284
|
+
const pid = handle.pid;
|
|
10285
|
+
try {
|
|
10286
|
+
process.kill(pid, "SIGTERM");
|
|
10287
|
+
} catch {
|
|
10288
|
+
return;
|
|
10289
|
+
}
|
|
10290
|
+
const KILL_TIMEOUT_MS = 5000;
|
|
10291
|
+
const POLL_INTERVAL_MS = 200;
|
|
10292
|
+
const deadline = Date.now() + KILL_TIMEOUT_MS;
|
|
10293
|
+
while (Date.now() < deadline) {
|
|
10294
|
+
try {
|
|
10295
|
+
process.kill(pid, 0);
|
|
10296
|
+
} catch {
|
|
10297
|
+
return;
|
|
10298
|
+
}
|
|
10299
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
10300
|
+
}
|
|
10301
|
+
try {
|
|
10302
|
+
process.kill(pid, "SIGKILL");
|
|
10303
|
+
} catch {}
|
|
10280
10304
|
}
|
|
10281
10305
|
async isAlive(handle) {
|
|
10282
10306
|
if (handle.type !== "process" || !handle.pid) {
|
|
@@ -10677,6 +10701,9 @@ var init_register_agent = __esm(() => {
|
|
|
10677
10701
|
init_client2();
|
|
10678
10702
|
init_machine();
|
|
10679
10703
|
});
|
|
10704
|
+
|
|
10705
|
+
// ../../services/backend/config/reliability.ts
|
|
10706
|
+
var HEARTBEAT_INTERVAL_MS = 30000, HEARTBEAT_TTL_MS = 60000, DAEMON_HEARTBEAT_INTERVAL_MS = 30000;
|
|
10680
10707
|
// ../../services/backend/prompts/base/cli/task-started/command.ts
|
|
10681
10708
|
function taskStartedCommand(params) {
|
|
10682
10709
|
const prefix = params.cliEnvPrefix || "";
|
|
@@ -10904,6 +10931,7 @@ async function waitForTask(chatroomId, options) {
|
|
|
10904
10931
|
sessionId,
|
|
10905
10932
|
chatroomId,
|
|
10906
10933
|
role,
|
|
10934
|
+
readyUntil: Date.now() + HEARTBEAT_TTL_MS,
|
|
10907
10935
|
connectionId
|
|
10908
10936
|
});
|
|
10909
10937
|
const connectionTime = new Date().toISOString().replace("T", " ").substring(0, 19);
|
|
@@ -10911,12 +10939,11 @@ async function waitForTask(chatroomId, options) {
|
|
|
10911
10939
|
console.log(`[${connectionTime}] ⏳ Connecting to chatroom as "${role}"...`);
|
|
10912
10940
|
}
|
|
10913
10941
|
try {
|
|
10914
|
-
const convexUrl2 = getConvexUrl();
|
|
10915
10942
|
const initPromptResult = await client2.query(api.messages.getInitPrompt, {
|
|
10916
10943
|
sessionId,
|
|
10917
10944
|
chatroomId,
|
|
10918
10945
|
role,
|
|
10919
|
-
convexUrl
|
|
10946
|
+
convexUrl
|
|
10920
10947
|
});
|
|
10921
10948
|
if (initPromptResult?.prompt) {
|
|
10922
10949
|
const connectedTime = new Date().toISOString().replace("T", " ").substring(0, 19);
|
|
@@ -10941,6 +10968,33 @@ async function waitForTask(chatroomId, options) {
|
|
|
10941
10968
|
}
|
|
10942
10969
|
}
|
|
10943
10970
|
} catch {}
|
|
10971
|
+
const heartbeatTimer = setInterval(() => {
|
|
10972
|
+
client2.mutation(api.participants.heartbeat, {
|
|
10973
|
+
sessionId,
|
|
10974
|
+
chatroomId,
|
|
10975
|
+
role,
|
|
10976
|
+
connectionId
|
|
10977
|
+
}).catch((err) => {
|
|
10978
|
+
if (!silent) {
|
|
10979
|
+
console.warn(`⚠️ Heartbeat failed: ${err.message}`);
|
|
10980
|
+
}
|
|
10981
|
+
});
|
|
10982
|
+
}, HEARTBEAT_INTERVAL_MS);
|
|
10983
|
+
heartbeatTimer.unref();
|
|
10984
|
+
let cleanedUp = false;
|
|
10985
|
+
const cleanup = async () => {
|
|
10986
|
+
if (cleanedUp)
|
|
10987
|
+
return;
|
|
10988
|
+
cleanedUp = true;
|
|
10989
|
+
clearInterval(heartbeatTimer);
|
|
10990
|
+
try {
|
|
10991
|
+
await client2.mutation(api.participants.leave, {
|
|
10992
|
+
sessionId,
|
|
10993
|
+
chatroomId,
|
|
10994
|
+
role
|
|
10995
|
+
});
|
|
10996
|
+
} catch {}
|
|
10997
|
+
};
|
|
10944
10998
|
let taskProcessed = false;
|
|
10945
10999
|
let unsubscribe = null;
|
|
10946
11000
|
const handlePendingTasks = async (pendingTasks) => {
|
|
@@ -10954,6 +11008,8 @@ async function waitForTask(chatroomId, options) {
|
|
|
10954
11008
|
if (currentConnectionId && currentConnectionId !== connectionId) {
|
|
10955
11009
|
if (unsubscribe)
|
|
10956
11010
|
unsubscribe();
|
|
11011
|
+
clearInterval(heartbeatTimer);
|
|
11012
|
+
cleanedUp = true;
|
|
10957
11013
|
const takeoverTime = new Date().toISOString().replace("T", " ").substring(0, 19);
|
|
10958
11014
|
console.log(`
|
|
10959
11015
|
${"─".repeat(50)}`);
|
|
@@ -11004,6 +11060,8 @@ ${"─".repeat(50)}`);
|
|
|
11004
11060
|
}
|
|
11005
11061
|
if (unsubscribe)
|
|
11006
11062
|
unsubscribe();
|
|
11063
|
+
clearInterval(heartbeatTimer);
|
|
11064
|
+
cleanedUp = true;
|
|
11007
11065
|
const activeUntil = Date.now() + DEFAULT_ACTIVE_TIMEOUT_MS;
|
|
11008
11066
|
await client2.mutation(api.participants.updateStatus, {
|
|
11009
11067
|
sessionId,
|
|
@@ -11040,18 +11098,20 @@ ${"─".repeat(50)}`);
|
|
|
11040
11098
|
const handleSignal = (_signal) => {
|
|
11041
11099
|
if (unsubscribe)
|
|
11042
11100
|
unsubscribe();
|
|
11043
|
-
|
|
11044
|
-
|
|
11101
|
+
cleanup().finally(() => {
|
|
11102
|
+
const signalTime = new Date().toISOString().replace("T", " ").substring(0, 19);
|
|
11103
|
+
console.log(`
|
|
11045
11104
|
${"─".repeat(50)}`);
|
|
11046
|
-
|
|
11105
|
+
console.log(`⚠️ RECONNECTION REQUIRED
|
|
11047
11106
|
`);
|
|
11048
|
-
|
|
11049
|
-
|
|
11050
|
-
|
|
11107
|
+
console.log(`[${signalTime}] Why: Process interrupted (unexpected termination)`);
|
|
11108
|
+
console.log(`Impact: You are no longer listening for tasks`);
|
|
11109
|
+
console.log(`Action: Run this command immediately to resume availability
|
|
11051
11110
|
`);
|
|
11052
|
-
|
|
11053
|
-
|
|
11054
|
-
|
|
11111
|
+
console.log(waitForTaskCommand({ chatroomId, role, cliEnvPrefix }));
|
|
11112
|
+
console.log(`${"─".repeat(50)}`);
|
|
11113
|
+
process.exit(0);
|
|
11114
|
+
});
|
|
11055
11115
|
};
|
|
11056
11116
|
process.on("SIGINT", () => handleSignal("SIGINT"));
|
|
11057
11117
|
process.on("SIGTERM", () => handleSignal("SIGTERM"));
|
|
@@ -13066,6 +13126,16 @@ async function handleStartAgent(ctx, command) {
|
|
|
13066
13126
|
} catch (e) {
|
|
13067
13127
|
console.log(` ⚠️ Failed to update PID in backend: ${e.message}`);
|
|
13068
13128
|
}
|
|
13129
|
+
if (startResult.onExit) {
|
|
13130
|
+
const spawnedPid = startResult.handle.pid;
|
|
13131
|
+
startResult.onExit((code2, signal) => {
|
|
13132
|
+
const ts = formatTimestamp();
|
|
13133
|
+
console.log(`[${ts}] ⚠️ Agent process exited unexpectedly ` + `(PID: ${spawnedPid}, role: ${role}, code: ${code2}, signal: ${signal})`);
|
|
13134
|
+
clearAgentPidEverywhere(ctx, chatroomId, role).catch((err) => {
|
|
13135
|
+
console.log(` ⚠️ Failed to clear PID after exit: ${err.message}`);
|
|
13136
|
+
});
|
|
13137
|
+
});
|
|
13138
|
+
}
|
|
13069
13139
|
}
|
|
13070
13140
|
return { result: msg, failed: false };
|
|
13071
13141
|
}
|
|
@@ -13326,9 +13396,19 @@ Run any chatroom command first to register this machine,`);
|
|
|
13326
13396
|
return ctx;
|
|
13327
13397
|
}
|
|
13328
13398
|
async function startCommandLoop(ctx) {
|
|
13399
|
+
const heartbeatTimer = setInterval(() => {
|
|
13400
|
+
ctx.client.mutation(api.machines.daemonHeartbeat, {
|
|
13401
|
+
sessionId: ctx.sessionId,
|
|
13402
|
+
machineId: ctx.machineId
|
|
13403
|
+
}).catch((err) => {
|
|
13404
|
+
console.warn(`[${formatTimestamp()}] ⚠️ Daemon heartbeat failed: ${err.message}`);
|
|
13405
|
+
});
|
|
13406
|
+
}, DAEMON_HEARTBEAT_INTERVAL_MS);
|
|
13407
|
+
heartbeatTimer.unref();
|
|
13329
13408
|
const shutdown = async () => {
|
|
13330
13409
|
console.log(`
|
|
13331
13410
|
[${formatTimestamp()}] Shutting down...`);
|
|
13411
|
+
clearInterval(heartbeatTimer);
|
|
13332
13412
|
try {
|
|
13333
13413
|
await ctx.client.mutation(api.machines.updateDaemonStatus, {
|
|
13334
13414
|
sessionId: ctx.sessionId,
|