chatroom-cli 1.2.7 → 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.
Files changed (2) hide show
  1. package/dist/index.js +188 -123
  2. 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(`[pi text] ${line}
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(`[pi thinking] ${line}
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(`[pi agent_end]
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(`[pi tool: ${name}]
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()}`);
@@ -11387,24 +11418,23 @@ Two requirements:
11387
11418
 
11388
11419
  ⚠️ WHEN THE PROCESS IS TERMINATED OR TIMED OUT
11389
11420
 
11390
- \`\`\`
11391
- @startuml
11392
- start
11393
- :Command terminated unexpectedly;
11394
- if (Urgent pending work?) then (yes)
11395
- :Finish urgent work;
11396
- :Reconnect with get-next-task;
11397
- else (no)
11398
- :Reconnect immediately;
11399
- note right: Team cannot reach you without it
11400
- endif
11401
- stop
11402
- @enduml
11421
+ \`\`\`mermaid
11422
+ flowchart TD
11423
+ A([Start]) --> B[Command terminated unexpectedly]
11424
+ B --> C{Urgent pending work?}
11425
+ C -->|yes| D[Finish urgent work]
11426
+ D --> E[Reconnect with get-next-task]
11427
+ C -->|no| E
11428
+ E --> F([Stop])
11403
11429
  \`\`\`
11404
11430
 
11405
11431
  \uD83D\uDCCB BACKLOG TASKS
11406
11432
  chatroom backlog list --chatroom-id=<chatroomId> --role=<role> --status=backlog
11407
- chatroom backlog --help`;
11433
+ chatroom backlog --help
11434
+
11435
+ \uD83D\uDCCB CONTEXT RECOVERY (after compaction/summarization)
11436
+ If your context was compacted, run: chatroom get-system-prompt --chatroom-id=<id> --role=<role>
11437
+ to reload your full system and role prompt.`;
11408
11438
  }
11409
11439
  var init_reminder = () => {};
11410
11440
  // ../../services/backend/prompts/config/index.ts
@@ -11454,6 +11484,7 @@ var init_utils = __esm(() => {
11454
11484
  // ../../services/backend/prompts/base/shared/getting-started-content.ts
11455
11485
  var init_getting_started_content = __esm(() => {
11456
11486
  init_utils();
11487
+ init_reminder();
11457
11488
  });
11458
11489
 
11459
11490
  // ../../services/backend/prompts/cli/index.ts
@@ -11791,18 +11822,6 @@ async function getNextTask(chatroomId, options) {
11791
11822
  harnessVersions: machineInfo.harnessVersions,
11792
11823
  availableModels
11793
11824
  });
11794
- const agentType = options.agentType ?? (machineInfo.availableHarnesses.length > 0 ? machineInfo.availableHarnesses[0] : undefined);
11795
- if (agentType) {
11796
- const workingDir = process.cwd();
11797
- await client2.mutation(api.machines.updateAgentConfig, {
11798
- sessionId,
11799
- machineId: machineInfo.machineId,
11800
- chatroomId,
11801
- role,
11802
- agentType,
11803
- workingDir
11804
- });
11805
- }
11806
11825
  } catch (machineError) {
11807
11826
  if (!silent) {
11808
11827
  console.warn(`⚠️ Machine registration failed: ${sanitizeUnknownForTerminal(machineError.message)}`);
@@ -12484,7 +12503,6 @@ async function listBacklog(chatroomId, options, deps) {
12484
12503
  "pending",
12485
12504
  "acknowledged",
12486
12505
  "in_progress",
12487
- "queued",
12488
12506
  "backlog",
12489
12507
  "backlog_acknowledged",
12490
12508
  "completed",
@@ -12845,8 +12863,6 @@ function getStatusEmoji(status) {
12845
12863
  return "\uD83D\uDCEC";
12846
12864
  case "in_progress":
12847
12865
  return "\uD83D\uDD35";
12848
- case "queued":
12849
- return "\uD83D\uDFE1";
12850
12866
  case "backlog":
12851
12867
  return "⚪";
12852
12868
  case "backlog_acknowledged":
@@ -13791,6 +13807,17 @@ var init_on_daemon_shutdown = __esm(() => {
13791
13807
  init_api3();
13792
13808
  });
13793
13809
 
13810
+ // src/infrastructure/machine/stop-reason.ts
13811
+ function resolveStopReason(code2, signal, wasIntentional) {
13812
+ if (wasIntentional)
13813
+ return "intentional_stop";
13814
+ if (signal !== null)
13815
+ return "process_terminated_with_signal";
13816
+ if (code2 === 0)
13817
+ return "process_exited_with_success";
13818
+ return "process_terminated_unexpectedly";
13819
+ }
13820
+
13794
13821
  // src/commands/machine/daemon-start/handlers/start-agent.ts
13795
13822
  async function executeStartAgent(ctx, args) {
13796
13823
  const { chatroomId, role, agentHarness, model, workingDir, reason } = args;
@@ -13905,15 +13932,24 @@ async function executeStartAgent(ctx, args) {
13905
13932
  });
13906
13933
  spawnResult.onExit(({ code: code2, signal }) => {
13907
13934
  const wasIntentional = ctx.deps.stops.consume(chatroomId, role);
13935
+ const stopReason = resolveStopReason(code2, signal, wasIntentional);
13908
13936
  ctx.events.emit("agent:exited", {
13909
13937
  chatroomId,
13910
13938
  role,
13911
13939
  pid,
13912
13940
  code: code2,
13913
13941
  signal,
13942
+ stopReason,
13914
13943
  intentional: wasIntentional
13915
13944
  });
13916
13945
  });
13946
+ if (spawnResult.onAgentEnd) {
13947
+ spawnResult.onAgentEnd(() => {
13948
+ try {
13949
+ ctx.deps.processes.kill(-pid, "SIGTERM");
13950
+ } catch {}
13951
+ });
13952
+ }
13917
13953
  let lastReportedTokenAt = 0;
13918
13954
  spawnResult.onOutput(() => {
13919
13955
  const now = Date.now();
@@ -14166,6 +14202,9 @@ async function refreshModels(ctx) {
14166
14202
  }
14167
14203
  if (!ctx.config)
14168
14204
  return;
14205
+ const freshConfig = ensureMachineRegistered();
14206
+ ctx.config.availableHarnesses = freshConfig.availableHarnesses;
14207
+ ctx.config.harnessVersions = freshConfig.harnessVersions;
14169
14208
  const totalCount = Object.values(models).flat().length;
14170
14209
  try {
14171
14210
  await ctx.deps.backend.mutation(api.machines.register, {
@@ -14182,6 +14221,41 @@ async function refreshModels(ctx) {
14182
14221
  console.warn(`[${formatTimestamp()}] ⚠️ Model refresh failed: ${error.message}`);
14183
14222
  }
14184
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
+ }
14185
14259
  async function startCommandLoop(ctx) {
14186
14260
  let heartbeatCount = 0;
14187
14261
  const heartbeatTimer = setInterval(() => {
@@ -14220,40 +14294,11 @@ Listening for commands...`);
14220
14294
  }, async (result) => {
14221
14295
  if (!result.events || result.events.length === 0)
14222
14296
  return;
14223
- const evictBefore = Date.now() - AGENT_REQUEST_DEADLINE_MS;
14224
- for (const [id, ts] of processedCommandIds) {
14225
- if (ts < evictBefore)
14226
- processedCommandIds.delete(id);
14227
- }
14228
- for (const [id, ts] of processedPingIds) {
14229
- if (ts < evictBefore)
14230
- processedPingIds.delete(id);
14231
- }
14297
+ evictStaleDedupEntries(processedCommandIds, processedPingIds);
14232
14298
  for (const event of result.events) {
14233
- const eventId = event._id.toString();
14234
14299
  try {
14235
14300
  console.log(`[${formatTimestamp()}] \uD83D\uDCE1 Stream command event: ${event.type}`);
14236
- if (event.type === "agent.requestStart") {
14237
- if (processedCommandIds.has(eventId))
14238
- continue;
14239
- processedCommandIds.set(eventId, Date.now());
14240
- await onRequestStartAgent(ctx, event);
14241
- } else if (event.type === "agent.requestStop") {
14242
- if (processedCommandIds.has(eventId))
14243
- continue;
14244
- processedCommandIds.set(eventId, Date.now());
14245
- await onRequestStopAgent(ctx, event);
14246
- } else if (event.type === "daemon.ping") {
14247
- if (processedPingIds.has(eventId))
14248
- continue;
14249
- processedPingIds.set(eventId, Date.now());
14250
- handlePing();
14251
- await ctx.deps.backend.mutation(api.machines.ackPing, {
14252
- sessionId: ctx.sessionId,
14253
- machineId: ctx.machineId,
14254
- pingEventId: event._id
14255
- });
14256
- }
14301
+ await dispatchCommandEvent(ctx, event, processedCommandIds, processedPingIds);
14257
14302
  } catch (err) {
14258
14303
  console.error(`[${formatTimestamp()}] ❌ Stream command event failed: ${err.message}`);
14259
14304
  }
@@ -14271,6 +14316,7 @@ var MODEL_REFRESH_INTERVAL_MS;
14271
14316
  var init_command_loop = __esm(() => {
14272
14317
  init_api3();
14273
14318
  init_client2();
14319
+ init_machine();
14274
14320
  init_on_daemon_shutdown();
14275
14321
  init_on_request_start_agent();
14276
14322
  init_on_request_stop_agent();
@@ -14337,8 +14383,9 @@ class DaemonEventBus {
14337
14383
 
14338
14384
  // src/events/daemon/agent/on-agent-exited.ts
14339
14385
  function onAgentExited(ctx, payload) {
14340
- const { chatroomId, role, pid, code: code2, signal, intentional } = payload;
14386
+ const { chatroomId, role, pid, code: code2, signal, stopReason, intentional } = payload;
14341
14387
  const ts = formatTimestamp();
14388
+ console.log(`[${ts}] Agent stopped: ${stopReason} (${role})`);
14342
14389
  if (intentional) {
14343
14390
  console.log(`[${ts}] ℹ️ Agent process exited after intentional stop ` + `(PID: ${pid}, role: ${role}, code: ${code2}, signal: ${signal})`);
14344
14391
  } else {
@@ -14351,6 +14398,8 @@ function onAgentExited(ctx, payload) {
14351
14398
  role,
14352
14399
  pid,
14353
14400
  intentional,
14401
+ stopReason,
14402
+ stopSignal: stopReason === "process_terminated_with_signal" ? signal ?? undefined : undefined,
14354
14403
  exitCode: code2 ?? undefined,
14355
14404
  signal: signal ?? undefined
14356
14405
  }).catch((err) => {
@@ -14446,11 +14495,7 @@ function createDefaultDeps16() {
14446
14495
  }
14447
14496
  };
14448
14497
  }
14449
- async function initDaemon() {
14450
- if (!acquireLock()) {
14451
- process.exit(1);
14452
- }
14453
- const convexUrl = getConvexUrl();
14498
+ function validateAuthentication(convexUrl) {
14454
14499
  const sessionId = getSessionId();
14455
14500
  if (!sessionId) {
14456
14501
  const otherUrls = getOtherSessionUrls();
@@ -14467,18 +14512,10 @@ Run: chatroom auth login`);
14467
14512
  releaseLock();
14468
14513
  process.exit(1);
14469
14514
  }
14470
- const machineId = getMachineId();
14471
- if (!machineId) {
14472
- console.error(`❌ Machine not registered`);
14473
- console.error(`
14474
- Run any chatroom command first to register this machine,`);
14475
- console.error(`for example: chatroom auth status`);
14476
- releaseLock();
14477
- process.exit(1);
14478
- }
14479
- const client2 = await getConvexClient();
14480
- const typedSessionId = sessionId;
14481
- 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 });
14482
14519
  if (!validation.valid) {
14483
14520
  console.error(`❌ Session invalid: ${validation.reason}`);
14484
14521
  console.error(`
@@ -14486,32 +14523,34 @@ Run: chatroom auth login`);
14486
14523
  releaseLock();
14487
14524
  process.exit(1);
14488
14525
  }
14526
+ }
14527
+ function setupMachine() {
14528
+ ensureMachineRegistered();
14489
14529
  const config3 = loadMachineConfig();
14490
- const openCodeService = new OpenCodeAgentService;
14491
- const piService = new PiAgentService;
14492
- const agentServices = new Map([
14493
- ["opencode", openCodeService],
14494
- ["pi", piService]
14495
- ]);
14530
+ return config3;
14531
+ }
14532
+ async function registerCapabilities(client2, sessionId, config3, agentServices) {
14533
+ const { machineId } = config3;
14496
14534
  const availableModels = await discoverModels(agentServices);
14497
- if (config3) {
14498
- try {
14499
- await client2.mutation(api.machines.register, {
14500
- sessionId: typedSessionId,
14501
- machineId,
14502
- hostname: config3.hostname,
14503
- os: config3.os,
14504
- availableHarnesses: config3.availableHarnesses,
14505
- harnessVersions: config3.harnessVersions,
14506
- availableModels
14507
- });
14508
- } catch (error) {
14509
- console.warn(`⚠️ Machine registration update failed: ${error.message}`);
14510
- }
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}`);
14511
14547
  }
14548
+ return availableModels;
14549
+ }
14550
+ async function connectDaemon(client2, sessionId, machineId, convexUrl) {
14512
14551
  try {
14513
14552
  await client2.mutation(api.machines.updateDaemonStatus, {
14514
- sessionId: typedSessionId,
14553
+ sessionId,
14515
14554
  machineId,
14516
14555
  connected: true
14517
14556
  });
@@ -14524,6 +14563,45 @@ Run: chatroom auth login`);
14524
14563
  releaseLock();
14525
14564
  process.exit(1);
14526
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);
14527
14605
  const deps = createDefaultDeps16();
14528
14606
  deps.backend.mutation = (endpoint, args) => client2.mutation(endpoint, args);
14529
14607
  deps.backend.query = (endpoint, args) => client2.query(endpoint, args);
@@ -14538,21 +14616,8 @@ Run: chatroom auth login`);
14538
14616
  agentServices
14539
14617
  };
14540
14618
  registerEventListeners(ctx);
14541
- console.log(`[${formatTimestamp()}] \uD83D\uDE80 Daemon started`);
14542
- console.log(` CLI version: ${getVersion()}`);
14543
- console.log(` Machine ID: ${machineId}`);
14544
- console.log(` Hostname: ${config3?.hostname ?? "Unknown"}`);
14545
- console.log(` Available harnesses: ${config3?.availableHarnesses.join(", ") || "none"}`);
14546
- console.log(` Available models: ${Object.keys(availableModels).length > 0 ? `${Object.values(availableModels).flat().length} models across ${Object.keys(availableModels).join(", ")}` : "none discovered"}`);
14547
- console.log(` PID: ${process.pid}`);
14548
- console.log(`
14549
- [${formatTimestamp()}] \uD83D\uDD04 Recovering agent state...`);
14550
- try {
14551
- await recoverAgentState(ctx);
14552
- } catch (e) {
14553
- console.log(` ⚠️ Recovery failed: ${e.message}`);
14554
- console.log(` Continuing with fresh state`);
14555
- }
14619
+ logStartup(ctx, availableModels);
14620
+ await recoverState(ctx);
14556
14621
  return ctx;
14557
14622
  }
14558
14623
  var init_init2 = __esm(() => {
@@ -15292,7 +15357,7 @@ program2.command("report-progress").description("Report progress on current task
15292
15357
  });
15293
15358
  });
15294
15359
  var backlogCommand = program2.command("backlog").description("Manage task queue and backlog");
15295
- backlogCommand.command("list").description("List tasks in a chatroom").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role").requiredOption("--status <status>", "Filter by status (pending|in_progress|queued|backlog|completed|cancelled|active|pending_review|archived|all)").option("--limit <n>", "Maximum number of tasks to show (required for --status=all)").option("--full", "Show full task content without truncation").action(async (options) => {
15360
+ backlogCommand.command("list").description("List tasks in a chatroom").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role").requiredOption("--status <status>", "Filter by status (pending|in_progress|backlog|completed|cancelled|active|pending_review|archived|all)").option("--limit <n>", "Maximum number of tasks to show (required for --status=all)").option("--full", "Show full task content without truncation").action(async (options) => {
15296
15361
  if (options.status === "all" && !options.limit) {
15297
15362
  console.error("❌ When using --status=all, you must specify --limit=<n>");
15298
15363
  console.error(" Example: chatroom backlog list --chatroom-id=<id> --role=builder --status=all --limit=50");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chatroom-cli",
3
- "version": "1.2.7",
3
+ "version": "1.4.0",
4
4
  "description": "CLI for multi-agent chatroom collaboration",
5
5
  "type": "module",
6
6
  "bin": {