chatroom-cli 1.0.69 → 1.0.72
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 +393 -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(`
|
|
@@ -11692,6 +11749,7 @@ var init_report_progress = __esm(() => {
|
|
|
11692
11749
|
// src/commands/backlog.ts
|
|
11693
11750
|
var exports_backlog = {};
|
|
11694
11751
|
__export(exports_backlog, {
|
|
11752
|
+
scoreBacklog: () => scoreBacklog,
|
|
11695
11753
|
resetBacklog: () => resetBacklog,
|
|
11696
11754
|
reopenBacklog: () => reopenBacklog,
|
|
11697
11755
|
patchBacklog: () => patchBacklog,
|
|
@@ -11990,6 +12048,70 @@ async function patchBacklog(chatroomId, options) {
|
|
|
11990
12048
|
process.exit(1);
|
|
11991
12049
|
}
|
|
11992
12050
|
}
|
|
12051
|
+
async function scoreBacklog(chatroomId, options) {
|
|
12052
|
+
const client2 = await getConvexClient();
|
|
12053
|
+
const sessionId = getSessionId();
|
|
12054
|
+
if (!sessionId) {
|
|
12055
|
+
console.error(`❌ Not authenticated. Please run: chatroom auth login`);
|
|
12056
|
+
process.exit(1);
|
|
12057
|
+
}
|
|
12058
|
+
if (!chatroomId || typeof chatroomId !== "string" || chatroomId.length < 20 || chatroomId.length > 40) {
|
|
12059
|
+
console.error(`❌ Invalid chatroom ID format: ID must be 20-40 characters (got ${chatroomId?.length || 0})`);
|
|
12060
|
+
process.exit(1);
|
|
12061
|
+
}
|
|
12062
|
+
if (!options.taskId || options.taskId.trim().length === 0) {
|
|
12063
|
+
console.error(`❌ Task ID is required`);
|
|
12064
|
+
process.exit(1);
|
|
12065
|
+
}
|
|
12066
|
+
if (options.complexity === undefined && options.value === undefined && options.priority === undefined) {
|
|
12067
|
+
console.error(`❌ At least one of --complexity, --value, or --priority is required`);
|
|
12068
|
+
console.error(` Example: chatroom backlog score --task-id=... --complexity=medium --value=high`);
|
|
12069
|
+
process.exit(1);
|
|
12070
|
+
}
|
|
12071
|
+
const validComplexity = ["low", "medium", "high"];
|
|
12072
|
+
if (options.complexity !== undefined && !validComplexity.includes(options.complexity)) {
|
|
12073
|
+
console.error(`❌ Invalid complexity: ${options.complexity}. Must be one of: ${validComplexity.join(", ")}`);
|
|
12074
|
+
process.exit(1);
|
|
12075
|
+
}
|
|
12076
|
+
const validValue = ["low", "medium", "high"];
|
|
12077
|
+
if (options.value !== undefined && !validValue.includes(options.value)) {
|
|
12078
|
+
console.error(`❌ Invalid value: ${options.value}. Must be one of: ${validValue.join(", ")}`);
|
|
12079
|
+
process.exit(1);
|
|
12080
|
+
}
|
|
12081
|
+
let priorityNum;
|
|
12082
|
+
if (options.priority !== undefined) {
|
|
12083
|
+
priorityNum = parseInt(options.priority, 10);
|
|
12084
|
+
if (isNaN(priorityNum)) {
|
|
12085
|
+
console.error(`❌ Invalid priority: ${options.priority}. Must be a number.`);
|
|
12086
|
+
process.exit(1);
|
|
12087
|
+
}
|
|
12088
|
+
}
|
|
12089
|
+
try {
|
|
12090
|
+
await client2.mutation(api.tasks.patchTask, {
|
|
12091
|
+
sessionId,
|
|
12092
|
+
taskId: options.taskId,
|
|
12093
|
+
complexity: options.complexity,
|
|
12094
|
+
value: options.value,
|
|
12095
|
+
priority: priorityNum
|
|
12096
|
+
});
|
|
12097
|
+
console.log("");
|
|
12098
|
+
console.log("✅ Task scored");
|
|
12099
|
+
console.log(` ID: ${options.taskId}`);
|
|
12100
|
+
if (options.complexity !== undefined) {
|
|
12101
|
+
console.log(` Complexity: ${options.complexity}`);
|
|
12102
|
+
}
|
|
12103
|
+
if (options.value !== undefined) {
|
|
12104
|
+
console.log(` Value: ${options.value}`);
|
|
12105
|
+
}
|
|
12106
|
+
if (priorityNum !== undefined) {
|
|
12107
|
+
console.log(` Priority: ${priorityNum}`);
|
|
12108
|
+
}
|
|
12109
|
+
console.log("");
|
|
12110
|
+
} catch (error) {
|
|
12111
|
+
console.error(`❌ Failed to score task: ${error.message}`);
|
|
12112
|
+
process.exit(1);
|
|
12113
|
+
}
|
|
12114
|
+
}
|
|
11993
12115
|
async function markForReviewBacklog(chatroomId, options) {
|
|
11994
12116
|
const client2 = await getConvexClient();
|
|
11995
12117
|
const sessionId = getSessionId();
|
|
@@ -12571,9 +12693,9 @@ var init_artifact = __esm(() => {
|
|
|
12571
12693
|
|
|
12572
12694
|
// src/commands/machine/pid.ts
|
|
12573
12695
|
import { createHash } from "node:crypto";
|
|
12574
|
-
import { existsSync as existsSync4, readFileSync as readFileSync6, writeFileSync as
|
|
12696
|
+
import { existsSync as existsSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync5, unlinkSync as unlinkSync3, mkdirSync as mkdirSync4 } from "node:fs";
|
|
12575
12697
|
import { homedir as homedir4 } from "node:os";
|
|
12576
|
-
import { join as
|
|
12698
|
+
import { join as join6 } from "node:path";
|
|
12577
12699
|
function getUrlHash() {
|
|
12578
12700
|
const url = getConvexUrl();
|
|
12579
12701
|
return createHash("sha256").update(url).digest("hex").substring(0, 8);
|
|
@@ -12587,7 +12709,7 @@ function ensureChatroomDir() {
|
|
|
12587
12709
|
}
|
|
12588
12710
|
}
|
|
12589
12711
|
function getPidFilePath() {
|
|
12590
|
-
return
|
|
12712
|
+
return join6(CHATROOM_DIR4, getPidFileName());
|
|
12591
12713
|
}
|
|
12592
12714
|
function isProcessRunning(pid) {
|
|
12593
12715
|
try {
|
|
@@ -12616,13 +12738,13 @@ function readPid() {
|
|
|
12616
12738
|
function writePid() {
|
|
12617
12739
|
ensureChatroomDir();
|
|
12618
12740
|
const pidPath = getPidFilePath();
|
|
12619
|
-
|
|
12741
|
+
writeFileSync5(pidPath, process.pid.toString(), "utf-8");
|
|
12620
12742
|
}
|
|
12621
12743
|
function removePid() {
|
|
12622
12744
|
const pidPath = getPidFilePath();
|
|
12623
12745
|
try {
|
|
12624
12746
|
if (existsSync4(pidPath)) {
|
|
12625
|
-
|
|
12747
|
+
unlinkSync3(pidPath);
|
|
12626
12748
|
}
|
|
12627
12749
|
} catch {}
|
|
12628
12750
|
}
|
|
@@ -12652,7 +12774,7 @@ function releaseLock() {
|
|
|
12652
12774
|
var CHATROOM_DIR4;
|
|
12653
12775
|
var init_pid = __esm(() => {
|
|
12654
12776
|
init_client2();
|
|
12655
|
-
CHATROOM_DIR4 =
|
|
12777
|
+
CHATROOM_DIR4 = join6(homedir4(), ".chatroom");
|
|
12656
12778
|
});
|
|
12657
12779
|
|
|
12658
12780
|
// src/commands/machine/daemon-start.ts
|
|
@@ -12854,7 +12976,8 @@ async function handleStartAgent(ctx, command) {
|
|
|
12854
12976
|
machineId: ctx.machineId,
|
|
12855
12977
|
chatroomId,
|
|
12856
12978
|
role,
|
|
12857
|
-
pid: startResult.handle.pid
|
|
12979
|
+
pid: startResult.handle.pid,
|
|
12980
|
+
model
|
|
12858
12981
|
});
|
|
12859
12982
|
console.log(` Updated backend with PID: ${startResult.handle.pid}`);
|
|
12860
12983
|
persistAgentPid(ctx.machineId, chatroomId, role, startResult.handle.pid, agentHarness);
|
|
@@ -12903,6 +13026,14 @@ async function handleStopAgent(ctx, command) {
|
|
|
12903
13026
|
console.log(` ⚠️ PID ${pidToKill} does not appear to belong to the expected agent`);
|
|
12904
13027
|
await clearAgentPidEverywhere(ctx, chatroomId, role);
|
|
12905
13028
|
console.log(` Cleared stale PID`);
|
|
13029
|
+
try {
|
|
13030
|
+
await ctx.client.mutation(api.participants.leave, {
|
|
13031
|
+
sessionId: ctx.sessionId,
|
|
13032
|
+
chatroomId,
|
|
13033
|
+
role
|
|
13034
|
+
});
|
|
13035
|
+
console.log(` Removed participant record`);
|
|
13036
|
+
} catch {}
|
|
12906
13037
|
return {
|
|
12907
13038
|
result: `PID ${pidToKill} appears stale (process not found or belongs to different program)`,
|
|
12908
13039
|
failed: true
|
|
@@ -12918,11 +13049,28 @@ async function handleStopAgent(ctx, command) {
|
|
|
12918
13049
|
console.log(` ✅ ${msg}`);
|
|
12919
13050
|
await clearAgentPidEverywhere(ctx, chatroomId, role);
|
|
12920
13051
|
console.log(` Cleared PID`);
|
|
13052
|
+
try {
|
|
13053
|
+
await ctx.client.mutation(api.participants.leave, {
|
|
13054
|
+
sessionId: ctx.sessionId,
|
|
13055
|
+
chatroomId,
|
|
13056
|
+
role
|
|
13057
|
+
});
|
|
13058
|
+
console.log(` Removed participant record`);
|
|
13059
|
+
} catch (leaveErr) {
|
|
13060
|
+
console.log(` ⚠️ Could not remove participant: ${leaveErr.message}`);
|
|
13061
|
+
}
|
|
12921
13062
|
return { result: msg, failed: false };
|
|
12922
13063
|
} catch (e) {
|
|
12923
13064
|
const err = e;
|
|
12924
13065
|
if (err.code === "ESRCH") {
|
|
12925
13066
|
await clearAgentPidEverywhere(ctx, chatroomId, role);
|
|
13067
|
+
try {
|
|
13068
|
+
await ctx.client.mutation(api.participants.leave, {
|
|
13069
|
+
sessionId: ctx.sessionId,
|
|
13070
|
+
chatroomId,
|
|
13071
|
+
role
|
|
13072
|
+
});
|
|
13073
|
+
} catch {}
|
|
12926
13074
|
const msg2 = "Process not found (may have already exited)";
|
|
12927
13075
|
console.log(` ⚠️ ${msg2}`);
|
|
12928
13076
|
return { result: msg2, failed: true };
|
|
@@ -12986,6 +13134,38 @@ async function processCommand(ctx, command) {
|
|
|
12986
13134
|
} catch {}
|
|
12987
13135
|
}
|
|
12988
13136
|
}
|
|
13137
|
+
async function discoverModels() {
|
|
13138
|
+
const models = [];
|
|
13139
|
+
try {
|
|
13140
|
+
const registry = getDriverRegistry();
|
|
13141
|
+
for (const driver of registry.all()) {
|
|
13142
|
+
if (driver.capabilities.dynamicModelDiscovery) {
|
|
13143
|
+
const driverModels = await driver.listModels();
|
|
13144
|
+
models.push(...driverModels);
|
|
13145
|
+
}
|
|
13146
|
+
}
|
|
13147
|
+
} catch {}
|
|
13148
|
+
return models;
|
|
13149
|
+
}
|
|
13150
|
+
async function refreshModels(ctx) {
|
|
13151
|
+
const models = await discoverModels();
|
|
13152
|
+
if (!ctx.config)
|
|
13153
|
+
return;
|
|
13154
|
+
try {
|
|
13155
|
+
await ctx.client.mutation(api.machines.register, {
|
|
13156
|
+
sessionId: ctx.sessionId,
|
|
13157
|
+
machineId: ctx.machineId,
|
|
13158
|
+
hostname: ctx.config.hostname,
|
|
13159
|
+
os: ctx.config.os,
|
|
13160
|
+
availableHarnesses: ctx.config.availableHarnesses,
|
|
13161
|
+
harnessVersions: ctx.config.harnessVersions,
|
|
13162
|
+
availableModels: models
|
|
13163
|
+
});
|
|
13164
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDD04 Model refresh: ${models.length > 0 ? `${models.length} models` : "none discovered"}`);
|
|
13165
|
+
} catch (error) {
|
|
13166
|
+
console.warn(`[${formatTimestamp()}] ⚠️ Model refresh failed: ${error.message}`);
|
|
13167
|
+
}
|
|
13168
|
+
}
|
|
12989
13169
|
async function initDaemon() {
|
|
12990
13170
|
if (!acquireLock()) {
|
|
12991
13171
|
process.exit(1);
|
|
@@ -13018,6 +13198,23 @@ Run any chatroom command first to register this machine,`);
|
|
|
13018
13198
|
}
|
|
13019
13199
|
const client2 = await getConvexClient();
|
|
13020
13200
|
const typedSessionId = sessionId;
|
|
13201
|
+
const config3 = loadMachineConfig();
|
|
13202
|
+
const availableModels = await discoverModels();
|
|
13203
|
+
if (config3) {
|
|
13204
|
+
try {
|
|
13205
|
+
await client2.mutation(api.machines.register, {
|
|
13206
|
+
sessionId: typedSessionId,
|
|
13207
|
+
machineId,
|
|
13208
|
+
hostname: config3.hostname,
|
|
13209
|
+
os: config3.os,
|
|
13210
|
+
availableHarnesses: config3.availableHarnesses,
|
|
13211
|
+
harnessVersions: config3.harnessVersions,
|
|
13212
|
+
availableModels
|
|
13213
|
+
});
|
|
13214
|
+
} catch (error) {
|
|
13215
|
+
console.warn(`⚠️ Machine registration update failed: ${error.message}`);
|
|
13216
|
+
}
|
|
13217
|
+
}
|
|
13021
13218
|
try {
|
|
13022
13219
|
await client2.mutation(api.machines.updateDaemonStatus, {
|
|
13023
13220
|
sessionId: typedSessionId,
|
|
@@ -13029,12 +13226,12 @@ Run any chatroom command first to register this machine,`);
|
|
|
13029
13226
|
releaseLock();
|
|
13030
13227
|
process.exit(1);
|
|
13031
13228
|
}
|
|
13032
|
-
const config3 = loadMachineConfig();
|
|
13033
13229
|
const ctx = { client: client2, sessionId: typedSessionId, machineId, config: config3 };
|
|
13034
13230
|
console.log(`[${formatTimestamp()}] \uD83D\uDE80 Daemon started`);
|
|
13035
13231
|
console.log(` Machine ID: ${machineId}`);
|
|
13036
13232
|
console.log(` Hostname: ${config3?.hostname ?? "Unknown"}`);
|
|
13037
13233
|
console.log(` Available harnesses: ${config3?.availableHarnesses.join(", ") || "none"}`);
|
|
13234
|
+
console.log(` Available models: ${availableModels.length > 0 ? availableModels.length : "none discovered"}`);
|
|
13038
13235
|
console.log(` PID: ${process.pid}`);
|
|
13039
13236
|
console.log(`
|
|
13040
13237
|
[${formatTimestamp()}] \uD83D\uDD04 Recovering agent state...`);
|
|
@@ -13109,12 +13306,19 @@ Listening for commands...`);
|
|
|
13109
13306
|
enqueueCommands(parsed);
|
|
13110
13307
|
await drainQueue();
|
|
13111
13308
|
});
|
|
13309
|
+
const modelRefreshTimer = setInterval(() => {
|
|
13310
|
+
refreshModels(ctx).catch((err) => {
|
|
13311
|
+
console.warn(`[${formatTimestamp()}] ⚠️ Model refresh error: ${err.message}`);
|
|
13312
|
+
});
|
|
13313
|
+
}, MODEL_REFRESH_INTERVAL_MS);
|
|
13314
|
+
modelRefreshTimer.unref();
|
|
13112
13315
|
return await new Promise(() => {});
|
|
13113
13316
|
}
|
|
13114
13317
|
async function daemonStart() {
|
|
13115
13318
|
const ctx = await initDaemon();
|
|
13116
13319
|
await startCommandLoop(ctx);
|
|
13117
13320
|
}
|
|
13321
|
+
var MODEL_REFRESH_INTERVAL_MS;
|
|
13118
13322
|
var init_daemon_start = __esm(() => {
|
|
13119
13323
|
init_pid();
|
|
13120
13324
|
init_api3();
|
|
@@ -13122,6 +13326,7 @@ var init_daemon_start = __esm(() => {
|
|
|
13122
13326
|
init_storage();
|
|
13123
13327
|
init_client2();
|
|
13124
13328
|
init_machine();
|
|
13329
|
+
MODEL_REFRESH_INTERVAL_MS = 5 * 60 * 1000;
|
|
13125
13330
|
});
|
|
13126
13331
|
|
|
13127
13332
|
// src/commands/machine/daemon-stop.ts
|
|
@@ -13809,6 +14014,11 @@ backlogCommand.command("patch-task").description("Update task scoring fields (co
|
|
|
13809
14014
|
const { patchBacklog: patchBacklog2 } = await Promise.resolve().then(() => (init_backlog(), exports_backlog));
|
|
13810
14015
|
await patchBacklog2(options.chatroomId, options);
|
|
13811
14016
|
});
|
|
14017
|
+
backlogCommand.command("score").description("Score a backlog task by complexity, value, and priority").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role").requiredOption("--task-id <taskId>", "Task ID to score").option("--complexity <level>", "Complexity level: low, medium, high").option("--value <level>", "Value level: low, medium, high").option("--priority <n>", "Priority number (higher = more important)").action(async (options) => {
|
|
14018
|
+
await maybeRequireAuth();
|
|
14019
|
+
const { scoreBacklog: scoreBacklog2 } = await Promise.resolve().then(() => (init_backlog(), exports_backlog));
|
|
14020
|
+
await scoreBacklog2(options.chatroomId, options);
|
|
14021
|
+
});
|
|
13812
14022
|
backlogCommand.command("reset-task").description("Reset a stuck in_progress task back to pending").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role").requiredOption("--task-id <taskId>", "Task ID to reset").action(async (options) => {
|
|
13813
14023
|
await maybeRequireAuth();
|
|
13814
14024
|
const { resetBacklog: resetBacklog2 } = await Promise.resolve().then(() => (init_backlog(), exports_backlog));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chatroom-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.72",
|
|
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",
|