chatroom-cli 1.2.3 → 1.2.7
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 +314 -396
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10371,6 +10371,20 @@ function listAgentEntries(machineId) {
|
|
|
10371
10371
|
}
|
|
10372
10372
|
return results;
|
|
10373
10373
|
}
|
|
10374
|
+
function persistEventCursor(machineId, lastSeenEventId) {
|
|
10375
|
+
try {
|
|
10376
|
+
const state = loadOrCreate(machineId);
|
|
10377
|
+
state.lastSeenEventId = lastSeenEventId;
|
|
10378
|
+
state.updatedAt = new Date().toISOString();
|
|
10379
|
+
saveDaemonState(state);
|
|
10380
|
+
} catch (err) {
|
|
10381
|
+
console.warn(`⚠️ Failed to persist event cursor: ${err.message}`);
|
|
10382
|
+
}
|
|
10383
|
+
}
|
|
10384
|
+
function loadEventCursor(machineId) {
|
|
10385
|
+
const state = loadDaemonState(machineId);
|
|
10386
|
+
return state?.lastSeenEventId ?? null;
|
|
10387
|
+
}
|
|
10374
10388
|
var CHATROOM_DIR3, STATE_DIR, STATE_VERSION = "1";
|
|
10375
10389
|
var init_daemon_state = __esm(() => {
|
|
10376
10390
|
CHATROOM_DIR3 = join4(homedir3(), ".chatroom");
|
|
@@ -11284,22 +11298,9 @@ async function registerAgent(chatroomId, options, deps) {
|
|
|
11284
11298
|
harnessVersions: machineInfo.harnessVersions,
|
|
11285
11299
|
availableModels
|
|
11286
11300
|
});
|
|
11287
|
-
const agentHarness = machineInfo.availableHarnesses.length > 0 ? machineInfo.availableHarnesses[0] : undefined;
|
|
11288
|
-
await d.backend.mutation(api.machines.saveTeamAgentConfig, {
|
|
11289
|
-
sessionId,
|
|
11290
|
-
chatroomId,
|
|
11291
|
-
role,
|
|
11292
|
-
type: "remote",
|
|
11293
|
-
machineId: machineInfo.machineId,
|
|
11294
|
-
agentHarness,
|
|
11295
|
-
workingDir: process.cwd()
|
|
11296
|
-
});
|
|
11297
11301
|
console.log(`✅ Registered as remote agent for role "${role}"`);
|
|
11298
11302
|
console.log(` Machine: ${machineInfo.hostname} (${machineInfo.machineId})`);
|
|
11299
11303
|
console.log(` Working directory: ${process.cwd()}`);
|
|
11300
|
-
if (agentHarness) {
|
|
11301
|
-
console.log(` Agent harness: ${agentHarness}`);
|
|
11302
|
-
}
|
|
11303
11304
|
} catch (error) {
|
|
11304
11305
|
console.error(`❌ Registration failed: ${error.message}`);
|
|
11305
11306
|
process.exit(1);
|
|
@@ -11327,7 +11328,7 @@ var init_register_agent = __esm(() => {
|
|
|
11327
11328
|
init_opencode();
|
|
11328
11329
|
init_pi();
|
|
11329
11330
|
});
|
|
11330
|
-
// ../../services/backend/prompts/
|
|
11331
|
+
// ../../services/backend/prompts/cli/task-started/command.ts
|
|
11331
11332
|
function taskStartedCommand(params) {
|
|
11332
11333
|
const prefix = params.cliEnvPrefix || "";
|
|
11333
11334
|
const chatroomId = params.chatroomId || "<chatroom-id>";
|
|
@@ -11351,22 +11352,22 @@ EOF`;
|
|
|
11351
11352
|
return baseCmd;
|
|
11352
11353
|
}
|
|
11353
11354
|
|
|
11354
|
-
// ../../services/backend/prompts/
|
|
11355
|
+
// ../../services/backend/prompts/cli/task-started/classification/new-feature.ts
|
|
11355
11356
|
var init_new_feature = () => {};
|
|
11356
|
-
// ../../services/backend/prompts/
|
|
11357
|
+
// ../../services/backend/prompts/cli/task-started/classification/index.ts
|
|
11357
11358
|
var init_classification = __esm(() => {
|
|
11358
11359
|
init_new_feature();
|
|
11359
11360
|
});
|
|
11360
|
-
// ../../services/backend/prompts/
|
|
11361
|
+
// ../../services/backend/prompts/cli/task-started/main-prompt.ts
|
|
11361
11362
|
var init_main_prompt = () => {};
|
|
11362
11363
|
|
|
11363
|
-
// ../../services/backend/prompts/
|
|
11364
|
+
// ../../services/backend/prompts/cli/task-started/index.ts
|
|
11364
11365
|
var init_task_started = __esm(() => {
|
|
11365
11366
|
init_classification();
|
|
11366
11367
|
init_main_prompt();
|
|
11367
11368
|
});
|
|
11368
11369
|
|
|
11369
|
-
// ../../services/backend/prompts/
|
|
11370
|
+
// ../../services/backend/prompts/cli/get-next-task/reminder.ts
|
|
11370
11371
|
function getNextTaskGuidance() {
|
|
11371
11372
|
return `\uD83D\uDD17 STAYING CONNECTED TO YOUR TEAM
|
|
11372
11373
|
|
|
@@ -11455,7 +11456,7 @@ var init_getting_started_content = __esm(() => {
|
|
|
11455
11456
|
init_utils();
|
|
11456
11457
|
});
|
|
11457
11458
|
|
|
11458
|
-
// ../../services/backend/prompts/
|
|
11459
|
+
// ../../services/backend/prompts/cli/index.ts
|
|
11459
11460
|
var init_cli = __esm(() => {
|
|
11460
11461
|
init_task_started();
|
|
11461
11462
|
init_reminder();
|
|
@@ -11481,7 +11482,7 @@ var init_errorCodes = __esm(() => {
|
|
|
11481
11482
|
];
|
|
11482
11483
|
});
|
|
11483
11484
|
|
|
11484
|
-
// ../../services/backend/prompts/
|
|
11485
|
+
// ../../services/backend/prompts/cli/get-next-task/command.ts
|
|
11485
11486
|
function getNextTaskCommand(params) {
|
|
11486
11487
|
const prefix = params.cliEnvPrefix || "";
|
|
11487
11488
|
const chatroomId = params.chatroomId || "<chatroom-id>";
|
|
@@ -12182,7 +12183,7 @@ function formatDecodeError(error) {
|
|
|
12182
12183
|
return message;
|
|
12183
12184
|
}
|
|
12184
12185
|
|
|
12185
|
-
// ../../services/backend/prompts/
|
|
12186
|
+
// ../../services/backend/prompts/cli/handoff/command.ts
|
|
12186
12187
|
function handoffCommand(params) {
|
|
12187
12188
|
const prefix = params.cliEnvPrefix || "";
|
|
12188
12189
|
const chatroomId = params.chatroomId || "<chatroom-id>";
|
|
@@ -13656,6 +13657,7 @@ async function getSystemPrompt(chatroomId, options, deps) {
|
|
|
13656
13657
|
const prompt = await d.backend.query(api.prompts.webapp.getAgentPrompt, {
|
|
13657
13658
|
chatroomId,
|
|
13658
13659
|
role,
|
|
13660
|
+
teamId: chatroom.teamId,
|
|
13659
13661
|
teamName: chatroom.teamName,
|
|
13660
13662
|
teamRoles: chatroom.teamRoles,
|
|
13661
13663
|
teamEntryPoint: chatroom.teamEntryPoint,
|
|
@@ -13676,56 +13678,14 @@ var init_get_system_prompt = __esm(() => {
|
|
|
13676
13678
|
});
|
|
13677
13679
|
|
|
13678
13680
|
// ../../services/backend/config/reliability.ts
|
|
13679
|
-
var DAEMON_HEARTBEAT_INTERVAL_MS = 30000;
|
|
13681
|
+
var DAEMON_HEARTBEAT_INTERVAL_MS = 30000, AGENT_REQUEST_DEADLINE_MS = 120000;
|
|
13680
13682
|
|
|
13681
13683
|
// src/commands/machine/daemon-start/utils.ts
|
|
13682
13684
|
function formatTimestamp() {
|
|
13683
13685
|
return new Date().toISOString().replace("T", " ").substring(0, 19);
|
|
13684
13686
|
}
|
|
13685
|
-
function parseMachineCommand(raw) {
|
|
13686
|
-
switch (raw.type) {
|
|
13687
|
-
case "ping":
|
|
13688
|
-
return { _id: raw._id, type: "ping", payload: {}, createdAt: raw.createdAt };
|
|
13689
|
-
case "status":
|
|
13690
|
-
return { _id: raw._id, type: "status", payload: {}, createdAt: raw.createdAt };
|
|
13691
|
-
case "start-agent": {
|
|
13692
|
-
const { chatroomId, role, agentHarness } = raw.payload;
|
|
13693
|
-
if (!chatroomId || !role || !agentHarness) {
|
|
13694
|
-
console.error(` ⚠️ Invalid start-agent command: missing chatroomId, role, or agentHarness`);
|
|
13695
|
-
return null;
|
|
13696
|
-
}
|
|
13697
|
-
return {
|
|
13698
|
-
_id: raw._id,
|
|
13699
|
-
type: "start-agent",
|
|
13700
|
-
payload: {
|
|
13701
|
-
chatroomId,
|
|
13702
|
-
role,
|
|
13703
|
-
agentHarness,
|
|
13704
|
-
model: raw.payload.model,
|
|
13705
|
-
workingDir: raw.payload.workingDir
|
|
13706
|
-
},
|
|
13707
|
-
createdAt: raw.createdAt
|
|
13708
|
-
};
|
|
13709
|
-
}
|
|
13710
|
-
case "stop-agent": {
|
|
13711
|
-
const { chatroomId, role } = raw.payload;
|
|
13712
|
-
if (!chatroomId || !role) {
|
|
13713
|
-
console.error(` ⚠️ Invalid stop-agent command: missing chatroomId or role`);
|
|
13714
|
-
return null;
|
|
13715
|
-
}
|
|
13716
|
-
return {
|
|
13717
|
-
_id: raw._id,
|
|
13718
|
-
type: "stop-agent",
|
|
13719
|
-
payload: { chatroomId, role },
|
|
13720
|
-
createdAt: raw.createdAt
|
|
13721
|
-
};
|
|
13722
|
-
}
|
|
13723
|
-
default:
|
|
13724
|
-
return null;
|
|
13725
|
-
}
|
|
13726
|
-
}
|
|
13727
13687
|
|
|
13728
|
-
// src/
|
|
13688
|
+
// src/events/lifecycle/on-agent-shutdown.ts
|
|
13729
13689
|
async function onAgentShutdown(ctx, options) {
|
|
13730
13690
|
const { chatroomId, role, pid, skipKill } = options;
|
|
13731
13691
|
try {
|
|
@@ -13784,42 +13744,13 @@ async function onAgentShutdown(ctx, options) {
|
|
|
13784
13744
|
console.log(` ⚠️ Failed to clear local PID for ${role}: ${e.message}`);
|
|
13785
13745
|
}
|
|
13786
13746
|
}
|
|
13787
|
-
let spawnedAgentCleared = false;
|
|
13788
|
-
if (killed || skipKill) {
|
|
13789
|
-
try {
|
|
13790
|
-
await ctx.deps.backend.mutation(api.machines.updateSpawnedAgent, {
|
|
13791
|
-
sessionId: ctx.sessionId,
|
|
13792
|
-
machineId: ctx.machineId,
|
|
13793
|
-
chatroomId,
|
|
13794
|
-
role,
|
|
13795
|
-
pid: undefined
|
|
13796
|
-
});
|
|
13797
|
-
spawnedAgentCleared = true;
|
|
13798
|
-
} catch (e) {
|
|
13799
|
-
console.log(` ⚠️ Failed to clear spawnedAgent for ${role}: ${e.message}`);
|
|
13800
|
-
}
|
|
13801
|
-
}
|
|
13802
|
-
let participantRemoved = false;
|
|
13803
|
-
try {
|
|
13804
|
-
await ctx.deps.backend.mutation(api.participants.leave, {
|
|
13805
|
-
sessionId: ctx.sessionId,
|
|
13806
|
-
chatroomId,
|
|
13807
|
-
role
|
|
13808
|
-
});
|
|
13809
|
-
participantRemoved = true;
|
|
13810
|
-
} catch (e) {
|
|
13811
|
-
console.log(` ⚠️ Failed to remove participant for ${role}: ${e.message}`);
|
|
13812
|
-
}
|
|
13813
13747
|
return {
|
|
13814
13748
|
killed: killed || (skipKill ?? false),
|
|
13815
|
-
cleaned:
|
|
13749
|
+
cleaned: killed || (skipKill ?? false)
|
|
13816
13750
|
};
|
|
13817
13751
|
}
|
|
13818
|
-
var init_on_agent_shutdown = __esm(() => {
|
|
13819
|
-
init_api3();
|
|
13820
|
-
});
|
|
13821
13752
|
|
|
13822
|
-
// src/
|
|
13753
|
+
// src/events/lifecycle/on-daemon-shutdown.ts
|
|
13823
13754
|
async function onDaemonShutdown(ctx) {
|
|
13824
13755
|
const agents = ctx.deps.machine.listAgentEntries(ctx.machineId);
|
|
13825
13756
|
if (agents.length > 0) {
|
|
@@ -13858,108 +13789,18 @@ async function onDaemonShutdown(ctx) {
|
|
|
13858
13789
|
var AGENT_SHUTDOWN_TIMEOUT_MS = 5000;
|
|
13859
13790
|
var init_on_daemon_shutdown = __esm(() => {
|
|
13860
13791
|
init_api3();
|
|
13861
|
-
init_on_agent_shutdown();
|
|
13862
13792
|
});
|
|
13863
13793
|
|
|
13864
|
-
// src/commands/machine/pid.ts
|
|
13865
|
-
import { createHash } from "node:crypto";
|
|
13866
|
-
import { existsSync as existsSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4, unlinkSync as unlinkSync2, mkdirSync as mkdirSync4 } from "node:fs";
|
|
13867
|
-
import { homedir as homedir4 } from "node:os";
|
|
13868
|
-
import { join as join5 } from "node:path";
|
|
13869
|
-
function getUrlHash() {
|
|
13870
|
-
const url = getConvexUrl();
|
|
13871
|
-
return createHash("sha256").update(url).digest("hex").substring(0, 8);
|
|
13872
|
-
}
|
|
13873
|
-
function getPidFileName() {
|
|
13874
|
-
return `daemon-${getUrlHash()}.pid`;
|
|
13875
|
-
}
|
|
13876
|
-
function ensureChatroomDir() {
|
|
13877
|
-
if (!existsSync4(CHATROOM_DIR4)) {
|
|
13878
|
-
mkdirSync4(CHATROOM_DIR4, { recursive: true, mode: 448 });
|
|
13879
|
-
}
|
|
13880
|
-
}
|
|
13881
|
-
function getPidFilePath() {
|
|
13882
|
-
return join5(CHATROOM_DIR4, getPidFileName());
|
|
13883
|
-
}
|
|
13884
|
-
function isProcessRunning(pid) {
|
|
13885
|
-
try {
|
|
13886
|
-
process.kill(pid, 0);
|
|
13887
|
-
return true;
|
|
13888
|
-
} catch {
|
|
13889
|
-
return false;
|
|
13890
|
-
}
|
|
13891
|
-
}
|
|
13892
|
-
function readPid() {
|
|
13893
|
-
const pidPath = getPidFilePath();
|
|
13894
|
-
if (!existsSync4(pidPath)) {
|
|
13895
|
-
return null;
|
|
13896
|
-
}
|
|
13897
|
-
try {
|
|
13898
|
-
const content = readFileSync6(pidPath, "utf-8").trim();
|
|
13899
|
-
const pid = parseInt(content, 10);
|
|
13900
|
-
if (isNaN(pid) || pid <= 0) {
|
|
13901
|
-
return null;
|
|
13902
|
-
}
|
|
13903
|
-
return pid;
|
|
13904
|
-
} catch {
|
|
13905
|
-
return null;
|
|
13906
|
-
}
|
|
13907
|
-
}
|
|
13908
|
-
function writePid() {
|
|
13909
|
-
ensureChatroomDir();
|
|
13910
|
-
const pidPath = getPidFilePath();
|
|
13911
|
-
writeFileSync4(pidPath, process.pid.toString(), "utf-8");
|
|
13912
|
-
}
|
|
13913
|
-
function removePid() {
|
|
13914
|
-
const pidPath = getPidFilePath();
|
|
13915
|
-
try {
|
|
13916
|
-
if (existsSync4(pidPath)) {
|
|
13917
|
-
unlinkSync2(pidPath);
|
|
13918
|
-
}
|
|
13919
|
-
} catch {}
|
|
13920
|
-
}
|
|
13921
|
-
function isDaemonRunning() {
|
|
13922
|
-
const pid = readPid();
|
|
13923
|
-
if (pid === null) {
|
|
13924
|
-
return { running: false, pid: null };
|
|
13925
|
-
}
|
|
13926
|
-
if (isProcessRunning(pid)) {
|
|
13927
|
-
return { running: true, pid };
|
|
13928
|
-
}
|
|
13929
|
-
removePid();
|
|
13930
|
-
return { running: false, pid: null };
|
|
13931
|
-
}
|
|
13932
|
-
function acquireLock() {
|
|
13933
|
-
const { running, pid } = isDaemonRunning();
|
|
13934
|
-
if (running) {
|
|
13935
|
-
console.error(`❌ Daemon already running for ${getConvexUrl()} (PID: ${pid})`);
|
|
13936
|
-
return false;
|
|
13937
|
-
}
|
|
13938
|
-
writePid();
|
|
13939
|
-
return true;
|
|
13940
|
-
}
|
|
13941
|
-
function releaseLock() {
|
|
13942
|
-
removePid();
|
|
13943
|
-
}
|
|
13944
|
-
var CHATROOM_DIR4;
|
|
13945
|
-
var init_pid = __esm(() => {
|
|
13946
|
-
init_client2();
|
|
13947
|
-
CHATROOM_DIR4 = join5(homedir4(), ".chatroom");
|
|
13948
|
-
});
|
|
13949
|
-
|
|
13950
|
-
// src/commands/machine/daemon-start/handlers/ping.ts
|
|
13951
|
-
function handlePing() {
|
|
13952
|
-
console.log(` ↪ Responding: pong`);
|
|
13953
|
-
return { result: "pong", failed: false };
|
|
13954
|
-
}
|
|
13955
|
-
|
|
13956
13794
|
// src/commands/machine/daemon-start/handlers/start-agent.ts
|
|
13957
|
-
async function
|
|
13958
|
-
const { chatroomId, role, agentHarness, model, workingDir } =
|
|
13795
|
+
async function executeStartAgent(ctx, args) {
|
|
13796
|
+
const { chatroomId, role, agentHarness, model, workingDir, reason } = args;
|
|
13959
13797
|
console.log(` ↪ start-agent command received`);
|
|
13960
13798
|
console.log(` Chatroom: ${chatroomId}`);
|
|
13961
13799
|
console.log(` Role: ${role}`);
|
|
13962
13800
|
console.log(` Harness: ${agentHarness}`);
|
|
13801
|
+
if (reason) {
|
|
13802
|
+
console.log(` Reason: ${reason}`);
|
|
13803
|
+
}
|
|
13963
13804
|
if (model) {
|
|
13964
13805
|
console.log(` Model: ${model}`);
|
|
13965
13806
|
}
|
|
@@ -13987,14 +13828,19 @@ async function handleStartAgent(ctx, command) {
|
|
|
13987
13828
|
chatroomId
|
|
13988
13829
|
});
|
|
13989
13830
|
const existingConfig = existingConfigs.configs.find((c) => c.machineId === ctx.machineId && c.role.toLowerCase() === role.toLowerCase());
|
|
13990
|
-
|
|
13991
|
-
|
|
13992
|
-
|
|
13993
|
-
|
|
13831
|
+
const backendPid = existingConfig?.spawnedAgentPid;
|
|
13832
|
+
const localEntry = ctx.deps.machine.listAgentEntries(ctx.machineId).find((e) => e.chatroomId === chatroomId && e.role.toLowerCase() === role.toLowerCase());
|
|
13833
|
+
const localPid = localEntry?.entry.pid;
|
|
13834
|
+
const pidsToKill = [
|
|
13835
|
+
...new Set([backendPid, localPid].filter((p) => p !== undefined))
|
|
13836
|
+
];
|
|
13837
|
+
const anyService = ctx.agentServices.values().next().value;
|
|
13838
|
+
for (const pid2 of pidsToKill) {
|
|
13839
|
+
const isAlive = anyService ? anyService.isAlive(pid2) : false;
|
|
13994
13840
|
if (isAlive) {
|
|
13995
|
-
console.log(` ⚠️ Existing agent detected (PID: ${
|
|
13996
|
-
await onAgentShutdown(ctx, { chatroomId, role, pid:
|
|
13997
|
-
console.log(` ✅ Existing agent stopped`);
|
|
13841
|
+
console.log(` ⚠️ Existing agent detected (PID: ${pid2}) — stopping before respawn`);
|
|
13842
|
+
await onAgentShutdown(ctx, { chatroomId, role, pid: pid2 });
|
|
13843
|
+
console.log(` ✅ Existing agent stopped (PID: ${pid2})`);
|
|
13998
13844
|
}
|
|
13999
13845
|
}
|
|
14000
13846
|
} catch (e) {
|
|
@@ -14085,19 +13931,26 @@ async function handleStartAgent(ctx, command) {
|
|
|
14085
13931
|
var init_start_agent = __esm(() => {
|
|
14086
13932
|
init_api3();
|
|
14087
13933
|
init_client2();
|
|
14088
|
-
init_on_agent_shutdown();
|
|
14089
13934
|
});
|
|
14090
13935
|
|
|
14091
|
-
// src/
|
|
14092
|
-
function
|
|
14093
|
-
|
|
14094
|
-
|
|
14095
|
-
|
|
14096
|
-
|
|
13936
|
+
// src/events/daemon/agent/on-request-start-agent.ts
|
|
13937
|
+
async function onRequestStartAgent(ctx, event) {
|
|
13938
|
+
if (Date.now() > event.deadline) {
|
|
13939
|
+
console.log(`[daemon] ⏰ Skipping expired agent.requestStart for role=${event.role} (deadline passed)`);
|
|
13940
|
+
return;
|
|
13941
|
+
}
|
|
13942
|
+
await executeStartAgent(ctx, {
|
|
13943
|
+
chatroomId: event.chatroomId,
|
|
13944
|
+
role: event.role,
|
|
13945
|
+
agentHarness: event.agentHarness,
|
|
13946
|
+
model: event.model,
|
|
13947
|
+
workingDir: event.workingDir,
|
|
13948
|
+
reason: event.reason
|
|
14097
13949
|
});
|
|
14098
|
-
console.log(` ↪ Responding with status`);
|
|
14099
|
-
return { result, failed: false };
|
|
14100
13950
|
}
|
|
13951
|
+
var init_on_request_start_agent = __esm(() => {
|
|
13952
|
+
init_start_agent();
|
|
13953
|
+
});
|
|
14101
13954
|
|
|
14102
13955
|
// src/commands/machine/daemon-start/handlers/shared.ts
|
|
14103
13956
|
async function clearAgentPidEverywhere(ctx, chatroomId, role) {
|
|
@@ -14119,8 +13972,8 @@ var init_shared = __esm(() => {
|
|
|
14119
13972
|
});
|
|
14120
13973
|
|
|
14121
13974
|
// src/commands/machine/daemon-start/handlers/stop-agent.ts
|
|
14122
|
-
async function
|
|
14123
|
-
const { chatroomId, role } =
|
|
13975
|
+
async function executeStopAgent(ctx, args) {
|
|
13976
|
+
const { chatroomId, role } = args;
|
|
14124
13977
|
console.log(` ↪ stop-agent command received`);
|
|
14125
13978
|
console.log(` Chatroom: ${chatroomId}`);
|
|
14126
13979
|
console.log(` Role: ${role}`);
|
|
@@ -14129,53 +13982,178 @@ async function handleStopAgent(ctx, command) {
|
|
|
14129
13982
|
chatroomId
|
|
14130
13983
|
});
|
|
14131
13984
|
const targetConfig = configsResult.configs.find((c) => c.machineId === ctx.machineId && c.role.toLowerCase() === role.toLowerCase());
|
|
14132
|
-
|
|
13985
|
+
const backendPid = targetConfig?.spawnedAgentPid;
|
|
13986
|
+
const localEntry = ctx.deps.machine.listAgentEntries(ctx.machineId).find((e) => e.chatroomId === chatroomId && e.role.toLowerCase() === role.toLowerCase());
|
|
13987
|
+
const localPid = localEntry?.entry.pid;
|
|
13988
|
+
const allPids = [...new Set([backendPid, localPid].filter((p) => p !== undefined))];
|
|
13989
|
+
if (allPids.length === 0) {
|
|
14133
13990
|
const msg = "No running agent found (no PID recorded)";
|
|
14134
13991
|
console.log(` ⚠️ ${msg}`);
|
|
14135
13992
|
return { result: msg, failed: true };
|
|
14136
13993
|
}
|
|
14137
|
-
const pidToKill = targetConfig.spawnedAgentPid;
|
|
14138
|
-
console.log(` Stopping agent with PID: ${pidToKill}`);
|
|
14139
13994
|
const anyService = ctx.agentServices.values().next().value;
|
|
14140
|
-
|
|
14141
|
-
|
|
14142
|
-
|
|
14143
|
-
|
|
14144
|
-
|
|
13995
|
+
let anyKilled = false;
|
|
13996
|
+
let lastError = null;
|
|
13997
|
+
for (const pid of allPids) {
|
|
13998
|
+
console.log(` Stopping agent with PID: ${pid}`);
|
|
13999
|
+
const isAlive = anyService ? anyService.isAlive(pid) : false;
|
|
14000
|
+
if (!isAlive) {
|
|
14001
|
+
console.log(` ⚠️ PID ${pid} not found — process already exited or was never started`);
|
|
14002
|
+
await clearAgentPidEverywhere(ctx, chatroomId, role);
|
|
14003
|
+
console.log(` Cleared stale PID`);
|
|
14004
|
+
try {
|
|
14005
|
+
await ctx.deps.backend.mutation(api.participants.leave, {
|
|
14006
|
+
sessionId: ctx.sessionId,
|
|
14007
|
+
chatroomId,
|
|
14008
|
+
role
|
|
14009
|
+
});
|
|
14010
|
+
console.log(` Removed participant record`);
|
|
14011
|
+
} catch {}
|
|
14012
|
+
continue;
|
|
14013
|
+
}
|
|
14145
14014
|
try {
|
|
14146
|
-
await ctx
|
|
14147
|
-
sessionId: ctx.sessionId,
|
|
14015
|
+
const shutdownResult = await onAgentShutdown(ctx, {
|
|
14148
14016
|
chatroomId,
|
|
14149
|
-
role
|
|
14017
|
+
role,
|
|
14018
|
+
pid
|
|
14150
14019
|
});
|
|
14151
|
-
|
|
14152
|
-
|
|
14153
|
-
|
|
14154
|
-
|
|
14155
|
-
|
|
14156
|
-
}
|
|
14020
|
+
const msg = shutdownResult.killed ? `Agent stopped (PID: ${pid})` : `Agent stop attempted (PID: ${pid}) — process may still be running`;
|
|
14021
|
+
console.log(` ${shutdownResult.killed ? "✅" : "⚠️ "} ${msg}`);
|
|
14022
|
+
if (shutdownResult.killed) {
|
|
14023
|
+
anyKilled = true;
|
|
14024
|
+
}
|
|
14025
|
+
} catch (e) {
|
|
14026
|
+
lastError = e;
|
|
14027
|
+
console.log(` ⚠️ Failed to stop agent (PID: ${pid}): ${e.message}`);
|
|
14028
|
+
}
|
|
14157
14029
|
}
|
|
14158
|
-
|
|
14159
|
-
const
|
|
14160
|
-
chatroomId,
|
|
14161
|
-
role,
|
|
14162
|
-
pid: pidToKill
|
|
14163
|
-
});
|
|
14164
|
-
const msg = shutdownResult.killed ? `Agent stopped (PID: ${pidToKill})` : `Agent stop attempted (PID: ${pidToKill}) — process may still be running`;
|
|
14165
|
-
console.log(` ${shutdownResult.killed ? "✅" : "⚠️ "} ${msg}`);
|
|
14166
|
-
return { result: msg, failed: !shutdownResult.killed };
|
|
14167
|
-
} catch (e) {
|
|
14168
|
-
const msg = `Failed to stop agent: ${e.message}`;
|
|
14030
|
+
if (lastError && !anyKilled) {
|
|
14031
|
+
const msg = `Failed to stop agent: ${lastError.message}`;
|
|
14169
14032
|
console.log(` ⚠️ ${msg}`);
|
|
14170
14033
|
return { result: msg, failed: true };
|
|
14171
14034
|
}
|
|
14035
|
+
if (!anyKilled) {
|
|
14036
|
+
return {
|
|
14037
|
+
result: `All recorded PIDs appear stale (processes not found or belong to different programs)`,
|
|
14038
|
+
failed: true
|
|
14039
|
+
};
|
|
14040
|
+
}
|
|
14041
|
+
const killedCount = allPids.length > 1 ? ` (${allPids.length} PIDs)` : ``;
|
|
14042
|
+
return { result: `Agent stopped${killedCount}`, failed: false };
|
|
14172
14043
|
}
|
|
14173
14044
|
var init_stop_agent = __esm(() => {
|
|
14174
14045
|
init_api3();
|
|
14175
|
-
init_on_agent_shutdown();
|
|
14176
14046
|
init_shared();
|
|
14177
14047
|
});
|
|
14178
14048
|
|
|
14049
|
+
// src/events/daemon/agent/on-request-stop-agent.ts
|
|
14050
|
+
async function onRequestStopAgent(ctx, event) {
|
|
14051
|
+
if (Date.now() > event.deadline) {
|
|
14052
|
+
console.log(`[daemon] ⏰ Skipping expired agent.requestStop for role=${event.role} (deadline passed)`);
|
|
14053
|
+
return;
|
|
14054
|
+
}
|
|
14055
|
+
await executeStopAgent(ctx, {
|
|
14056
|
+
chatroomId: event.chatroomId,
|
|
14057
|
+
role: event.role,
|
|
14058
|
+
reason: event.reason
|
|
14059
|
+
});
|
|
14060
|
+
}
|
|
14061
|
+
var init_on_request_stop_agent = __esm(() => {
|
|
14062
|
+
init_stop_agent();
|
|
14063
|
+
});
|
|
14064
|
+
|
|
14065
|
+
// src/commands/machine/pid.ts
|
|
14066
|
+
import { createHash } from "node:crypto";
|
|
14067
|
+
import { existsSync as existsSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4, unlinkSync as unlinkSync2, mkdirSync as mkdirSync4 } from "node:fs";
|
|
14068
|
+
import { homedir as homedir4 } from "node:os";
|
|
14069
|
+
import { join as join5 } from "node:path";
|
|
14070
|
+
function getUrlHash() {
|
|
14071
|
+
const url = getConvexUrl();
|
|
14072
|
+
return createHash("sha256").update(url).digest("hex").substring(0, 8);
|
|
14073
|
+
}
|
|
14074
|
+
function getPidFileName() {
|
|
14075
|
+
return `daemon-${getUrlHash()}.pid`;
|
|
14076
|
+
}
|
|
14077
|
+
function ensureChatroomDir() {
|
|
14078
|
+
if (!existsSync4(CHATROOM_DIR4)) {
|
|
14079
|
+
mkdirSync4(CHATROOM_DIR4, { recursive: true, mode: 448 });
|
|
14080
|
+
}
|
|
14081
|
+
}
|
|
14082
|
+
function getPidFilePath() {
|
|
14083
|
+
return join5(CHATROOM_DIR4, getPidFileName());
|
|
14084
|
+
}
|
|
14085
|
+
function isProcessRunning(pid) {
|
|
14086
|
+
try {
|
|
14087
|
+
process.kill(pid, 0);
|
|
14088
|
+
return true;
|
|
14089
|
+
} catch {
|
|
14090
|
+
return false;
|
|
14091
|
+
}
|
|
14092
|
+
}
|
|
14093
|
+
function readPid() {
|
|
14094
|
+
const pidPath = getPidFilePath();
|
|
14095
|
+
if (!existsSync4(pidPath)) {
|
|
14096
|
+
return null;
|
|
14097
|
+
}
|
|
14098
|
+
try {
|
|
14099
|
+
const content = readFileSync6(pidPath, "utf-8").trim();
|
|
14100
|
+
const pid = parseInt(content, 10);
|
|
14101
|
+
if (isNaN(pid) || pid <= 0) {
|
|
14102
|
+
return null;
|
|
14103
|
+
}
|
|
14104
|
+
return pid;
|
|
14105
|
+
} catch {
|
|
14106
|
+
return null;
|
|
14107
|
+
}
|
|
14108
|
+
}
|
|
14109
|
+
function writePid() {
|
|
14110
|
+
ensureChatroomDir();
|
|
14111
|
+
const pidPath = getPidFilePath();
|
|
14112
|
+
writeFileSync4(pidPath, process.pid.toString(), "utf-8");
|
|
14113
|
+
}
|
|
14114
|
+
function removePid() {
|
|
14115
|
+
const pidPath = getPidFilePath();
|
|
14116
|
+
try {
|
|
14117
|
+
if (existsSync4(pidPath)) {
|
|
14118
|
+
unlinkSync2(pidPath);
|
|
14119
|
+
}
|
|
14120
|
+
} catch {}
|
|
14121
|
+
}
|
|
14122
|
+
function isDaemonRunning() {
|
|
14123
|
+
const pid = readPid();
|
|
14124
|
+
if (pid === null) {
|
|
14125
|
+
return { running: false, pid: null };
|
|
14126
|
+
}
|
|
14127
|
+
if (isProcessRunning(pid)) {
|
|
14128
|
+
return { running: true, pid };
|
|
14129
|
+
}
|
|
14130
|
+
removePid();
|
|
14131
|
+
return { running: false, pid: null };
|
|
14132
|
+
}
|
|
14133
|
+
function acquireLock() {
|
|
14134
|
+
const { running, pid } = isDaemonRunning();
|
|
14135
|
+
if (running) {
|
|
14136
|
+
console.error(`❌ Daemon already running for ${getConvexUrl()} (PID: ${pid})`);
|
|
14137
|
+
return false;
|
|
14138
|
+
}
|
|
14139
|
+
writePid();
|
|
14140
|
+
return true;
|
|
14141
|
+
}
|
|
14142
|
+
function releaseLock() {
|
|
14143
|
+
removePid();
|
|
14144
|
+
}
|
|
14145
|
+
var CHATROOM_DIR4;
|
|
14146
|
+
var init_pid = __esm(() => {
|
|
14147
|
+
init_client2();
|
|
14148
|
+
CHATROOM_DIR4 = join5(homedir4(), ".chatroom");
|
|
14149
|
+
});
|
|
14150
|
+
|
|
14151
|
+
// src/commands/machine/daemon-start/handlers/ping.ts
|
|
14152
|
+
function handlePing() {
|
|
14153
|
+
console.log(` ↪ Responding: pong`);
|
|
14154
|
+
return { result: "pong", failed: false };
|
|
14155
|
+
}
|
|
14156
|
+
|
|
14179
14157
|
// src/commands/machine/daemon-start/command-loop.ts
|
|
14180
14158
|
async function refreshModels(ctx) {
|
|
14181
14159
|
const models = {};
|
|
@@ -14204,70 +14182,6 @@ async function refreshModels(ctx) {
|
|
|
14204
14182
|
console.warn(`[${formatTimestamp()}] ⚠️ Model refresh failed: ${error.message}`);
|
|
14205
14183
|
}
|
|
14206
14184
|
}
|
|
14207
|
-
async function processCommand(ctx, command) {
|
|
14208
|
-
console.log(`[${formatTimestamp()}] \uD83D\uDCE8 Command received: ${command.type}`);
|
|
14209
|
-
try {
|
|
14210
|
-
await ctx.deps.backend.mutation(api.machines.ackCommand, {
|
|
14211
|
-
sessionId: ctx.sessionId,
|
|
14212
|
-
commandId: command._id,
|
|
14213
|
-
status: "processing"
|
|
14214
|
-
});
|
|
14215
|
-
ctx.events.emit("command:processing", {
|
|
14216
|
-
commandId: command._id.toString(),
|
|
14217
|
-
type: command.type
|
|
14218
|
-
});
|
|
14219
|
-
let commandResult;
|
|
14220
|
-
switch (command.type) {
|
|
14221
|
-
case "ping":
|
|
14222
|
-
commandResult = handlePing();
|
|
14223
|
-
break;
|
|
14224
|
-
case "status":
|
|
14225
|
-
commandResult = handleStatus(ctx);
|
|
14226
|
-
break;
|
|
14227
|
-
case "start-agent":
|
|
14228
|
-
commandResult = await handleStartAgent(ctx, command);
|
|
14229
|
-
break;
|
|
14230
|
-
case "stop-agent":
|
|
14231
|
-
commandResult = await handleStopAgent(ctx, command);
|
|
14232
|
-
break;
|
|
14233
|
-
default: {
|
|
14234
|
-
const _exhaustive = command;
|
|
14235
|
-
commandResult = {
|
|
14236
|
-
result: `Unknown command type: ${_exhaustive.type}`,
|
|
14237
|
-
failed: true
|
|
14238
|
-
};
|
|
14239
|
-
}
|
|
14240
|
-
}
|
|
14241
|
-
const finalStatus = commandResult.failed ? "failed" : "completed";
|
|
14242
|
-
await ctx.deps.backend.mutation(api.machines.ackCommand, {
|
|
14243
|
-
sessionId: ctx.sessionId,
|
|
14244
|
-
commandId: command._id,
|
|
14245
|
-
status: finalStatus,
|
|
14246
|
-
result: commandResult.result
|
|
14247
|
-
});
|
|
14248
|
-
ctx.events.emit("command:completed", {
|
|
14249
|
-
commandId: command._id.toString(),
|
|
14250
|
-
type: command.type,
|
|
14251
|
-
failed: commandResult.failed,
|
|
14252
|
-
result: commandResult.result
|
|
14253
|
-
});
|
|
14254
|
-
if (commandResult.failed) {
|
|
14255
|
-
console.log(` ❌ Command failed: ${commandResult.result}`);
|
|
14256
|
-
} else {
|
|
14257
|
-
console.log(` ✅ Command completed`);
|
|
14258
|
-
}
|
|
14259
|
-
} catch (error) {
|
|
14260
|
-
console.error(` ❌ Command failed: ${error.message}`);
|
|
14261
|
-
try {
|
|
14262
|
-
await ctx.deps.backend.mutation(api.machines.ackCommand, {
|
|
14263
|
-
sessionId: ctx.sessionId,
|
|
14264
|
-
commandId: command._id,
|
|
14265
|
-
status: "failed",
|
|
14266
|
-
result: error.message
|
|
14267
|
-
});
|
|
14268
|
-
} catch {}
|
|
14269
|
-
}
|
|
14270
|
-
}
|
|
14271
14185
|
async function startCommandLoop(ctx) {
|
|
14272
14186
|
let heartbeatCount = 0;
|
|
14273
14187
|
const heartbeatTimer = setInterval(() => {
|
|
@@ -14294,66 +14208,56 @@ async function startCommandLoop(ctx) {
|
|
|
14294
14208
|
process.on("SIGTERM", shutdown);
|
|
14295
14209
|
process.on("SIGHUP", shutdown);
|
|
14296
14210
|
const wsClient2 = await getConvexWsClient();
|
|
14297
|
-
const commandQueue = [];
|
|
14298
|
-
const queuedCommandIds = new Set;
|
|
14299
|
-
let drainingQueue = false;
|
|
14300
|
-
const enqueueCommands = (commands) => {
|
|
14301
|
-
for (const command of commands) {
|
|
14302
|
-
const commandId = command._id.toString();
|
|
14303
|
-
if (queuedCommandIds.has(commandId))
|
|
14304
|
-
continue;
|
|
14305
|
-
queuedCommandIds.add(commandId);
|
|
14306
|
-
commandQueue.push(command);
|
|
14307
|
-
}
|
|
14308
|
-
};
|
|
14309
|
-
const drainQueue = async () => {
|
|
14310
|
-
if (drainingQueue)
|
|
14311
|
-
return;
|
|
14312
|
-
drainingQueue = true;
|
|
14313
|
-
try {
|
|
14314
|
-
while (commandQueue.length > 0) {
|
|
14315
|
-
const command = commandQueue.shift();
|
|
14316
|
-
const commandId = command._id.toString();
|
|
14317
|
-
queuedCommandIds.delete(commandId);
|
|
14318
|
-
try {
|
|
14319
|
-
await processCommand(ctx, command);
|
|
14320
|
-
} catch (error) {
|
|
14321
|
-
console.error(` ❌ Command processing failed: ${error.message}`);
|
|
14322
|
-
}
|
|
14323
|
-
}
|
|
14324
|
-
} finally {
|
|
14325
|
-
drainingQueue = false;
|
|
14326
|
-
}
|
|
14327
|
-
};
|
|
14328
14211
|
console.log(`
|
|
14329
14212
|
Listening for commands...`);
|
|
14330
14213
|
console.log(`Press Ctrl+C to stop
|
|
14331
14214
|
`);
|
|
14332
|
-
|
|
14215
|
+
const processedCommandIds = new Map;
|
|
14216
|
+
const processedPingIds = new Map;
|
|
14217
|
+
wsClient2.onUpdate(api.machines.getCommandEvents, {
|
|
14333
14218
|
sessionId: ctx.sessionId,
|
|
14334
14219
|
machineId: ctx.machineId
|
|
14335
14220
|
}, async (result) => {
|
|
14336
|
-
if (!result.
|
|
14221
|
+
if (!result.events || result.events.length === 0)
|
|
14337
14222
|
return;
|
|
14338
|
-
const
|
|
14339
|
-
for (const
|
|
14340
|
-
|
|
14341
|
-
|
|
14342
|
-
|
|
14343
|
-
|
|
14344
|
-
|
|
14345
|
-
|
|
14223
|
+
const evictBefore = Date.now() - AGENT_REQUEST_DEADLINE_MS;
|
|
14224
|
+
for (const [id, ts] of processedCommandIds) {
|
|
14225
|
+
if (ts < evictBefore)
|
|
14226
|
+
processedCommandIds.delete(id);
|
|
14227
|
+
}
|
|
14228
|
+
for (const [id, ts] of processedPingIds) {
|
|
14229
|
+
if (ts < evictBefore)
|
|
14230
|
+
processedPingIds.delete(id);
|
|
14231
|
+
}
|
|
14232
|
+
for (const event of result.events) {
|
|
14233
|
+
const eventId = event._id.toString();
|
|
14234
|
+
try {
|
|
14235
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDCE1 Stream command event: ${event.type}`);
|
|
14236
|
+
if (event.type === "agent.requestStart") {
|
|
14237
|
+
if (processedCommandIds.has(eventId))
|
|
14238
|
+
continue;
|
|
14239
|
+
processedCommandIds.set(eventId, Date.now());
|
|
14240
|
+
await onRequestStartAgent(ctx, event);
|
|
14241
|
+
} else if (event.type === "agent.requestStop") {
|
|
14242
|
+
if (processedCommandIds.has(eventId))
|
|
14243
|
+
continue;
|
|
14244
|
+
processedCommandIds.set(eventId, Date.now());
|
|
14245
|
+
await onRequestStopAgent(ctx, event);
|
|
14246
|
+
} else if (event.type === "daemon.ping") {
|
|
14247
|
+
if (processedPingIds.has(eventId))
|
|
14248
|
+
continue;
|
|
14249
|
+
processedPingIds.set(eventId, Date.now());
|
|
14250
|
+
handlePing();
|
|
14251
|
+
await ctx.deps.backend.mutation(api.machines.ackPing, {
|
|
14346
14252
|
sessionId: ctx.sessionId,
|
|
14347
|
-
|
|
14348
|
-
|
|
14349
|
-
result: `Invalid command: type="${raw.type}" missing required payload fields`
|
|
14253
|
+
machineId: ctx.machineId,
|
|
14254
|
+
pingEventId: event._id
|
|
14350
14255
|
});
|
|
14351
|
-
|
|
14352
|
-
|
|
14256
|
+
}
|
|
14257
|
+
} catch (err) {
|
|
14258
|
+
console.error(`[${formatTimestamp()}] ❌ Stream command event failed: ${err.message}`);
|
|
14353
14259
|
}
|
|
14354
14260
|
}
|
|
14355
|
-
enqueueCommands(parsed);
|
|
14356
|
-
await drainQueue();
|
|
14357
14261
|
});
|
|
14358
14262
|
const modelRefreshTimer = setInterval(() => {
|
|
14359
14263
|
refreshModels(ctx).catch((err) => {
|
|
@@ -14368,9 +14272,9 @@ var init_command_loop = __esm(() => {
|
|
|
14368
14272
|
init_api3();
|
|
14369
14273
|
init_client2();
|
|
14370
14274
|
init_on_daemon_shutdown();
|
|
14275
|
+
init_on_request_start_agent();
|
|
14276
|
+
init_on_request_stop_agent();
|
|
14371
14277
|
init_pid();
|
|
14372
|
-
init_start_agent();
|
|
14373
|
-
init_stop_agent();
|
|
14374
14278
|
MODEL_REFRESH_INTERVAL_MS = 5 * 60 * 1000;
|
|
14375
14279
|
});
|
|
14376
14280
|
|
|
@@ -14402,7 +14306,7 @@ var init_state_recovery = __esm(() => {
|
|
|
14402
14306
|
init_shared();
|
|
14403
14307
|
});
|
|
14404
14308
|
|
|
14405
|
-
// src/
|
|
14309
|
+
// src/events/daemon/event-bus.ts
|
|
14406
14310
|
class DaemonEventBus {
|
|
14407
14311
|
listeners = new Map;
|
|
14408
14312
|
on(event, listener) {
|
|
@@ -14431,54 +14335,66 @@ class DaemonEventBus {
|
|
|
14431
14335
|
}
|
|
14432
14336
|
}
|
|
14433
14337
|
|
|
14434
|
-
// src/
|
|
14338
|
+
// src/events/daemon/agent/on-agent-exited.ts
|
|
14339
|
+
function onAgentExited(ctx, payload) {
|
|
14340
|
+
const { chatroomId, role, pid, code: code2, signal, intentional } = payload;
|
|
14341
|
+
const ts = formatTimestamp();
|
|
14342
|
+
if (intentional) {
|
|
14343
|
+
console.log(`[${ts}] ℹ️ Agent process exited after intentional stop ` + `(PID: ${pid}, role: ${role}, code: ${code2}, signal: ${signal})`);
|
|
14344
|
+
} else {
|
|
14345
|
+
console.log(`[${ts}] ⚠️ Agent process exited ` + `(PID: ${pid}, role: ${role}, code: ${code2}, signal: ${signal})`);
|
|
14346
|
+
}
|
|
14347
|
+
ctx.deps.backend.mutation(api.machines.recordAgentExited, {
|
|
14348
|
+
sessionId: ctx.sessionId,
|
|
14349
|
+
machineId: ctx.machineId,
|
|
14350
|
+
chatroomId,
|
|
14351
|
+
role,
|
|
14352
|
+
pid,
|
|
14353
|
+
intentional,
|
|
14354
|
+
exitCode: code2 ?? undefined,
|
|
14355
|
+
signal: signal ?? undefined
|
|
14356
|
+
}).catch((err) => {
|
|
14357
|
+
console.log(` ⚠️ Failed to record agent exit event: ${err.message}`);
|
|
14358
|
+
});
|
|
14359
|
+
ctx.deps.machine.clearAgentPid(ctx.machineId, chatroomId, role);
|
|
14360
|
+
for (const service of ctx.agentServices.values()) {
|
|
14361
|
+
service.untrack(pid);
|
|
14362
|
+
}
|
|
14363
|
+
}
|
|
14364
|
+
var init_on_agent_exited = __esm(() => {
|
|
14365
|
+
init_api3();
|
|
14366
|
+
});
|
|
14367
|
+
|
|
14368
|
+
// src/events/daemon/agent/on-agent-started.ts
|
|
14369
|
+
function onAgentStarted(ctx, payload) {
|
|
14370
|
+
const ts = formatTimestamp();
|
|
14371
|
+
console.log(`[${ts}] \uD83D\uDFE2 Agent started: ${payload.role} (PID: ${payload.pid}, harness: ${payload.harness})`);
|
|
14372
|
+
}
|
|
14373
|
+
var init_on_agent_started = () => {};
|
|
14374
|
+
|
|
14375
|
+
// src/events/daemon/agent/on-agent-stopped.ts
|
|
14376
|
+
function onAgentStopped(ctx, payload) {
|
|
14377
|
+
const ts = formatTimestamp();
|
|
14378
|
+
console.log(`[${ts}] \uD83D\uDD34 Agent stopped: ${payload.role} (PID: ${payload.pid})`);
|
|
14379
|
+
}
|
|
14380
|
+
var init_on_agent_stopped = () => {};
|
|
14381
|
+
|
|
14382
|
+
// src/events/daemon/register-listeners.ts
|
|
14435
14383
|
function registerEventListeners(ctx) {
|
|
14436
14384
|
const unsubs = [];
|
|
14437
|
-
unsubs.push(ctx.events.on("agent:exited", (payload) =>
|
|
14438
|
-
|
|
14439
|
-
|
|
14440
|
-
if (intentional) {
|
|
14441
|
-
console.log(`[${ts}] ℹ️ Agent process exited after intentional stop ` + `(PID: ${pid}, role: ${role}, code: ${code2}, signal: ${signal})`);
|
|
14442
|
-
} else {
|
|
14443
|
-
console.log(`[${ts}] ⚠️ Agent process exited ` + `(PID: ${pid}, role: ${role}, code: ${code2}, signal: ${signal})`);
|
|
14444
|
-
}
|
|
14445
|
-
ctx.deps.backend.mutation(api.machines.updateSpawnedAgent, {
|
|
14446
|
-
sessionId: ctx.sessionId,
|
|
14447
|
-
machineId: ctx.machineId,
|
|
14448
|
-
chatroomId,
|
|
14449
|
-
role,
|
|
14450
|
-
pid: undefined
|
|
14451
|
-
}).catch((err) => {
|
|
14452
|
-
console.log(` ⚠️ Failed to clear PID in backend: ${err.message}`);
|
|
14453
|
-
});
|
|
14454
|
-
ctx.deps.machine.clearAgentPid(ctx.machineId, chatroomId, role);
|
|
14455
|
-
for (const service of ctx.agentServices.values()) {
|
|
14456
|
-
service.untrack(pid);
|
|
14457
|
-
}
|
|
14458
|
-
ctx.deps.backend.mutation(api.participants.leave, {
|
|
14459
|
-
sessionId: ctx.sessionId,
|
|
14460
|
-
chatroomId,
|
|
14461
|
-
role
|
|
14462
|
-
}).catch((err) => {
|
|
14463
|
-
console.log(` ⚠️ Could not remove participant: ${err.message}`);
|
|
14464
|
-
});
|
|
14465
|
-
}));
|
|
14466
|
-
unsubs.push(ctx.events.on("agent:started", (payload) => {
|
|
14467
|
-
const ts = formatTimestamp();
|
|
14468
|
-
console.log(`[${ts}] \uD83D\uDFE2 Agent started: ${payload.role} (PID: ${payload.pid}, harness: ${payload.harness})`);
|
|
14469
|
-
}));
|
|
14470
|
-
unsubs.push(ctx.events.on("agent:stopped", (payload) => {
|
|
14471
|
-
const ts = formatTimestamp();
|
|
14472
|
-
console.log(`[${ts}] \uD83D\uDD34 Agent stopped: ${payload.role} (PID: ${payload.pid})`);
|
|
14473
|
-
}));
|
|
14385
|
+
unsubs.push(ctx.events.on("agent:exited", (payload) => onAgentExited(ctx, payload)));
|
|
14386
|
+
unsubs.push(ctx.events.on("agent:started", (payload) => onAgentStarted(ctx, payload)));
|
|
14387
|
+
unsubs.push(ctx.events.on("agent:stopped", (payload) => onAgentStopped(ctx, payload)));
|
|
14474
14388
|
return () => {
|
|
14475
14389
|
for (const unsub of unsubs) {
|
|
14476
14390
|
unsub();
|
|
14477
14391
|
}
|
|
14478
14392
|
};
|
|
14479
14393
|
}
|
|
14480
|
-
var
|
|
14481
|
-
|
|
14394
|
+
var init_register_listeners = __esm(() => {
|
|
14395
|
+
init_on_agent_exited();
|
|
14396
|
+
init_on_agent_started();
|
|
14397
|
+
init_on_agent_stopped();
|
|
14482
14398
|
});
|
|
14483
14399
|
|
|
14484
14400
|
// src/commands/machine/daemon-start/init.ts
|
|
@@ -14520,7 +14436,9 @@ function createDefaultDeps16() {
|
|
|
14520
14436
|
machine: {
|
|
14521
14437
|
clearAgentPid,
|
|
14522
14438
|
persistAgentPid,
|
|
14523
|
-
listAgentEntries
|
|
14439
|
+
listAgentEntries,
|
|
14440
|
+
persistEventCursor,
|
|
14441
|
+
loadEventCursor
|
|
14524
14442
|
},
|
|
14525
14443
|
clock: {
|
|
14526
14444
|
now: () => Date.now(),
|
|
@@ -14649,7 +14567,7 @@ var init_init2 = __esm(() => {
|
|
|
14649
14567
|
init_error_formatting();
|
|
14650
14568
|
init_version();
|
|
14651
14569
|
init_pid();
|
|
14652
|
-
|
|
14570
|
+
init_register_listeners();
|
|
14653
14571
|
});
|
|
14654
14572
|
|
|
14655
14573
|
// src/commands/machine/daemon-start/index.ts
|