chatroom-cli 1.0.68 → 1.0.71
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 +323 -183
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -10199,6 +10199,205 @@ var init_machine = __esm(() => {
|
|
|
10199
10199
|
init_daemon_state();
|
|
10200
10200
|
});
|
|
10201
10201
|
|
|
10202
|
+
// src/infrastructure/agent-drivers/process-driver.ts
|
|
10203
|
+
import { spawn } from "node:child_process";
|
|
10204
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
10205
|
+
import { writeFileSync as writeFileSync4, unlinkSync as unlinkSync2 } from "node:fs";
|
|
10206
|
+
import { tmpdir } from "node:os";
|
|
10207
|
+
import { join as join5 } from "node:path";
|
|
10208
|
+
function writeTempPromptFile(prompt) {
|
|
10209
|
+
const tempPath = join5(tmpdir(), `chatroom-prompt-${randomUUID2()}.txt`);
|
|
10210
|
+
writeFileSync4(tempPath, prompt, { encoding: "utf-8", mode: 384 });
|
|
10211
|
+
return tempPath;
|
|
10212
|
+
}
|
|
10213
|
+
function scheduleCleanup(filePath, delayMs = 5000) {
|
|
10214
|
+
setTimeout(() => {
|
|
10215
|
+
try {
|
|
10216
|
+
unlinkSync2(filePath);
|
|
10217
|
+
} catch {}
|
|
10218
|
+
}, delayMs);
|
|
10219
|
+
}
|
|
10220
|
+
function buildCombinedPrompt(rolePrompt, initialMessage) {
|
|
10221
|
+
return `${rolePrompt}
|
|
10222
|
+
|
|
10223
|
+
${initialMessage}`;
|
|
10224
|
+
}
|
|
10225
|
+
|
|
10226
|
+
class ProcessDriver {
|
|
10227
|
+
async start(options) {
|
|
10228
|
+
const config = this.buildSpawnConfig(options);
|
|
10229
|
+
console.log(` Spawning ${this.harness} agent...`);
|
|
10230
|
+
console.log(` Working dir: ${options.workingDir}`);
|
|
10231
|
+
if (options.harnessVersion) {
|
|
10232
|
+
console.log(` Harness version: v${options.harnessVersion.version} (major: ${options.harnessVersion.major})`);
|
|
10233
|
+
}
|
|
10234
|
+
if (options.model) {
|
|
10235
|
+
console.log(` Model: ${options.model}`);
|
|
10236
|
+
}
|
|
10237
|
+
try {
|
|
10238
|
+
const childProcess = spawn(config.command, config.args, {
|
|
10239
|
+
cwd: options.workingDir,
|
|
10240
|
+
stdio: config.stdio,
|
|
10241
|
+
detached: true,
|
|
10242
|
+
shell: false
|
|
10243
|
+
});
|
|
10244
|
+
if (config.writePromptToStdin && config.stdinPrompt) {
|
|
10245
|
+
childProcess.stdin?.write(config.stdinPrompt);
|
|
10246
|
+
childProcess.stdin?.end();
|
|
10247
|
+
}
|
|
10248
|
+
config.afterSpawn?.(childProcess);
|
|
10249
|
+
childProcess.unref();
|
|
10250
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
10251
|
+
if (childProcess.killed || childProcess.exitCode !== null) {
|
|
10252
|
+
return {
|
|
10253
|
+
success: false,
|
|
10254
|
+
message: `Agent process exited immediately (exit code: ${childProcess.exitCode})`
|
|
10255
|
+
};
|
|
10256
|
+
}
|
|
10257
|
+
const handle = {
|
|
10258
|
+
harness: this.harness,
|
|
10259
|
+
type: "process",
|
|
10260
|
+
pid: childProcess.pid,
|
|
10261
|
+
workingDir: options.workingDir
|
|
10262
|
+
};
|
|
10263
|
+
return {
|
|
10264
|
+
success: true,
|
|
10265
|
+
message: "Agent spawned successfully",
|
|
10266
|
+
handle
|
|
10267
|
+
};
|
|
10268
|
+
} catch (error) {
|
|
10269
|
+
return {
|
|
10270
|
+
success: false,
|
|
10271
|
+
message: `Failed to spawn agent: ${error.message}`
|
|
10272
|
+
};
|
|
10273
|
+
}
|
|
10274
|
+
}
|
|
10275
|
+
async stop(handle) {
|
|
10276
|
+
if (handle.type !== "process" || !handle.pid) {
|
|
10277
|
+
throw new Error(`Cannot stop: handle has no PID (type=${handle.type})`);
|
|
10278
|
+
}
|
|
10279
|
+
process.kill(handle.pid, "SIGTERM");
|
|
10280
|
+
}
|
|
10281
|
+
async isAlive(handle) {
|
|
10282
|
+
if (handle.type !== "process" || !handle.pid) {
|
|
10283
|
+
return false;
|
|
10284
|
+
}
|
|
10285
|
+
try {
|
|
10286
|
+
process.kill(handle.pid, 0);
|
|
10287
|
+
return true;
|
|
10288
|
+
} catch {
|
|
10289
|
+
return false;
|
|
10290
|
+
}
|
|
10291
|
+
}
|
|
10292
|
+
async recover(_workingDir) {
|
|
10293
|
+
return [];
|
|
10294
|
+
}
|
|
10295
|
+
async listModels() {
|
|
10296
|
+
return [];
|
|
10297
|
+
}
|
|
10298
|
+
}
|
|
10299
|
+
var init_process_driver = () => {};
|
|
10300
|
+
|
|
10301
|
+
// src/infrastructure/agent-drivers/opencode-process-driver.ts
|
|
10302
|
+
import { execSync as execSync2 } from "node:child_process";
|
|
10303
|
+
var OpenCodeProcessDriver;
|
|
10304
|
+
var init_opencode_process_driver = __esm(() => {
|
|
10305
|
+
init_process_driver();
|
|
10306
|
+
init_types();
|
|
10307
|
+
OpenCodeProcessDriver = class OpenCodeProcessDriver extends ProcessDriver {
|
|
10308
|
+
harness = "opencode";
|
|
10309
|
+
capabilities = {
|
|
10310
|
+
sessionPersistence: false,
|
|
10311
|
+
abort: false,
|
|
10312
|
+
modelSelection: true,
|
|
10313
|
+
compaction: false,
|
|
10314
|
+
eventStreaming: false,
|
|
10315
|
+
messageInjection: false,
|
|
10316
|
+
dynamicModelDiscovery: true
|
|
10317
|
+
};
|
|
10318
|
+
buildSpawnConfig(options) {
|
|
10319
|
+
const command = AGENT_HARNESS_COMMANDS[this.harness];
|
|
10320
|
+
const combinedPrompt = buildCombinedPrompt(options.rolePrompt, options.initialMessage);
|
|
10321
|
+
const args = ["run"];
|
|
10322
|
+
if (options.model) {
|
|
10323
|
+
args.push("--model", options.model);
|
|
10324
|
+
}
|
|
10325
|
+
return {
|
|
10326
|
+
command,
|
|
10327
|
+
args,
|
|
10328
|
+
stdio: ["pipe", "inherit", "inherit"],
|
|
10329
|
+
writePromptToStdin: true,
|
|
10330
|
+
stdinPrompt: combinedPrompt
|
|
10331
|
+
};
|
|
10332
|
+
}
|
|
10333
|
+
async listModels() {
|
|
10334
|
+
try {
|
|
10335
|
+
const output = execSync2("opencode models", {
|
|
10336
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
10337
|
+
timeout: 1e4
|
|
10338
|
+
}).toString().trim();
|
|
10339
|
+
if (!output)
|
|
10340
|
+
return [];
|
|
10341
|
+
return output.split(`
|
|
10342
|
+
`).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
10343
|
+
} catch {
|
|
10344
|
+
return [];
|
|
10345
|
+
}
|
|
10346
|
+
}
|
|
10347
|
+
};
|
|
10348
|
+
});
|
|
10349
|
+
|
|
10350
|
+
// src/infrastructure/agent-drivers/registry.ts
|
|
10351
|
+
class DefaultDriverRegistry {
|
|
10352
|
+
drivers;
|
|
10353
|
+
constructor(drivers) {
|
|
10354
|
+
this.drivers = new Map;
|
|
10355
|
+
for (const driver of drivers) {
|
|
10356
|
+
this.drivers.set(driver.harness, driver);
|
|
10357
|
+
}
|
|
10358
|
+
}
|
|
10359
|
+
get(harness) {
|
|
10360
|
+
const driver = this.drivers.get(harness);
|
|
10361
|
+
if (!driver) {
|
|
10362
|
+
throw new Error(`No driver registered for harness: ${harness}`);
|
|
10363
|
+
}
|
|
10364
|
+
return driver;
|
|
10365
|
+
}
|
|
10366
|
+
all() {
|
|
10367
|
+
return Array.from(this.drivers.values());
|
|
10368
|
+
}
|
|
10369
|
+
capabilities(harness) {
|
|
10370
|
+
return this.get(harness).capabilities;
|
|
10371
|
+
}
|
|
10372
|
+
}
|
|
10373
|
+
function getDriverRegistry() {
|
|
10374
|
+
if (!registryInstance) {
|
|
10375
|
+
registryInstance = new DefaultDriverRegistry([new OpenCodeProcessDriver]);
|
|
10376
|
+
}
|
|
10377
|
+
return registryInstance;
|
|
10378
|
+
}
|
|
10379
|
+
var registryInstance = null;
|
|
10380
|
+
var init_registry = __esm(() => {
|
|
10381
|
+
init_opencode_process_driver();
|
|
10382
|
+
});
|
|
10383
|
+
|
|
10384
|
+
// src/infrastructure/agent-drivers/index.ts
|
|
10385
|
+
var exports_agent_drivers = {};
|
|
10386
|
+
__export(exports_agent_drivers, {
|
|
10387
|
+
writeTempPromptFile: () => writeTempPromptFile,
|
|
10388
|
+
scheduleCleanup: () => scheduleCleanup,
|
|
10389
|
+
getDriverRegistry: () => getDriverRegistry,
|
|
10390
|
+
buildCombinedPrompt: () => buildCombinedPrompt,
|
|
10391
|
+
ProcessDriver: () => ProcessDriver,
|
|
10392
|
+
OpenCodeProcessDriver: () => OpenCodeProcessDriver
|
|
10393
|
+
});
|
|
10394
|
+
var init_agent_drivers = __esm(() => {
|
|
10395
|
+
init_registry();
|
|
10396
|
+
init_process_driver();
|
|
10397
|
+
init_process_driver();
|
|
10398
|
+
init_opencode_process_driver();
|
|
10399
|
+
});
|
|
10400
|
+
|
|
10202
10401
|
// src/commands/auth-status.ts
|
|
10203
10402
|
var exports_auth_status = {};
|
|
10204
10403
|
__export(exports_auth_status, {
|
|
@@ -10239,6 +10438,17 @@ ${"═".repeat(50)}`);
|
|
|
10239
10438
|
}
|
|
10240
10439
|
try {
|
|
10241
10440
|
const machineInfo = ensureMachineRegistered();
|
|
10441
|
+
let availableModels = [];
|
|
10442
|
+
try {
|
|
10443
|
+
const { getDriverRegistry: getDriverRegistry2 } = await Promise.resolve().then(() => (init_agent_drivers(), exports_agent_drivers));
|
|
10444
|
+
const registry = getDriverRegistry2();
|
|
10445
|
+
for (const driver of registry.all()) {
|
|
10446
|
+
if (driver.capabilities.dynamicModelDiscovery) {
|
|
10447
|
+
const models = await driver.listModels();
|
|
10448
|
+
availableModels = availableModels.concat(models);
|
|
10449
|
+
}
|
|
10450
|
+
}
|
|
10451
|
+
} catch {}
|
|
10242
10452
|
await client2.mutation(api.machines.register, {
|
|
10243
10453
|
sessionId: authData.sessionId,
|
|
10244
10454
|
machineId: machineInfo.machineId,
|
|
@@ -10246,7 +10456,7 @@ ${"═".repeat(50)}`);
|
|
|
10246
10456
|
os: machineInfo.os,
|
|
10247
10457
|
availableHarnesses: machineInfo.availableHarnesses,
|
|
10248
10458
|
harnessVersions: machineInfo.harnessVersions,
|
|
10249
|
-
availableModels
|
|
10459
|
+
availableModels
|
|
10250
10460
|
});
|
|
10251
10461
|
console.log(`
|
|
10252
10462
|
\uD83D\uDDA5️ Machine registered: ${machineInfo.hostname}`);
|
|
@@ -10254,6 +10464,9 @@ ${"═".repeat(50)}`);
|
|
|
10254
10464
|
if (machineInfo.availableHarnesses.length > 0) {
|
|
10255
10465
|
console.log(` Harnesses: ${machineInfo.availableHarnesses.join(", ")}`);
|
|
10256
10466
|
}
|
|
10467
|
+
if (availableModels.length > 0) {
|
|
10468
|
+
console.log(` Models: ${availableModels.length} discovered`);
|
|
10469
|
+
}
|
|
10257
10470
|
} catch (machineError) {
|
|
10258
10471
|
const err = machineError;
|
|
10259
10472
|
console.log(`
|
|
@@ -10498,180 +10711,6 @@ var init_config2 = __esm(() => {
|
|
|
10498
10711
|
WEB_SERVER_PORT = parseInt(process.env.WEB_PORT || "3456", 10);
|
|
10499
10712
|
});
|
|
10500
10713
|
|
|
10501
|
-
// src/infrastructure/agent-drivers/process-driver.ts
|
|
10502
|
-
import { spawn } from "node:child_process";
|
|
10503
|
-
function buildCombinedPrompt(rolePrompt, initialMessage) {
|
|
10504
|
-
return `${rolePrompt}
|
|
10505
|
-
|
|
10506
|
-
${initialMessage}`;
|
|
10507
|
-
}
|
|
10508
|
-
|
|
10509
|
-
class ProcessDriver {
|
|
10510
|
-
async start(options) {
|
|
10511
|
-
const config3 = this.buildSpawnConfig(options);
|
|
10512
|
-
console.log(` Spawning ${this.harness} agent...`);
|
|
10513
|
-
console.log(` Working dir: ${options.workingDir}`);
|
|
10514
|
-
if (options.harnessVersion) {
|
|
10515
|
-
console.log(` Harness version: v${options.harnessVersion.version} (major: ${options.harnessVersion.major})`);
|
|
10516
|
-
}
|
|
10517
|
-
if (options.model) {
|
|
10518
|
-
console.log(` Model: ${options.model}`);
|
|
10519
|
-
}
|
|
10520
|
-
try {
|
|
10521
|
-
const childProcess = spawn(config3.command, config3.args, {
|
|
10522
|
-
cwd: options.workingDir,
|
|
10523
|
-
stdio: config3.stdio,
|
|
10524
|
-
detached: true,
|
|
10525
|
-
shell: false
|
|
10526
|
-
});
|
|
10527
|
-
if (config3.writePromptToStdin && config3.stdinPrompt) {
|
|
10528
|
-
childProcess.stdin?.write(config3.stdinPrompt);
|
|
10529
|
-
childProcess.stdin?.end();
|
|
10530
|
-
}
|
|
10531
|
-
config3.afterSpawn?.(childProcess);
|
|
10532
|
-
childProcess.unref();
|
|
10533
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
10534
|
-
if (childProcess.killed || childProcess.exitCode !== null) {
|
|
10535
|
-
return {
|
|
10536
|
-
success: false,
|
|
10537
|
-
message: `Agent process exited immediately (exit code: ${childProcess.exitCode})`
|
|
10538
|
-
};
|
|
10539
|
-
}
|
|
10540
|
-
const handle = {
|
|
10541
|
-
harness: this.harness,
|
|
10542
|
-
type: "process",
|
|
10543
|
-
pid: childProcess.pid,
|
|
10544
|
-
workingDir: options.workingDir
|
|
10545
|
-
};
|
|
10546
|
-
return {
|
|
10547
|
-
success: true,
|
|
10548
|
-
message: "Agent spawned successfully",
|
|
10549
|
-
handle
|
|
10550
|
-
};
|
|
10551
|
-
} catch (error) {
|
|
10552
|
-
return {
|
|
10553
|
-
success: false,
|
|
10554
|
-
message: `Failed to spawn agent: ${error.message}`
|
|
10555
|
-
};
|
|
10556
|
-
}
|
|
10557
|
-
}
|
|
10558
|
-
async stop(handle) {
|
|
10559
|
-
if (handle.type !== "process" || !handle.pid) {
|
|
10560
|
-
throw new Error(`Cannot stop: handle has no PID (type=${handle.type})`);
|
|
10561
|
-
}
|
|
10562
|
-
process.kill(handle.pid, "SIGTERM");
|
|
10563
|
-
}
|
|
10564
|
-
async isAlive(handle) {
|
|
10565
|
-
if (handle.type !== "process" || !handle.pid) {
|
|
10566
|
-
return false;
|
|
10567
|
-
}
|
|
10568
|
-
try {
|
|
10569
|
-
process.kill(handle.pid, 0);
|
|
10570
|
-
return true;
|
|
10571
|
-
} catch {
|
|
10572
|
-
return false;
|
|
10573
|
-
}
|
|
10574
|
-
}
|
|
10575
|
-
async recover(_workingDir) {
|
|
10576
|
-
return [];
|
|
10577
|
-
}
|
|
10578
|
-
async listModels() {
|
|
10579
|
-
return [];
|
|
10580
|
-
}
|
|
10581
|
-
}
|
|
10582
|
-
var init_process_driver = () => {};
|
|
10583
|
-
|
|
10584
|
-
// src/infrastructure/agent-drivers/opencode-process-driver.ts
|
|
10585
|
-
import { execSync as execSync2 } from "node:child_process";
|
|
10586
|
-
var OpenCodeProcessDriver;
|
|
10587
|
-
var init_opencode_process_driver = __esm(() => {
|
|
10588
|
-
init_process_driver();
|
|
10589
|
-
init_types();
|
|
10590
|
-
OpenCodeProcessDriver = class OpenCodeProcessDriver extends ProcessDriver {
|
|
10591
|
-
harness = "opencode";
|
|
10592
|
-
capabilities = {
|
|
10593
|
-
sessionPersistence: false,
|
|
10594
|
-
abort: false,
|
|
10595
|
-
modelSelection: true,
|
|
10596
|
-
compaction: false,
|
|
10597
|
-
eventStreaming: false,
|
|
10598
|
-
messageInjection: false,
|
|
10599
|
-
dynamicModelDiscovery: true
|
|
10600
|
-
};
|
|
10601
|
-
buildSpawnConfig(options) {
|
|
10602
|
-
const command = AGENT_HARNESS_COMMANDS[this.harness];
|
|
10603
|
-
const combinedPrompt = buildCombinedPrompt(options.rolePrompt, options.initialMessage);
|
|
10604
|
-
const args = ["run"];
|
|
10605
|
-
if (options.model) {
|
|
10606
|
-
args.push("--model", options.model);
|
|
10607
|
-
}
|
|
10608
|
-
return {
|
|
10609
|
-
command,
|
|
10610
|
-
args,
|
|
10611
|
-
stdio: ["pipe", "inherit", "inherit"],
|
|
10612
|
-
writePromptToStdin: true,
|
|
10613
|
-
stdinPrompt: combinedPrompt
|
|
10614
|
-
};
|
|
10615
|
-
}
|
|
10616
|
-
async listModels() {
|
|
10617
|
-
try {
|
|
10618
|
-
const output = execSync2("opencode models", {
|
|
10619
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
10620
|
-
timeout: 1e4
|
|
10621
|
-
}).toString().trim();
|
|
10622
|
-
if (!output)
|
|
10623
|
-
return [];
|
|
10624
|
-
return output.split(`
|
|
10625
|
-
`).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
10626
|
-
} catch {
|
|
10627
|
-
return [];
|
|
10628
|
-
}
|
|
10629
|
-
}
|
|
10630
|
-
};
|
|
10631
|
-
});
|
|
10632
|
-
|
|
10633
|
-
// src/infrastructure/agent-drivers/registry.ts
|
|
10634
|
-
class DefaultDriverRegistry {
|
|
10635
|
-
drivers;
|
|
10636
|
-
constructor(drivers) {
|
|
10637
|
-
this.drivers = new Map;
|
|
10638
|
-
for (const driver of drivers) {
|
|
10639
|
-
this.drivers.set(driver.harness, driver);
|
|
10640
|
-
}
|
|
10641
|
-
}
|
|
10642
|
-
get(harness) {
|
|
10643
|
-
const driver = this.drivers.get(harness);
|
|
10644
|
-
if (!driver) {
|
|
10645
|
-
throw new Error(`No driver registered for harness: ${harness}`);
|
|
10646
|
-
}
|
|
10647
|
-
return driver;
|
|
10648
|
-
}
|
|
10649
|
-
all() {
|
|
10650
|
-
return Array.from(this.drivers.values());
|
|
10651
|
-
}
|
|
10652
|
-
capabilities(harness) {
|
|
10653
|
-
return this.get(harness).capabilities;
|
|
10654
|
-
}
|
|
10655
|
-
}
|
|
10656
|
-
function getDriverRegistry() {
|
|
10657
|
-
if (!registryInstance) {
|
|
10658
|
-
registryInstance = new DefaultDriverRegistry([new OpenCodeProcessDriver]);
|
|
10659
|
-
}
|
|
10660
|
-
return registryInstance;
|
|
10661
|
-
}
|
|
10662
|
-
var registryInstance = null;
|
|
10663
|
-
var init_registry = __esm(() => {
|
|
10664
|
-
init_opencode_process_driver();
|
|
10665
|
-
});
|
|
10666
|
-
|
|
10667
|
-
// src/infrastructure/agent-drivers/index.ts
|
|
10668
|
-
var init_agent_drivers = __esm(() => {
|
|
10669
|
-
init_registry();
|
|
10670
|
-
init_process_driver();
|
|
10671
|
-
init_process_driver();
|
|
10672
|
-
init_opencode_process_driver();
|
|
10673
|
-
});
|
|
10674
|
-
|
|
10675
10714
|
// src/commands/wait-for-task.ts
|
|
10676
10715
|
var exports_wait_for_task = {};
|
|
10677
10716
|
__export(exports_wait_for_task, {
|
|
@@ -10985,6 +11024,24 @@ ATTACHED BACKLOG (${originMessage.attachedTasks.length})`);
|
|
|
10985
11024
|
console.log(`${attachedTask.content}`);
|
|
10986
11025
|
}
|
|
10987
11026
|
}
|
|
11027
|
+
const followUpCount = taskDeliveryPrompt.json?.contextWindow?.followUpCountSinceOrigin ?? 0;
|
|
11028
|
+
const originCreatedAt = taskDeliveryPrompt.json?.contextWindow?.originMessageCreatedAt;
|
|
11029
|
+
if (followUpCount >= 5) {
|
|
11030
|
+
console.log(`
|
|
11031
|
+
⚠️ WARNING: ${followUpCount} follow-up messages since this pinned message.`);
|
|
11032
|
+
console.log(` The user may have moved on to a different topic.`);
|
|
11033
|
+
console.log(` Consider asking if this context is still relevant.`);
|
|
11034
|
+
}
|
|
11035
|
+
if (originCreatedAt) {
|
|
11036
|
+
const ageMs = Date.now() - originCreatedAt;
|
|
11037
|
+
const ageHours = ageMs / (1000 * 60 * 60);
|
|
11038
|
+
if (ageHours >= 24) {
|
|
11039
|
+
const ageDays = Math.floor(ageHours / 24);
|
|
11040
|
+
console.log(`
|
|
11041
|
+
⚠️ WARNING: This pinned message is ${ageDays} day(s) old.`);
|
|
11042
|
+
console.log(` The context may be outdated.`);
|
|
11043
|
+
}
|
|
11044
|
+
}
|
|
10988
11045
|
console.log(`</user-message>`);
|
|
10989
11046
|
}
|
|
10990
11047
|
console.log(`
|
|
@@ -12571,9 +12628,9 @@ var init_artifact = __esm(() => {
|
|
|
12571
12628
|
|
|
12572
12629
|
// src/commands/machine/pid.ts
|
|
12573
12630
|
import { createHash } from "node:crypto";
|
|
12574
|
-
import { existsSync as existsSync4, readFileSync as readFileSync6, writeFileSync as
|
|
12631
|
+
import { existsSync as existsSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync5, unlinkSync as unlinkSync3, mkdirSync as mkdirSync4 } from "node:fs";
|
|
12575
12632
|
import { homedir as homedir4 } from "node:os";
|
|
12576
|
-
import { join as
|
|
12633
|
+
import { join as join6 } from "node:path";
|
|
12577
12634
|
function getUrlHash() {
|
|
12578
12635
|
const url = getConvexUrl();
|
|
12579
12636
|
return createHash("sha256").update(url).digest("hex").substring(0, 8);
|
|
@@ -12587,7 +12644,7 @@ function ensureChatroomDir() {
|
|
|
12587
12644
|
}
|
|
12588
12645
|
}
|
|
12589
12646
|
function getPidFilePath() {
|
|
12590
|
-
return
|
|
12647
|
+
return join6(CHATROOM_DIR4, getPidFileName());
|
|
12591
12648
|
}
|
|
12592
12649
|
function isProcessRunning(pid) {
|
|
12593
12650
|
try {
|
|
@@ -12616,13 +12673,13 @@ function readPid() {
|
|
|
12616
12673
|
function writePid() {
|
|
12617
12674
|
ensureChatroomDir();
|
|
12618
12675
|
const pidPath = getPidFilePath();
|
|
12619
|
-
|
|
12676
|
+
writeFileSync5(pidPath, process.pid.toString(), "utf-8");
|
|
12620
12677
|
}
|
|
12621
12678
|
function removePid() {
|
|
12622
12679
|
const pidPath = getPidFilePath();
|
|
12623
12680
|
try {
|
|
12624
12681
|
if (existsSync4(pidPath)) {
|
|
12625
|
-
|
|
12682
|
+
unlinkSync3(pidPath);
|
|
12626
12683
|
}
|
|
12627
12684
|
} catch {}
|
|
12628
12685
|
}
|
|
@@ -12652,7 +12709,7 @@ function releaseLock() {
|
|
|
12652
12709
|
var CHATROOM_DIR4;
|
|
12653
12710
|
var init_pid = __esm(() => {
|
|
12654
12711
|
init_client2();
|
|
12655
|
-
CHATROOM_DIR4 =
|
|
12712
|
+
CHATROOM_DIR4 = join6(homedir4(), ".chatroom");
|
|
12656
12713
|
});
|
|
12657
12714
|
|
|
12658
12715
|
// src/commands/machine/daemon-start.ts
|
|
@@ -12854,7 +12911,8 @@ async function handleStartAgent(ctx, command) {
|
|
|
12854
12911
|
machineId: ctx.machineId,
|
|
12855
12912
|
chatroomId,
|
|
12856
12913
|
role,
|
|
12857
|
-
pid: startResult.handle.pid
|
|
12914
|
+
pid: startResult.handle.pid,
|
|
12915
|
+
model
|
|
12858
12916
|
});
|
|
12859
12917
|
console.log(` Updated backend with PID: ${startResult.handle.pid}`);
|
|
12860
12918
|
persistAgentPid(ctx.machineId, chatroomId, role, startResult.handle.pid, agentHarness);
|
|
@@ -12903,6 +12961,14 @@ async function handleStopAgent(ctx, command) {
|
|
|
12903
12961
|
console.log(` ⚠️ PID ${pidToKill} does not appear to belong to the expected agent`);
|
|
12904
12962
|
await clearAgentPidEverywhere(ctx, chatroomId, role);
|
|
12905
12963
|
console.log(` Cleared stale PID`);
|
|
12964
|
+
try {
|
|
12965
|
+
await ctx.client.mutation(api.participants.leave, {
|
|
12966
|
+
sessionId: ctx.sessionId,
|
|
12967
|
+
chatroomId,
|
|
12968
|
+
role
|
|
12969
|
+
});
|
|
12970
|
+
console.log(` Removed participant record`);
|
|
12971
|
+
} catch {}
|
|
12906
12972
|
return {
|
|
12907
12973
|
result: `PID ${pidToKill} appears stale (process not found or belongs to different program)`,
|
|
12908
12974
|
failed: true
|
|
@@ -12918,11 +12984,28 @@ async function handleStopAgent(ctx, command) {
|
|
|
12918
12984
|
console.log(` ✅ ${msg}`);
|
|
12919
12985
|
await clearAgentPidEverywhere(ctx, chatroomId, role);
|
|
12920
12986
|
console.log(` Cleared PID`);
|
|
12987
|
+
try {
|
|
12988
|
+
await ctx.client.mutation(api.participants.leave, {
|
|
12989
|
+
sessionId: ctx.sessionId,
|
|
12990
|
+
chatroomId,
|
|
12991
|
+
role
|
|
12992
|
+
});
|
|
12993
|
+
console.log(` Removed participant record`);
|
|
12994
|
+
} catch (leaveErr) {
|
|
12995
|
+
console.log(` ⚠️ Could not remove participant: ${leaveErr.message}`);
|
|
12996
|
+
}
|
|
12921
12997
|
return { result: msg, failed: false };
|
|
12922
12998
|
} catch (e) {
|
|
12923
12999
|
const err = e;
|
|
12924
13000
|
if (err.code === "ESRCH") {
|
|
12925
13001
|
await clearAgentPidEverywhere(ctx, chatroomId, role);
|
|
13002
|
+
try {
|
|
13003
|
+
await ctx.client.mutation(api.participants.leave, {
|
|
13004
|
+
sessionId: ctx.sessionId,
|
|
13005
|
+
chatroomId,
|
|
13006
|
+
role
|
|
13007
|
+
});
|
|
13008
|
+
} catch {}
|
|
12926
13009
|
const msg2 = "Process not found (may have already exited)";
|
|
12927
13010
|
console.log(` ⚠️ ${msg2}`);
|
|
12928
13011
|
return { result: msg2, failed: true };
|
|
@@ -12986,6 +13069,38 @@ async function processCommand(ctx, command) {
|
|
|
12986
13069
|
} catch {}
|
|
12987
13070
|
}
|
|
12988
13071
|
}
|
|
13072
|
+
async function discoverModels() {
|
|
13073
|
+
const models = [];
|
|
13074
|
+
try {
|
|
13075
|
+
const registry = getDriverRegistry();
|
|
13076
|
+
for (const driver of registry.all()) {
|
|
13077
|
+
if (driver.capabilities.dynamicModelDiscovery) {
|
|
13078
|
+
const driverModels = await driver.listModels();
|
|
13079
|
+
models.push(...driverModels);
|
|
13080
|
+
}
|
|
13081
|
+
}
|
|
13082
|
+
} catch {}
|
|
13083
|
+
return models;
|
|
13084
|
+
}
|
|
13085
|
+
async function refreshModels(ctx) {
|
|
13086
|
+
const models = await discoverModels();
|
|
13087
|
+
if (!ctx.config)
|
|
13088
|
+
return;
|
|
13089
|
+
try {
|
|
13090
|
+
await ctx.client.mutation(api.machines.register, {
|
|
13091
|
+
sessionId: ctx.sessionId,
|
|
13092
|
+
machineId: ctx.machineId,
|
|
13093
|
+
hostname: ctx.config.hostname,
|
|
13094
|
+
os: ctx.config.os,
|
|
13095
|
+
availableHarnesses: ctx.config.availableHarnesses,
|
|
13096
|
+
harnessVersions: ctx.config.harnessVersions,
|
|
13097
|
+
availableModels: models
|
|
13098
|
+
});
|
|
13099
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDD04 Model refresh: ${models.length > 0 ? `${models.length} models` : "none discovered"}`);
|
|
13100
|
+
} catch (error) {
|
|
13101
|
+
console.warn(`[${formatTimestamp()}] ⚠️ Model refresh failed: ${error.message}`);
|
|
13102
|
+
}
|
|
13103
|
+
}
|
|
12989
13104
|
async function initDaemon() {
|
|
12990
13105
|
if (!acquireLock()) {
|
|
12991
13106
|
process.exit(1);
|
|
@@ -13018,6 +13133,23 @@ Run any chatroom command first to register this machine,`);
|
|
|
13018
13133
|
}
|
|
13019
13134
|
const client2 = await getConvexClient();
|
|
13020
13135
|
const typedSessionId = sessionId;
|
|
13136
|
+
const config3 = loadMachineConfig();
|
|
13137
|
+
const availableModels = await discoverModels();
|
|
13138
|
+
if (config3) {
|
|
13139
|
+
try {
|
|
13140
|
+
await client2.mutation(api.machines.register, {
|
|
13141
|
+
sessionId: typedSessionId,
|
|
13142
|
+
machineId,
|
|
13143
|
+
hostname: config3.hostname,
|
|
13144
|
+
os: config3.os,
|
|
13145
|
+
availableHarnesses: config3.availableHarnesses,
|
|
13146
|
+
harnessVersions: config3.harnessVersions,
|
|
13147
|
+
availableModels
|
|
13148
|
+
});
|
|
13149
|
+
} catch (error) {
|
|
13150
|
+
console.warn(`⚠️ Machine registration update failed: ${error.message}`);
|
|
13151
|
+
}
|
|
13152
|
+
}
|
|
13021
13153
|
try {
|
|
13022
13154
|
await client2.mutation(api.machines.updateDaemonStatus, {
|
|
13023
13155
|
sessionId: typedSessionId,
|
|
@@ -13029,12 +13161,12 @@ Run any chatroom command first to register this machine,`);
|
|
|
13029
13161
|
releaseLock();
|
|
13030
13162
|
process.exit(1);
|
|
13031
13163
|
}
|
|
13032
|
-
const config3 = loadMachineConfig();
|
|
13033
13164
|
const ctx = { client: client2, sessionId: typedSessionId, machineId, config: config3 };
|
|
13034
13165
|
console.log(`[${formatTimestamp()}] \uD83D\uDE80 Daemon started`);
|
|
13035
13166
|
console.log(` Machine ID: ${machineId}`);
|
|
13036
13167
|
console.log(` Hostname: ${config3?.hostname ?? "Unknown"}`);
|
|
13037
13168
|
console.log(` Available harnesses: ${config3?.availableHarnesses.join(", ") || "none"}`);
|
|
13169
|
+
console.log(` Available models: ${availableModels.length > 0 ? availableModels.length : "none discovered"}`);
|
|
13038
13170
|
console.log(` PID: ${process.pid}`);
|
|
13039
13171
|
console.log(`
|
|
13040
13172
|
[${formatTimestamp()}] \uD83D\uDD04 Recovering agent state...`);
|
|
@@ -13109,12 +13241,19 @@ Listening for commands...`);
|
|
|
13109
13241
|
enqueueCommands(parsed);
|
|
13110
13242
|
await drainQueue();
|
|
13111
13243
|
});
|
|
13244
|
+
const modelRefreshTimer = setInterval(() => {
|
|
13245
|
+
refreshModels(ctx).catch((err) => {
|
|
13246
|
+
console.warn(`[${formatTimestamp()}] ⚠️ Model refresh error: ${err.message}`);
|
|
13247
|
+
});
|
|
13248
|
+
}, MODEL_REFRESH_INTERVAL_MS);
|
|
13249
|
+
modelRefreshTimer.unref();
|
|
13112
13250
|
return await new Promise(() => {});
|
|
13113
13251
|
}
|
|
13114
13252
|
async function daemonStart() {
|
|
13115
13253
|
const ctx = await initDaemon();
|
|
13116
13254
|
await startCommandLoop(ctx);
|
|
13117
13255
|
}
|
|
13256
|
+
var MODEL_REFRESH_INTERVAL_MS;
|
|
13118
13257
|
var init_daemon_start = __esm(() => {
|
|
13119
13258
|
init_pid();
|
|
13120
13259
|
init_api3();
|
|
@@ -13122,6 +13261,7 @@ var init_daemon_start = __esm(() => {
|
|
|
13122
13261
|
init_storage();
|
|
13123
13262
|
init_client2();
|
|
13124
13263
|
init_machine();
|
|
13264
|
+
MODEL_REFRESH_INTERVAL_MS = 5 * 60 * 1000;
|
|
13125
13265
|
});
|
|
13126
13266
|
|
|
13127
13267
|
// src/commands/machine/daemon-stop.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chatroom-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.71",
|
|
4
4
|
"description": "CLI for multi-agent chatroom collaboration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"commander": "^14.0.0",
|
|
20
|
-
"convex": "^1.31.0"
|
|
20
|
+
"convex": "^1.31.0",
|
|
21
|
+
"convex-helpers": "^0.1.108"
|
|
21
22
|
},
|
|
22
23
|
"devDependencies": {
|
|
23
24
|
"@types/bun": "latest",
|