chatroom-cli 1.0.79 → 1.0.82
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 +112 -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 = 90000, 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,46 @@ 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
|
+
}).then((result) => {
|
|
10978
|
+
if (result?.status === "rejoin_required") {
|
|
10979
|
+
if (!silent) {
|
|
10980
|
+
console.warn(`⚠️ Participant record missing — re-joining chatroom`);
|
|
10981
|
+
}
|
|
10982
|
+
return client2.mutation(api.participants.join, {
|
|
10983
|
+
sessionId,
|
|
10984
|
+
chatroomId,
|
|
10985
|
+
role,
|
|
10986
|
+
readyUntil: Date.now() + HEARTBEAT_TTL_MS,
|
|
10987
|
+
connectionId
|
|
10988
|
+
});
|
|
10989
|
+
}
|
|
10990
|
+
}).catch((err) => {
|
|
10991
|
+
if (!silent) {
|
|
10992
|
+
console.warn(`⚠️ Heartbeat failed: ${err.message}`);
|
|
10993
|
+
}
|
|
10994
|
+
});
|
|
10995
|
+
}, HEARTBEAT_INTERVAL_MS);
|
|
10996
|
+
heartbeatTimer.unref();
|
|
10997
|
+
let cleanedUp = false;
|
|
10998
|
+
const cleanup = async () => {
|
|
10999
|
+
if (cleanedUp)
|
|
11000
|
+
return;
|
|
11001
|
+
cleanedUp = true;
|
|
11002
|
+
clearInterval(heartbeatTimer);
|
|
11003
|
+
try {
|
|
11004
|
+
await client2.mutation(api.participants.leave, {
|
|
11005
|
+
sessionId,
|
|
11006
|
+
chatroomId,
|
|
11007
|
+
role
|
|
11008
|
+
});
|
|
11009
|
+
} catch {}
|
|
11010
|
+
};
|
|
10944
11011
|
let taskProcessed = false;
|
|
10945
11012
|
let unsubscribe = null;
|
|
10946
11013
|
const handlePendingTasks = async (pendingTasks) => {
|
|
@@ -10954,6 +11021,8 @@ async function waitForTask(chatroomId, options) {
|
|
|
10954
11021
|
if (currentConnectionId && currentConnectionId !== connectionId) {
|
|
10955
11022
|
if (unsubscribe)
|
|
10956
11023
|
unsubscribe();
|
|
11024
|
+
clearInterval(heartbeatTimer);
|
|
11025
|
+
cleanedUp = true;
|
|
10957
11026
|
const takeoverTime = new Date().toISOString().replace("T", " ").substring(0, 19);
|
|
10958
11027
|
console.log(`
|
|
10959
11028
|
${"─".repeat(50)}`);
|
|
@@ -11004,6 +11073,8 @@ ${"─".repeat(50)}`);
|
|
|
11004
11073
|
}
|
|
11005
11074
|
if (unsubscribe)
|
|
11006
11075
|
unsubscribe();
|
|
11076
|
+
clearInterval(heartbeatTimer);
|
|
11077
|
+
cleanedUp = true;
|
|
11007
11078
|
const activeUntil = Date.now() + DEFAULT_ACTIVE_TIMEOUT_MS;
|
|
11008
11079
|
await client2.mutation(api.participants.updateStatus, {
|
|
11009
11080
|
sessionId,
|
|
@@ -11040,18 +11111,20 @@ ${"─".repeat(50)}`);
|
|
|
11040
11111
|
const handleSignal = (_signal) => {
|
|
11041
11112
|
if (unsubscribe)
|
|
11042
11113
|
unsubscribe();
|
|
11043
|
-
|
|
11044
|
-
|
|
11114
|
+
cleanup().finally(() => {
|
|
11115
|
+
const signalTime = new Date().toISOString().replace("T", " ").substring(0, 19);
|
|
11116
|
+
console.log(`
|
|
11045
11117
|
${"─".repeat(50)}`);
|
|
11046
|
-
|
|
11118
|
+
console.log(`⚠️ RECONNECTION REQUIRED
|
|
11047
11119
|
`);
|
|
11048
|
-
|
|
11049
|
-
|
|
11050
|
-
|
|
11120
|
+
console.log(`[${signalTime}] Why: Process interrupted (unexpected termination)`);
|
|
11121
|
+
console.log(`Impact: You are no longer listening for tasks`);
|
|
11122
|
+
console.log(`Action: Run this command immediately to resume availability
|
|
11051
11123
|
`);
|
|
11052
|
-
|
|
11053
|
-
|
|
11054
|
-
|
|
11124
|
+
console.log(waitForTaskCommand({ chatroomId, role, cliEnvPrefix }));
|
|
11125
|
+
console.log(`${"─".repeat(50)}`);
|
|
11126
|
+
process.exit(0);
|
|
11127
|
+
});
|
|
11055
11128
|
};
|
|
11056
11129
|
process.on("SIGINT", () => handleSignal("SIGINT"));
|
|
11057
11130
|
process.on("SIGTERM", () => handleSignal("SIGTERM"));
|
|
@@ -13066,6 +13139,16 @@ async function handleStartAgent(ctx, command) {
|
|
|
13066
13139
|
} catch (e) {
|
|
13067
13140
|
console.log(` ⚠️ Failed to update PID in backend: ${e.message}`);
|
|
13068
13141
|
}
|
|
13142
|
+
if (startResult.onExit) {
|
|
13143
|
+
const spawnedPid = startResult.handle.pid;
|
|
13144
|
+
startResult.onExit((code2, signal) => {
|
|
13145
|
+
const ts = formatTimestamp();
|
|
13146
|
+
console.log(`[${ts}] ⚠️ Agent process exited unexpectedly ` + `(PID: ${spawnedPid}, role: ${role}, code: ${code2}, signal: ${signal})`);
|
|
13147
|
+
clearAgentPidEverywhere(ctx, chatroomId, role).catch((err) => {
|
|
13148
|
+
console.log(` ⚠️ Failed to clear PID after exit: ${err.message}`);
|
|
13149
|
+
});
|
|
13150
|
+
});
|
|
13151
|
+
}
|
|
13069
13152
|
}
|
|
13070
13153
|
return { result: msg, failed: false };
|
|
13071
13154
|
}
|
|
@@ -13310,6 +13393,7 @@ Run any chatroom command first to register this machine,`);
|
|
|
13310
13393
|
}
|
|
13311
13394
|
const ctx = { client: client2, sessionId: typedSessionId, machineId, config: config3 };
|
|
13312
13395
|
console.log(`[${formatTimestamp()}] \uD83D\uDE80 Daemon started`);
|
|
13396
|
+
console.log(` CLI version: ${getVersion()}`);
|
|
13313
13397
|
console.log(` Machine ID: ${machineId}`);
|
|
13314
13398
|
console.log(` Hostname: ${config3?.hostname ?? "Unknown"}`);
|
|
13315
13399
|
console.log(` Available harnesses: ${config3?.availableHarnesses.join(", ") || "none"}`);
|
|
@@ -13326,9 +13410,23 @@ Run any chatroom command first to register this machine,`);
|
|
|
13326
13410
|
return ctx;
|
|
13327
13411
|
}
|
|
13328
13412
|
async function startCommandLoop(ctx) {
|
|
13413
|
+
let heartbeatCount = 0;
|
|
13414
|
+
const heartbeatTimer = setInterval(() => {
|
|
13415
|
+
ctx.client.mutation(api.machines.daemonHeartbeat, {
|
|
13416
|
+
sessionId: ctx.sessionId,
|
|
13417
|
+
machineId: ctx.machineId
|
|
13418
|
+
}).then(() => {
|
|
13419
|
+
heartbeatCount++;
|
|
13420
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDC93 Daemon heartbeat #${heartbeatCount} OK`);
|
|
13421
|
+
}).catch((err) => {
|
|
13422
|
+
console.warn(`[${formatTimestamp()}] ⚠️ Daemon heartbeat failed: ${err.message}`);
|
|
13423
|
+
});
|
|
13424
|
+
}, DAEMON_HEARTBEAT_INTERVAL_MS);
|
|
13425
|
+
heartbeatTimer.unref();
|
|
13329
13426
|
const shutdown = async () => {
|
|
13330
13427
|
console.log(`
|
|
13331
13428
|
[${formatTimestamp()}] Shutting down...`);
|
|
13429
|
+
clearInterval(heartbeatTimer);
|
|
13332
13430
|
try {
|
|
13333
13431
|
await ctx.client.mutation(api.machines.updateDaemonStatus, {
|
|
13334
13432
|
sessionId: ctx.sessionId,
|
|
@@ -13424,6 +13522,7 @@ var init_daemon_start = __esm(() => {
|
|
|
13424
13522
|
init_storage();
|
|
13425
13523
|
init_client2();
|
|
13426
13524
|
init_machine();
|
|
13525
|
+
init_version();
|
|
13427
13526
|
MODEL_REFRESH_INTERVAL_MS = 5 * 60 * 1000;
|
|
13428
13527
|
});
|
|
13429
13528
|
|