chatroom-cli 1.23.8 → 1.25.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 +253 -146
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -52767,7 +52767,7 @@ async function viewStep(chatroomId, options, deps) {
52767
52767
  }
52768
52768
  if (spec.skills) {
52769
52769
  console.log("");
52770
- console.log("Skills:");
52770
+ console.log("Skills (activate before starting):");
52771
52771
  console.log(spec.skills);
52772
52772
  }
52773
52773
  if (spec.requirements) {
@@ -54411,6 +54411,45 @@ async function getAllPRs(cwd) {
54411
54411
  return [];
54412
54412
  }
54413
54413
  }
54414
+ async function getPRCommits(cwd, prNumber) {
54415
+ const repoSlug = await getOriginRepoSlug(cwd);
54416
+ const repoFlag = repoSlug ? ` --repo ${JSON.stringify(repoSlug)}` : "";
54417
+ const result = await runCommand(`gh pr view ${prNumber} --json commits${repoFlag}`, cwd);
54418
+ if ("error" in result) {
54419
+ return [];
54420
+ }
54421
+ const output = result.stdout.trim();
54422
+ if (!output)
54423
+ return [];
54424
+ try {
54425
+ const parsed = JSON.parse(output);
54426
+ if (typeof parsed !== "object" || parsed === null || !("commits" in parsed))
54427
+ return [];
54428
+ const commits = parsed.commits;
54429
+ if (!Array.isArray(commits))
54430
+ return [];
54431
+ return commits.map((c) => {
54432
+ const commit = c;
54433
+ const oid = typeof commit.oid === "string" ? commit.oid : "";
54434
+ const headline = typeof commit.messageHeadline === "string" ? commit.messageHeadline : "";
54435
+ const date = typeof commit.committedDate === "string" ? commit.committedDate : "";
54436
+ let authorLogin = "";
54437
+ if (Array.isArray(commit.authors) && commit.authors.length > 0) {
54438
+ const first = commit.authors[0];
54439
+ authorLogin = typeof first.login === "string" ? first.login : typeof first.name === "string" ? first.name : "";
54440
+ }
54441
+ return {
54442
+ sha: oid,
54443
+ shortSha: oid.slice(0, 7),
54444
+ message: headline,
54445
+ author: authorLogin,
54446
+ date
54447
+ };
54448
+ });
54449
+ } catch {
54450
+ return [];
54451
+ }
54452
+ }
54414
54453
  async function getRemotes(cwd) {
54415
54454
  const result = await runGit("remote -v", cwd);
54416
54455
  if ("error" in result)
@@ -54442,6 +54481,43 @@ async function getCommitsAhead(workingDir) {
54442
54481
  const count = parseInt(result.stdout.trim(), 10);
54443
54482
  return Number.isNaN(count) ? 0 : count;
54444
54483
  }
54484
+ async function getCommitStatusChecks(cwd, ref) {
54485
+ const repoSlug = await getOriginRepoSlug(cwd);
54486
+ if (!repoSlug)
54487
+ return null;
54488
+ try {
54489
+ const [checkRunsResult, statusResult] = await Promise.all([
54490
+ runCommand(`gh api repos/${repoSlug}/commits/${encodeURIComponent(ref)}/check-runs --jq '{check_runs: [.check_runs[] | {name: .name, status: .status, conclusion: .conclusion}], total_count: .total_count}'`, cwd),
54491
+ runCommand(`gh api repos/${repoSlug}/commits/${encodeURIComponent(ref)}/status --jq '.state'`, cwd)
54492
+ ]);
54493
+ if ("error" in checkRunsResult || "error" in statusResult)
54494
+ return null;
54495
+ const checkRunsData = JSON.parse(checkRunsResult.stdout.trim());
54496
+ const combinedState = statusResult.stdout.trim() || "pending";
54497
+ let state = combinedState;
54498
+ if (checkRunsData.total_count > 0) {
54499
+ const conclusions = checkRunsData.check_runs.map((cr) => cr.conclusion);
54500
+ if (conclusions.some((c) => c === "failure" || c === "timed_out")) {
54501
+ state = "failure";
54502
+ } else if (conclusions.every((c) => c === "success" || c === "skipped" || c === "neutral")) {
54503
+ state = "success";
54504
+ } else if (checkRunsData.check_runs.some((cr) => cr.status !== "completed")) {
54505
+ state = "pending";
54506
+ }
54507
+ }
54508
+ return {
54509
+ state,
54510
+ checkRuns: checkRunsData.check_runs.map((cr) => ({
54511
+ name: cr.name,
54512
+ status: cr.status,
54513
+ conclusion: cr.conclusion
54514
+ })),
54515
+ totalCount: checkRunsData.total_count
54516
+ };
54517
+ } catch {
54518
+ return null;
54519
+ }
54520
+ }
54445
54521
  var execAsync2;
54446
54522
  var init_git_reader = __esm(() => {
54447
54523
  execAsync2 = promisify2(exec2);
@@ -54597,6 +54673,21 @@ async function processPRAction(ctx, req) {
54597
54673
  console.warn(`[${formatTimestamp()}] ⚠️ Failed to refresh git state after PR action: ${getErrorMessage(err)}`);
54598
54674
  });
54599
54675
  }
54676
+ async function processPRCommits(ctx, req) {
54677
+ const prNumber = req.prNumber;
54678
+ if (!prNumber) {
54679
+ throw new Error("pr_commits request missing prNumber");
54680
+ }
54681
+ const commits = await getPRCommits(req.workingDir, prNumber);
54682
+ await ctx.deps.backend.mutation(api.workspaces.upsertPRCommits, {
54683
+ sessionId: ctx.sessionId,
54684
+ machineId: ctx.machineId,
54685
+ workingDir: req.workingDir,
54686
+ prNumber,
54687
+ commits
54688
+ });
54689
+ console.log(`[${formatTimestamp()}] \uD83D\uDCCB PR commits pushed: ${req.workingDir} (#${prNumber}, ${commits.length} commits)`);
54690
+ }
54600
54691
  async function processCommitDetail(ctx, req) {
54601
54692
  if (!req.sha) {
54602
54693
  throw new Error("commit_detail request missing sha");
@@ -54694,6 +54785,9 @@ async function processRequests(ctx, requests, processedRequestIds, dedupTtlMs) {
54694
54785
  case "pr_action":
54695
54786
  await processPRAction(ctx, req);
54696
54787
  break;
54788
+ case "pr_commits":
54789
+ await processPRCommits(ctx, req);
54790
+ break;
54697
54791
  }
54698
54792
  await ctx.deps.backend.mutation(api.workspaces.updateRequestStatus, {
54699
54793
  sessionId: ctx.sessionId,
@@ -54784,11 +54878,12 @@ async function pushSingleWorkspaceGitState(ctx, workingDir) {
54784
54878
  }
54785
54879
  const openPRs = await getOpenPRsForBranch(workingDir, branchResult.branch);
54786
54880
  const allPRs = await getAllPRs(workingDir);
54881
+ const headCommitStatus = await getCommitStatusChecks(workingDir, branchResult.branch);
54787
54882
  const branch = branchResult.branch;
54788
54883
  const isDirty2 = dirtyResult;
54789
54884
  const diffStat = diffStatResult.status === "available" ? diffStatResult.diffStat : { filesChanged: 0, insertions: 0, deletions: 0 };
54790
54885
  const hasMoreCommits = commits.length >= COMMITS_PER_PAGE;
54791
- const stateHash = createHash3("md5").update(JSON.stringify({ branch, isDirty: isDirty2, diffStat, commitsAhead, shas: commits.map((c) => c.sha), prs: openPRs.map((pr) => pr.number), allPrs: allPRs.map((pr) => `${pr.number}:${pr.state}`), remotes: remotes.map((r) => `${r.name}:${r.url}`) })).digest("hex");
54886
+ const stateHash = createHash3("md5").update(JSON.stringify({ branch, isDirty: isDirty2, diffStat, commitsAhead, shas: commits.map((c) => c.sha), prs: openPRs.map((pr) => pr.number), allPrs: allPRs.map((pr) => `${pr.number}:${pr.state}`), remotes: remotes.map((r) => `${r.name}:${r.url}`), headCommitStatus })).digest("hex");
54792
54887
  if (ctx.lastPushedGitState.get(stateKey) === stateHash) {
54793
54888
  return;
54794
54889
  }
@@ -54805,7 +54900,8 @@ async function pushSingleWorkspaceGitState(ctx, workingDir) {
54805
54900
  openPullRequests: openPRs,
54806
54901
  allPullRequests: allPRs,
54807
54902
  remotes,
54808
- commitsAhead
54903
+ commitsAhead,
54904
+ headCommitStatus
54809
54905
  });
54810
54906
  ctx.lastPushedGitState.set(stateKey, stateHash);
54811
54907
  console.log(`[${formatTimestamp()}] \uD83D\uDD00 Git state pushed: ${workingDir} (${branch}${isDirty2 ? ", dirty" : ", clean"})`);
@@ -54887,142 +54983,6 @@ var init_git_heartbeat = __esm(() => {
54887
54983
  init_convex_error();
54888
54984
  });
54889
54985
 
54890
- // src/infrastructure/services/workspace/file-tree-scanner.ts
54891
- import { exec as exec4 } from "node:child_process";
54892
- import { promisify as promisify4 } from "node:util";
54893
- async function scanFileTree(rootDir, options) {
54894
- const maxEntries = options?.maxEntries ?? DEFAULT_MAX_ENTRIES;
54895
- const scannedAt = Date.now();
54896
- const filePaths = await getGitFiles(rootDir);
54897
- const filteredPaths = filePaths.filter((p) => !isExcluded(p));
54898
- const entries = buildEntries(filteredPaths, rootDir, maxEntries);
54899
- return {
54900
- entries,
54901
- scannedAt,
54902
- rootDir
54903
- };
54904
- }
54905
- async function getGitFiles(rootDir) {
54906
- const env2 = {
54907
- ...process.env,
54908
- GIT_TERMINAL_PROMPT: "0",
54909
- GIT_PAGER: "cat",
54910
- NO_COLOR: "1"
54911
- };
54912
- try {
54913
- const tracked = await execAsync3("git ls-files", {
54914
- cwd: rootDir,
54915
- env: env2,
54916
- maxBuffer: 10 * 1024 * 1024
54917
- });
54918
- const untracked = await execAsync3("git ls-files --others --exclude-standard", {
54919
- cwd: rootDir,
54920
- env: env2,
54921
- maxBuffer: 10 * 1024 * 1024
54922
- });
54923
- const trackedFiles = parseLines(tracked.stdout);
54924
- const untrackedFiles = parseLines(untracked.stdout);
54925
- const allFiles = new Set([...trackedFiles, ...untrackedFiles]);
54926
- return Array.from(allFiles);
54927
- } catch {
54928
- return [];
54929
- }
54930
- }
54931
- function parseLines(output) {
54932
- return output.split(`
54933
- `).map((line) => line.trim()).filter((line) => line.length > 0);
54934
- }
54935
- function isExcluded(filePath) {
54936
- const segments = filePath.split("/");
54937
- return segments.some((segment) => ALWAYS_EXCLUDE.has(segment));
54938
- }
54939
- function buildEntries(filePaths, rootDir, maxEntries) {
54940
- const directories = new Set;
54941
- for (const filePath of filePaths) {
54942
- const parts = filePath.split("/");
54943
- for (let i2 = 1;i2 < parts.length; i2++) {
54944
- directories.add(parts.slice(0, i2).join("/"));
54945
- }
54946
- }
54947
- const entries = [];
54948
- const sortedDirs = Array.from(directories).sort();
54949
- for (const dir of sortedDirs) {
54950
- if (entries.length >= maxEntries)
54951
- break;
54952
- entries.push({ path: dir, type: "directory" });
54953
- }
54954
- const sortedFiles = filePaths.slice().sort();
54955
- for (const file of sortedFiles) {
54956
- if (entries.length >= maxEntries)
54957
- break;
54958
- entries.push({ path: file, type: "file" });
54959
- }
54960
- return entries;
54961
- }
54962
- var execAsync3, DEFAULT_MAX_ENTRIES = 1e4, ALWAYS_EXCLUDE;
54963
- var init_file_tree_scanner = __esm(() => {
54964
- execAsync3 = promisify4(exec4);
54965
- ALWAYS_EXCLUDE = new Set([
54966
- "node_modules",
54967
- ".git",
54968
- "dist",
54969
- "build",
54970
- ".next",
54971
- "coverage",
54972
- "__pycache__",
54973
- ".turbo"
54974
- ]);
54975
- });
54976
-
54977
- // src/commands/machine/daemon-start/file-tree-heartbeat.ts
54978
- import { createHash as createHash4 } from "node:crypto";
54979
- async function pushFileTree(ctx) {
54980
- let workspaces;
54981
- try {
54982
- workspaces = await ctx.deps.backend.query(api.workspaces.listWorkspacesForMachine, {
54983
- sessionId: ctx.sessionId,
54984
- machineId: ctx.machineId
54985
- });
54986
- } catch (err) {
54987
- console.warn(`[${formatTimestamp()}] ⚠️ Failed to query workspaces for file tree sync: ${getErrorMessage(err)}`);
54988
- return;
54989
- }
54990
- const uniqueWorkingDirs = new Set(workspaces.map((ws) => ws.workingDir));
54991
- if (uniqueWorkingDirs.size === 0)
54992
- return;
54993
- for (const workingDir of uniqueWorkingDirs) {
54994
- try {
54995
- await pushSingleWorkspaceFileTree(ctx, workingDir);
54996
- } catch (err) {
54997
- console.warn(`[${formatTimestamp()}] ⚠️ File tree push failed for ${workingDir}: ${getErrorMessage(err)}`);
54998
- }
54999
- }
55000
- }
55001
- async function pushSingleWorkspaceFileTree(ctx, workingDir) {
55002
- const tree = await scanFileTree(workingDir);
55003
- const treeJson = JSON.stringify(tree);
55004
- const stateKey = `filetree:${ctx.machineId}::${workingDir}`;
55005
- const treeHash = createHash4("md5").update(treeJson).digest("hex");
55006
- if (ctx.lastPushedGitState.get(stateKey) === treeHash) {
55007
- return;
55008
- }
55009
- await ctx.deps.backend.mutation(api.workspaceFiles.syncFileTree, {
55010
- sessionId: ctx.sessionId,
55011
- machineId: ctx.machineId,
55012
- workingDir,
55013
- treeJson,
55014
- treeHash,
55015
- scannedAt: tree.scannedAt
55016
- });
55017
- ctx.lastPushedGitState.set(stateKey, treeHash);
55018
- console.log(`[${formatTimestamp()}] \uD83D\uDCC1 File tree pushed: ${workingDir} (${tree.entries.length} entries)`);
55019
- }
55020
- var init_file_tree_heartbeat = __esm(() => {
55021
- init_api3();
55022
- init_file_tree_scanner();
55023
- init_convex_error();
55024
- });
55025
-
55026
54986
  // src/infrastructure/services/workspace/workspace-resolver.ts
55027
54987
  import { readFile as readFile2, readdir, stat } from "node:fs/promises";
55028
54988
  import { join as join8, basename, resolve as resolve3 } from "node:path";
@@ -55278,7 +55238,7 @@ var init_command_discovery = __esm(() => {
55278
55238
  });
55279
55239
 
55280
55240
  // src/commands/machine/daemon-start/command-sync-heartbeat.ts
55281
- import { createHash as createHash5 } from "node:crypto";
55241
+ import { createHash as createHash4 } from "node:crypto";
55282
55242
  async function pushCommands(ctx) {
55283
55243
  let workspaces;
55284
55244
  try {
@@ -55304,7 +55264,7 @@ async function pushCommands(ctx) {
55304
55264
  async function pushSingleWorkspaceCommands(ctx, workingDir) {
55305
55265
  const commands = await discoverCommands(workingDir);
55306
55266
  const stateKey = `commands:${ctx.machineId}::${workingDir}`;
55307
- const commandsHash = createHash5("md5").update(JSON.stringify(commands)).digest("hex");
55267
+ const commandsHash = createHash4("md5").update(JSON.stringify(commands)).digest("hex");
55308
55268
  if (ctx.lastPushedGitState.get(stateKey) === commandsHash) {
55309
55269
  return;
55310
55270
  }
@@ -55486,6 +55446,153 @@ var init_file_content_subscription = __esm(() => {
55486
55446
  init_convex_error();
55487
55447
  });
55488
55448
 
55449
+ // src/infrastructure/services/workspace/file-tree-scanner.ts
55450
+ import { exec as exec4 } from "node:child_process";
55451
+ import { promisify as promisify4 } from "node:util";
55452
+ async function scanFileTree(rootDir, options) {
55453
+ const maxEntries = options?.maxEntries ?? DEFAULT_MAX_ENTRIES;
55454
+ const scannedAt = Date.now();
55455
+ const filePaths = await getGitFiles(rootDir);
55456
+ const filteredPaths = filePaths.filter((p) => !isExcluded(p));
55457
+ const entries = buildEntries(filteredPaths, rootDir, maxEntries);
55458
+ return {
55459
+ entries,
55460
+ scannedAt,
55461
+ rootDir
55462
+ };
55463
+ }
55464
+ async function getGitFiles(rootDir) {
55465
+ const env2 = {
55466
+ ...process.env,
55467
+ GIT_TERMINAL_PROMPT: "0",
55468
+ GIT_PAGER: "cat",
55469
+ NO_COLOR: "1"
55470
+ };
55471
+ try {
55472
+ const tracked = await execAsync3("git ls-files", {
55473
+ cwd: rootDir,
55474
+ env: env2,
55475
+ maxBuffer: 10 * 1024 * 1024
55476
+ });
55477
+ const untracked = await execAsync3("git ls-files --others --exclude-standard", {
55478
+ cwd: rootDir,
55479
+ env: env2,
55480
+ maxBuffer: 10 * 1024 * 1024
55481
+ });
55482
+ const trackedFiles = parseLines(tracked.stdout);
55483
+ const untrackedFiles = parseLines(untracked.stdout);
55484
+ const allFiles = new Set([...trackedFiles, ...untrackedFiles]);
55485
+ return Array.from(allFiles);
55486
+ } catch {
55487
+ return [];
55488
+ }
55489
+ }
55490
+ function parseLines(output) {
55491
+ return output.split(`
55492
+ `).map((line) => line.trim()).filter((line) => line.length > 0);
55493
+ }
55494
+ function isExcluded(filePath) {
55495
+ const segments = filePath.split("/");
55496
+ return segments.some((segment) => ALWAYS_EXCLUDE.has(segment));
55497
+ }
55498
+ function buildEntries(filePaths, rootDir, maxEntries) {
55499
+ const directories = new Set;
55500
+ for (const filePath of filePaths) {
55501
+ const parts = filePath.split("/");
55502
+ for (let i2 = 1;i2 < parts.length; i2++) {
55503
+ directories.add(parts.slice(0, i2).join("/"));
55504
+ }
55505
+ }
55506
+ const entries = [];
55507
+ const sortedDirs = Array.from(directories).sort();
55508
+ for (const dir of sortedDirs) {
55509
+ if (entries.length >= maxEntries)
55510
+ break;
55511
+ entries.push({ path: dir, type: "directory" });
55512
+ }
55513
+ const sortedFiles = filePaths.slice().sort();
55514
+ for (const file of sortedFiles) {
55515
+ if (entries.length >= maxEntries)
55516
+ break;
55517
+ entries.push({ path: file, type: "file" });
55518
+ }
55519
+ return entries;
55520
+ }
55521
+ var execAsync3, DEFAULT_MAX_ENTRIES = 1e4, ALWAYS_EXCLUDE;
55522
+ var init_file_tree_scanner = __esm(() => {
55523
+ execAsync3 = promisify4(exec4);
55524
+ ALWAYS_EXCLUDE = new Set([
55525
+ "node_modules",
55526
+ ".git",
55527
+ "dist",
55528
+ "build",
55529
+ ".next",
55530
+ "coverage",
55531
+ "__pycache__",
55532
+ ".turbo"
55533
+ ]);
55534
+ });
55535
+
55536
+ // src/commands/machine/daemon-start/file-tree-subscription.ts
55537
+ import { createHash as createHash5 } from "node:crypto";
55538
+ function startFileTreeSubscription(ctx, wsClient2) {
55539
+ let processing = false;
55540
+ const unsubscribe = wsClient2.onUpdate(api.workspaceFiles.getPendingFileTreeRequests, {
55541
+ sessionId: ctx.sessionId,
55542
+ machineId: ctx.machineId
55543
+ }, (requests) => {
55544
+ if (!requests || requests.length === 0)
55545
+ return;
55546
+ if (processing)
55547
+ return;
55548
+ processing = true;
55549
+ fulfillFileTreeRequests(ctx, requests).catch((err) => {
55550
+ console.warn(`[${formatTimestamp()}] ⚠️ File tree subscription processing failed: ${getErrorMessage(err)}`);
55551
+ }).finally(() => {
55552
+ processing = false;
55553
+ });
55554
+ }, (err) => {
55555
+ console.warn(`[${formatTimestamp()}] ⚠️ File tree subscription error: ${getErrorMessage(err)}`);
55556
+ });
55557
+ console.log(`[${formatTimestamp()}] \uD83C\uDF33 File tree subscription started (reactive)`);
55558
+ return {
55559
+ stop: () => {
55560
+ unsubscribe();
55561
+ console.log(`[${formatTimestamp()}] \uD83C\uDF33 File tree subscription stopped`);
55562
+ }
55563
+ };
55564
+ }
55565
+ async function fulfillFileTreeRequests(ctx, requests) {
55566
+ for (const request of requests) {
55567
+ try {
55568
+ const tree = await scanFileTree(request.workingDir);
55569
+ const treeJson = JSON.stringify(tree);
55570
+ const treeHash = createHash5("md5").update(treeJson).digest("hex");
55571
+ await ctx.deps.backend.mutation(api.workspaceFiles.syncFileTree, {
55572
+ sessionId: ctx.sessionId,
55573
+ machineId: ctx.machineId,
55574
+ workingDir: request.workingDir,
55575
+ treeJson,
55576
+ treeHash,
55577
+ scannedAt: tree.scannedAt
55578
+ });
55579
+ await ctx.deps.backend.mutation(api.workspaceFiles.fulfillFileTreeRequest, {
55580
+ sessionId: ctx.sessionId,
55581
+ machineId: ctx.machineId,
55582
+ workingDir: request.workingDir
55583
+ });
55584
+ console.log(`[${formatTimestamp()}] \uD83C\uDF33 File tree fulfilled: ${request.workingDir} (${tree.entries.length} entries)`);
55585
+ } catch (err) {
55586
+ console.warn(`[${formatTimestamp()}] ⚠️ File tree fulfillment failed for ${request.workingDir}: ${getErrorMessage(err)}`);
55587
+ }
55588
+ }
55589
+ }
55590
+ var init_file_tree_subscription = __esm(() => {
55591
+ init_api3();
55592
+ init_file_tree_scanner();
55593
+ init_convex_error();
55594
+ });
55595
+
55489
55596
  // src/commands/machine/daemon-start/handlers/ping.ts
55490
55597
  function handlePing() {
55491
55598
  console.log(` ↪ Responding: pong`);
@@ -57110,9 +57217,6 @@ async function startCommandLoop(ctx) {
57110
57217
  pushGitState(ctx).catch((err) => {
57111
57218
  console.warn(`[${formatTimestamp()}] ⚠️ Git state push failed: ${getErrorMessage(err)}`);
57112
57219
  });
57113
- pushFileTree(ctx).catch((err) => {
57114
- console.warn(`[${formatTimestamp()}] ⚠️ File tree push failed: ${getErrorMessage(err)}`);
57115
- });
57116
57220
  pushCommands(ctx).catch((err) => {
57117
57221
  console.warn(`[${formatTimestamp()}] ⚠️ Command sync failed: ${getErrorMessage(err)}`);
57118
57222
  });
@@ -57123,8 +57227,8 @@ async function startCommandLoop(ctx) {
57123
57227
  heartbeatTimer.unref();
57124
57228
  let gitSubscriptionHandle = null;
57125
57229
  let fileContentSubscriptionHandle = null;
57230
+ let fileTreeSubscriptionHandle = null;
57126
57231
  pushGitState(ctx).catch(() => {});
57127
- pushFileTree(ctx).catch(() => {});
57128
57232
  pushCommands(ctx).catch(() => {});
57129
57233
  const shutdown = async () => {
57130
57234
  console.log(`
@@ -57134,6 +57238,8 @@ async function startCommandLoop(ctx) {
57134
57238
  gitSubscriptionHandle.stop();
57135
57239
  if (fileContentSubscriptionHandle)
57136
57240
  fileContentSubscriptionHandle.stop();
57241
+ if (fileTreeSubscriptionHandle)
57242
+ fileTreeSubscriptionHandle.stop();
57137
57243
  await onDaemonShutdown(ctx);
57138
57244
  if (ctx.stopLocalApi) {
57139
57245
  await ctx.stopLocalApi().catch(() => {});
@@ -57147,6 +57253,7 @@ async function startCommandLoop(ctx) {
57147
57253
  const wsClient2 = await getConvexWsClient();
57148
57254
  gitSubscriptionHandle = startGitRequestSubscription(ctx, wsClient2);
57149
57255
  fileContentSubscriptionHandle = startFileContentSubscription(ctx, wsClient2);
57256
+ fileTreeSubscriptionHandle = startFileTreeSubscription(ctx, wsClient2);
57150
57257
  console.log(`
57151
57258
  Listening for commands...`);
57152
57259
  console.log(`Press Ctrl+C to stop
@@ -57189,9 +57296,9 @@ var init_command_loop = __esm(() => {
57189
57296
  init_on_request_stop_agent();
57190
57297
  init_pid();
57191
57298
  init_git_heartbeat();
57192
- init_file_tree_heartbeat();
57193
57299
  init_command_sync_heartbeat();
57194
57300
  init_file_content_subscription();
57301
+ init_file_tree_subscription();
57195
57302
  init_git_subscription();
57196
57303
  init_command_runner();
57197
57304
  init_init2();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chatroom-cli",
3
- "version": "1.23.8",
3
+ "version": "1.25.0",
4
4
  "description": "CLI for multi-agent chatroom collaboration",
5
5
  "type": "module",
6
6
  "bin": {