chatroom-cli 1.66.1 → 1.68.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.
package/dist/index.js CHANGED
@@ -81119,7 +81119,10 @@ function formatDecodeError(error) {
81119
81119
 
81120
81120
  // ../../services/backend/prompts/native/session-continuity.ts
81121
81121
  function getNativeHandoffTurnEndGuidance(nextRole) {
81122
- const lines = ["", "**End your turn now** — stop tool calls. Your session stays active."];
81122
+ const lines = [
81123
+ "",
81124
+ "**Handoff must be your last action this turn.** After running handoff, **End your turn now** — stop tool calls. Your session stays active."
81125
+ ];
81123
81126
  if (nextRole.toLowerCase() === "user") {
81124
81127
  lines.push("The system delivers the next chatroom task when the user sends one.");
81125
81128
  } else {
@@ -102198,6 +102201,583 @@ var init_file_tree_scanner = __esm(() => {
102198
102201
  init_workspace_visibility_policy();
102199
102202
  });
102200
102203
 
102204
+ // src/infrastructure/services/workspace/git-workspace-porcelain.ts
102205
+ import { existsSync as existsSync7 } from "node:fs";
102206
+ import path5 from "node:path";
102207
+ function isEmptyRepoHeadError(error40) {
102208
+ const message = error40.message.toLowerCase();
102209
+ return message.includes("unknown revision") || message.includes("bad revision") || message.includes("ambiguous argument") || message.includes("needed a single revision");
102210
+ }
102211
+ function parseGitPorcelainZ(stdout) {
102212
+ const entries2 = [];
102213
+ const parts2 = stdout.split("\x00");
102214
+ let i2 = 0;
102215
+ while (i2 < parts2.length) {
102216
+ const token = parts2[i2];
102217
+ if (!token) {
102218
+ i2++;
102219
+ continue;
102220
+ }
102221
+ const xy = token.slice(0, 2);
102222
+ const rest = token.slice(3);
102223
+ if ((xy[0] === "R" || xy[0] === "C") && rest) {
102224
+ i2++;
102225
+ const dest = parts2[i2] ?? "";
102226
+ entries2.push({
102227
+ xy,
102228
+ path: dest.replace(/\\/g, "/"),
102229
+ fromPath: rest.replace(/\\/g, "/")
102230
+ });
102231
+ } else if (rest) {
102232
+ entries2.push({ xy, path: rest.replace(/\\/g, "/") });
102233
+ }
102234
+ i2++;
102235
+ }
102236
+ return entries2;
102237
+ }
102238
+ function toWorkspaceRelativePath(args2) {
102239
+ const raw = args2.pathInWorkTree.replace(/\\/g, "/").replace(/\/+$/, "");
102240
+ if (args2.node.pathspec.length > 0) {
102241
+ const spec = (args2.node.pathspec[0] ?? "").replace(/\/+$/, "");
102242
+ if (raw === spec)
102243
+ return args2.node.relativePath || null;
102244
+ if (!raw.startsWith(spec + "/"))
102245
+ return null;
102246
+ const stripped = raw.slice(spec.length + 1);
102247
+ if (args2.node.relativePath) {
102248
+ return `${args2.node.relativePath}/${stripped}`.replace(/\/+/g, "/");
102249
+ }
102250
+ return stripped;
102251
+ }
102252
+ if (args2.node.relativePath) {
102253
+ return `${args2.node.relativePath}/${raw}`.replace(/\/+/g, "/");
102254
+ }
102255
+ return raw;
102256
+ }
102257
+ function hasDelete(xy) {
102258
+ return xy[0] === "D" || xy[1] === "D";
102259
+ }
102260
+ function hasAdd(xy) {
102261
+ return xy[0] === "A" || xy[1] === "A";
102262
+ }
102263
+ function isRename(xy) {
102264
+ return xy[0] === "R" || xy[1] === "R";
102265
+ }
102266
+ function isCopy(xy) {
102267
+ return xy[0] === "C" || xy[1] === "C";
102268
+ }
102269
+ function kindForEntry(entry) {
102270
+ const { xy, path: entryPath } = entry;
102271
+ const events = [];
102272
+ const isDir = entryPath.endsWith("/");
102273
+ if (xy === "??") {
102274
+ events.push({ kind: isDir ? "addDir" : "add", path: entryPath });
102275
+ } else if (hasDelete(xy)) {
102276
+ events.push({ kind: isDir ? "unlinkDir" : "unlink", path: entryPath });
102277
+ } else if (hasAdd(xy)) {
102278
+ events.push({ kind: isDir ? "addDir" : "add", path: entryPath });
102279
+ } else if (isRename(xy)) {
102280
+ events.push({ kind: isDir ? "addDir" : "add", path: entryPath });
102281
+ } else if (isCopy(xy)) {
102282
+ events.push({ kind: isDir ? "addDir" : "add", path: entryPath });
102283
+ } else {
102284
+ events.push({ kind: "change", path: entryPath });
102285
+ }
102286
+ return { events };
102287
+ }
102288
+ function diffPorcelainSnapshots(args2) {
102289
+ const events = [];
102290
+ const prevMap = new Map;
102291
+ for (const entry of args2.prev) {
102292
+ const wsPath = toWorkspaceRelativePath({
102293
+ workspaceRoot: args2.workspaceRoot,
102294
+ node: args2.node,
102295
+ pathInWorkTree: entry.path
102296
+ });
102297
+ if (wsPath !== null) {
102298
+ prevMap.set(wsPath, entry.xy);
102299
+ }
102300
+ }
102301
+ const handledFromPaths = new Set;
102302
+ for (const entry of args2.next) {
102303
+ const wsPath = toWorkspaceRelativePath({
102304
+ workspaceRoot: args2.workspaceRoot,
102305
+ node: args2.node,
102306
+ pathInWorkTree: entry.path
102307
+ });
102308
+ if (wsPath === null)
102309
+ continue;
102310
+ const prevXy = prevMap.get(wsPath);
102311
+ if (prevXy === undefined || prevXy !== entry.xy) {
102312
+ const entryEvents = kindForEntry(entry);
102313
+ for (const e of entryEvents.events) {
102314
+ events.push({ kind: e.kind, path: wsPath });
102315
+ }
102316
+ }
102317
+ if (entry.fromPath && (entry.xy[0] === "R" || entry.xy[1] === "R")) {
102318
+ const fromWsPath = toWorkspaceRelativePath({
102319
+ workspaceRoot: args2.workspaceRoot,
102320
+ node: args2.node,
102321
+ pathInWorkTree: entry.fromPath
102322
+ });
102323
+ if (fromWsPath !== null && !handledFromPaths.has(fromWsPath)) {
102324
+ handledFromPaths.add(fromWsPath);
102325
+ events.push({
102326
+ kind: entry.fromPath.endsWith("/") ? "unlinkDir" : "unlink",
102327
+ path: fromWsPath
102328
+ });
102329
+ }
102330
+ }
102331
+ }
102332
+ events.sort((a, b) => a.path.localeCompare(b.path));
102333
+ return events;
102334
+ }
102335
+ function diffPorcelainAgainstKnownPaths(args2) {
102336
+ const events = [];
102337
+ for (const entry of args2.next) {
102338
+ const wsPath = toWorkspaceRelativePath({
102339
+ workspaceRoot: args2.workspaceRoot,
102340
+ node: args2.node,
102341
+ pathInWorkTree: entry.path
102342
+ });
102343
+ if (wsPath === null)
102344
+ continue;
102345
+ if (wsPath in args2.knownPaths)
102346
+ continue;
102347
+ const entryEvents = kindForEntry(entry);
102348
+ for (const e of entryEvents.events) {
102349
+ events.push({ kind: e.kind, path: wsPath });
102350
+ }
102351
+ }
102352
+ events.sort((a, b) => a.path.localeCompare(b.path));
102353
+ return events;
102354
+ }
102355
+ function porcelainPathsLeftSnapshot(args2) {
102356
+ const nextWsPaths = new Set;
102357
+ for (const entry of args2.next) {
102358
+ const wsPath = toWorkspaceRelativePath({
102359
+ workspaceRoot: args2.workspaceRoot,
102360
+ node: args2.node,
102361
+ pathInWorkTree: entry.path
102362
+ });
102363
+ if (wsPath !== null)
102364
+ nextWsPaths.add(wsPath);
102365
+ }
102366
+ const left3 = [];
102367
+ for (const entry of args2.prev) {
102368
+ const wsPath = toWorkspaceRelativePath({
102369
+ workspaceRoot: args2.workspaceRoot,
102370
+ node: args2.node,
102371
+ pathInWorkTree: entry.path
102372
+ });
102373
+ if (wsPath === null)
102374
+ continue;
102375
+ if (!nextWsPaths.has(wsPath))
102376
+ left3.push(wsPath);
102377
+ }
102378
+ return left3.sort((a, b) => a.localeCompare(b));
102379
+ }
102380
+ function porcelainUntrackedDeletedEvents(args2) {
102381
+ const exists4 = args2.pathExists ?? ((p) => existsSync7(p));
102382
+ const left3 = porcelainPathsLeftSnapshot({
102383
+ workspaceRoot: args2.workspaceRoot,
102384
+ node: args2.node,
102385
+ prev: args2.prev,
102386
+ next: args2.next
102387
+ });
102388
+ if (left3.length === 0)
102389
+ return [];
102390
+ const prevByWsPath = new Map;
102391
+ for (const entry of args2.prev) {
102392
+ const wsPath = toWorkspaceRelativePath({
102393
+ workspaceRoot: args2.workspaceRoot,
102394
+ node: args2.node,
102395
+ pathInWorkTree: entry.path
102396
+ });
102397
+ if (wsPath !== null)
102398
+ prevByWsPath.set(wsPath, entry);
102399
+ }
102400
+ const events = [];
102401
+ for (const wsPath of left3) {
102402
+ const prevEntry = prevByWsPath.get(wsPath);
102403
+ if (prevEntry?.xy !== "??")
102404
+ continue;
102405
+ const absPath = path5.join(args2.node.workTree, prevEntry.path);
102406
+ if (!exists4(absPath)) {
102407
+ events.push({
102408
+ kind: prevEntry.path.endsWith("/") ? "unlinkDir" : "unlink",
102409
+ path: wsPath
102410
+ });
102411
+ }
102412
+ }
102413
+ events.sort((a, b) => a.path.localeCompare(b.path));
102414
+ return events;
102415
+ }
102416
+ async function readGitHead(workTree) {
102417
+ const result = await runGit(["rev-parse", "HEAD"], workTree, {
102418
+ timeout: GIT_POLL_TIMEOUT_MS
102419
+ });
102420
+ if ("error" in result) {
102421
+ if (isEmptyRepoHeadError(result.error))
102422
+ return { head: null };
102423
+ throw new GitWorkspaceCommandError({
102424
+ operation: "readGitHead",
102425
+ workTree,
102426
+ relativePath: "",
102427
+ cause: result.error
102428
+ });
102429
+ }
102430
+ const head5 = result.stdout.trim();
102431
+ return { head: head5.length > 0 ? head5 : null };
102432
+ }
102433
+ function headChanged(prev, next4) {
102434
+ if (prev.head === null && next4.head === null)
102435
+ return false;
102436
+ return prev.head !== next4.head;
102437
+ }
102438
+ async function readGitPorcelainStatus(node) {
102439
+ const args2 = ["status", "--porcelain=v1", "-z", "-uall", "--"];
102440
+ if (node.pathspec.length > 0)
102441
+ args2.push(...node.pathspec);
102442
+ const result = await runGit(args2, node.workTree, { timeout: GIT_POLL_TIMEOUT_MS });
102443
+ if ("error" in result) {
102444
+ throw new GitWorkspaceCommandError({
102445
+ operation: "readGitPorcelainStatus",
102446
+ workTree: node.workTree,
102447
+ relativePath: node.relativePath,
102448
+ cause: result.error
102449
+ });
102450
+ }
102451
+ return parseGitPorcelainZ(result.stdout);
102452
+ }
102453
+ var GIT_POLL_TIMEOUT_MS = 1e4, GitWorkspaceCommandError;
102454
+ var init_git_workspace_porcelain = __esm(() => {
102455
+ init_run_command();
102456
+ GitWorkspaceCommandError = class GitWorkspaceCommandError extends Error {
102457
+ operation;
102458
+ workTree;
102459
+ relativePath;
102460
+ cause;
102461
+ constructor(args2) {
102462
+ const label = args2.relativePath || args2.workTree;
102463
+ super(`${args2.operation} failed for ${label}: ${args2.cause.message}`);
102464
+ this.name = "GitWorkspaceCommandError";
102465
+ this.operation = args2.operation;
102466
+ this.workTree = args2.workTree;
102467
+ this.relativePath = args2.relativePath;
102468
+ this.cause = args2.cause;
102469
+ }
102470
+ };
102471
+ });
102472
+
102473
+ // src/infrastructure/services/workspace/git-workspace-change-source.ts
102474
+ function flattenGitRepoNodes(root) {
102475
+ const out = [root];
102476
+ for (const child of root.children) {
102477
+ out.push(...flattenGitRepoNodes(child));
102478
+ }
102479
+ return out;
102480
+ }
102481
+ function computeBackoff(failures3, pollIntervalMs) {
102482
+ if (failures3 <= 0)
102483
+ return pollIntervalMs;
102484
+ const backoff = pollIntervalMs * 2 ** Math.min(failures3 - 1, 5);
102485
+ return Math.min(backoff, MAX_BACKOFF_MS);
102486
+ }
102487
+ async function pollGitWorkspaceNode(args2) {
102488
+ const [nextHead, nextEntries] = await Promise.all([
102489
+ readGitHead(args2.node.workTree),
102490
+ readGitPorcelainStatus(args2.node)
102491
+ ]);
102492
+ let needsReconcile = false;
102493
+ const events = [];
102494
+ if (args2.prev.prevHead.head !== null && headChanged(args2.prev.prevHead, nextHead)) {
102495
+ needsReconcile = true;
102496
+ }
102497
+ if (args2.prev.baselineEstablished) {
102498
+ const left3 = porcelainPathsLeftSnapshot({
102499
+ workspaceRoot: args2.options.hierarchy.workspaceRoot,
102500
+ node: args2.node,
102501
+ prev: args2.prev.prevEntries,
102502
+ next: nextEntries
102503
+ });
102504
+ const deletedUntracked = porcelainUntrackedDeletedEvents({
102505
+ workspaceRoot: args2.options.hierarchy.workspaceRoot,
102506
+ node: args2.node,
102507
+ prev: args2.prev.prevEntries,
102508
+ next: nextEntries
102509
+ });
102510
+ events.push(...deletedUntracked);
102511
+ const deletedPaths = new Set(deletedUntracked.map((e) => e.path));
102512
+ if (left3.some((wsPath) => !deletedPaths.has(wsPath))) {
102513
+ needsReconcile = true;
102514
+ }
102515
+ const diffEvents = diffPorcelainSnapshots({
102516
+ workspaceRoot: args2.options.hierarchy.workspaceRoot,
102517
+ node: args2.node,
102518
+ prev: args2.prev.prevEntries,
102519
+ next: nextEntries
102520
+ });
102521
+ events.push(...diffEvents);
102522
+ } else if (args2.options.getKnownPaths) {
102523
+ const knownPaths = args2.options.getKnownPaths();
102524
+ const gapFillEvents = diffPorcelainAgainstKnownPaths({
102525
+ workspaceRoot: args2.options.hierarchy.workspaceRoot,
102526
+ node: args2.node,
102527
+ knownPaths,
102528
+ next: nextEntries
102529
+ });
102530
+ events.push(...gapFillEvents);
102531
+ }
102532
+ return {
102533
+ events,
102534
+ needsReconcile,
102535
+ nextState: {
102536
+ prevEntries: nextEntries,
102537
+ prevHead: nextHead,
102538
+ baselineEstablished: true
102539
+ }
102540
+ };
102541
+ }
102542
+ function createGitWorkspaceChangeSource(options) {
102543
+ const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
102544
+ const nodes = flattenGitRepoNodes(options.hierarchy.root);
102545
+ const state = new Map;
102546
+ for (const node of nodes) {
102547
+ state.set(node.workTree, {
102548
+ prevEntries: [],
102549
+ prevHead: { head: null },
102550
+ baselineEstablished: false
102551
+ });
102552
+ }
102553
+ let stopped = false;
102554
+ let timer = null;
102555
+ let currentPoll = Promise.resolve();
102556
+ let nextPollDelayMs = pollIntervalMs;
102557
+ let consecutiveFailureTicks = 0;
102558
+ let persistentFailureReported = false;
102559
+ const nodeFailureCounts = new Map;
102560
+ const schedule2 = (delay3) => {
102561
+ if (stopped)
102562
+ return;
102563
+ timer = setTimeout(() => {
102564
+ timer = null;
102565
+ currentPoll = runPoll();
102566
+ currentPoll.finally(() => {
102567
+ if (!stopped)
102568
+ schedule2(nextPollDelayMs);
102569
+ });
102570
+ }, delay3);
102571
+ timer.unref?.();
102572
+ };
102573
+ const runPoll = async () => {
102574
+ if (stopped)
102575
+ return;
102576
+ const allEvents = [];
102577
+ let needsReconcile = false;
102578
+ let tickHadFailure = false;
102579
+ let maxNodeFailures = 0;
102580
+ const results = await Promise.allSettled(nodes.map(async (node) => {
102581
+ const prev = state.get(node.workTree) ?? {
102582
+ prevEntries: [],
102583
+ prevHead: { head: null },
102584
+ baselineEstablished: false
102585
+ };
102586
+ const result = await pollGitWorkspaceNode({
102587
+ options,
102588
+ node,
102589
+ prev
102590
+ });
102591
+ allEvents.push(...result.events);
102592
+ if (result.needsReconcile)
102593
+ needsReconcile = true;
102594
+ state.set(node.workTree, result.nextState);
102595
+ nodeFailureCounts.set(node.workTree, 0);
102596
+ return node;
102597
+ }));
102598
+ for (let i2 = 0;i2 < results.length; i2++) {
102599
+ const result = results[i2];
102600
+ const node = nodes[i2];
102601
+ if (!node || result.status === "fulfilled")
102602
+ continue;
102603
+ tickHadFailure = true;
102604
+ options.onError?.(result.reason);
102605
+ const prevFailures = nodeFailureCounts.get(node.workTree) ?? 0;
102606
+ const nextFailures = prevFailures + 1;
102607
+ nodeFailureCounts.set(node.workTree, nextFailures);
102608
+ maxNodeFailures = Math.max(maxNodeFailures, nextFailures);
102609
+ }
102610
+ if (tickHadFailure) {
102611
+ consecutiveFailureTicks += 1;
102612
+ nextPollDelayMs = computeBackoff(maxNodeFailures, pollIntervalMs);
102613
+ if (!persistentFailureReported && consecutiveFailureTicks >= PERSISTENT_FAILURE_THRESHOLD) {
102614
+ persistentFailureReported = true;
102615
+ await Promise.resolve(options.onPersistentFailure?.());
102616
+ }
102617
+ } else {
102618
+ consecutiveFailureTicks = 0;
102619
+ nextPollDelayMs = pollIntervalMs;
102620
+ }
102621
+ if (stopped)
102622
+ return;
102623
+ if (needsReconcile) {
102624
+ await Promise.resolve(options.onNeedsReconcile?.());
102625
+ }
102626
+ const filtered = allEvents.filter((event) => {
102627
+ if (!event.path)
102628
+ return false;
102629
+ if (options.shouldIgnore?.(event.path))
102630
+ return false;
102631
+ return true;
102632
+ });
102633
+ if (filtered.length === 0)
102634
+ return;
102635
+ const byPath = new Map;
102636
+ for (const event of filtered)
102637
+ byPath.set(event.path, event);
102638
+ const events = [...byPath.values()].sort((a, b) => a.path.localeCompare(b.path));
102639
+ try {
102640
+ await Promise.resolve(options.onEvents(events));
102641
+ } catch (error40) {
102642
+ options.onError?.(error40);
102643
+ }
102644
+ };
102645
+ let resolveReady;
102646
+ const ready = new Promise((r) => {
102647
+ resolveReady = r;
102648
+ });
102649
+ currentPoll = runPoll();
102650
+ currentPoll.finally(() => {
102651
+ resolveReady();
102652
+ if (!stopped)
102653
+ schedule2(nextPollDelayMs);
102654
+ });
102655
+ return {
102656
+ ready,
102657
+ stop: async () => {
102658
+ stopped = true;
102659
+ if (timer)
102660
+ clearTimeout(timer);
102661
+ timer = null;
102662
+ await currentPoll;
102663
+ }
102664
+ };
102665
+ }
102666
+ var DEFAULT_POLL_INTERVAL_MS = 1000, MAX_BACKOFF_MS = 30000, PERSISTENT_FAILURE_THRESHOLD = 3;
102667
+ var init_git_workspace_change_source = __esm(() => {
102668
+ init_git_workspace_porcelain();
102669
+ });
102670
+
102671
+ // src/infrastructure/services/workspace/git-workspace-hierarchy.ts
102672
+ import { promises as fsPromises3 } from "node:fs";
102673
+ import path6 from "node:path";
102674
+ function normalizeRel(p) {
102675
+ return p.replace(/\\/g, "/").replace(/^\.\/+/, "").replace(/\/+$/, "");
102676
+ }
102677
+ async function revParse(workTree, arg) {
102678
+ const result = await runGit(["rev-parse", arg], workTree);
102679
+ if ("error" in result)
102680
+ return null;
102681
+ const value = result.stdout.trim();
102682
+ return value.length > 0 ? value : null;
102683
+ }
102684
+ async function resolveGitDir(workTree) {
102685
+ const raw = await revParse(workTree, "--git-dir");
102686
+ if (!raw)
102687
+ return null;
102688
+ return path6.isAbsolute(raw) ? raw : path6.resolve(workTree, raw);
102689
+ }
102690
+ async function findNestedWorkTrees(workspaceRoot) {
102691
+ const found = [];
102692
+ async function visit(relDir) {
102693
+ const absDir = relDir ? path6.join(workspaceRoot, relDir) : workspaceRoot;
102694
+ let dirents;
102695
+ try {
102696
+ dirents = await fsPromises3.readdir(absDir, { withFileTypes: true });
102697
+ } catch {
102698
+ return;
102699
+ }
102700
+ for (const ent of dirents) {
102701
+ const name = ent.name;
102702
+ const relativePath = relDir ? `${relDir}/${name}` : name;
102703
+ if (name === ".git") {
102704
+ if (relDir) {
102705
+ found.push(path6.resolve(workspaceRoot, relDir));
102706
+ }
102707
+ continue;
102708
+ }
102709
+ if (!ent.isDirectory())
102710
+ continue;
102711
+ if (isAlwaysExcludedDirName(name))
102712
+ continue;
102713
+ if (!isPathVisible(relativePath))
102714
+ continue;
102715
+ await visit(relativePath);
102716
+ }
102717
+ }
102718
+ await visit("");
102719
+ return [...new Set(found.map((p) => path6.resolve(p)))].sort((a, b) => a.length - b.length || a.localeCompare(b));
102720
+ }
102721
+ async function discoverGitWorkspaceHierarchy(workingDir) {
102722
+ let workspaceRoot;
102723
+ try {
102724
+ workspaceRoot = await fsPromises3.realpath(workingDir);
102725
+ } catch {
102726
+ return null;
102727
+ }
102728
+ const inside = await runGit(["rev-parse", "--is-inside-work-tree"], workspaceRoot);
102729
+ if ("error" in inside || inside.stdout.trim() !== "true")
102730
+ return null;
102731
+ const toplevelRaw = await revParse(workspaceRoot, "--show-toplevel");
102732
+ const gitDir = await resolveGitDir(workspaceRoot);
102733
+ if (!toplevelRaw || !gitDir)
102734
+ return null;
102735
+ const toplevel = path6.resolve(toplevelRaw);
102736
+ const relFromToplevel = normalizeRel(path6.relative(toplevel, workspaceRoot));
102737
+ if (relFromToplevel.startsWith(".."))
102738
+ return null;
102739
+ const pathspec = relFromToplevel && toplevel !== workspaceRoot ? [relFromToplevel] : [];
102740
+ const nestedWorkTrees = await findNestedWorkTrees(workspaceRoot);
102741
+ const nestedNodes = [];
102742
+ for (const workTree of nestedWorkTrees) {
102743
+ const nestedGitDir = await resolveGitDir(workTree);
102744
+ if (!nestedGitDir)
102745
+ continue;
102746
+ nestedNodes.push({
102747
+ workTree,
102748
+ gitDir: nestedGitDir,
102749
+ relativePath: normalizeRel(path6.relative(workspaceRoot, workTree)),
102750
+ pathspec: [],
102751
+ children: []
102752
+ });
102753
+ }
102754
+ const root = {
102755
+ workTree: toplevel,
102756
+ gitDir,
102757
+ relativePath: "",
102758
+ pathspec,
102759
+ children: []
102760
+ };
102761
+ const sorted = nestedNodes.sort((a, b) => a.workTree.length - b.workTree.length || a.workTree.localeCompare(b.workTree));
102762
+ for (const node of sorted) {
102763
+ let parent = root;
102764
+ for (const candidate of sorted) {
102765
+ if (candidate === node)
102766
+ continue;
102767
+ const prefix = candidate.workTree.endsWith(path6.sep) ? candidate.workTree : candidate.workTree + path6.sep;
102768
+ if (node.workTree.startsWith(prefix) && candidate.workTree.length >= parent.workTree.length) {
102769
+ parent = candidate;
102770
+ }
102771
+ }
102772
+ parent.children.push(node);
102773
+ }
102774
+ return { workspaceRoot, root };
102775
+ }
102776
+ var init_git_workspace_hierarchy = __esm(() => {
102777
+ init_run_command();
102778
+ init_workspace_visibility_policy();
102779
+ });
102780
+
102201
102781
  // ../../node_modules/.pnpm/readdirp@5.0.0/node_modules/readdirp/index.js
102202
102782
  import { lstat, readdir, realpath as realpath3, stat as stat2 } from "node:fs/promises";
102203
102783
  import { join as pjoin, relative as prelative, resolve as presolve, sep as psep } from "node:path";
@@ -102296,7 +102876,7 @@ var init_readdirp = __esm(() => {
102296
102876
  this._directoryFilter = normalizeFilter(opts.directoryFilter);
102297
102877
  const statMethod = opts.lstat ? lstat : stat2;
102298
102878
  if (wantBigintFsStats) {
102299
- this._stat = (path5) => statMethod(path5, { bigint: true });
102879
+ this._stat = (path7) => statMethod(path7, { bigint: true });
102300
102880
  } else {
102301
102881
  this._stat = statMethod;
102302
102882
  }
@@ -102321,8 +102901,8 @@ var init_readdirp = __esm(() => {
102321
102901
  const par2 = this.parent;
102322
102902
  const fil = par2 && par2.files;
102323
102903
  if (fil && fil.length > 0) {
102324
- const { path: path5, depth } = par2;
102325
- const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path5));
102904
+ const { path: path7, depth } = par2;
102905
+ const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path7));
102326
102906
  const awaited = await Promise.all(slice);
102327
102907
  for (const entry of awaited) {
102328
102908
  if (!entry)
@@ -102362,20 +102942,20 @@ var init_readdirp = __esm(() => {
102362
102942
  this.reading = false;
102363
102943
  }
102364
102944
  }
102365
- async _exploreDir(path5, depth) {
102945
+ async _exploreDir(path7, depth) {
102366
102946
  let files;
102367
102947
  try {
102368
- files = await readdir(path5, this._rdOptions);
102948
+ files = await readdir(path7, this._rdOptions);
102369
102949
  } catch (error40) {
102370
102950
  this._onError(error40);
102371
102951
  }
102372
- return { files, depth, path: path5 };
102952
+ return { files, depth, path: path7 };
102373
102953
  }
102374
- async _formatEntry(dirent, path5) {
102954
+ async _formatEntry(dirent, path7) {
102375
102955
  let entry;
102376
102956
  const basename2 = this._isDirent ? dirent.name : dirent;
102377
102957
  try {
102378
- const fullPath = presolve(pjoin(path5, basename2));
102958
+ const fullPath = presolve(pjoin(path7, basename2));
102379
102959
  entry = { path: prelative(this._root, fullPath), fullPath, basename: basename2 };
102380
102960
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
102381
102961
  } catch (err) {
@@ -102435,16 +103015,16 @@ import { watch as fs_watch, unwatchFile, watchFile } from "node:fs";
102435
103015
  import { realpath as fsrealpath, lstat as lstat2, open, stat as stat3 } from "node:fs/promises";
102436
103016
  import { type as osType } from "node:os";
102437
103017
  import * as sp from "node:path";
102438
- function createFsWatchInstance(path5, options, listener, errHandler, emitRaw) {
103018
+ function createFsWatchInstance(path7, options, listener, errHandler, emitRaw) {
102439
103019
  const handleEvent = (rawEvent, evPath) => {
102440
- listener(path5);
102441
- emitRaw(rawEvent, evPath, { watchedPath: path5 });
102442
- if (evPath && path5 !== evPath) {
102443
- fsWatchBroadcast(sp.resolve(path5, evPath), KEY_LISTENERS, sp.join(path5, evPath));
103020
+ listener(path7);
103021
+ emitRaw(rawEvent, evPath, { watchedPath: path7 });
103022
+ if (evPath && path7 !== evPath) {
103023
+ fsWatchBroadcast(sp.resolve(path7, evPath), KEY_LISTENERS, sp.join(path7, evPath));
102444
103024
  }
102445
103025
  };
102446
103026
  try {
102447
- return fs_watch(path5, {
103027
+ return fs_watch(path7, {
102448
103028
  persistent: options.persistent
102449
103029
  }, handleEvent);
102450
103030
  } catch (error40) {
@@ -102460,13 +103040,13 @@ class NodeFsHandler {
102460
103040
  this.fsw = fsW;
102461
103041
  this._boundHandleError = (error40) => fsW._handleError(error40);
102462
103042
  }
102463
- _watchWithNodeFs(path5, listener) {
103043
+ _watchWithNodeFs(path7, listener) {
102464
103044
  const opts = this.fsw.options;
102465
- const directory = sp.dirname(path5);
102466
- const basename3 = sp.basename(path5);
103045
+ const directory = sp.dirname(path7);
103046
+ const basename3 = sp.basename(path7);
102467
103047
  const parent = this.fsw._getWatchedDir(directory);
102468
103048
  parent.add(basename3);
102469
- const absolutePath = sp.resolve(path5);
103049
+ const absolutePath = sp.resolve(path7);
102470
103050
  const options = {
102471
103051
  persistent: opts.persistent
102472
103052
  };
@@ -102476,12 +103056,12 @@ class NodeFsHandler {
102476
103056
  if (opts.usePolling) {
102477
103057
  const enableBin = opts.interval !== opts.binaryInterval;
102478
103058
  options.interval = enableBin && isBinaryPath(basename3) ? opts.binaryInterval : opts.interval;
102479
- closer = setFsWatchFileListener(path5, absolutePath, options, {
103059
+ closer = setFsWatchFileListener(path7, absolutePath, options, {
102480
103060
  listener,
102481
103061
  rawEmitter: this.fsw._emitRaw
102482
103062
  });
102483
103063
  } else {
102484
- closer = setFsWatchListener(path5, absolutePath, options, {
103064
+ closer = setFsWatchListener(path7, absolutePath, options, {
102485
103065
  listener,
102486
103066
  errHandler: this._boundHandleError,
102487
103067
  rawEmitter: this.fsw._emitRaw
@@ -102499,7 +103079,7 @@ class NodeFsHandler {
102499
103079
  let prevStats = stats;
102500
103080
  if (parent.has(basename3))
102501
103081
  return;
102502
- const listener = async (path5, newStats) => {
103082
+ const listener = async (path7, newStats) => {
102503
103083
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file2, 5))
102504
103084
  return;
102505
103085
  if (!newStats || newStats.mtimeMs === 0) {
@@ -102513,11 +103093,11 @@ class NodeFsHandler {
102513
103093
  this.fsw._emit(EV.CHANGE, file2, newStats2);
102514
103094
  }
102515
103095
  if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
102516
- this.fsw._closeFile(path5);
103096
+ this.fsw._closeFile(path7);
102517
103097
  prevStats = newStats2;
102518
103098
  const closer2 = this._watchWithNodeFs(file2, listener);
102519
103099
  if (closer2)
102520
- this.fsw._addPathCloser(path5, closer2);
103100
+ this.fsw._addPathCloser(path7, closer2);
102521
103101
  } else {
102522
103102
  prevStats = newStats2;
102523
103103
  }
@@ -102541,7 +103121,7 @@ class NodeFsHandler {
102541
103121
  }
102542
103122
  return closer;
102543
103123
  }
102544
- async _handleSymlink(entry, directory, path5, item) {
103124
+ async _handleSymlink(entry, directory, path7, item) {
102545
103125
  if (this.fsw.closed) {
102546
103126
  return;
102547
103127
  }
@@ -102551,7 +103131,7 @@ class NodeFsHandler {
102551
103131
  this.fsw._incrReadyCount();
102552
103132
  let linkPath;
102553
103133
  try {
102554
- linkPath = await fsrealpath(path5);
103134
+ linkPath = await fsrealpath(path7);
102555
103135
  } catch (e) {
102556
103136
  this.fsw._emitReady();
102557
103137
  return true;
@@ -102561,12 +103141,12 @@ class NodeFsHandler {
102561
103141
  if (dir.has(item)) {
102562
103142
  if (this.fsw._symlinkPaths.get(full) !== linkPath) {
102563
103143
  this.fsw._symlinkPaths.set(full, linkPath);
102564
- this.fsw._emit(EV.CHANGE, path5, entry.stats);
103144
+ this.fsw._emit(EV.CHANGE, path7, entry.stats);
102565
103145
  }
102566
103146
  } else {
102567
103147
  dir.add(item);
102568
103148
  this.fsw._symlinkPaths.set(full, linkPath);
102569
- this.fsw._emit(EV.ADD, path5, entry.stats);
103149
+ this.fsw._emit(EV.ADD, path7, entry.stats);
102570
103150
  }
102571
103151
  this.fsw._emitReady();
102572
103152
  return true;
@@ -102596,9 +103176,9 @@ class NodeFsHandler {
102596
103176
  return;
102597
103177
  }
102598
103178
  const item = entry.path;
102599
- let path5 = sp.join(directory, item);
103179
+ let path7 = sp.join(directory, item);
102600
103180
  current.add(item);
102601
- if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path5, item)) {
103181
+ if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path7, item)) {
102602
103182
  return;
102603
103183
  }
102604
103184
  if (this.fsw.closed) {
@@ -102607,8 +103187,8 @@ class NodeFsHandler {
102607
103187
  }
102608
103188
  if (item === target || !target && !previous.has(item)) {
102609
103189
  this.fsw._incrReadyCount();
102610
- path5 = sp.join(dir, sp.relative(dir, path5));
102611
- this._addToNodeFs(path5, initialAdd, wh, depth + 1);
103190
+ path7 = sp.join(dir, sp.relative(dir, path7));
103191
+ this._addToNodeFs(path7, initialAdd, wh, depth + 1);
102612
103192
  }
102613
103193
  }).on(EV.ERROR, this._boundHandleError);
102614
103194
  return new Promise((resolve6, reject) => {
@@ -102657,13 +103237,13 @@ class NodeFsHandler {
102657
103237
  }
102658
103238
  return closer;
102659
103239
  }
102660
- async _addToNodeFs(path5, initialAdd, priorWh, depth, target) {
103240
+ async _addToNodeFs(path7, initialAdd, priorWh, depth, target) {
102661
103241
  const ready = this.fsw._emitReady;
102662
- if (this.fsw._isIgnored(path5) || this.fsw.closed) {
103242
+ if (this.fsw._isIgnored(path7) || this.fsw.closed) {
102663
103243
  ready();
102664
103244
  return false;
102665
103245
  }
102666
- const wh = this.fsw._getWatchHelpers(path5);
103246
+ const wh = this.fsw._getWatchHelpers(path7);
102667
103247
  if (priorWh) {
102668
103248
  wh.filterPath = (entry) => priorWh.filterPath(entry);
102669
103249
  wh.filterDir = (entry) => priorWh.filterDir(entry);
@@ -102679,8 +103259,8 @@ class NodeFsHandler {
102679
103259
  const follow = this.fsw.options.followSymlinks;
102680
103260
  let closer;
102681
103261
  if (stats.isDirectory()) {
102682
- const absPath = sp.resolve(path5);
102683
- const targetPath = follow ? await fsrealpath(path5) : path5;
103262
+ const absPath = sp.resolve(path7);
103263
+ const targetPath = follow ? await fsrealpath(path7) : path7;
102684
103264
  if (this.fsw.closed)
102685
103265
  return;
102686
103266
  closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
@@ -102690,29 +103270,29 @@ class NodeFsHandler {
102690
103270
  this.fsw._symlinkPaths.set(absPath, targetPath);
102691
103271
  }
102692
103272
  } else if (stats.isSymbolicLink()) {
102693
- const targetPath = follow ? await fsrealpath(path5) : path5;
103273
+ const targetPath = follow ? await fsrealpath(path7) : path7;
102694
103274
  if (this.fsw.closed)
102695
103275
  return;
102696
103276
  const parent = sp.dirname(wh.watchPath);
102697
103277
  this.fsw._getWatchedDir(parent).add(wh.watchPath);
102698
103278
  this.fsw._emit(EV.ADD, wh.watchPath, stats);
102699
- closer = await this._handleDir(parent, stats, initialAdd, depth, path5, wh, targetPath);
103279
+ closer = await this._handleDir(parent, stats, initialAdd, depth, path7, wh, targetPath);
102700
103280
  if (this.fsw.closed)
102701
103281
  return;
102702
103282
  if (targetPath !== undefined) {
102703
- this.fsw._symlinkPaths.set(sp.resolve(path5), targetPath);
103283
+ this.fsw._symlinkPaths.set(sp.resolve(path7), targetPath);
102704
103284
  }
102705
103285
  } else {
102706
103286
  closer = this._handleFile(wh.watchPath, stats, initialAdd);
102707
103287
  }
102708
103288
  ready();
102709
103289
  if (closer)
102710
- this.fsw._addPathCloser(path5, closer);
103290
+ this.fsw._addPathCloser(path7, closer);
102711
103291
  return false;
102712
103292
  } catch (error40) {
102713
103293
  if (this.fsw._handleError(error40)) {
102714
103294
  ready();
102715
- return path5;
103295
+ return path7;
102716
103296
  }
102717
103297
  }
102718
103298
  }
@@ -102750,12 +103330,12 @@ var STR_DATA = "data", STR_END = "end", STR_CLOSE = "close", EMPTY_FN = () => {}
102750
103330
  foreach(cont[listenerType], (listener) => {
102751
103331
  listener(val1, val2, val3);
102752
103332
  });
102753
- }, setFsWatchListener = (path5, fullPath, options, handlers) => {
103333
+ }, setFsWatchListener = (path7, fullPath, options, handlers) => {
102754
103334
  const { listener, errHandler, rawEmitter } = handlers;
102755
103335
  let cont = FsWatchInstances.get(fullPath);
102756
103336
  let watcher;
102757
103337
  if (!options.persistent) {
102758
- watcher = createFsWatchInstance(path5, options, listener, errHandler, rawEmitter);
103338
+ watcher = createFsWatchInstance(path7, options, listener, errHandler, rawEmitter);
102759
103339
  if (!watcher)
102760
103340
  return;
102761
103341
  return watcher.close.bind(watcher);
@@ -102765,7 +103345,7 @@ var STR_DATA = "data", STR_END = "end", STR_CLOSE = "close", EMPTY_FN = () => {}
102765
103345
  addAndConvert(cont, KEY_ERR, errHandler);
102766
103346
  addAndConvert(cont, KEY_RAW, rawEmitter);
102767
103347
  } else {
102768
- watcher = createFsWatchInstance(path5, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, fsWatchBroadcast.bind(null, fullPath, KEY_RAW));
103348
+ watcher = createFsWatchInstance(path7, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, fsWatchBroadcast.bind(null, fullPath, KEY_RAW));
102769
103349
  if (!watcher)
102770
103350
  return;
102771
103351
  watcher.on(EV.ERROR, async (error40) => {
@@ -102774,7 +103354,7 @@ var STR_DATA = "data", STR_END = "end", STR_CLOSE = "close", EMPTY_FN = () => {}
102774
103354
  cont.watcherUnusable = true;
102775
103355
  if (isWindows && error40.code === "EPERM") {
102776
103356
  try {
102777
- const fd = await open(path5, "r");
103357
+ const fd = await open(path7, "r");
102778
103358
  await fd.close();
102779
103359
  broadcastErr(error40);
102780
103360
  } catch (err) {}
@@ -102802,7 +103382,7 @@ var STR_DATA = "data", STR_END = "end", STR_CLOSE = "close", EMPTY_FN = () => {}
102802
103382
  Object.freeze(cont);
102803
103383
  }
102804
103384
  };
102805
- }, FsWatchFileInstances, setFsWatchFileListener = (path5, fullPath, options, handlers) => {
103385
+ }, FsWatchFileInstances, setFsWatchFileListener = (path7, fullPath, options, handlers) => {
102806
103386
  const { listener, rawEmitter } = handlers;
102807
103387
  let cont = FsWatchFileInstances.get(fullPath);
102808
103388
  const copts = cont && cont.options;
@@ -102824,7 +103404,7 @@ var STR_DATA = "data", STR_END = "end", STR_CLOSE = "close", EMPTY_FN = () => {}
102824
103404
  });
102825
103405
  const currmtime = curr.mtimeMs;
102826
103406
  if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
102827
- foreach(cont.listeners, (listener2) => listener2(path5, curr));
103407
+ foreach(cont.listeners, (listener2) => listener2(path7, curr));
102828
103408
  }
102829
103409
  })
102830
103410
  };
@@ -103160,24 +103740,24 @@ function createPattern(matcher) {
103160
103740
  }
103161
103741
  return () => false;
103162
103742
  }
103163
- function normalizePath(path5) {
103164
- if (typeof path5 !== "string")
103743
+ function normalizePath(path7) {
103744
+ if (typeof path7 !== "string")
103165
103745
  throw new Error("string expected");
103166
- path5 = sp2.normalize(path5);
103167
- path5 = path5.replace(/\\/g, "/");
103746
+ path7 = sp2.normalize(path7);
103747
+ path7 = path7.replace(/\\/g, "/");
103168
103748
  let prepend4 = false;
103169
- if (path5.startsWith("//"))
103749
+ if (path7.startsWith("//"))
103170
103750
  prepend4 = true;
103171
- path5 = path5.replace(DOUBLE_SLASH_RE, "/");
103751
+ path7 = path7.replace(DOUBLE_SLASH_RE, "/");
103172
103752
  if (prepend4)
103173
- path5 = "/" + path5;
103174
- return path5;
103753
+ path7 = "/" + path7;
103754
+ return path7;
103175
103755
  }
103176
103756
  function matchPatterns(patterns, testString, stats) {
103177
- const path5 = normalizePath(testString);
103757
+ const path7 = normalizePath(testString);
103178
103758
  for (let index = 0;index < patterns.length; index++) {
103179
103759
  const pattern2 = patterns[index];
103180
- if (pattern2(path5, stats)) {
103760
+ if (pattern2(path7, stats)) {
103181
103761
  return true;
103182
103762
  }
103183
103763
  }
@@ -103258,10 +103838,10 @@ class WatchHelper {
103258
103838
  dirParts;
103259
103839
  followSymlinks;
103260
103840
  statMethod;
103261
- constructor(path5, follow, fsw) {
103841
+ constructor(path7, follow, fsw) {
103262
103842
  this.fsw = fsw;
103263
- const watchPath = path5;
103264
- this.path = path5 = path5.replace(REPLACER_RE, "");
103843
+ const watchPath = path7;
103844
+ this.path = path7 = path7.replace(REPLACER_RE, "");
103265
103845
  this.watchPath = watchPath;
103266
103846
  this.fullWatchPath = sp2.resolve(watchPath);
103267
103847
  this.dirParts = [];
@@ -103308,17 +103888,17 @@ var SLASH = "/", SLASH_SLASH = "//", ONE_DOT = ".", TWO_DOTS = "..", STRING_TYPE
103308
103888
  str = SLASH + str;
103309
103889
  }
103310
103890
  return str;
103311
- }, normalizePathToUnix = (path5) => toUnix(sp2.normalize(toUnix(path5))), normalizeIgnored = (cwd = "") => (path5) => {
103312
- if (typeof path5 === "string") {
103313
- return normalizePathToUnix(sp2.isAbsolute(path5) ? path5 : sp2.join(cwd, path5));
103891
+ }, normalizePathToUnix = (path7) => toUnix(sp2.normalize(toUnix(path7))), normalizeIgnored = (cwd = "") => (path7) => {
103892
+ if (typeof path7 === "string") {
103893
+ return normalizePathToUnix(sp2.isAbsolute(path7) ? path7 : sp2.join(cwd, path7));
103314
103894
  } else {
103315
- return path5;
103895
+ return path7;
103316
103896
  }
103317
- }, getAbsolutePath = (path5, cwd) => {
103318
- if (sp2.isAbsolute(path5)) {
103319
- return path5;
103897
+ }, getAbsolutePath = (path7, cwd) => {
103898
+ if (sp2.isAbsolute(path7)) {
103899
+ return path7;
103320
103900
  }
103321
- return sp2.join(cwd, path5);
103901
+ return sp2.join(cwd, path7);
103322
103902
  }, EMPTY_SET, STAT_METHOD_F = "stat", STAT_METHOD_L = "lstat", FSWatcher;
103323
103903
  var init_chokidar = __esm(() => {
103324
103904
  init_readdirp();
@@ -103434,20 +104014,20 @@ var init_chokidar = __esm(() => {
103434
104014
  this._closePromise = undefined;
103435
104015
  let paths = unifyPaths(paths_);
103436
104016
  if (cwd) {
103437
- paths = paths.map((path5) => {
103438
- const absPath = getAbsolutePath(path5, cwd);
104017
+ paths = paths.map((path7) => {
104018
+ const absPath = getAbsolutePath(path7, cwd);
103439
104019
  return absPath;
103440
104020
  });
103441
104021
  }
103442
- paths.forEach((path5) => {
103443
- this._removeIgnoredPath(path5);
104022
+ paths.forEach((path7) => {
104023
+ this._removeIgnoredPath(path7);
103444
104024
  });
103445
104025
  this._userIgnored = undefined;
103446
104026
  if (!this._readyCount)
103447
104027
  this._readyCount = 0;
103448
104028
  this._readyCount += paths.length;
103449
- Promise.all(paths.map(async (path5) => {
103450
- const res = await this._nodeFsHandler._addToNodeFs(path5, !_internal, undefined, 0, _origAdd);
104029
+ Promise.all(paths.map(async (path7) => {
104030
+ const res = await this._nodeFsHandler._addToNodeFs(path7, !_internal, undefined, 0, _origAdd);
103451
104031
  if (res)
103452
104032
  this._emitReady();
103453
104033
  return res;
@@ -103466,17 +104046,17 @@ var init_chokidar = __esm(() => {
103466
104046
  return this;
103467
104047
  const paths = unifyPaths(paths_);
103468
104048
  const { cwd } = this.options;
103469
- paths.forEach((path5) => {
103470
- if (!sp2.isAbsolute(path5) && !this._closers.has(path5)) {
104049
+ paths.forEach((path7) => {
104050
+ if (!sp2.isAbsolute(path7) && !this._closers.has(path7)) {
103471
104051
  if (cwd)
103472
- path5 = sp2.join(cwd, path5);
103473
- path5 = sp2.resolve(path5);
104052
+ path7 = sp2.join(cwd, path7);
104053
+ path7 = sp2.resolve(path7);
103474
104054
  }
103475
- this._closePath(path5);
103476
- this._addIgnoredPath(path5);
103477
- if (this._watched.has(path5)) {
104055
+ this._closePath(path7);
104056
+ this._addIgnoredPath(path7);
104057
+ if (this._watched.has(path7)) {
103478
104058
  this._addIgnoredPath({
103479
- path: path5,
104059
+ path: path7,
103480
104060
  recursive: true
103481
104061
  });
103482
104062
  }
@@ -103525,38 +104105,38 @@ var init_chokidar = __esm(() => {
103525
104105
  if (event !== EVENTS.ERROR)
103526
104106
  this.emit(EVENTS.ALL, event, ...args2);
103527
104107
  }
103528
- async _emit(event, path5, stats) {
104108
+ async _emit(event, path7, stats) {
103529
104109
  if (this.closed)
103530
104110
  return;
103531
104111
  const opts = this.options;
103532
104112
  if (isWindows)
103533
- path5 = sp2.normalize(path5);
104113
+ path7 = sp2.normalize(path7);
103534
104114
  if (opts.cwd)
103535
- path5 = sp2.relative(opts.cwd, path5);
103536
- const args2 = [path5];
104115
+ path7 = sp2.relative(opts.cwd, path7);
104116
+ const args2 = [path7];
103537
104117
  if (stats != null)
103538
104118
  args2.push(stats);
103539
104119
  const awf = opts.awaitWriteFinish;
103540
104120
  let pw;
103541
- if (awf && (pw = this._pendingWrites.get(path5))) {
104121
+ if (awf && (pw = this._pendingWrites.get(path7))) {
103542
104122
  pw.lastChange = new Date;
103543
104123
  return this;
103544
104124
  }
103545
104125
  if (opts.atomic) {
103546
104126
  if (event === EVENTS.UNLINK) {
103547
- this._pendingUnlinks.set(path5, [event, ...args2]);
104127
+ this._pendingUnlinks.set(path7, [event, ...args2]);
103548
104128
  setTimeout(() => {
103549
- this._pendingUnlinks.forEach((entry, path6) => {
104129
+ this._pendingUnlinks.forEach((entry, path8) => {
103550
104130
  this.emit(...entry);
103551
104131
  this.emit(EVENTS.ALL, ...entry);
103552
- this._pendingUnlinks.delete(path6);
104132
+ this._pendingUnlinks.delete(path8);
103553
104133
  });
103554
104134
  }, typeof opts.atomic === "number" ? opts.atomic : 100);
103555
104135
  return this;
103556
104136
  }
103557
- if (event === EVENTS.ADD && this._pendingUnlinks.has(path5)) {
104137
+ if (event === EVENTS.ADD && this._pendingUnlinks.has(path7)) {
103558
104138
  event = EVENTS.CHANGE;
103559
- this._pendingUnlinks.delete(path5);
104139
+ this._pendingUnlinks.delete(path7);
103560
104140
  }
103561
104141
  }
103562
104142
  if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
@@ -103574,16 +104154,16 @@ var init_chokidar = __esm(() => {
103574
104154
  this.emitWithAll(event, args2);
103575
104155
  }
103576
104156
  };
103577
- this._awaitWriteFinish(path5, awf.stabilityThreshold, event, awfEmit);
104157
+ this._awaitWriteFinish(path7, awf.stabilityThreshold, event, awfEmit);
103578
104158
  return this;
103579
104159
  }
103580
104160
  if (event === EVENTS.CHANGE) {
103581
- const isThrottled = !this._throttle(EVENTS.CHANGE, path5, 50);
104161
+ const isThrottled = !this._throttle(EVENTS.CHANGE, path7, 50);
103582
104162
  if (isThrottled)
103583
104163
  return this;
103584
104164
  }
103585
104165
  if (opts.alwaysStat && stats === undefined && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
103586
- const fullPath = opts.cwd ? sp2.join(opts.cwd, path5) : path5;
104166
+ const fullPath = opts.cwd ? sp2.join(opts.cwd, path7) : path7;
103587
104167
  let stats2;
103588
104168
  try {
103589
104169
  stats2 = await stat4(fullPath);
@@ -103602,23 +104182,23 @@ var init_chokidar = __esm(() => {
103602
104182
  }
103603
104183
  return error40 || this.closed;
103604
104184
  }
103605
- _throttle(actionType, path5, timeout3) {
104185
+ _throttle(actionType, path7, timeout3) {
103606
104186
  if (!this._throttled.has(actionType)) {
103607
104187
  this._throttled.set(actionType, new Map);
103608
104188
  }
103609
104189
  const action = this._throttled.get(actionType);
103610
104190
  if (!action)
103611
104191
  throw new Error("invalid throttle");
103612
- const actionPath = action.get(path5);
104192
+ const actionPath = action.get(path7);
103613
104193
  if (actionPath) {
103614
104194
  actionPath.count++;
103615
104195
  return false;
103616
104196
  }
103617
104197
  let timeoutObject;
103618
104198
  const clear = () => {
103619
- const item = action.get(path5);
104199
+ const item = action.get(path7);
103620
104200
  const count3 = item ? item.count : 0;
103621
- action.delete(path5);
104201
+ action.delete(path7);
103622
104202
  clearTimeout(timeoutObject);
103623
104203
  if (item)
103624
104204
  clearTimeout(item.timeoutObject);
@@ -103626,50 +104206,50 @@ var init_chokidar = __esm(() => {
103626
104206
  };
103627
104207
  timeoutObject = setTimeout(clear, timeout3);
103628
104208
  const thr = { timeoutObject, clear, count: 0 };
103629
- action.set(path5, thr);
104209
+ action.set(path7, thr);
103630
104210
  return thr;
103631
104211
  }
103632
104212
  _incrReadyCount() {
103633
104213
  return this._readyCount++;
103634
104214
  }
103635
- _awaitWriteFinish(path5, threshold, event, awfEmit) {
104215
+ _awaitWriteFinish(path7, threshold, event, awfEmit) {
103636
104216
  const awf = this.options.awaitWriteFinish;
103637
104217
  if (typeof awf !== "object")
103638
104218
  return;
103639
104219
  const pollInterval = awf.pollInterval;
103640
104220
  let timeoutHandler;
103641
- let fullPath = path5;
103642
- if (this.options.cwd && !sp2.isAbsolute(path5)) {
103643
- fullPath = sp2.join(this.options.cwd, path5);
104221
+ let fullPath = path7;
104222
+ if (this.options.cwd && !sp2.isAbsolute(path7)) {
104223
+ fullPath = sp2.join(this.options.cwd, path7);
103644
104224
  }
103645
104225
  const now = new Date;
103646
104226
  const writes = this._pendingWrites;
103647
104227
  function awaitWriteFinishFn(prevStat) {
103648
104228
  statcb(fullPath, (err, curStat) => {
103649
- if (err || !writes.has(path5)) {
104229
+ if (err || !writes.has(path7)) {
103650
104230
  if (err && err.code !== "ENOENT")
103651
104231
  awfEmit(err);
103652
104232
  return;
103653
104233
  }
103654
104234
  const now2 = Number(new Date);
103655
104235
  if (prevStat && curStat.size !== prevStat.size) {
103656
- writes.get(path5).lastChange = now2;
104236
+ writes.get(path7).lastChange = now2;
103657
104237
  }
103658
- const pw = writes.get(path5);
104238
+ const pw = writes.get(path7);
103659
104239
  const df = now2 - pw.lastChange;
103660
104240
  if (df >= threshold) {
103661
- writes.delete(path5);
104241
+ writes.delete(path7);
103662
104242
  awfEmit(undefined, curStat);
103663
104243
  } else {
103664
104244
  timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
103665
104245
  }
103666
104246
  });
103667
104247
  }
103668
- if (!writes.has(path5)) {
103669
- writes.set(path5, {
104248
+ if (!writes.has(path7)) {
104249
+ writes.set(path7, {
103670
104250
  lastChange: now,
103671
104251
  cancelWait: () => {
103672
- writes.delete(path5);
104252
+ writes.delete(path7);
103673
104253
  clearTimeout(timeoutHandler);
103674
104254
  return event;
103675
104255
  }
@@ -103677,8 +104257,8 @@ var init_chokidar = __esm(() => {
103677
104257
  timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval);
103678
104258
  }
103679
104259
  }
103680
- _isIgnored(path5, stats) {
103681
- if (this.options.atomic && DOT_RE.test(path5))
104260
+ _isIgnored(path7, stats) {
104261
+ if (this.options.atomic && DOT_RE.test(path7))
103682
104262
  return true;
103683
104263
  if (!this._userIgnored) {
103684
104264
  const { cwd } = this.options;
@@ -103688,13 +104268,13 @@ var init_chokidar = __esm(() => {
103688
104268
  const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
103689
104269
  this._userIgnored = anymatch(list, undefined);
103690
104270
  }
103691
- return this._userIgnored(path5, stats);
104271
+ return this._userIgnored(path7, stats);
103692
104272
  }
103693
- _isntIgnored(path5, stat5) {
103694
- return !this._isIgnored(path5, stat5);
104273
+ _isntIgnored(path7, stat5) {
104274
+ return !this._isIgnored(path7, stat5);
103695
104275
  }
103696
- _getWatchHelpers(path5) {
103697
- return new WatchHelper(path5, this.options.followSymlinks, this);
104276
+ _getWatchHelpers(path7) {
104277
+ return new WatchHelper(path7, this.options.followSymlinks, this);
103698
104278
  }
103699
104279
  _getWatchedDir(directory) {
103700
104280
  const dir = sp2.resolve(directory);
@@ -103708,57 +104288,57 @@ var init_chokidar = __esm(() => {
103708
104288
  return Boolean(Number(stats.mode) & 256);
103709
104289
  }
103710
104290
  _remove(directory, item, isDirectory) {
103711
- const path5 = sp2.join(directory, item);
103712
- const fullPath = sp2.resolve(path5);
103713
- isDirectory = isDirectory != null ? isDirectory : this._watched.has(path5) || this._watched.has(fullPath);
103714
- if (!this._throttle("remove", path5, 100))
104291
+ const path7 = sp2.join(directory, item);
104292
+ const fullPath = sp2.resolve(path7);
104293
+ isDirectory = isDirectory != null ? isDirectory : this._watched.has(path7) || this._watched.has(fullPath);
104294
+ if (!this._throttle("remove", path7, 100))
103715
104295
  return;
103716
104296
  if (!isDirectory && this._watched.size === 1) {
103717
104297
  this.add(directory, item, true);
103718
104298
  }
103719
- const wp = this._getWatchedDir(path5);
104299
+ const wp = this._getWatchedDir(path7);
103720
104300
  const nestedDirectoryChildren = wp.getChildren();
103721
- nestedDirectoryChildren.forEach((nested2) => this._remove(path5, nested2));
104301
+ nestedDirectoryChildren.forEach((nested2) => this._remove(path7, nested2));
103722
104302
  const parent = this._getWatchedDir(directory);
103723
104303
  const wasTracked = parent.has(item);
103724
104304
  parent.remove(item);
103725
104305
  if (this._symlinkPaths.has(fullPath)) {
103726
104306
  this._symlinkPaths.delete(fullPath);
103727
104307
  }
103728
- let relPath = path5;
104308
+ let relPath = path7;
103729
104309
  if (this.options.cwd)
103730
- relPath = sp2.relative(this.options.cwd, path5);
104310
+ relPath = sp2.relative(this.options.cwd, path7);
103731
104311
  if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
103732
104312
  const event = this._pendingWrites.get(relPath).cancelWait();
103733
104313
  if (event === EVENTS.ADD)
103734
104314
  return;
103735
104315
  }
103736
- this._watched.delete(path5);
104316
+ this._watched.delete(path7);
103737
104317
  this._watched.delete(fullPath);
103738
104318
  const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
103739
- if (wasTracked && !this._isIgnored(path5))
103740
- this._emit(eventName, path5);
103741
- this._closePath(path5);
104319
+ if (wasTracked && !this._isIgnored(path7))
104320
+ this._emit(eventName, path7);
104321
+ this._closePath(path7);
103742
104322
  }
103743
- _closePath(path5) {
103744
- this._closeFile(path5);
103745
- const dir = sp2.dirname(path5);
103746
- this._getWatchedDir(dir).remove(sp2.basename(path5));
104323
+ _closePath(path7) {
104324
+ this._closeFile(path7);
104325
+ const dir = sp2.dirname(path7);
104326
+ this._getWatchedDir(dir).remove(sp2.basename(path7));
103747
104327
  }
103748
- _closeFile(path5) {
103749
- const closers = this._closers.get(path5);
104328
+ _closeFile(path7) {
104329
+ const closers = this._closers.get(path7);
103750
104330
  if (!closers)
103751
104331
  return;
103752
104332
  closers.forEach((closer) => closer());
103753
- this._closers.delete(path5);
104333
+ this._closers.delete(path7);
103754
104334
  }
103755
- _addPathCloser(path5, closer) {
104335
+ _addPathCloser(path7, closer) {
103756
104336
  if (!closer)
103757
104337
  return;
103758
- let list = this._closers.get(path5);
104338
+ let list = this._closers.get(path7);
103759
104339
  if (!list) {
103760
104340
  list = [];
103761
- this._closers.set(path5, list);
104341
+ this._closers.set(path7, list);
103762
104342
  }
103763
104343
  list.push(closer);
103764
104344
  }
@@ -103783,7 +104363,7 @@ var init_chokidar = __esm(() => {
103783
104363
  });
103784
104364
 
103785
104365
  // src/infrastructure/services/workspace/workspace-fs-watcher.ts
103786
- import path5 from "node:path";
104366
+ import path7 from "node:path";
103787
104367
  function isTooManyOpenFilesError(error40) {
103788
104368
  if (!(error40 instanceof Error))
103789
104369
  return false;
@@ -103791,10 +104371,10 @@ function isTooManyOpenFilesError(error40) {
103791
104371
  return errno === "EMFILE" || errno === "ENOSPC" || error40.message.includes("EMFILE");
103792
104372
  }
103793
104373
  function toRelativePath(rootDir, absolutePath) {
103794
- return path5.relative(rootDir, absolutePath).replace(/\\/g, "/").replace(/^\.?\//, "");
104374
+ return path7.relative(rootDir, absolutePath).replace(/\\/g, "/").replace(/^\.?\//, "");
103795
104375
  }
103796
104376
  function createWorkspaceFsWatcher(options) {
103797
- const absWorkingDir = path5.resolve(options.workingDir);
104377
+ const absWorkingDir = path7.resolve(options.workingDir);
103798
104378
  const debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;
103799
104379
  let stopped = false;
103800
104380
  let debounceTimer = null;
@@ -103860,22 +104440,46 @@ var init_workspace_fs_watcher = __esm(() => {
103860
104440
  init_workspace_visibility_policy();
103861
104441
  });
103862
104442
 
104443
+ // src/infrastructure/services/workspace/workspace-change-source.ts
104444
+ function countGitRepoNodes(root) {
104445
+ return 1 + root.children.reduce((sum2, child) => sum2 + countGitRepoNodes(child), 0);
104446
+ }
104447
+ async function createWorkspaceChangeSource(options) {
104448
+ const hierarchy = await discoverGitWorkspaceHierarchy(options.workingDir);
104449
+ if (hierarchy !== null) {
104450
+ return {
104451
+ mode: "git",
104452
+ source: createGitWorkspaceChangeSource({ ...options, hierarchy }),
104453
+ gitRepoCount: countGitRepoNodes(hierarchy.root)
104454
+ };
104455
+ }
104456
+ return {
104457
+ mode: "fs",
104458
+ source: createWorkspaceFsWatcher(options)
104459
+ };
104460
+ }
104461
+ var init_workspace_change_source = __esm(() => {
104462
+ init_git_workspace_change_source();
104463
+ init_git_workspace_hierarchy();
104464
+ init_workspace_fs_watcher();
104465
+ });
104466
+
103863
104467
  // src/infrastructure/services/workspace/workspace-sync-diff.ts
103864
104468
  function diffPathIndexes(previous, next4) {
103865
104469
  const added = [];
103866
104470
  const removed = [];
103867
104471
  const typeChanged = [];
103868
104472
  const prev = previous ?? {};
103869
- for (const [path6, type] of Object.entries(next4)) {
103870
- if (!(path6 in prev)) {
103871
- added.push(path6);
103872
- } else if (prev[path6] !== type) {
103873
- typeChanged.push(path6);
104473
+ for (const [path8, type] of Object.entries(next4)) {
104474
+ if (!(path8 in prev)) {
104475
+ added.push(path8);
104476
+ } else if (prev[path8] !== type) {
104477
+ typeChanged.push(path8);
103874
104478
  }
103875
104479
  }
103876
- for (const path6 of Object.keys(prev)) {
103877
- if (!(path6 in next4)) {
103878
- removed.push(path6);
104480
+ for (const path8 of Object.keys(prev)) {
104481
+ if (!(path8 in next4)) {
104482
+ removed.push(path8);
103879
104483
  }
103880
104484
  }
103881
104485
  added.sort();
@@ -103961,7 +104565,7 @@ function createManifestFromTree(args2) {
103961
104565
  };
103962
104566
  }
103963
104567
  function entriesFromPathIndex(paths) {
103964
- return Object.entries(paths).map(([path6, type]) => ({ path: path6, type })).sort((a, b) => a.path.localeCompare(b.path));
104568
+ return Object.entries(paths).map(([path8, type]) => ({ path: path8, type })).sort((a, b) => a.path.localeCompare(b.path));
103965
104569
  }
103966
104570
  var SYNC_STATE_VERSION = "2", SYNC_STATE_DIR;
103967
104571
  var init_workspace_sync_state = __esm(() => {
@@ -103970,7 +104574,7 @@ var init_workspace_sync_state = __esm(() => {
103970
104574
 
103971
104575
  // src/infrastructure/services/workspace/workspace-file-tree-coordinator.ts
103972
104576
  import { randomUUID as randomUUID9 } from "node:crypto";
103973
- import path6 from "node:path";
104577
+ import path8 from "node:path";
103974
104578
  function deltaEntry(paths, pathValue) {
103975
104579
  const type = paths[pathValue];
103976
104580
  if (type === undefined)
@@ -104036,7 +104640,7 @@ async function addDirectorySubtree(rootDir, relativeDir, paths) {
104036
104640
  return;
104037
104641
  ensureParentDirectories(paths, relativeDir);
104038
104642
  paths[relativeDir] = "directory";
104039
- const subtree = await scanFileTree(path6.join(rootDir, relativeDir));
104643
+ const subtree = await scanFileTree(path8.join(rootDir, relativeDir));
104040
104644
  for (const entry of subtree.entries) {
104041
104645
  const prefixedPath = `${relativeDir}/${entry.path}`;
104042
104646
  if (await isWorkspacePathIgnored(rootDir, prefixedPath))
@@ -104175,31 +104779,69 @@ async function startWorkspaceFileTreeCoordinator(options) {
104175
104779
  await flushPending();
104176
104780
  const ignoreRuleSets = await loadAllWorkspaceIgnoreRuleSets(workingDir);
104177
104781
  const shouldIgnorePath = (relativePath) => isPathIgnoredByRuleSets(ignoreRuleSets, relativePath);
104178
- let watcher = createWorkspaceFsWatcher({
104179
- workingDir,
104180
- shouldIgnore: shouldIgnorePath,
104181
- onEvents: async (events) => {
104182
- await enqueueSerial(async () => {
104183
- const nextPaths = await applyFsEvents(workingDir, manifest.paths, events);
104184
- if (nextPaths === null) {
104185
- await reconcileNow();
104186
- return;
104187
- }
104188
- await commitPaths(nextPaths);
104189
- });
104190
- },
104191
- onError: (error40) => {
104192
- options.onError?.(error40);
104193
- if (isTooManyOpenFilesError(error40) && watcher) {
104194
- const activeWatcher = watcher;
104195
- watcher = null;
104196
- activeWatcher.stop().finally(() => scheduleReconcile(1000));
104782
+ let changeSource = null;
104783
+ let changeSourceMode = "fs";
104784
+ let gitDegraded = false;
104785
+ const handleChangeSourceEvents = async (events) => {
104786
+ await enqueueSerial(async () => {
104787
+ const nextPaths = await applyFsEvents(workingDir, manifest.paths, events);
104788
+ if (nextPaths === null) {
104789
+ await reconcileNow();
104197
104790
  return;
104198
104791
  }
104199
- scheduleReconcile(1000);
104792
+ await commitPaths(nextPaths);
104793
+ });
104794
+ };
104795
+ const handleChangeSourceError = (error40) => {
104796
+ if (error40 instanceof GitWorkspaceCommandError) {
104797
+ console.warn(`[workspace-file-tree] git poll error (${error40.operation}) workTree=${error40.workTree} relativePath=${error40.relativePath || "."}: ${error40.cause.message}`);
104200
104798
  }
104201
- });
104202
- await watcher.ready;
104799
+ options.onError?.(error40);
104800
+ if (changeSourceMode === "fs" && isTooManyOpenFilesError(error40) && changeSource) {
104801
+ const active2 = changeSource;
104802
+ changeSource = null;
104803
+ active2.stop().finally(() => scheduleReconcile(1000));
104804
+ return;
104805
+ }
104806
+ scheduleReconcile(1000);
104807
+ };
104808
+ const degradeGitToFs = async (reason) => {
104809
+ if (gitDegraded || changeSourceMode !== "git" || !changeSource)
104810
+ return;
104811
+ gitDegraded = true;
104812
+ console.log(`[workspace-file-tree] degrading to fs watcher: ${reason}`);
104813
+ const active2 = changeSource;
104814
+ changeSource = null;
104815
+ changeSourceMode = "fs";
104816
+ await active2.stop();
104817
+ const fs12 = createWorkspaceFsWatcher({
104818
+ workingDir,
104819
+ shouldIgnore: shouldIgnorePath,
104820
+ onEvents: handleChangeSourceEvents,
104821
+ onError: handleChangeSourceError
104822
+ });
104823
+ changeSource = fs12;
104824
+ await fs12.ready;
104825
+ console.log("[workspace-file-tree] change source: fs (degraded from git)");
104826
+ };
104827
+ const change = await createWorkspaceChangeSource({
104828
+ workingDir,
104829
+ pollIntervalMs: options.changeSourcePollIntervalMs,
104830
+ shouldIgnore: shouldIgnorePath,
104831
+ getKnownPaths: () => manifest.paths,
104832
+ onEvents: handleChangeSourceEvents,
104833
+ onNeedsReconcile: () => enqueueSerial(reconcileNow),
104834
+ onError: handleChangeSourceError,
104835
+ onPersistentFailure: () => degradeGitToFs("persistent git poll failures")
104836
+ });
104837
+ changeSource = change.source;
104838
+ changeSourceMode = change.mode;
104839
+ if (change.mode === "git") {
104840
+ console.log(`[workspace-file-tree] change source: git (${change.gitRepoCount ?? 1} repo${(change.gitRepoCount ?? 1) === 1 ? "" : "s"})`);
104841
+ } else {
104842
+ console.log("[workspace-file-tree] change source: fs");
104843
+ }
104844
+ await changeSource.ready;
104203
104845
  scheduleReconcile();
104204
104846
  return {
104205
104847
  workingDir,
@@ -104212,8 +104854,8 @@ async function startWorkspaceFileTreeCoordinator(options) {
104212
104854
  if (reconcileTimer)
104213
104855
  clearTimeout(reconcileTimer);
104214
104856
  reconcileTimer = null;
104215
- await watcher?.stop();
104216
- watcher = null;
104857
+ await changeSource?.stop();
104858
+ changeSource = null;
104217
104859
  await serial;
104218
104860
  await saveWorkspaceSyncManifest(manifest);
104219
104861
  }
@@ -104223,6 +104865,8 @@ var DEFAULT_RECONCILE_INTERVAL_MS, DEFAULT_CHECKPOINT_EVERY_REVISIONS = 100, REC
104223
104865
  var init_workspace_file_tree_coordinator = __esm(() => {
104224
104866
  init_file_tree_data_hash();
104225
104867
  init_file_tree_scanner();
104868
+ init_git_workspace_porcelain();
104869
+ init_workspace_change_source();
104226
104870
  init_workspace_fs_watcher();
104227
104871
  init_workspace_ignore();
104228
104872
  init_workspace_sync_state();
@@ -111430,7 +112074,7 @@ __export(exports_opencode_install, {
111430
112074
  installTool: () => installTool
111431
112075
  });
111432
112076
  import * as os2 from "os";
111433
- import * as path7 from "path";
112077
+ import * as path9 from "path";
111434
112078
  async function isChatroomInstalledDefault() {
111435
112079
  try {
111436
112080
  const { execSync: execSync3 } = await import("child_process");
@@ -111800,9 +112444,9 @@ After logging in, try this command again.\`;
111800
112444
  const fsService = yield* OpenCodeInstallFsService;
111801
112445
  const { checkExisting = true } = options;
111802
112446
  const homeDir = os2.homedir();
111803
- const toolDir = path7.join(homeDir, ".config", "opencode", "tool");
111804
- const toolPath = path7.join(toolDir, "chatroom.ts");
111805
- const handoffToolPath = path7.join(toolDir, "chatroom-handoff.ts");
112447
+ const toolDir = path9.join(homeDir, ".config", "opencode", "tool");
112448
+ const toolPath = path9.join(toolDir, "chatroom.ts");
112449
+ const handoffToolPath = path9.join(toolDir, "chatroom-handoff.ts");
111806
112450
  if (checkExisting) {
111807
112451
  const existingFiles = [];
111808
112452
  const toolExists = yield* fsService.access(toolPath);
@@ -112357,4 +113001,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
112357
113001
  });
112358
113002
  program2.parse();
112359
113003
 
112360
- //# debugId=CC11114DB63A703A64756E2164756E21
113004
+ //# debugId=B20428C3563382D064756E2164756E21