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.
Files changed (2) hide show
  1. package/dist/index.js +323 -183
  2. 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 writeFileSync4, unlinkSync as unlinkSync2, mkdirSync as mkdirSync4 } from "node:fs";
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 join5 } from "node:path";
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 join5(CHATROOM_DIR4, getPidFileName());
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
- writeFileSync4(pidPath, process.pid.toString(), "utf-8");
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
- unlinkSync2(pidPath);
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 = join5(homedir4(), ".chatroom");
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.68",
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",