chatroom-cli 1.2.4 → 1.3.0
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 +285 -389
- 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");
|
|
@@ -11314,7 +11328,7 @@ var init_register_agent = __esm(() => {
|
|
|
11314
11328
|
init_opencode();
|
|
11315
11329
|
init_pi();
|
|
11316
11330
|
});
|
|
11317
|
-
// ../../services/backend/prompts/
|
|
11331
|
+
// ../../services/backend/prompts/cli/task-started/command.ts
|
|
11318
11332
|
function taskStartedCommand(params) {
|
|
11319
11333
|
const prefix = params.cliEnvPrefix || "";
|
|
11320
11334
|
const chatroomId = params.chatroomId || "<chatroom-id>";
|
|
@@ -11338,22 +11352,22 @@ EOF`;
|
|
|
11338
11352
|
return baseCmd;
|
|
11339
11353
|
}
|
|
11340
11354
|
|
|
11341
|
-
// ../../services/backend/prompts/
|
|
11355
|
+
// ../../services/backend/prompts/cli/task-started/classification/new-feature.ts
|
|
11342
11356
|
var init_new_feature = () => {};
|
|
11343
|
-
// ../../services/backend/prompts/
|
|
11357
|
+
// ../../services/backend/prompts/cli/task-started/classification/index.ts
|
|
11344
11358
|
var init_classification = __esm(() => {
|
|
11345
11359
|
init_new_feature();
|
|
11346
11360
|
});
|
|
11347
|
-
// ../../services/backend/prompts/
|
|
11361
|
+
// ../../services/backend/prompts/cli/task-started/main-prompt.ts
|
|
11348
11362
|
var init_main_prompt = () => {};
|
|
11349
11363
|
|
|
11350
|
-
// ../../services/backend/prompts/
|
|
11364
|
+
// ../../services/backend/prompts/cli/task-started/index.ts
|
|
11351
11365
|
var init_task_started = __esm(() => {
|
|
11352
11366
|
init_classification();
|
|
11353
11367
|
init_main_prompt();
|
|
11354
11368
|
});
|
|
11355
11369
|
|
|
11356
|
-
// ../../services/backend/prompts/
|
|
11370
|
+
// ../../services/backend/prompts/cli/get-next-task/reminder.ts
|
|
11357
11371
|
function getNextTaskGuidance() {
|
|
11358
11372
|
return `\uD83D\uDD17 STAYING CONNECTED TO YOUR TEAM
|
|
11359
11373
|
|
|
@@ -11373,24 +11387,23 @@ Two requirements:
|
|
|
11373
11387
|
|
|
11374
11388
|
⚠️ WHEN THE PROCESS IS TERMINATED OR TIMED OUT
|
|
11375
11389
|
|
|
11376
|
-
\`\`\`
|
|
11377
|
-
|
|
11378
|
-
|
|
11379
|
-
|
|
11380
|
-
|
|
11381
|
-
|
|
11382
|
-
|
|
11383
|
-
|
|
11384
|
-
:Reconnect immediately;
|
|
11385
|
-
note right: Team cannot reach you without it
|
|
11386
|
-
endif
|
|
11387
|
-
stop
|
|
11388
|
-
@enduml
|
|
11390
|
+
\`\`\`mermaid
|
|
11391
|
+
flowchart TD
|
|
11392
|
+
A([Start]) --> B[Command terminated unexpectedly]
|
|
11393
|
+
B --> C{Urgent pending work?}
|
|
11394
|
+
C -->|yes| D[Finish urgent work]
|
|
11395
|
+
D --> E[Reconnect with get-next-task]
|
|
11396
|
+
C -->|no| E
|
|
11397
|
+
E --> F([Stop])
|
|
11389
11398
|
\`\`\`
|
|
11390
11399
|
|
|
11391
11400
|
\uD83D\uDCCB BACKLOG TASKS
|
|
11392
11401
|
chatroom backlog list --chatroom-id=<chatroomId> --role=<role> --status=backlog
|
|
11393
|
-
chatroom backlog --help
|
|
11402
|
+
chatroom backlog --help
|
|
11403
|
+
|
|
11404
|
+
\uD83D\uDCCB CONTEXT RECOVERY (after compaction/summarization)
|
|
11405
|
+
If your context was compacted, run: chatroom get-system-prompt --chatroom-id=<id> --role=<role>
|
|
11406
|
+
to reload your full system and role prompt.`;
|
|
11394
11407
|
}
|
|
11395
11408
|
var init_reminder = () => {};
|
|
11396
11409
|
// ../../services/backend/prompts/config/index.ts
|
|
@@ -11440,9 +11453,10 @@ var init_utils = __esm(() => {
|
|
|
11440
11453
|
// ../../services/backend/prompts/base/shared/getting-started-content.ts
|
|
11441
11454
|
var init_getting_started_content = __esm(() => {
|
|
11442
11455
|
init_utils();
|
|
11456
|
+
init_reminder();
|
|
11443
11457
|
});
|
|
11444
11458
|
|
|
11445
|
-
// ../../services/backend/prompts/
|
|
11459
|
+
// ../../services/backend/prompts/cli/index.ts
|
|
11446
11460
|
var init_cli = __esm(() => {
|
|
11447
11461
|
init_task_started();
|
|
11448
11462
|
init_reminder();
|
|
@@ -11468,7 +11482,7 @@ var init_errorCodes = __esm(() => {
|
|
|
11468
11482
|
];
|
|
11469
11483
|
});
|
|
11470
11484
|
|
|
11471
|
-
// ../../services/backend/prompts/
|
|
11485
|
+
// ../../services/backend/prompts/cli/get-next-task/command.ts
|
|
11472
11486
|
function getNextTaskCommand(params) {
|
|
11473
11487
|
const prefix = params.cliEnvPrefix || "";
|
|
11474
11488
|
const chatroomId = params.chatroomId || "<chatroom-id>";
|
|
@@ -11777,18 +11791,6 @@ async function getNextTask(chatroomId, options) {
|
|
|
11777
11791
|
harnessVersions: machineInfo.harnessVersions,
|
|
11778
11792
|
availableModels
|
|
11779
11793
|
});
|
|
11780
|
-
const agentType = options.agentType ?? (machineInfo.availableHarnesses.length > 0 ? machineInfo.availableHarnesses[0] : undefined);
|
|
11781
|
-
if (agentType) {
|
|
11782
|
-
const workingDir = process.cwd();
|
|
11783
|
-
await client2.mutation(api.machines.updateAgentConfig, {
|
|
11784
|
-
sessionId,
|
|
11785
|
-
machineId: machineInfo.machineId,
|
|
11786
|
-
chatroomId,
|
|
11787
|
-
role,
|
|
11788
|
-
agentType,
|
|
11789
|
-
workingDir
|
|
11790
|
-
});
|
|
11791
|
-
}
|
|
11792
11794
|
} catch (machineError) {
|
|
11793
11795
|
if (!silent) {
|
|
11794
11796
|
console.warn(`⚠️ Machine registration failed: ${sanitizeUnknownForTerminal(machineError.message)}`);
|
|
@@ -12169,7 +12171,7 @@ function formatDecodeError(error) {
|
|
|
12169
12171
|
return message;
|
|
12170
12172
|
}
|
|
12171
12173
|
|
|
12172
|
-
// ../../services/backend/prompts/
|
|
12174
|
+
// ../../services/backend/prompts/cli/handoff/command.ts
|
|
12173
12175
|
function handoffCommand(params) {
|
|
12174
12176
|
const prefix = params.cliEnvPrefix || "";
|
|
12175
12177
|
const chatroomId = params.chatroomId || "<chatroom-id>";
|
|
@@ -12470,7 +12472,6 @@ async function listBacklog(chatroomId, options, deps) {
|
|
|
12470
12472
|
"pending",
|
|
12471
12473
|
"acknowledged",
|
|
12472
12474
|
"in_progress",
|
|
12473
|
-
"queued",
|
|
12474
12475
|
"backlog",
|
|
12475
12476
|
"backlog_acknowledged",
|
|
12476
12477
|
"completed",
|
|
@@ -12831,8 +12832,6 @@ function getStatusEmoji(status) {
|
|
|
12831
12832
|
return "\uD83D\uDCEC";
|
|
12832
12833
|
case "in_progress":
|
|
12833
12834
|
return "\uD83D\uDD35";
|
|
12834
|
-
case "queued":
|
|
12835
|
-
return "\uD83D\uDFE1";
|
|
12836
12835
|
case "backlog":
|
|
12837
12836
|
return "⚪";
|
|
12838
12837
|
case "backlog_acknowledged":
|
|
@@ -13643,6 +13642,7 @@ async function getSystemPrompt(chatroomId, options, deps) {
|
|
|
13643
13642
|
const prompt = await d.backend.query(api.prompts.webapp.getAgentPrompt, {
|
|
13644
13643
|
chatroomId,
|
|
13645
13644
|
role,
|
|
13645
|
+
teamId: chatroom.teamId,
|
|
13646
13646
|
teamName: chatroom.teamName,
|
|
13647
13647
|
teamRoles: chatroom.teamRoles,
|
|
13648
13648
|
teamEntryPoint: chatroom.teamEntryPoint,
|
|
@@ -13663,66 +13663,14 @@ var init_get_system_prompt = __esm(() => {
|
|
|
13663
13663
|
});
|
|
13664
13664
|
|
|
13665
13665
|
// ../../services/backend/config/reliability.ts
|
|
13666
|
-
var DAEMON_HEARTBEAT_INTERVAL_MS = 30000;
|
|
13666
|
+
var DAEMON_HEARTBEAT_INTERVAL_MS = 30000, AGENT_REQUEST_DEADLINE_MS = 120000;
|
|
13667
13667
|
|
|
13668
13668
|
// src/commands/machine/daemon-start/utils.ts
|
|
13669
13669
|
function formatTimestamp() {
|
|
13670
13670
|
return new Date().toISOString().replace("T", " ").substring(0, 19);
|
|
13671
13671
|
}
|
|
13672
|
-
function parseMachineCommand(raw) {
|
|
13673
|
-
switch (raw.type) {
|
|
13674
|
-
case "ping":
|
|
13675
|
-
return { _id: raw._id, type: "ping", payload: {}, createdAt: raw.createdAt };
|
|
13676
|
-
case "status":
|
|
13677
|
-
return { _id: raw._id, type: "status", payload: {}, createdAt: raw.createdAt };
|
|
13678
|
-
case "start-agent": {
|
|
13679
|
-
const { chatroomId, role, agentHarness } = raw.payload;
|
|
13680
|
-
if (!chatroomId || !role || !agentHarness) {
|
|
13681
|
-
console.error(` ⚠️ Invalid start-agent command: missing chatroomId, role, or agentHarness`);
|
|
13682
|
-
return null;
|
|
13683
|
-
}
|
|
13684
|
-
if (!raw.reason) {
|
|
13685
|
-
console.error(` ⚠️ Invalid start-agent command: missing required reason field`);
|
|
13686
|
-
return null;
|
|
13687
|
-
}
|
|
13688
|
-
return {
|
|
13689
|
-
_id: raw._id,
|
|
13690
|
-
type: "start-agent",
|
|
13691
|
-
reason: raw.reason,
|
|
13692
|
-
payload: {
|
|
13693
|
-
chatroomId,
|
|
13694
|
-
role,
|
|
13695
|
-
agentHarness,
|
|
13696
|
-
model: raw.payload.model,
|
|
13697
|
-
workingDir: raw.payload.workingDir
|
|
13698
|
-
},
|
|
13699
|
-
createdAt: raw.createdAt
|
|
13700
|
-
};
|
|
13701
|
-
}
|
|
13702
|
-
case "stop-agent": {
|
|
13703
|
-
const { chatroomId, role } = raw.payload;
|
|
13704
|
-
if (!chatroomId || !role) {
|
|
13705
|
-
console.error(` ⚠️ Invalid stop-agent command: missing chatroomId or role`);
|
|
13706
|
-
return null;
|
|
13707
|
-
}
|
|
13708
|
-
if (!raw.reason) {
|
|
13709
|
-
console.error(` ⚠️ Invalid stop-agent command: missing required reason field`);
|
|
13710
|
-
return null;
|
|
13711
|
-
}
|
|
13712
|
-
return {
|
|
13713
|
-
_id: raw._id,
|
|
13714
|
-
type: "stop-agent",
|
|
13715
|
-
reason: raw.reason,
|
|
13716
|
-
payload: { chatroomId, role },
|
|
13717
|
-
createdAt: raw.createdAt
|
|
13718
|
-
};
|
|
13719
|
-
}
|
|
13720
|
-
default:
|
|
13721
|
-
return null;
|
|
13722
|
-
}
|
|
13723
|
-
}
|
|
13724
13672
|
|
|
13725
|
-
// src/
|
|
13673
|
+
// src/events/lifecycle/on-agent-shutdown.ts
|
|
13726
13674
|
async function onAgentShutdown(ctx, options) {
|
|
13727
13675
|
const { chatroomId, role, pid, skipKill } = options;
|
|
13728
13676
|
try {
|
|
@@ -13781,42 +13729,13 @@ async function onAgentShutdown(ctx, options) {
|
|
|
13781
13729
|
console.log(` ⚠️ Failed to clear local PID for ${role}: ${e.message}`);
|
|
13782
13730
|
}
|
|
13783
13731
|
}
|
|
13784
|
-
let spawnedAgentCleared = false;
|
|
13785
|
-
if (killed || skipKill) {
|
|
13786
|
-
try {
|
|
13787
|
-
await ctx.deps.backend.mutation(api.machines.updateSpawnedAgent, {
|
|
13788
|
-
sessionId: ctx.sessionId,
|
|
13789
|
-
machineId: ctx.machineId,
|
|
13790
|
-
chatroomId,
|
|
13791
|
-
role,
|
|
13792
|
-
pid: undefined
|
|
13793
|
-
});
|
|
13794
|
-
spawnedAgentCleared = true;
|
|
13795
|
-
} catch (e) {
|
|
13796
|
-
console.log(` ⚠️ Failed to clear spawnedAgent for ${role}: ${e.message}`);
|
|
13797
|
-
}
|
|
13798
|
-
}
|
|
13799
|
-
let participantRemoved = false;
|
|
13800
|
-
try {
|
|
13801
|
-
await ctx.deps.backend.mutation(api.participants.leave, {
|
|
13802
|
-
sessionId: ctx.sessionId,
|
|
13803
|
-
chatroomId,
|
|
13804
|
-
role
|
|
13805
|
-
});
|
|
13806
|
-
participantRemoved = true;
|
|
13807
|
-
} catch (e) {
|
|
13808
|
-
console.log(` ⚠️ Failed to remove participant for ${role}: ${e.message}`);
|
|
13809
|
-
}
|
|
13810
13732
|
return {
|
|
13811
13733
|
killed: killed || (skipKill ?? false),
|
|
13812
|
-
cleaned:
|
|
13734
|
+
cleaned: killed || (skipKill ?? false)
|
|
13813
13735
|
};
|
|
13814
13736
|
}
|
|
13815
|
-
var init_on_agent_shutdown = __esm(() => {
|
|
13816
|
-
init_api3();
|
|
13817
|
-
});
|
|
13818
13737
|
|
|
13819
|
-
// src/
|
|
13738
|
+
// src/events/lifecycle/on-daemon-shutdown.ts
|
|
13820
13739
|
async function onDaemonShutdown(ctx) {
|
|
13821
13740
|
const agents = ctx.deps.machine.listAgentEntries(ctx.machineId);
|
|
13822
13741
|
if (agents.length > 0) {
|
|
@@ -13855,110 +13774,28 @@ async function onDaemonShutdown(ctx) {
|
|
|
13855
13774
|
var AGENT_SHUTDOWN_TIMEOUT_MS = 5000;
|
|
13856
13775
|
var init_on_daemon_shutdown = __esm(() => {
|
|
13857
13776
|
init_api3();
|
|
13858
|
-
init_on_agent_shutdown();
|
|
13859
13777
|
});
|
|
13860
13778
|
|
|
13861
|
-
// src/
|
|
13862
|
-
|
|
13863
|
-
|
|
13864
|
-
|
|
13865
|
-
|
|
13866
|
-
|
|
13867
|
-
|
|
13868
|
-
|
|
13869
|
-
|
|
13870
|
-
function getPidFileName() {
|
|
13871
|
-
return `daemon-${getUrlHash()}.pid`;
|
|
13872
|
-
}
|
|
13873
|
-
function ensureChatroomDir() {
|
|
13874
|
-
if (!existsSync4(CHATROOM_DIR4)) {
|
|
13875
|
-
mkdirSync4(CHATROOM_DIR4, { recursive: true, mode: 448 });
|
|
13876
|
-
}
|
|
13877
|
-
}
|
|
13878
|
-
function getPidFilePath() {
|
|
13879
|
-
return join5(CHATROOM_DIR4, getPidFileName());
|
|
13880
|
-
}
|
|
13881
|
-
function isProcessRunning(pid) {
|
|
13882
|
-
try {
|
|
13883
|
-
process.kill(pid, 0);
|
|
13884
|
-
return true;
|
|
13885
|
-
} catch {
|
|
13886
|
-
return false;
|
|
13887
|
-
}
|
|
13888
|
-
}
|
|
13889
|
-
function readPid() {
|
|
13890
|
-
const pidPath = getPidFilePath();
|
|
13891
|
-
if (!existsSync4(pidPath)) {
|
|
13892
|
-
return null;
|
|
13893
|
-
}
|
|
13894
|
-
try {
|
|
13895
|
-
const content = readFileSync6(pidPath, "utf-8").trim();
|
|
13896
|
-
const pid = parseInt(content, 10);
|
|
13897
|
-
if (isNaN(pid) || pid <= 0) {
|
|
13898
|
-
return null;
|
|
13899
|
-
}
|
|
13900
|
-
return pid;
|
|
13901
|
-
} catch {
|
|
13902
|
-
return null;
|
|
13903
|
-
}
|
|
13904
|
-
}
|
|
13905
|
-
function writePid() {
|
|
13906
|
-
ensureChatroomDir();
|
|
13907
|
-
const pidPath = getPidFilePath();
|
|
13908
|
-
writeFileSync4(pidPath, process.pid.toString(), "utf-8");
|
|
13909
|
-
}
|
|
13910
|
-
function removePid() {
|
|
13911
|
-
const pidPath = getPidFilePath();
|
|
13912
|
-
try {
|
|
13913
|
-
if (existsSync4(pidPath)) {
|
|
13914
|
-
unlinkSync2(pidPath);
|
|
13915
|
-
}
|
|
13916
|
-
} catch {}
|
|
13917
|
-
}
|
|
13918
|
-
function isDaemonRunning() {
|
|
13919
|
-
const pid = readPid();
|
|
13920
|
-
if (pid === null) {
|
|
13921
|
-
return { running: false, pid: null };
|
|
13922
|
-
}
|
|
13923
|
-
if (isProcessRunning(pid)) {
|
|
13924
|
-
return { running: true, pid };
|
|
13925
|
-
}
|
|
13926
|
-
removePid();
|
|
13927
|
-
return { running: false, pid: null };
|
|
13928
|
-
}
|
|
13929
|
-
function acquireLock() {
|
|
13930
|
-
const { running, pid } = isDaemonRunning();
|
|
13931
|
-
if (running) {
|
|
13932
|
-
console.error(`❌ Daemon already running for ${getConvexUrl()} (PID: ${pid})`);
|
|
13933
|
-
return false;
|
|
13934
|
-
}
|
|
13935
|
-
writePid();
|
|
13936
|
-
return true;
|
|
13937
|
-
}
|
|
13938
|
-
function releaseLock() {
|
|
13939
|
-
removePid();
|
|
13940
|
-
}
|
|
13941
|
-
var CHATROOM_DIR4;
|
|
13942
|
-
var init_pid = __esm(() => {
|
|
13943
|
-
init_client2();
|
|
13944
|
-
CHATROOM_DIR4 = join5(homedir4(), ".chatroom");
|
|
13945
|
-
});
|
|
13946
|
-
|
|
13947
|
-
// src/commands/machine/daemon-start/handlers/ping.ts
|
|
13948
|
-
function handlePing() {
|
|
13949
|
-
console.log(` ↪ Responding: pong`);
|
|
13950
|
-
return { result: "pong", failed: false };
|
|
13779
|
+
// src/infrastructure/machine/stop-reason.ts
|
|
13780
|
+
function resolveStopReason(code2, signal, wasIntentional) {
|
|
13781
|
+
if (wasIntentional)
|
|
13782
|
+
return "intentional_stop";
|
|
13783
|
+
if (signal !== null)
|
|
13784
|
+
return "process_terminated_with_signal";
|
|
13785
|
+
if (code2 === 0)
|
|
13786
|
+
return "process_exited_with_success";
|
|
13787
|
+
return "process_terminated_unexpectedly";
|
|
13951
13788
|
}
|
|
13952
13789
|
|
|
13953
13790
|
// src/commands/machine/daemon-start/handlers/start-agent.ts
|
|
13954
|
-
async function
|
|
13955
|
-
const { chatroomId, role, agentHarness, model, workingDir } =
|
|
13791
|
+
async function executeStartAgent(ctx, args) {
|
|
13792
|
+
const { chatroomId, role, agentHarness, model, workingDir, reason } = args;
|
|
13956
13793
|
console.log(` ↪ start-agent command received`);
|
|
13957
13794
|
console.log(` Chatroom: ${chatroomId}`);
|
|
13958
13795
|
console.log(` Role: ${role}`);
|
|
13959
13796
|
console.log(` Harness: ${agentHarness}`);
|
|
13960
|
-
if (
|
|
13961
|
-
console.log(` Reason: ${
|
|
13797
|
+
if (reason) {
|
|
13798
|
+
console.log(` Reason: ${reason}`);
|
|
13962
13799
|
}
|
|
13963
13800
|
if (model) {
|
|
13964
13801
|
console.log(` Model: ${model}`);
|
|
@@ -14064,12 +13901,14 @@ async function handleStartAgent(ctx, command) {
|
|
|
14064
13901
|
});
|
|
14065
13902
|
spawnResult.onExit(({ code: code2, signal }) => {
|
|
14066
13903
|
const wasIntentional = ctx.deps.stops.consume(chatroomId, role);
|
|
13904
|
+
const stopReason = resolveStopReason(code2, signal, wasIntentional);
|
|
14067
13905
|
ctx.events.emit("agent:exited", {
|
|
14068
13906
|
chatroomId,
|
|
14069
13907
|
role,
|
|
14070
13908
|
pid,
|
|
14071
13909
|
code: code2,
|
|
14072
13910
|
signal,
|
|
13911
|
+
stopReason,
|
|
14073
13912
|
intentional: wasIntentional
|
|
14074
13913
|
});
|
|
14075
13914
|
});
|
|
@@ -14090,19 +13929,26 @@ async function handleStartAgent(ctx, command) {
|
|
|
14090
13929
|
var init_start_agent = __esm(() => {
|
|
14091
13930
|
init_api3();
|
|
14092
13931
|
init_client2();
|
|
14093
|
-
init_on_agent_shutdown();
|
|
14094
13932
|
});
|
|
14095
13933
|
|
|
14096
|
-
// src/
|
|
14097
|
-
function
|
|
14098
|
-
|
|
14099
|
-
|
|
14100
|
-
|
|
14101
|
-
|
|
13934
|
+
// src/events/daemon/agent/on-request-start-agent.ts
|
|
13935
|
+
async function onRequestStartAgent(ctx, event) {
|
|
13936
|
+
if (Date.now() > event.deadline) {
|
|
13937
|
+
console.log(`[daemon] ⏰ Skipping expired agent.requestStart for role=${event.role} (deadline passed)`);
|
|
13938
|
+
return;
|
|
13939
|
+
}
|
|
13940
|
+
await executeStartAgent(ctx, {
|
|
13941
|
+
chatroomId: event.chatroomId,
|
|
13942
|
+
role: event.role,
|
|
13943
|
+
agentHarness: event.agentHarness,
|
|
13944
|
+
model: event.model,
|
|
13945
|
+
workingDir: event.workingDir,
|
|
13946
|
+
reason: event.reason
|
|
14102
13947
|
});
|
|
14103
|
-
console.log(` ↪ Responding with status`);
|
|
14104
|
-
return { result, failed: false };
|
|
14105
13948
|
}
|
|
13949
|
+
var init_on_request_start_agent = __esm(() => {
|
|
13950
|
+
init_start_agent();
|
|
13951
|
+
});
|
|
14106
13952
|
|
|
14107
13953
|
// src/commands/machine/daemon-start/handlers/shared.ts
|
|
14108
13954
|
async function clearAgentPidEverywhere(ctx, chatroomId, role) {
|
|
@@ -14124,8 +13970,8 @@ var init_shared = __esm(() => {
|
|
|
14124
13970
|
});
|
|
14125
13971
|
|
|
14126
13972
|
// src/commands/machine/daemon-start/handlers/stop-agent.ts
|
|
14127
|
-
async function
|
|
14128
|
-
const { chatroomId, role } =
|
|
13973
|
+
async function executeStopAgent(ctx, args) {
|
|
13974
|
+
const { chatroomId, role } = args;
|
|
14129
13975
|
console.log(` ↪ stop-agent command received`);
|
|
14130
13976
|
console.log(` Chatroom: ${chatroomId}`);
|
|
14131
13977
|
console.log(` Role: ${role}`);
|
|
@@ -14150,7 +13996,7 @@ async function handleStopAgent(ctx, command) {
|
|
|
14150
13996
|
console.log(` Stopping agent with PID: ${pid}`);
|
|
14151
13997
|
const isAlive = anyService ? anyService.isAlive(pid) : false;
|
|
14152
13998
|
if (!isAlive) {
|
|
14153
|
-
console.log(` ⚠️ PID ${pid}
|
|
13999
|
+
console.log(` ⚠️ PID ${pid} not found — process already exited or was never started`);
|
|
14154
14000
|
await clearAgentPidEverywhere(ctx, chatroomId, role);
|
|
14155
14001
|
console.log(` Cleared stale PID`);
|
|
14156
14002
|
try {
|
|
@@ -14195,10 +14041,117 @@ async function handleStopAgent(ctx, command) {
|
|
|
14195
14041
|
}
|
|
14196
14042
|
var init_stop_agent = __esm(() => {
|
|
14197
14043
|
init_api3();
|
|
14198
|
-
init_on_agent_shutdown();
|
|
14199
14044
|
init_shared();
|
|
14200
14045
|
});
|
|
14201
14046
|
|
|
14047
|
+
// src/events/daemon/agent/on-request-stop-agent.ts
|
|
14048
|
+
async function onRequestStopAgent(ctx, event) {
|
|
14049
|
+
if (Date.now() > event.deadline) {
|
|
14050
|
+
console.log(`[daemon] ⏰ Skipping expired agent.requestStop for role=${event.role} (deadline passed)`);
|
|
14051
|
+
return;
|
|
14052
|
+
}
|
|
14053
|
+
await executeStopAgent(ctx, {
|
|
14054
|
+
chatroomId: event.chatroomId,
|
|
14055
|
+
role: event.role,
|
|
14056
|
+
reason: event.reason
|
|
14057
|
+
});
|
|
14058
|
+
}
|
|
14059
|
+
var init_on_request_stop_agent = __esm(() => {
|
|
14060
|
+
init_stop_agent();
|
|
14061
|
+
});
|
|
14062
|
+
|
|
14063
|
+
// src/commands/machine/pid.ts
|
|
14064
|
+
import { createHash } from "node:crypto";
|
|
14065
|
+
import { existsSync as existsSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4, unlinkSync as unlinkSync2, mkdirSync as mkdirSync4 } from "node:fs";
|
|
14066
|
+
import { homedir as homedir4 } from "node:os";
|
|
14067
|
+
import { join as join5 } from "node:path";
|
|
14068
|
+
function getUrlHash() {
|
|
14069
|
+
const url = getConvexUrl();
|
|
14070
|
+
return createHash("sha256").update(url).digest("hex").substring(0, 8);
|
|
14071
|
+
}
|
|
14072
|
+
function getPidFileName() {
|
|
14073
|
+
return `daemon-${getUrlHash()}.pid`;
|
|
14074
|
+
}
|
|
14075
|
+
function ensureChatroomDir() {
|
|
14076
|
+
if (!existsSync4(CHATROOM_DIR4)) {
|
|
14077
|
+
mkdirSync4(CHATROOM_DIR4, { recursive: true, mode: 448 });
|
|
14078
|
+
}
|
|
14079
|
+
}
|
|
14080
|
+
function getPidFilePath() {
|
|
14081
|
+
return join5(CHATROOM_DIR4, getPidFileName());
|
|
14082
|
+
}
|
|
14083
|
+
function isProcessRunning(pid) {
|
|
14084
|
+
try {
|
|
14085
|
+
process.kill(pid, 0);
|
|
14086
|
+
return true;
|
|
14087
|
+
} catch {
|
|
14088
|
+
return false;
|
|
14089
|
+
}
|
|
14090
|
+
}
|
|
14091
|
+
function readPid() {
|
|
14092
|
+
const pidPath = getPidFilePath();
|
|
14093
|
+
if (!existsSync4(pidPath)) {
|
|
14094
|
+
return null;
|
|
14095
|
+
}
|
|
14096
|
+
try {
|
|
14097
|
+
const content = readFileSync6(pidPath, "utf-8").trim();
|
|
14098
|
+
const pid = parseInt(content, 10);
|
|
14099
|
+
if (isNaN(pid) || pid <= 0) {
|
|
14100
|
+
return null;
|
|
14101
|
+
}
|
|
14102
|
+
return pid;
|
|
14103
|
+
} catch {
|
|
14104
|
+
return null;
|
|
14105
|
+
}
|
|
14106
|
+
}
|
|
14107
|
+
function writePid() {
|
|
14108
|
+
ensureChatroomDir();
|
|
14109
|
+
const pidPath = getPidFilePath();
|
|
14110
|
+
writeFileSync4(pidPath, process.pid.toString(), "utf-8");
|
|
14111
|
+
}
|
|
14112
|
+
function removePid() {
|
|
14113
|
+
const pidPath = getPidFilePath();
|
|
14114
|
+
try {
|
|
14115
|
+
if (existsSync4(pidPath)) {
|
|
14116
|
+
unlinkSync2(pidPath);
|
|
14117
|
+
}
|
|
14118
|
+
} catch {}
|
|
14119
|
+
}
|
|
14120
|
+
function isDaemonRunning() {
|
|
14121
|
+
const pid = readPid();
|
|
14122
|
+
if (pid === null) {
|
|
14123
|
+
return { running: false, pid: null };
|
|
14124
|
+
}
|
|
14125
|
+
if (isProcessRunning(pid)) {
|
|
14126
|
+
return { running: true, pid };
|
|
14127
|
+
}
|
|
14128
|
+
removePid();
|
|
14129
|
+
return { running: false, pid: null };
|
|
14130
|
+
}
|
|
14131
|
+
function acquireLock() {
|
|
14132
|
+
const { running, pid } = isDaemonRunning();
|
|
14133
|
+
if (running) {
|
|
14134
|
+
console.error(`❌ Daemon already running for ${getConvexUrl()} (PID: ${pid})`);
|
|
14135
|
+
return false;
|
|
14136
|
+
}
|
|
14137
|
+
writePid();
|
|
14138
|
+
return true;
|
|
14139
|
+
}
|
|
14140
|
+
function releaseLock() {
|
|
14141
|
+
removePid();
|
|
14142
|
+
}
|
|
14143
|
+
var CHATROOM_DIR4;
|
|
14144
|
+
var init_pid = __esm(() => {
|
|
14145
|
+
init_client2();
|
|
14146
|
+
CHATROOM_DIR4 = join5(homedir4(), ".chatroom");
|
|
14147
|
+
});
|
|
14148
|
+
|
|
14149
|
+
// src/commands/machine/daemon-start/handlers/ping.ts
|
|
14150
|
+
function handlePing() {
|
|
14151
|
+
console.log(` ↪ Responding: pong`);
|
|
14152
|
+
return { result: "pong", failed: false };
|
|
14153
|
+
}
|
|
14154
|
+
|
|
14202
14155
|
// src/commands/machine/daemon-start/command-loop.ts
|
|
14203
14156
|
async function refreshModels(ctx) {
|
|
14204
14157
|
const models = {};
|
|
@@ -14227,70 +14180,6 @@ async function refreshModels(ctx) {
|
|
|
14227
14180
|
console.warn(`[${formatTimestamp()}] ⚠️ Model refresh failed: ${error.message}`);
|
|
14228
14181
|
}
|
|
14229
14182
|
}
|
|
14230
|
-
async function processCommand(ctx, command) {
|
|
14231
|
-
console.log(`[${formatTimestamp()}] \uD83D\uDCE8 Command received: ${command.type}`);
|
|
14232
|
-
try {
|
|
14233
|
-
await ctx.deps.backend.mutation(api.machines.ackCommand, {
|
|
14234
|
-
sessionId: ctx.sessionId,
|
|
14235
|
-
commandId: command._id,
|
|
14236
|
-
status: "processing"
|
|
14237
|
-
});
|
|
14238
|
-
ctx.events.emit("command:processing", {
|
|
14239
|
-
commandId: command._id.toString(),
|
|
14240
|
-
type: command.type
|
|
14241
|
-
});
|
|
14242
|
-
let commandResult;
|
|
14243
|
-
switch (command.type) {
|
|
14244
|
-
case "ping":
|
|
14245
|
-
commandResult = handlePing();
|
|
14246
|
-
break;
|
|
14247
|
-
case "status":
|
|
14248
|
-
commandResult = handleStatus(ctx);
|
|
14249
|
-
break;
|
|
14250
|
-
case "start-agent":
|
|
14251
|
-
commandResult = await handleStartAgent(ctx, command);
|
|
14252
|
-
break;
|
|
14253
|
-
case "stop-agent":
|
|
14254
|
-
commandResult = await handleStopAgent(ctx, command);
|
|
14255
|
-
break;
|
|
14256
|
-
default: {
|
|
14257
|
-
const _exhaustive = command;
|
|
14258
|
-
commandResult = {
|
|
14259
|
-
result: `Unknown command type: ${_exhaustive.type}`,
|
|
14260
|
-
failed: true
|
|
14261
|
-
};
|
|
14262
|
-
}
|
|
14263
|
-
}
|
|
14264
|
-
const finalStatus = commandResult.failed ? "failed" : "completed";
|
|
14265
|
-
await ctx.deps.backend.mutation(api.machines.ackCommand, {
|
|
14266
|
-
sessionId: ctx.sessionId,
|
|
14267
|
-
commandId: command._id,
|
|
14268
|
-
status: finalStatus,
|
|
14269
|
-
result: commandResult.result
|
|
14270
|
-
});
|
|
14271
|
-
ctx.events.emit("command:completed", {
|
|
14272
|
-
commandId: command._id.toString(),
|
|
14273
|
-
type: command.type,
|
|
14274
|
-
failed: commandResult.failed,
|
|
14275
|
-
result: commandResult.result
|
|
14276
|
-
});
|
|
14277
|
-
if (commandResult.failed) {
|
|
14278
|
-
console.log(` ❌ Command failed: ${commandResult.result}`);
|
|
14279
|
-
} else {
|
|
14280
|
-
console.log(` ✅ Command completed`);
|
|
14281
|
-
}
|
|
14282
|
-
} catch (error) {
|
|
14283
|
-
console.error(` ❌ Command failed: ${error.message}`);
|
|
14284
|
-
try {
|
|
14285
|
-
await ctx.deps.backend.mutation(api.machines.ackCommand, {
|
|
14286
|
-
sessionId: ctx.sessionId,
|
|
14287
|
-
commandId: command._id,
|
|
14288
|
-
status: "failed",
|
|
14289
|
-
result: error.message
|
|
14290
|
-
});
|
|
14291
|
-
} catch {}
|
|
14292
|
-
}
|
|
14293
|
-
}
|
|
14294
14183
|
async function startCommandLoop(ctx) {
|
|
14295
14184
|
let heartbeatCount = 0;
|
|
14296
14185
|
const heartbeatTimer = setInterval(() => {
|
|
@@ -14317,66 +14206,56 @@ async function startCommandLoop(ctx) {
|
|
|
14317
14206
|
process.on("SIGTERM", shutdown);
|
|
14318
14207
|
process.on("SIGHUP", shutdown);
|
|
14319
14208
|
const wsClient2 = await getConvexWsClient();
|
|
14320
|
-
const commandQueue = [];
|
|
14321
|
-
const queuedCommandIds = new Set;
|
|
14322
|
-
let drainingQueue = false;
|
|
14323
|
-
const enqueueCommands = (commands) => {
|
|
14324
|
-
for (const command of commands) {
|
|
14325
|
-
const commandId = command._id.toString();
|
|
14326
|
-
if (queuedCommandIds.has(commandId))
|
|
14327
|
-
continue;
|
|
14328
|
-
queuedCommandIds.add(commandId);
|
|
14329
|
-
commandQueue.push(command);
|
|
14330
|
-
}
|
|
14331
|
-
};
|
|
14332
|
-
const drainQueue = async () => {
|
|
14333
|
-
if (drainingQueue)
|
|
14334
|
-
return;
|
|
14335
|
-
drainingQueue = true;
|
|
14336
|
-
try {
|
|
14337
|
-
while (commandQueue.length > 0) {
|
|
14338
|
-
const command = commandQueue.shift();
|
|
14339
|
-
const commandId = command._id.toString();
|
|
14340
|
-
queuedCommandIds.delete(commandId);
|
|
14341
|
-
try {
|
|
14342
|
-
await processCommand(ctx, command);
|
|
14343
|
-
} catch (error) {
|
|
14344
|
-
console.error(` ❌ Command processing failed: ${error.message}`);
|
|
14345
|
-
}
|
|
14346
|
-
}
|
|
14347
|
-
} finally {
|
|
14348
|
-
drainingQueue = false;
|
|
14349
|
-
}
|
|
14350
|
-
};
|
|
14351
14209
|
console.log(`
|
|
14352
14210
|
Listening for commands...`);
|
|
14353
14211
|
console.log(`Press Ctrl+C to stop
|
|
14354
14212
|
`);
|
|
14355
|
-
|
|
14213
|
+
const processedCommandIds = new Map;
|
|
14214
|
+
const processedPingIds = new Map;
|
|
14215
|
+
wsClient2.onUpdate(api.machines.getCommandEvents, {
|
|
14356
14216
|
sessionId: ctx.sessionId,
|
|
14357
14217
|
machineId: ctx.machineId
|
|
14358
14218
|
}, async (result) => {
|
|
14359
|
-
if (!result.
|
|
14219
|
+
if (!result.events || result.events.length === 0)
|
|
14360
14220
|
return;
|
|
14361
|
-
const
|
|
14362
|
-
for (const
|
|
14363
|
-
|
|
14364
|
-
|
|
14365
|
-
|
|
14366
|
-
|
|
14367
|
-
|
|
14368
|
-
|
|
14221
|
+
const evictBefore = Date.now() - AGENT_REQUEST_DEADLINE_MS;
|
|
14222
|
+
for (const [id, ts] of processedCommandIds) {
|
|
14223
|
+
if (ts < evictBefore)
|
|
14224
|
+
processedCommandIds.delete(id);
|
|
14225
|
+
}
|
|
14226
|
+
for (const [id, ts] of processedPingIds) {
|
|
14227
|
+
if (ts < evictBefore)
|
|
14228
|
+
processedPingIds.delete(id);
|
|
14229
|
+
}
|
|
14230
|
+
for (const event of result.events) {
|
|
14231
|
+
const eventId = event._id.toString();
|
|
14232
|
+
try {
|
|
14233
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDCE1 Stream command event: ${event.type}`);
|
|
14234
|
+
if (event.type === "agent.requestStart") {
|
|
14235
|
+
if (processedCommandIds.has(eventId))
|
|
14236
|
+
continue;
|
|
14237
|
+
processedCommandIds.set(eventId, Date.now());
|
|
14238
|
+
await onRequestStartAgent(ctx, event);
|
|
14239
|
+
} else if (event.type === "agent.requestStop") {
|
|
14240
|
+
if (processedCommandIds.has(eventId))
|
|
14241
|
+
continue;
|
|
14242
|
+
processedCommandIds.set(eventId, Date.now());
|
|
14243
|
+
await onRequestStopAgent(ctx, event);
|
|
14244
|
+
} else if (event.type === "daemon.ping") {
|
|
14245
|
+
if (processedPingIds.has(eventId))
|
|
14246
|
+
continue;
|
|
14247
|
+
processedPingIds.set(eventId, Date.now());
|
|
14248
|
+
handlePing();
|
|
14249
|
+
await ctx.deps.backend.mutation(api.machines.ackPing, {
|
|
14369
14250
|
sessionId: ctx.sessionId,
|
|
14370
|
-
|
|
14371
|
-
|
|
14372
|
-
result: `Invalid command: type="${raw.type}" missing required payload fields`
|
|
14251
|
+
machineId: ctx.machineId,
|
|
14252
|
+
pingEventId: event._id
|
|
14373
14253
|
});
|
|
14374
|
-
|
|
14375
|
-
|
|
14254
|
+
}
|
|
14255
|
+
} catch (err) {
|
|
14256
|
+
console.error(`[${formatTimestamp()}] ❌ Stream command event failed: ${err.message}`);
|
|
14376
14257
|
}
|
|
14377
14258
|
}
|
|
14378
|
-
enqueueCommands(parsed);
|
|
14379
|
-
await drainQueue();
|
|
14380
14259
|
});
|
|
14381
14260
|
const modelRefreshTimer = setInterval(() => {
|
|
14382
14261
|
refreshModels(ctx).catch((err) => {
|
|
@@ -14391,9 +14270,9 @@ var init_command_loop = __esm(() => {
|
|
|
14391
14270
|
init_api3();
|
|
14392
14271
|
init_client2();
|
|
14393
14272
|
init_on_daemon_shutdown();
|
|
14273
|
+
init_on_request_start_agent();
|
|
14274
|
+
init_on_request_stop_agent();
|
|
14394
14275
|
init_pid();
|
|
14395
|
-
init_start_agent();
|
|
14396
|
-
init_stop_agent();
|
|
14397
14276
|
MODEL_REFRESH_INTERVAL_MS = 5 * 60 * 1000;
|
|
14398
14277
|
});
|
|
14399
14278
|
|
|
@@ -14425,7 +14304,7 @@ var init_state_recovery = __esm(() => {
|
|
|
14425
14304
|
init_shared();
|
|
14426
14305
|
});
|
|
14427
14306
|
|
|
14428
|
-
// src/
|
|
14307
|
+
// src/events/daemon/event-bus.ts
|
|
14429
14308
|
class DaemonEventBus {
|
|
14430
14309
|
listeners = new Map;
|
|
14431
14310
|
on(event, listener) {
|
|
@@ -14454,54 +14333,69 @@ class DaemonEventBus {
|
|
|
14454
14333
|
}
|
|
14455
14334
|
}
|
|
14456
14335
|
|
|
14457
|
-
// src/
|
|
14336
|
+
// src/events/daemon/agent/on-agent-exited.ts
|
|
14337
|
+
function onAgentExited(ctx, payload) {
|
|
14338
|
+
const { chatroomId, role, pid, code: code2, signal, stopReason, intentional } = payload;
|
|
14339
|
+
const ts = formatTimestamp();
|
|
14340
|
+
console.log(`[${ts}] Agent stopped: ${stopReason} (${role})`);
|
|
14341
|
+
if (intentional) {
|
|
14342
|
+
console.log(`[${ts}] ℹ️ Agent process exited after intentional stop ` + `(PID: ${pid}, role: ${role}, code: ${code2}, signal: ${signal})`);
|
|
14343
|
+
} else {
|
|
14344
|
+
console.log(`[${ts}] ⚠️ Agent process exited ` + `(PID: ${pid}, role: ${role}, code: ${code2}, signal: ${signal})`);
|
|
14345
|
+
}
|
|
14346
|
+
ctx.deps.backend.mutation(api.machines.recordAgentExited, {
|
|
14347
|
+
sessionId: ctx.sessionId,
|
|
14348
|
+
machineId: ctx.machineId,
|
|
14349
|
+
chatroomId,
|
|
14350
|
+
role,
|
|
14351
|
+
pid,
|
|
14352
|
+
intentional,
|
|
14353
|
+
stopReason,
|
|
14354
|
+
stopSignal: stopReason === "process_terminated_with_signal" ? signal ?? undefined : undefined,
|
|
14355
|
+
exitCode: code2 ?? undefined,
|
|
14356
|
+
signal: signal ?? undefined
|
|
14357
|
+
}).catch((err) => {
|
|
14358
|
+
console.log(` ⚠️ Failed to record agent exit event: ${err.message}`);
|
|
14359
|
+
});
|
|
14360
|
+
ctx.deps.machine.clearAgentPid(ctx.machineId, chatroomId, role);
|
|
14361
|
+
for (const service of ctx.agentServices.values()) {
|
|
14362
|
+
service.untrack(pid);
|
|
14363
|
+
}
|
|
14364
|
+
}
|
|
14365
|
+
var init_on_agent_exited = __esm(() => {
|
|
14366
|
+
init_api3();
|
|
14367
|
+
});
|
|
14368
|
+
|
|
14369
|
+
// src/events/daemon/agent/on-agent-started.ts
|
|
14370
|
+
function onAgentStarted(ctx, payload) {
|
|
14371
|
+
const ts = formatTimestamp();
|
|
14372
|
+
console.log(`[${ts}] \uD83D\uDFE2 Agent started: ${payload.role} (PID: ${payload.pid}, harness: ${payload.harness})`);
|
|
14373
|
+
}
|
|
14374
|
+
var init_on_agent_started = () => {};
|
|
14375
|
+
|
|
14376
|
+
// src/events/daemon/agent/on-agent-stopped.ts
|
|
14377
|
+
function onAgentStopped(ctx, payload) {
|
|
14378
|
+
const ts = formatTimestamp();
|
|
14379
|
+
console.log(`[${ts}] \uD83D\uDD34 Agent stopped: ${payload.role} (PID: ${payload.pid})`);
|
|
14380
|
+
}
|
|
14381
|
+
var init_on_agent_stopped = () => {};
|
|
14382
|
+
|
|
14383
|
+
// src/events/daemon/register-listeners.ts
|
|
14458
14384
|
function registerEventListeners(ctx) {
|
|
14459
14385
|
const unsubs = [];
|
|
14460
|
-
unsubs.push(ctx.events.on("agent:exited", (payload) =>
|
|
14461
|
-
|
|
14462
|
-
|
|
14463
|
-
if (intentional) {
|
|
14464
|
-
console.log(`[${ts}] ℹ️ Agent process exited after intentional stop ` + `(PID: ${pid}, role: ${role}, code: ${code2}, signal: ${signal})`);
|
|
14465
|
-
} else {
|
|
14466
|
-
console.log(`[${ts}] ⚠️ Agent process exited ` + `(PID: ${pid}, role: ${role}, code: ${code2}, signal: ${signal})`);
|
|
14467
|
-
}
|
|
14468
|
-
ctx.deps.backend.mutation(api.machines.updateSpawnedAgent, {
|
|
14469
|
-
sessionId: ctx.sessionId,
|
|
14470
|
-
machineId: ctx.machineId,
|
|
14471
|
-
chatroomId,
|
|
14472
|
-
role,
|
|
14473
|
-
pid: undefined
|
|
14474
|
-
}).catch((err) => {
|
|
14475
|
-
console.log(` ⚠️ Failed to clear PID in backend: ${err.message}`);
|
|
14476
|
-
});
|
|
14477
|
-
ctx.deps.machine.clearAgentPid(ctx.machineId, chatroomId, role);
|
|
14478
|
-
for (const service of ctx.agentServices.values()) {
|
|
14479
|
-
service.untrack(pid);
|
|
14480
|
-
}
|
|
14481
|
-
ctx.deps.backend.mutation(api.participants.leave, {
|
|
14482
|
-
sessionId: ctx.sessionId,
|
|
14483
|
-
chatroomId,
|
|
14484
|
-
role
|
|
14485
|
-
}).catch((err) => {
|
|
14486
|
-
console.log(` ⚠️ Could not remove participant: ${err.message}`);
|
|
14487
|
-
});
|
|
14488
|
-
}));
|
|
14489
|
-
unsubs.push(ctx.events.on("agent:started", (payload) => {
|
|
14490
|
-
const ts = formatTimestamp();
|
|
14491
|
-
console.log(`[${ts}] \uD83D\uDFE2 Agent started: ${payload.role} (PID: ${payload.pid}, harness: ${payload.harness})`);
|
|
14492
|
-
}));
|
|
14493
|
-
unsubs.push(ctx.events.on("agent:stopped", (payload) => {
|
|
14494
|
-
const ts = formatTimestamp();
|
|
14495
|
-
console.log(`[${ts}] \uD83D\uDD34 Agent stopped: ${payload.role} (PID: ${payload.pid})`);
|
|
14496
|
-
}));
|
|
14386
|
+
unsubs.push(ctx.events.on("agent:exited", (payload) => onAgentExited(ctx, payload)));
|
|
14387
|
+
unsubs.push(ctx.events.on("agent:started", (payload) => onAgentStarted(ctx, payload)));
|
|
14388
|
+
unsubs.push(ctx.events.on("agent:stopped", (payload) => onAgentStopped(ctx, payload)));
|
|
14497
14389
|
return () => {
|
|
14498
14390
|
for (const unsub of unsubs) {
|
|
14499
14391
|
unsub();
|
|
14500
14392
|
}
|
|
14501
14393
|
};
|
|
14502
14394
|
}
|
|
14503
|
-
var
|
|
14504
|
-
|
|
14395
|
+
var init_register_listeners = __esm(() => {
|
|
14396
|
+
init_on_agent_exited();
|
|
14397
|
+
init_on_agent_started();
|
|
14398
|
+
init_on_agent_stopped();
|
|
14505
14399
|
});
|
|
14506
14400
|
|
|
14507
14401
|
// src/commands/machine/daemon-start/init.ts
|
|
@@ -14543,7 +14437,9 @@ function createDefaultDeps16() {
|
|
|
14543
14437
|
machine: {
|
|
14544
14438
|
clearAgentPid,
|
|
14545
14439
|
persistAgentPid,
|
|
14546
|
-
listAgentEntries
|
|
14440
|
+
listAgentEntries,
|
|
14441
|
+
persistEventCursor,
|
|
14442
|
+
loadEventCursor
|
|
14547
14443
|
},
|
|
14548
14444
|
clock: {
|
|
14549
14445
|
now: () => Date.now(),
|
|
@@ -14672,7 +14568,7 @@ var init_init2 = __esm(() => {
|
|
|
14672
14568
|
init_error_formatting();
|
|
14673
14569
|
init_version();
|
|
14674
14570
|
init_pid();
|
|
14675
|
-
|
|
14571
|
+
init_register_listeners();
|
|
14676
14572
|
});
|
|
14677
14573
|
|
|
14678
14574
|
// src/commands/machine/daemon-start/index.ts
|
|
@@ -15397,7 +15293,7 @@ program2.command("report-progress").description("Report progress on current task
|
|
|
15397
15293
|
});
|
|
15398
15294
|
});
|
|
15399
15295
|
var backlogCommand = program2.command("backlog").description("Manage task queue and backlog");
|
|
15400
|
-
backlogCommand.command("list").description("List tasks in a chatroom").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role").requiredOption("--status <status>", "Filter by status (pending|in_progress|
|
|
15296
|
+
backlogCommand.command("list").description("List tasks in a chatroom").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role").requiredOption("--status <status>", "Filter by status (pending|in_progress|backlog|completed|cancelled|active|pending_review|archived|all)").option("--limit <n>", "Maximum number of tasks to show (required for --status=all)").option("--full", "Show full task content without truncation").action(async (options) => {
|
|
15401
15297
|
if (options.status === "all" && !options.limit) {
|
|
15402
15298
|
console.error("❌ When using --status=all, you must specify --limit=<n>");
|
|
15403
15299
|
console.error(" Example: chatroom backlog list --chatroom-id=<id> --role=builder --status=all --limit=50");
|