chatroom-cli 1.3.0 → 1.4.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 +156 -92
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10280,10 +10280,6 @@ function ensureMachineRegistered() {
|
|
|
10280
10280
|
harnessVersions: config.harnessVersions
|
|
10281
10281
|
};
|
|
10282
10282
|
}
|
|
10283
|
-
function getMachineId() {
|
|
10284
|
-
const config = loadMachineConfig();
|
|
10285
|
-
return config?.machineId ?? null;
|
|
10286
|
-
}
|
|
10287
10283
|
var CHATROOM_DIR2, MACHINE_FILE = "machine.json";
|
|
10288
10284
|
var init_storage2 = __esm(() => {
|
|
10289
10285
|
init_detection();
|
|
@@ -10756,6 +10752,9 @@ var init_pi_agent_service = __esm(() => {
|
|
|
10756
10752
|
const pid = childProcess.pid;
|
|
10757
10753
|
const context = options.context;
|
|
10758
10754
|
const entry = this.registerProcess(pid, context);
|
|
10755
|
+
const roleTag = context.role ?? "unknown";
|
|
10756
|
+
const chatroomSuffix = context.chatroomId ? `@${context.chatroomId.slice(-6)}` : "";
|
|
10757
|
+
const logPrefix = `[pi:${roleTag}${chatroomSuffix}`;
|
|
10759
10758
|
const outputCallbacks = [];
|
|
10760
10759
|
if (childProcess.stdout) {
|
|
10761
10760
|
const reader = new PiRpcReader(childProcess.stdout);
|
|
@@ -10767,7 +10766,7 @@ var init_pi_agent_service = __esm(() => {
|
|
|
10767
10766
|
for (const line of textBuffer.split(`
|
|
10768
10767
|
`)) {
|
|
10769
10768
|
if (line)
|
|
10770
|
-
process.stdout.write(
|
|
10769
|
+
process.stdout.write(`${logPrefix} text] ${line}
|
|
10771
10770
|
`);
|
|
10772
10771
|
}
|
|
10773
10772
|
textBuffer = "";
|
|
@@ -10778,7 +10777,7 @@ var init_pi_agent_service = __esm(() => {
|
|
|
10778
10777
|
for (const line of thinkingBuffer.split(`
|
|
10779
10778
|
`)) {
|
|
10780
10779
|
if (line)
|
|
10781
|
-
process.stdout.write(
|
|
10780
|
+
process.stdout.write(`${logPrefix} thinking] ${line}
|
|
10782
10781
|
`);
|
|
10783
10782
|
}
|
|
10784
10783
|
thinkingBuffer = "";
|
|
@@ -10811,15 +10810,38 @@ var init_pi_agent_service = __esm(() => {
|
|
|
10811
10810
|
reader.onAgentEnd(() => {
|
|
10812
10811
|
flushText();
|
|
10813
10812
|
flushThinking();
|
|
10814
|
-
process.stdout.write(
|
|
10813
|
+
process.stdout.write(`${logPrefix} agent_end]
|
|
10815
10814
|
`);
|
|
10816
10815
|
});
|
|
10817
10816
|
reader.onToolCall((name) => {
|
|
10818
10817
|
flushText();
|
|
10819
10818
|
flushThinking();
|
|
10820
|
-
process.stdout.write(
|
|
10819
|
+
process.stdout.write(`${logPrefix} tool: ${name}]
|
|
10821
10820
|
`);
|
|
10822
10821
|
});
|
|
10822
|
+
if (childProcess.stderr) {
|
|
10823
|
+
childProcess.stderr.pipe(process.stderr, { end: false });
|
|
10824
|
+
childProcess.stderr.on("data", () => {
|
|
10825
|
+
entry.lastOutputAt = Date.now();
|
|
10826
|
+
for (const cb of outputCallbacks)
|
|
10827
|
+
cb();
|
|
10828
|
+
});
|
|
10829
|
+
}
|
|
10830
|
+
return {
|
|
10831
|
+
pid,
|
|
10832
|
+
onExit: (cb) => {
|
|
10833
|
+
childProcess.on("exit", (code2, signal) => {
|
|
10834
|
+
this.deleteProcess(pid);
|
|
10835
|
+
cb({ code: code2, signal, context });
|
|
10836
|
+
});
|
|
10837
|
+
},
|
|
10838
|
+
onOutput: (cb) => {
|
|
10839
|
+
outputCallbacks.push(cb);
|
|
10840
|
+
},
|
|
10841
|
+
onAgentEnd: (cb) => {
|
|
10842
|
+
reader.onAgentEnd(cb);
|
|
10843
|
+
}
|
|
10844
|
+
};
|
|
10823
10845
|
}
|
|
10824
10846
|
if (childProcess.stderr) {
|
|
10825
10847
|
childProcess.stderr.pipe(process.stderr, { end: false });
|
|
@@ -11298,6 +11320,15 @@ async function registerAgent(chatroomId, options, deps) {
|
|
|
11298
11320
|
harnessVersions: machineInfo.harnessVersions,
|
|
11299
11321
|
availableModels
|
|
11300
11322
|
});
|
|
11323
|
+
try {
|
|
11324
|
+
await d.backend.mutation(api.machines.recordAgentRegistered, {
|
|
11325
|
+
sessionId,
|
|
11326
|
+
chatroomId,
|
|
11327
|
+
role,
|
|
11328
|
+
agentType: "remote",
|
|
11329
|
+
machineId: machineInfo.machineId
|
|
11330
|
+
});
|
|
11331
|
+
} catch {}
|
|
11301
11332
|
console.log(`✅ Registered as remote agent for role "${role}"`);
|
|
11302
11333
|
console.log(` Machine: ${machineInfo.hostname} (${machineInfo.machineId})`);
|
|
11303
11334
|
console.log(` Working directory: ${process.cwd()}`);
|
|
@@ -13912,6 +13943,13 @@ async function executeStartAgent(ctx, args) {
|
|
|
13912
13943
|
intentional: wasIntentional
|
|
13913
13944
|
});
|
|
13914
13945
|
});
|
|
13946
|
+
if (spawnResult.onAgentEnd) {
|
|
13947
|
+
spawnResult.onAgentEnd(() => {
|
|
13948
|
+
try {
|
|
13949
|
+
ctx.deps.processes.kill(-pid, "SIGTERM");
|
|
13950
|
+
} catch {}
|
|
13951
|
+
});
|
|
13952
|
+
}
|
|
13915
13953
|
let lastReportedTokenAt = 0;
|
|
13916
13954
|
spawnResult.onOutput(() => {
|
|
13917
13955
|
const now = Date.now();
|
|
@@ -14164,6 +14202,9 @@ async function refreshModels(ctx) {
|
|
|
14164
14202
|
}
|
|
14165
14203
|
if (!ctx.config)
|
|
14166
14204
|
return;
|
|
14205
|
+
const freshConfig = ensureMachineRegistered();
|
|
14206
|
+
ctx.config.availableHarnesses = freshConfig.availableHarnesses;
|
|
14207
|
+
ctx.config.harnessVersions = freshConfig.harnessVersions;
|
|
14167
14208
|
const totalCount = Object.values(models).flat().length;
|
|
14168
14209
|
try {
|
|
14169
14210
|
await ctx.deps.backend.mutation(api.machines.register, {
|
|
@@ -14180,6 +14221,41 @@ async function refreshModels(ctx) {
|
|
|
14180
14221
|
console.warn(`[${formatTimestamp()}] ⚠️ Model refresh failed: ${error.message}`);
|
|
14181
14222
|
}
|
|
14182
14223
|
}
|
|
14224
|
+
function evictStaleDedupEntries(processedCommandIds, processedPingIds) {
|
|
14225
|
+
const evictBefore = Date.now() - AGENT_REQUEST_DEADLINE_MS;
|
|
14226
|
+
for (const [id, ts] of processedCommandIds) {
|
|
14227
|
+
if (ts < evictBefore)
|
|
14228
|
+
processedCommandIds.delete(id);
|
|
14229
|
+
}
|
|
14230
|
+
for (const [id, ts] of processedPingIds) {
|
|
14231
|
+
if (ts < evictBefore)
|
|
14232
|
+
processedPingIds.delete(id);
|
|
14233
|
+
}
|
|
14234
|
+
}
|
|
14235
|
+
async function dispatchCommandEvent(ctx, event, processedCommandIds, processedPingIds) {
|
|
14236
|
+
const eventId = event._id.toString();
|
|
14237
|
+
if (event.type === "agent.requestStart") {
|
|
14238
|
+
if (processedCommandIds.has(eventId))
|
|
14239
|
+
return;
|
|
14240
|
+
processedCommandIds.set(eventId, Date.now());
|
|
14241
|
+
await onRequestStartAgent(ctx, event);
|
|
14242
|
+
} else if (event.type === "agent.requestStop") {
|
|
14243
|
+
if (processedCommandIds.has(eventId))
|
|
14244
|
+
return;
|
|
14245
|
+
processedCommandIds.set(eventId, Date.now());
|
|
14246
|
+
await onRequestStopAgent(ctx, event);
|
|
14247
|
+
} else if (event.type === "daemon.ping") {
|
|
14248
|
+
if (processedPingIds.has(eventId))
|
|
14249
|
+
return;
|
|
14250
|
+
processedPingIds.set(eventId, Date.now());
|
|
14251
|
+
handlePing();
|
|
14252
|
+
await ctx.deps.backend.mutation(api.machines.ackPing, {
|
|
14253
|
+
sessionId: ctx.sessionId,
|
|
14254
|
+
machineId: ctx.machineId,
|
|
14255
|
+
pingEventId: event._id
|
|
14256
|
+
});
|
|
14257
|
+
}
|
|
14258
|
+
}
|
|
14183
14259
|
async function startCommandLoop(ctx) {
|
|
14184
14260
|
let heartbeatCount = 0;
|
|
14185
14261
|
const heartbeatTimer = setInterval(() => {
|
|
@@ -14218,40 +14294,11 @@ Listening for commands...`);
|
|
|
14218
14294
|
}, async (result) => {
|
|
14219
14295
|
if (!result.events || result.events.length === 0)
|
|
14220
14296
|
return;
|
|
14221
|
-
|
|
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
|
-
}
|
|
14297
|
+
evictStaleDedupEntries(processedCommandIds, processedPingIds);
|
|
14230
14298
|
for (const event of result.events) {
|
|
14231
|
-
const eventId = event._id.toString();
|
|
14232
14299
|
try {
|
|
14233
14300
|
console.log(`[${formatTimestamp()}] \uD83D\uDCE1 Stream command event: ${event.type}`);
|
|
14234
|
-
|
|
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, {
|
|
14250
|
-
sessionId: ctx.sessionId,
|
|
14251
|
-
machineId: ctx.machineId,
|
|
14252
|
-
pingEventId: event._id
|
|
14253
|
-
});
|
|
14254
|
-
}
|
|
14301
|
+
await dispatchCommandEvent(ctx, event, processedCommandIds, processedPingIds);
|
|
14255
14302
|
} catch (err) {
|
|
14256
14303
|
console.error(`[${formatTimestamp()}] ❌ Stream command event failed: ${err.message}`);
|
|
14257
14304
|
}
|
|
@@ -14269,6 +14316,7 @@ var MODEL_REFRESH_INTERVAL_MS;
|
|
|
14269
14316
|
var init_command_loop = __esm(() => {
|
|
14270
14317
|
init_api3();
|
|
14271
14318
|
init_client2();
|
|
14319
|
+
init_machine();
|
|
14272
14320
|
init_on_daemon_shutdown();
|
|
14273
14321
|
init_on_request_start_agent();
|
|
14274
14322
|
init_on_request_stop_agent();
|
|
@@ -14447,11 +14495,7 @@ function createDefaultDeps16() {
|
|
|
14447
14495
|
}
|
|
14448
14496
|
};
|
|
14449
14497
|
}
|
|
14450
|
-
|
|
14451
|
-
if (!acquireLock()) {
|
|
14452
|
-
process.exit(1);
|
|
14453
|
-
}
|
|
14454
|
-
const convexUrl = getConvexUrl();
|
|
14498
|
+
function validateAuthentication(convexUrl) {
|
|
14455
14499
|
const sessionId = getSessionId();
|
|
14456
14500
|
if (!sessionId) {
|
|
14457
14501
|
const otherUrls = getOtherSessionUrls();
|
|
@@ -14468,18 +14512,10 @@ Run: chatroom auth login`);
|
|
|
14468
14512
|
releaseLock();
|
|
14469
14513
|
process.exit(1);
|
|
14470
14514
|
}
|
|
14471
|
-
|
|
14472
|
-
|
|
14473
|
-
|
|
14474
|
-
|
|
14475
|
-
Run any chatroom command first to register this machine,`);
|
|
14476
|
-
console.error(`for example: chatroom auth status`);
|
|
14477
|
-
releaseLock();
|
|
14478
|
-
process.exit(1);
|
|
14479
|
-
}
|
|
14480
|
-
const client2 = await getConvexClient();
|
|
14481
|
-
const typedSessionId = sessionId;
|
|
14482
|
-
const validation = await client2.query(api.cliAuth.validateSession, { sessionId: typedSessionId });
|
|
14515
|
+
return sessionId;
|
|
14516
|
+
}
|
|
14517
|
+
async function validateSession(client2, sessionId, convexUrl) {
|
|
14518
|
+
const validation = await client2.query(api.cliAuth.validateSession, { sessionId });
|
|
14483
14519
|
if (!validation.valid) {
|
|
14484
14520
|
console.error(`❌ Session invalid: ${validation.reason}`);
|
|
14485
14521
|
console.error(`
|
|
@@ -14487,32 +14523,34 @@ Run: chatroom auth login`);
|
|
|
14487
14523
|
releaseLock();
|
|
14488
14524
|
process.exit(1);
|
|
14489
14525
|
}
|
|
14526
|
+
}
|
|
14527
|
+
function setupMachine() {
|
|
14528
|
+
ensureMachineRegistered();
|
|
14490
14529
|
const config3 = loadMachineConfig();
|
|
14491
|
-
|
|
14492
|
-
|
|
14493
|
-
|
|
14494
|
-
|
|
14495
|
-
["pi", piService]
|
|
14496
|
-
]);
|
|
14530
|
+
return config3;
|
|
14531
|
+
}
|
|
14532
|
+
async function registerCapabilities(client2, sessionId, config3, agentServices) {
|
|
14533
|
+
const { machineId } = config3;
|
|
14497
14534
|
const availableModels = await discoverModels(agentServices);
|
|
14498
|
-
|
|
14499
|
-
|
|
14500
|
-
|
|
14501
|
-
|
|
14502
|
-
|
|
14503
|
-
|
|
14504
|
-
|
|
14505
|
-
|
|
14506
|
-
|
|
14507
|
-
|
|
14508
|
-
|
|
14509
|
-
|
|
14510
|
-
console.warn(`⚠️ Machine registration update failed: ${error.message}`);
|
|
14511
|
-
}
|
|
14535
|
+
try {
|
|
14536
|
+
await client2.mutation(api.machines.register, {
|
|
14537
|
+
sessionId,
|
|
14538
|
+
machineId,
|
|
14539
|
+
hostname: config3.hostname,
|
|
14540
|
+
os: config3.os,
|
|
14541
|
+
availableHarnesses: config3.availableHarnesses,
|
|
14542
|
+
harnessVersions: config3.harnessVersions,
|
|
14543
|
+
availableModels
|
|
14544
|
+
});
|
|
14545
|
+
} catch (error) {
|
|
14546
|
+
console.warn(`⚠️ Machine registration update failed: ${error.message}`);
|
|
14512
14547
|
}
|
|
14548
|
+
return availableModels;
|
|
14549
|
+
}
|
|
14550
|
+
async function connectDaemon(client2, sessionId, machineId, convexUrl) {
|
|
14513
14551
|
try {
|
|
14514
14552
|
await client2.mutation(api.machines.updateDaemonStatus, {
|
|
14515
|
-
sessionId
|
|
14553
|
+
sessionId,
|
|
14516
14554
|
machineId,
|
|
14517
14555
|
connected: true
|
|
14518
14556
|
});
|
|
@@ -14525,6 +14563,45 @@ Run: chatroom auth login`);
|
|
|
14525
14563
|
releaseLock();
|
|
14526
14564
|
process.exit(1);
|
|
14527
14565
|
}
|
|
14566
|
+
}
|
|
14567
|
+
function logStartup(ctx, availableModels) {
|
|
14568
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDE80 Daemon started`);
|
|
14569
|
+
console.log(` CLI version: ${getVersion()}`);
|
|
14570
|
+
console.log(` Machine ID: ${ctx.machineId}`);
|
|
14571
|
+
console.log(` Hostname: ${ctx.config?.hostname ?? "unknown"}`);
|
|
14572
|
+
console.log(` Available harnesses: ${ctx.config?.availableHarnesses.join(", ") || "none"}`);
|
|
14573
|
+
console.log(` Available models: ${Object.keys(availableModels).length > 0 ? `${Object.values(availableModels).flat().length} models across ${Object.keys(availableModels).join(", ")}` : "none discovered"}`);
|
|
14574
|
+
console.log(` PID: ${process.pid}`);
|
|
14575
|
+
}
|
|
14576
|
+
async function recoverState(ctx) {
|
|
14577
|
+
console.log(`
|
|
14578
|
+
[${formatTimestamp()}] \uD83D\uDD04 Recovering agent state...`);
|
|
14579
|
+
try {
|
|
14580
|
+
await recoverAgentState(ctx);
|
|
14581
|
+
} catch (e) {
|
|
14582
|
+
console.log(` ⚠️ Recovery failed: ${e.message}`);
|
|
14583
|
+
console.log(` Continuing with fresh state`);
|
|
14584
|
+
}
|
|
14585
|
+
}
|
|
14586
|
+
async function initDaemon() {
|
|
14587
|
+
if (!acquireLock()) {
|
|
14588
|
+
process.exit(1);
|
|
14589
|
+
}
|
|
14590
|
+
const convexUrl = getConvexUrl();
|
|
14591
|
+
const sessionId = validateAuthentication(convexUrl);
|
|
14592
|
+
const client2 = await getConvexClient();
|
|
14593
|
+
const typedSessionId = sessionId;
|
|
14594
|
+
await validateSession(client2, typedSessionId, convexUrl);
|
|
14595
|
+
const config3 = setupMachine();
|
|
14596
|
+
const { machineId } = config3;
|
|
14597
|
+
const openCodeService = new OpenCodeAgentService;
|
|
14598
|
+
const piService = new PiAgentService;
|
|
14599
|
+
const agentServices = new Map([
|
|
14600
|
+
["opencode", openCodeService],
|
|
14601
|
+
["pi", piService]
|
|
14602
|
+
]);
|
|
14603
|
+
const availableModels = await registerCapabilities(client2, typedSessionId, config3, agentServices);
|
|
14604
|
+
await connectDaemon(client2, typedSessionId, machineId, convexUrl);
|
|
14528
14605
|
const deps = createDefaultDeps16();
|
|
14529
14606
|
deps.backend.mutation = (endpoint, args) => client2.mutation(endpoint, args);
|
|
14530
14607
|
deps.backend.query = (endpoint, args) => client2.query(endpoint, args);
|
|
@@ -14539,21 +14616,8 @@ Run: chatroom auth login`);
|
|
|
14539
14616
|
agentServices
|
|
14540
14617
|
};
|
|
14541
14618
|
registerEventListeners(ctx);
|
|
14542
|
-
|
|
14543
|
-
|
|
14544
|
-
console.log(` Machine ID: ${machineId}`);
|
|
14545
|
-
console.log(` Hostname: ${config3?.hostname ?? "Unknown"}`);
|
|
14546
|
-
console.log(` Available harnesses: ${config3?.availableHarnesses.join(", ") || "none"}`);
|
|
14547
|
-
console.log(` Available models: ${Object.keys(availableModels).length > 0 ? `${Object.values(availableModels).flat().length} models across ${Object.keys(availableModels).join(", ")}` : "none discovered"}`);
|
|
14548
|
-
console.log(` PID: ${process.pid}`);
|
|
14549
|
-
console.log(`
|
|
14550
|
-
[${formatTimestamp()}] \uD83D\uDD04 Recovering agent state...`);
|
|
14551
|
-
try {
|
|
14552
|
-
await recoverAgentState(ctx);
|
|
14553
|
-
} catch (e) {
|
|
14554
|
-
console.log(` ⚠️ Recovery failed: ${e.message}`);
|
|
14555
|
-
console.log(` Continuing with fresh state`);
|
|
14556
|
-
}
|
|
14619
|
+
logStartup(ctx, availableModels);
|
|
14620
|
+
await recoverState(ctx);
|
|
14557
14621
|
return ctx;
|
|
14558
14622
|
}
|
|
14559
14623
|
var init_init2 = __esm(() => {
|