chatroom-cli 1.11.1 → 1.11.2
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 +39 -50
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11134,34 +11134,10 @@ var init_daemon_state = __esm(() => {
|
|
|
11134
11134
|
STATE_DIR = join4(CHATROOM_DIR3, "machines", "state");
|
|
11135
11135
|
});
|
|
11136
11136
|
|
|
11137
|
-
// src/infrastructure/machine/intentional-stops.ts
|
|
11138
|
-
function agentKey2(chatroomId, role) {
|
|
11139
|
-
return `${chatroomId}:${role.toLowerCase()}`;
|
|
11140
|
-
}
|
|
11141
|
-
function markIntentionalStop(chatroomId, role, reason = "user.stop") {
|
|
11142
|
-
pendingStops.set(agentKey2(chatroomId, role), reason);
|
|
11143
|
-
}
|
|
11144
|
-
function consumeIntentionalStop(chatroomId, role) {
|
|
11145
|
-
const key = agentKey2(chatroomId, role);
|
|
11146
|
-
const reason = pendingStops.get(key) ?? null;
|
|
11147
|
-
if (reason !== null) {
|
|
11148
|
-
pendingStops.delete(key);
|
|
11149
|
-
}
|
|
11150
|
-
return reason;
|
|
11151
|
-
}
|
|
11152
|
-
function clearIntentionalStop(chatroomId, role) {
|
|
11153
|
-
pendingStops.delete(agentKey2(chatroomId, role));
|
|
11154
|
-
}
|
|
11155
|
-
var pendingStops;
|
|
11156
|
-
var init_intentional_stops = __esm(() => {
|
|
11157
|
-
pendingStops = new Map;
|
|
11158
|
-
});
|
|
11159
|
-
|
|
11160
11137
|
// src/infrastructure/machine/index.ts
|
|
11161
11138
|
var init_machine = __esm(() => {
|
|
11162
11139
|
init_storage2();
|
|
11163
11140
|
init_daemon_state();
|
|
11164
|
-
init_intentional_stops();
|
|
11165
11141
|
});
|
|
11166
11142
|
|
|
11167
11143
|
// src/commands/auth-status/index.ts
|
|
@@ -14285,11 +14261,16 @@ function formatTimestamp() {
|
|
|
14285
14261
|
return new Date().toISOString().replace("T", " ").substring(0, 19);
|
|
14286
14262
|
}
|
|
14287
14263
|
|
|
14264
|
+
// src/commands/machine/daemon-start/types.ts
|
|
14265
|
+
function agentKey2(chatroomId, role) {
|
|
14266
|
+
return `${chatroomId}:${role.toLowerCase()}`;
|
|
14267
|
+
}
|
|
14268
|
+
|
|
14288
14269
|
// src/events/lifecycle/on-agent-shutdown.ts
|
|
14289
14270
|
async function onAgentShutdown(ctx, options) {
|
|
14290
14271
|
const { chatroomId, role, pid, skipKill } = options;
|
|
14291
14272
|
try {
|
|
14292
|
-
ctx.
|
|
14273
|
+
ctx.pendingStops.set(agentKey2(chatroomId, role), options.stopReason ?? "user.stop");
|
|
14293
14274
|
} catch (e) {
|
|
14294
14275
|
console.log(` ⚠️ Failed to mark intentional stop for ${role}: ${e.message}`);
|
|
14295
14276
|
}
|
|
@@ -14349,6 +14330,7 @@ async function onAgentShutdown(ctx, options) {
|
|
|
14349
14330
|
cleaned: killed || (skipKill ?? false)
|
|
14350
14331
|
};
|
|
14351
14332
|
}
|
|
14333
|
+
var init_on_agent_shutdown = () => {};
|
|
14352
14334
|
|
|
14353
14335
|
// src/events/lifecycle/on-daemon-shutdown.ts
|
|
14354
14336
|
async function onDaemonShutdown(ctx) {
|
|
@@ -14389,6 +14371,7 @@ async function onDaemonShutdown(ctx) {
|
|
|
14389
14371
|
var AGENT_SHUTDOWN_TIMEOUT_MS = 5000;
|
|
14390
14372
|
var init_on_daemon_shutdown = __esm(() => {
|
|
14391
14373
|
init_api3();
|
|
14374
|
+
init_on_agent_shutdown();
|
|
14392
14375
|
});
|
|
14393
14376
|
|
|
14394
14377
|
// src/commands/machine/daemon-start/handlers/shared.ts
|
|
@@ -14675,12 +14658,12 @@ class DaemonEventBus {
|
|
|
14675
14658
|
|
|
14676
14659
|
// src/events/daemon/agent/on-agent-exited.ts
|
|
14677
14660
|
function onAgentExited(ctx, payload) {
|
|
14678
|
-
const { chatroomId, role, pid, code: code2, signal, stopReason
|
|
14661
|
+
const { chatroomId, role, pid, code: code2, signal, stopReason } = payload;
|
|
14679
14662
|
const ts = formatTimestamp();
|
|
14680
14663
|
console.log(`[${ts}] Agent stopped: ${stopReason} (${role})`);
|
|
14681
14664
|
const isDaemonRespawn = stopReason === "daemon.respawn";
|
|
14682
|
-
const isIntentional =
|
|
14683
|
-
if (isIntentional) {
|
|
14665
|
+
const isIntentional = stopReason === "user.stop" || stopReason === "platform.team_switch" || stopReason === "agent_process.turn_end" || stopReason === "agent_process.turn_end_quick_fail";
|
|
14666
|
+
if (isIntentional && !isDaemonRespawn) {
|
|
14684
14667
|
console.log(`[${ts}] ℹ️ Agent process exited after intentional stop ` + `(PID: ${pid}, role: ${role}, code: ${code2}, signal: ${signal})`);
|
|
14685
14668
|
} else if (isDaemonRespawn) {
|
|
14686
14669
|
console.log(`[${ts}] \uD83D\uDD04 Agent process stopped for respawn ` + `(PID: ${pid}, role: ${role}, code: ${code2}, signal: ${signal})`);
|
|
@@ -14693,11 +14676,11 @@ function onAgentExited(ctx, payload) {
|
|
|
14693
14676
|
chatroomId,
|
|
14694
14677
|
role,
|
|
14695
14678
|
pid,
|
|
14696
|
-
intentional,
|
|
14697
14679
|
stopReason,
|
|
14698
14680
|
stopSignal: stopReason === "agent_process.signal" ? signal ?? undefined : undefined,
|
|
14699
14681
|
exitCode: code2 ?? undefined,
|
|
14700
|
-
signal: signal ?? undefined
|
|
14682
|
+
signal: signal ?? undefined,
|
|
14683
|
+
agentHarness: payload.agentHarness
|
|
14701
14684
|
}).catch((err) => {
|
|
14702
14685
|
console.log(` ⚠️ Failed to record agent exit event: ${err.message}`);
|
|
14703
14686
|
});
|
|
@@ -14773,11 +14756,6 @@ function createDefaultDeps19() {
|
|
|
14773
14756
|
fs: {
|
|
14774
14757
|
stat
|
|
14775
14758
|
},
|
|
14776
|
-
stops: {
|
|
14777
|
-
mark: markIntentionalStop,
|
|
14778
|
-
consume: consumeIntentionalStop,
|
|
14779
|
-
clear: clearIntentionalStop
|
|
14780
|
-
},
|
|
14781
14759
|
machine: {
|
|
14782
14760
|
clearAgentPid,
|
|
14783
14761
|
persistAgentPid,
|
|
@@ -14909,7 +14887,7 @@ async function initDaemon() {
|
|
|
14909
14887
|
agentServices,
|
|
14910
14888
|
activeWorkingDirs: new Set,
|
|
14911
14889
|
lastPushedGitState: new Map,
|
|
14912
|
-
|
|
14890
|
+
pendingStops: new Map
|
|
14913
14891
|
};
|
|
14914
14892
|
registerEventListeners(ctx);
|
|
14915
14893
|
logStartup(ctx, availableModels);
|
|
@@ -14922,7 +14900,6 @@ var init_init2 = __esm(() => {
|
|
|
14922
14900
|
init_storage();
|
|
14923
14901
|
init_client2();
|
|
14924
14902
|
init_machine();
|
|
14925
|
-
init_intentional_stops();
|
|
14926
14903
|
init_remote_agents();
|
|
14927
14904
|
init_harness_spawning();
|
|
14928
14905
|
init_error_formatting();
|
|
@@ -15031,10 +15008,9 @@ async function executeStartAgent(ctx, args) {
|
|
|
15031
15008
|
return { result: msg2, failed: true };
|
|
15032
15009
|
}
|
|
15033
15010
|
const { pid } = spawnResult;
|
|
15011
|
+
const spawnedAt = Date.now();
|
|
15034
15012
|
const msg = `Agent spawned (PID: ${pid})`;
|
|
15035
15013
|
console.log(` ✅ ${msg}`);
|
|
15036
|
-
const agentEndKey = `${chatroomId}:${role.toLowerCase()}`;
|
|
15037
|
-
ctx.agentEndedTurn.delete(agentEndKey);
|
|
15038
15014
|
ctx.deps.spawning.recordSpawn(chatroomId);
|
|
15039
15015
|
try {
|
|
15040
15016
|
await ctx.deps.backend.mutation(api.machines.updateSpawnedAgent, {
|
|
@@ -15061,7 +15037,11 @@ async function executeStartAgent(ctx, args) {
|
|
|
15061
15037
|
ctx.activeWorkingDirs.add(workingDir);
|
|
15062
15038
|
spawnResult.onExit(({ code: code2, signal }) => {
|
|
15063
15039
|
ctx.deps.spawning.recordExit(chatroomId);
|
|
15064
|
-
const
|
|
15040
|
+
const key = agentKey2(chatroomId, role);
|
|
15041
|
+
const pendingReason = ctx.pendingStops.get(key) ?? null;
|
|
15042
|
+
if (pendingReason) {
|
|
15043
|
+
ctx.pendingStops.delete(key);
|
|
15044
|
+
}
|
|
15065
15045
|
const stopReason = pendingReason ?? resolveStopReason(code2, signal, false);
|
|
15066
15046
|
ctx.events.emit("agent:exited", {
|
|
15067
15047
|
chatroomId,
|
|
@@ -15070,12 +15050,16 @@ async function executeStartAgent(ctx, args) {
|
|
|
15070
15050
|
code: code2,
|
|
15071
15051
|
signal,
|
|
15072
15052
|
stopReason,
|
|
15073
|
-
|
|
15053
|
+
agentHarness
|
|
15074
15054
|
});
|
|
15075
15055
|
});
|
|
15076
15056
|
if (spawnResult.onAgentEnd) {
|
|
15077
15057
|
spawnResult.onAgentEnd(() => {
|
|
15078
|
-
|
|
15058
|
+
const elapsed = Date.now() - spawnedAt;
|
|
15059
|
+
const isHealthyTurn = elapsed >= MIN_HEALTHY_TURN_MS;
|
|
15060
|
+
const stopReason = isHealthyTurn ? "agent_process.turn_end" : "agent_process.turn_end_quick_fail";
|
|
15061
|
+
const key = agentKey2(chatroomId, role);
|
|
15062
|
+
ctx.pendingStops.set(key, stopReason);
|
|
15079
15063
|
try {
|
|
15080
15064
|
ctx.deps.processes.kill(-pid, "SIGTERM");
|
|
15081
15065
|
} catch {}
|
|
@@ -15095,23 +15079,27 @@ async function executeStartAgent(ctx, args) {
|
|
|
15095
15079
|
});
|
|
15096
15080
|
return { result: msg, failed: false };
|
|
15097
15081
|
}
|
|
15082
|
+
var MIN_HEALTHY_TURN_MS = 30000;
|
|
15098
15083
|
var init_start_agent = __esm(() => {
|
|
15099
15084
|
init_api3();
|
|
15100
15085
|
init_client2();
|
|
15086
|
+
init_on_agent_shutdown();
|
|
15101
15087
|
});
|
|
15102
15088
|
|
|
15103
15089
|
// src/events/daemon/agent/on-request-start-agent.ts
|
|
15104
15090
|
async function onRequestStartAgent(ctx, event) {
|
|
15091
|
+
const eventId = event._id.toString();
|
|
15105
15092
|
if (Date.now() > event.deadline) {
|
|
15106
|
-
console.log(`[daemon] ⏰ Skipping expired agent.requestStart for role=${event.role} (deadline passed)`);
|
|
15093
|
+
console.log(`[daemon] ⏰ Skipping expired agent.requestStart for role=${event.role} (id: ${eventId}, deadline passed)`);
|
|
15107
15094
|
return;
|
|
15108
15095
|
}
|
|
15109
15096
|
const spawnCheck = ctx.deps.spawning.shouldAllowSpawn(event.chatroomId, event.reason);
|
|
15110
15097
|
if (!spawnCheck.allowed) {
|
|
15111
15098
|
const retryMsg = spawnCheck.retryAfterMs ? ` Retry after ${spawnCheck.retryAfterMs}ms.` : "";
|
|
15112
|
-
console.warn(`[daemon] ⚠️ Spawn suppressed for chatroom=${event.chatroomId} role=${event.role} reason=${event.reason}.${retryMsg}`);
|
|
15099
|
+
console.warn(`[daemon] ⚠️ Spawn suppressed for chatroom=${event.chatroomId} role=${event.role} reason=${event.reason} (id: ${eventId}).${retryMsg}`);
|
|
15113
15100
|
return;
|
|
15114
15101
|
}
|
|
15102
|
+
console.log(`[daemon] Processing agent.requestStart (id: ${eventId})`);
|
|
15115
15103
|
await executeStartAgent(ctx, {
|
|
15116
15104
|
chatroomId: event.chatroomId,
|
|
15117
15105
|
role: event.role,
|
|
@@ -15200,6 +15188,7 @@ async function executeStopAgent(ctx, args) {
|
|
|
15200
15188
|
}
|
|
15201
15189
|
var init_stop_agent = __esm(() => {
|
|
15202
15190
|
init_api3();
|
|
15191
|
+
init_on_agent_shutdown();
|
|
15203
15192
|
init_shared();
|
|
15204
15193
|
});
|
|
15205
15194
|
|
|
@@ -15775,12 +15764,12 @@ class PiRestartPolicy {
|
|
|
15775
15764
|
if (task.status !== "pending" && task.status !== "acknowledged") {
|
|
15776
15765
|
return false;
|
|
15777
15766
|
}
|
|
15778
|
-
if (!context?.
|
|
15767
|
+
if (!context?.pendingStops) {
|
|
15779
15768
|
return false;
|
|
15780
15769
|
}
|
|
15781
|
-
const key = `${task.chatroomId}:${agentConfig.role}`;
|
|
15782
|
-
const
|
|
15783
|
-
return
|
|
15770
|
+
const key = `${task.chatroomId}:${agentConfig.role.toLowerCase()}`;
|
|
15771
|
+
const pendingReason = context.pendingStops.get(key);
|
|
15772
|
+
return pendingReason === "agent_process.turn_end";
|
|
15784
15773
|
}
|
|
15785
15774
|
}
|
|
15786
15775
|
function getRestartPolicyForHarness(harness) {
|
|
@@ -15814,7 +15803,7 @@ function startTaskMonitor(ctx) {
|
|
|
15814
15803
|
try {
|
|
15815
15804
|
const wsClient2 = await getConvexWsClient();
|
|
15816
15805
|
const agentEndContext = {
|
|
15817
|
-
|
|
15806
|
+
pendingStops: ctx.pendingStops
|
|
15818
15807
|
};
|
|
15819
15808
|
unsubscribe = wsClient2.onUpdate(api.machines.getAssignedTasks, {
|
|
15820
15809
|
sessionId: ctx.sessionId,
|
|
@@ -16008,7 +15997,7 @@ Listening for commands...`);
|
|
|
16008
15997
|
evictStaleDedupEntries(processedCommandIds, processedPingIds, processedGitRefreshIds);
|
|
16009
15998
|
for (const event of result.events) {
|
|
16010
15999
|
try {
|
|
16011
|
-
console.log(`[${formatTimestamp()}] \uD83D\uDCE1 Stream command event: ${event.type}`);
|
|
16000
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDCE1 Stream command event: ${event.type} (id: ${event._id})`);
|
|
16012
16001
|
await dispatchCommandEvent(ctx, event, processedCommandIds, processedPingIds, processedGitRefreshIds);
|
|
16013
16002
|
} catch (err) {
|
|
16014
16003
|
console.error(`[${formatTimestamp()}] ❌ Stream command event failed: ${err.message}`);
|