@buildautomaton/cli 0.1.62 → 0.1.64

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
@@ -3653,6 +3653,47 @@ var require_websocket_server = __commonJS({
3653
3653
  }
3654
3654
  });
3655
3655
 
3656
+ // src/paths/normalize-resolved-path.ts
3657
+ import fs from "node:fs";
3658
+ import path from "node:path";
3659
+ function normalizeResolvedPath(resolved) {
3660
+ const abs = path.resolve(resolved);
3661
+ try {
3662
+ return fs.realpathSync.native(abs);
3663
+ } catch {
3664
+ return abs;
3665
+ }
3666
+ }
3667
+ var init_normalize_resolved_path = __esm({
3668
+ "src/paths/normalize-resolved-path.ts"() {
3669
+ "use strict";
3670
+ }
3671
+ });
3672
+
3673
+ // src/files/cwd/bridge-root.ts
3674
+ function getBridgeRoot() {
3675
+ if (bridgeRootPath == null) {
3676
+ bridgeRootPath = normalizeResolvedPath(process.cwd());
3677
+ }
3678
+ return bridgeRootPath;
3679
+ }
3680
+ var bridgeRootPath;
3681
+ var init_bridge_root = __esm({
3682
+ "src/files/cwd/bridge-root.ts"() {
3683
+ "use strict";
3684
+ init_normalize_resolved_path();
3685
+ bridgeRootPath = null;
3686
+ }
3687
+ });
3688
+
3689
+ // src/files/cwd/index.ts
3690
+ var init_cwd = __esm({
3691
+ "src/files/cwd/index.ts"() {
3692
+ "use strict";
3693
+ init_bridge_root();
3694
+ }
3695
+ });
3696
+
3656
3697
  // ../../node_modules/.pnpm/tree-kill@1.2.2/node_modules/tree-kill/index.js
3657
3698
  var require_tree_kill = __commonJS({
3658
3699
  "../../node_modules/.pnpm/tree-kill@1.2.2/node_modules/tree-kill/index.js"(exports, module) {
@@ -4175,8 +4216,8 @@ var init_parseUtil = __esm({
4175
4216
  init_errors();
4176
4217
  init_en();
4177
4218
  makeIssue = (params) => {
4178
- const { data, path: path79, errorMaps, issueData } = params;
4179
- const fullPath = [...path79, ...issueData.path || []];
4219
+ const { data, path: path82, errorMaps, issueData } = params;
4220
+ const fullPath = [...path82, ...issueData.path || []];
4180
4221
  const fullIssue = {
4181
4222
  ...issueData,
4182
4223
  path: fullPath
@@ -4484,11 +4525,11 @@ var init_types = __esm({
4484
4525
  init_parseUtil();
4485
4526
  init_util();
4486
4527
  ParseInputLazyPath = class {
4487
- constructor(parent, value, path79, key) {
4528
+ constructor(parent, value, path82, key) {
4488
4529
  this._cachedPath = [];
4489
4530
  this.parent = parent;
4490
4531
  this.data = value;
4491
- this._path = path79;
4532
+ this._path = path82;
4492
4533
  this._key = key;
4493
4534
  }
4494
4535
  get path() {
@@ -8103,10 +8144,10 @@ function assignProp(target, prop, value) {
8103
8144
  configurable: true
8104
8145
  });
8105
8146
  }
8106
- function getElementAtPath(obj, path79) {
8107
- if (!path79)
8147
+ function getElementAtPath(obj, path82) {
8148
+ if (!path82)
8108
8149
  return obj;
8109
- return path79.reduce((acc, key) => acc?.[key], obj);
8150
+ return path82.reduce((acc, key) => acc?.[key], obj);
8110
8151
  }
8111
8152
  function promiseAllObject(promisesObj) {
8112
8153
  const keys = Object.keys(promisesObj);
@@ -8355,11 +8396,11 @@ function aborted(x, startIndex = 0) {
8355
8396
  }
8356
8397
  return false;
8357
8398
  }
8358
- function prefixIssues(path79, issues) {
8399
+ function prefixIssues(path82, issues) {
8359
8400
  return issues.map((iss) => {
8360
8401
  var _a2;
8361
8402
  (_a2 = iss).path ?? (_a2.path = []);
8362
- iss.path.unshift(path79);
8403
+ iss.path.unshift(path82);
8363
8404
  return iss;
8364
8405
  });
8365
8406
  }
@@ -8548,7 +8589,7 @@ function treeifyError(error40, _mapper) {
8548
8589
  return issue2.message;
8549
8590
  };
8550
8591
  const result = { errors: [] };
8551
- const processError = (error41, path79 = []) => {
8592
+ const processError = (error41, path82 = []) => {
8552
8593
  var _a2, _b;
8553
8594
  for (const issue2 of error41.issues) {
8554
8595
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -8558,7 +8599,7 @@ function treeifyError(error40, _mapper) {
8558
8599
  } else if (issue2.code === "invalid_element") {
8559
8600
  processError({ issues: issue2.issues }, issue2.path);
8560
8601
  } else {
8561
- const fullpath = [...path79, ...issue2.path];
8602
+ const fullpath = [...path82, ...issue2.path];
8562
8603
  if (fullpath.length === 0) {
8563
8604
  result.errors.push(mapper(issue2));
8564
8605
  continue;
@@ -8588,9 +8629,9 @@ function treeifyError(error40, _mapper) {
8588
8629
  processError(error40);
8589
8630
  return result;
8590
8631
  }
8591
- function toDotPath(path79) {
8632
+ function toDotPath(path82) {
8592
8633
  const segs = [];
8593
- for (const seg of path79) {
8634
+ for (const seg of path82) {
8594
8635
  if (typeof seg === "number")
8595
8636
  segs.push(`[${seg}]`);
8596
8637
  else if (typeof seg === "symbol")
@@ -21299,6 +21340,16 @@ var init_acp = __esm({
21299
21340
  }
21300
21341
  });
21301
21342
 
21343
+ // src/runtime/yield-to-event-loop.ts
21344
+ function yieldToEventLoop() {
21345
+ return new Promise((resolve35) => setImmediate(resolve35));
21346
+ }
21347
+ var init_yield_to_event_loop = __esm({
21348
+ "src/runtime/yield-to-event-loop.ts"() {
21349
+ "use strict";
21350
+ }
21351
+ });
21352
+
21302
21353
  // ../../node_modules/.pnpm/ignore@7.0.5/node_modules/ignore/index.js
21303
21354
  var require_ignore = __commonJS({
21304
21355
  "../../node_modules/.pnpm/ignore@7.0.5/node_modules/ignore/index.js"(exports, module) {
@@ -21596,7 +21647,7 @@ var require_ignore = __commonJS({
21596
21647
  // path matching.
21597
21648
  // - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
21598
21649
  // @returns {TestResult} true if a file is ignored
21599
- test(path79, checkUnignored, mode) {
21650
+ test(path82, checkUnignored, mode) {
21600
21651
  let ignored = false;
21601
21652
  let unignored = false;
21602
21653
  let matchedRule;
@@ -21605,7 +21656,7 @@ var require_ignore = __commonJS({
21605
21656
  if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
21606
21657
  return;
21607
21658
  }
21608
- const matched = rule[mode].test(path79);
21659
+ const matched = rule[mode].test(path82);
21609
21660
  if (!matched) {
21610
21661
  return;
21611
21662
  }
@@ -21626,17 +21677,17 @@ var require_ignore = __commonJS({
21626
21677
  var throwError = (message, Ctor) => {
21627
21678
  throw new Ctor(message);
21628
21679
  };
21629
- var checkPath = (path79, originalPath, doThrow) => {
21630
- if (!isString(path79)) {
21680
+ var checkPath = (path82, originalPath, doThrow) => {
21681
+ if (!isString(path82)) {
21631
21682
  return doThrow(
21632
21683
  `path must be a string, but got \`${originalPath}\``,
21633
21684
  TypeError
21634
21685
  );
21635
21686
  }
21636
- if (!path79) {
21687
+ if (!path82) {
21637
21688
  return doThrow(`path must not be empty`, TypeError);
21638
21689
  }
21639
- if (checkPath.isNotRelative(path79)) {
21690
+ if (checkPath.isNotRelative(path82)) {
21640
21691
  const r = "`path.relative()`d";
21641
21692
  return doThrow(
21642
21693
  `path should be a ${r} string, but got "${originalPath}"`,
@@ -21645,7 +21696,7 @@ var require_ignore = __commonJS({
21645
21696
  }
21646
21697
  return true;
21647
21698
  };
21648
- var isNotRelative = (path79) => REGEX_TEST_INVALID_PATH.test(path79);
21699
+ var isNotRelative = (path82) => REGEX_TEST_INVALID_PATH.test(path82);
21649
21700
  checkPath.isNotRelative = isNotRelative;
21650
21701
  checkPath.convert = (p) => p;
21651
21702
  var Ignore = class {
@@ -21675,19 +21726,19 @@ var require_ignore = __commonJS({
21675
21726
  }
21676
21727
  // @returns {TestResult}
21677
21728
  _test(originalPath, cache2, checkUnignored, slices) {
21678
- const path79 = originalPath && checkPath.convert(originalPath);
21729
+ const path82 = originalPath && checkPath.convert(originalPath);
21679
21730
  checkPath(
21680
- path79,
21731
+ path82,
21681
21732
  originalPath,
21682
21733
  this._strictPathCheck ? throwError : RETURN_FALSE
21683
21734
  );
21684
- return this._t(path79, cache2, checkUnignored, slices);
21735
+ return this._t(path82, cache2, checkUnignored, slices);
21685
21736
  }
21686
- checkIgnore(path79) {
21687
- if (!REGEX_TEST_TRAILING_SLASH.test(path79)) {
21688
- return this.test(path79);
21737
+ checkIgnore(path82) {
21738
+ if (!REGEX_TEST_TRAILING_SLASH.test(path82)) {
21739
+ return this.test(path82);
21689
21740
  }
21690
- const slices = path79.split(SLASH).filter(Boolean);
21741
+ const slices = path82.split(SLASH).filter(Boolean);
21691
21742
  slices.pop();
21692
21743
  if (slices.length) {
21693
21744
  const parent = this._t(
@@ -21700,18 +21751,18 @@ var require_ignore = __commonJS({
21700
21751
  return parent;
21701
21752
  }
21702
21753
  }
21703
- return this._rules.test(path79, false, MODE_CHECK_IGNORE);
21754
+ return this._rules.test(path82, false, MODE_CHECK_IGNORE);
21704
21755
  }
21705
- _t(path79, cache2, checkUnignored, slices) {
21706
- if (path79 in cache2) {
21707
- return cache2[path79];
21756
+ _t(path82, cache2, checkUnignored, slices) {
21757
+ if (path82 in cache2) {
21758
+ return cache2[path82];
21708
21759
  }
21709
21760
  if (!slices) {
21710
- slices = path79.split(SLASH).filter(Boolean);
21761
+ slices = path82.split(SLASH).filter(Boolean);
21711
21762
  }
21712
21763
  slices.pop();
21713
21764
  if (!slices.length) {
21714
- return cache2[path79] = this._rules.test(path79, checkUnignored, MODE_IGNORE);
21765
+ return cache2[path82] = this._rules.test(path82, checkUnignored, MODE_IGNORE);
21715
21766
  }
21716
21767
  const parent = this._t(
21717
21768
  slices.join(SLASH) + SLASH,
@@ -21719,29 +21770,29 @@ var require_ignore = __commonJS({
21719
21770
  checkUnignored,
21720
21771
  slices
21721
21772
  );
21722
- return cache2[path79] = parent.ignored ? parent : this._rules.test(path79, checkUnignored, MODE_IGNORE);
21773
+ return cache2[path82] = parent.ignored ? parent : this._rules.test(path82, checkUnignored, MODE_IGNORE);
21723
21774
  }
21724
- ignores(path79) {
21725
- return this._test(path79, this._ignoreCache, false).ignored;
21775
+ ignores(path82) {
21776
+ return this._test(path82, this._ignoreCache, false).ignored;
21726
21777
  }
21727
21778
  createFilter() {
21728
- return (path79) => !this.ignores(path79);
21779
+ return (path82) => !this.ignores(path82);
21729
21780
  }
21730
21781
  filter(paths) {
21731
21782
  return makeArray(paths).filter(this.createFilter());
21732
21783
  }
21733
21784
  // @returns {TestResult}
21734
- test(path79) {
21735
- return this._test(path79, this._testCache, true);
21785
+ test(path82) {
21786
+ return this._test(path82, this._testCache, true);
21736
21787
  }
21737
21788
  };
21738
21789
  var factory = (options) => new Ignore(options);
21739
- var isPathValid = (path79) => checkPath(path79 && checkPath.convert(path79), path79, RETURN_FALSE);
21790
+ var isPathValid = (path82) => checkPath(path82 && checkPath.convert(path82), path82, RETURN_FALSE);
21740
21791
  var setupWindows = () => {
21741
21792
  const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
21742
21793
  checkPath.convert = makePosix;
21743
21794
  const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
21744
- checkPath.isNotRelative = (path79) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path79) || isNotRelative(path79);
21795
+ checkPath.isNotRelative = (path82) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path82) || isNotRelative(path82);
21745
21796
  };
21746
21797
  if (
21747
21798
  // Detect `process` so that it can run in browsers.
@@ -22530,10 +22581,10 @@ var require_src2 = __commonJS({
22530
22581
  var fs_1 = __require("fs");
22531
22582
  var debug_1 = __importDefault(require_src());
22532
22583
  var log2 = debug_1.default("@kwsites/file-exists");
22533
- function check2(path79, isFile, isDirectory) {
22534
- log2(`checking %s`, path79);
22584
+ function check2(path82, isFile, isDirectory) {
22585
+ log2(`checking %s`, path82);
22535
22586
  try {
22536
- const stat2 = fs_1.statSync(path79);
22587
+ const stat2 = fs_1.statSync(path82);
22537
22588
  if (stat2.isFile() && isFile) {
22538
22589
  log2(`[OK] path represents a file`);
22539
22590
  return true;
@@ -22553,8 +22604,8 @@ var require_src2 = __commonJS({
22553
22604
  throw e;
22554
22605
  }
22555
22606
  }
22556
- function exists2(path79, type = exports.READABLE) {
22557
- return check2(path79, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
22607
+ function exists2(path82, type = exports.READABLE) {
22608
+ return check2(path82, (type & exports.FILE) > 0, (type & exports.FOLDER) > 0);
22558
22609
  }
22559
22610
  exports.exists = exists2;
22560
22611
  exports.FILE = 1;
@@ -22617,6 +22668,112 @@ var require_dist2 = __commonJS({
22617
22668
  }
22618
22669
  });
22619
22670
 
22671
+ // src/files/ensure-under-cwd.ts
22672
+ import path73 from "node:path";
22673
+ function ensureUnderCwd(relativePath, cwd = getBridgeRoot()) {
22674
+ const normalized = path73.normalize(relativePath).replace(/^(\.\/)+/, "");
22675
+ const resolved = path73.resolve(cwd, normalized);
22676
+ if (!resolved.startsWith(cwd + path73.sep) && resolved !== cwd) {
22677
+ return null;
22678
+ }
22679
+ return resolved;
22680
+ }
22681
+ var init_ensure_under_cwd = __esm({
22682
+ "src/files/ensure-under-cwd.ts"() {
22683
+ "use strict";
22684
+ init_cwd();
22685
+ }
22686
+ });
22687
+
22688
+ // src/files/list-dir/types.ts
22689
+ var LIST_DIR_YIELD_EVERY;
22690
+ var init_types2 = __esm({
22691
+ "src/files/list-dir/types.ts"() {
22692
+ "use strict";
22693
+ LIST_DIR_YIELD_EVERY = 256;
22694
+ }
22695
+ });
22696
+
22697
+ // src/files/list-dir/map-dir-entry.ts
22698
+ import path74 from "node:path";
22699
+ import fs47 from "node:fs";
22700
+ async function mapDirEntry(d, relativePath, resolved) {
22701
+ const entryPath = path74.join(relativePath || ".", d.name).replace(/\\/g, "/");
22702
+ const fullPath = path74.join(resolved, d.name);
22703
+ let isDir = d.isDirectory();
22704
+ if (d.isSymbolicLink()) {
22705
+ try {
22706
+ const targetStat = await fs47.promises.stat(fullPath);
22707
+ isDir = targetStat.isDirectory();
22708
+ } catch {
22709
+ isDir = false;
22710
+ }
22711
+ }
22712
+ return {
22713
+ name: d.name,
22714
+ path: entryPath,
22715
+ isDir,
22716
+ isSymlink: d.isSymbolicLink()
22717
+ };
22718
+ }
22719
+ var init_map_dir_entry = __esm({
22720
+ "src/files/list-dir/map-dir-entry.ts"() {
22721
+ "use strict";
22722
+ }
22723
+ });
22724
+
22725
+ // src/files/list-dir/sort-entries.ts
22726
+ function sortListEntries(entries) {
22727
+ return entries.sort((a, b) => {
22728
+ if (a.isDir !== b.isDir) return a.isDir ? -1 : 1;
22729
+ return a.name.localeCompare(b.name, void 0, { sensitivity: "base" });
22730
+ });
22731
+ }
22732
+ var init_sort_entries = __esm({
22733
+ "src/files/list-dir/sort-entries.ts"() {
22734
+ "use strict";
22735
+ }
22736
+ });
22737
+
22738
+ // src/files/list-dir/index.ts
22739
+ var list_dir_exports = {};
22740
+ __export(list_dir_exports, {
22741
+ listDirAsync: () => listDirAsync
22742
+ });
22743
+ import fs48 from "node:fs";
22744
+ async function listDirAsync(relativePath, sessionParentPath = getBridgeRoot()) {
22745
+ await yieldToEventLoop();
22746
+ const resolved = ensureUnderCwd(relativePath || ".", sessionParentPath);
22747
+ if (!resolved) {
22748
+ return { error: "Path is outside working directory" };
22749
+ }
22750
+ try {
22751
+ const names = await fs48.promises.readdir(resolved, { withFileTypes: true });
22752
+ const entries = [];
22753
+ for (let i = 0; i < names.length; i++) {
22754
+ if (i > 0 && i % LIST_DIR_YIELD_EVERY === 0) {
22755
+ await yieldToEventLoop();
22756
+ }
22757
+ entries.push(await mapDirEntry(names[i], relativePath, resolved));
22758
+ }
22759
+ return { entries: sortListEntries(entries) };
22760
+ } catch (err) {
22761
+ const message = err instanceof Error ? err.message : String(err);
22762
+ return { error: message };
22763
+ }
22764
+ }
22765
+ var init_list_dir = __esm({
22766
+ "src/files/list-dir/index.ts"() {
22767
+ "use strict";
22768
+ init_ensure_under_cwd();
22769
+ init_cwd();
22770
+ init_yield_to_event_loop();
22771
+ init_types2();
22772
+ init_map_dir_entry();
22773
+ init_sort_entries();
22774
+ }
22775
+ });
22776
+
22620
22777
  // ../../node_modules/.pnpm/ws@8.19.0/node_modules/ws/wrapper.mjs
22621
22778
  var import_stream = __toESM(require_stream(), 1);
22622
22779
  var import_receiver = __toESM(require_receiver(), 1);
@@ -22787,26 +22944,8 @@ function sendWsMessage(ws, payload) {
22787
22944
  }
22788
22945
  }
22789
22946
 
22790
- // src/paths/normalize-resolved-path.ts
22791
- import fs from "node:fs";
22792
- import path from "node:path";
22793
- function normalizeResolvedPath(resolved) {
22794
- const abs = path.resolve(resolved);
22795
- try {
22796
- return fs.realpathSync.native(abs);
22797
- } catch {
22798
- return abs;
22799
- }
22800
- }
22801
-
22802
- // src/files/cwd/bridge-root.ts
22803
- var bridgeRootPath = null;
22804
- function getBridgeRoot() {
22805
- if (bridgeRootPath == null) {
22806
- bridgeRootPath = normalizeResolvedPath(process.cwd());
22807
- }
22808
- return bridgeRootPath;
22809
- }
22947
+ // src/agents/acp/clients/sdk/sdk-stdio-acp-client.ts
22948
+ init_cwd();
22810
22949
 
22811
22950
  // src/agents/acp/clients/agent-stderr-capture.ts
22812
22951
  var STDERR_CAPTURE_MAX = 48e3;
@@ -23514,7 +23653,6 @@ var StoryCheckpointSummarySchema = CheckpointSummarySchema.extend({
23514
23653
 
23515
23654
  // ../types/src/sessions.ts
23516
23655
  init_zod();
23517
- var BUILTIN_SESSION_CHANGE_SUMMARY_FOLLOW_UP_CATALOG_PROMPT_ID = "__builtin_change_summary__";
23518
23656
  var SessionMetaSchema = external_exports.object({
23519
23657
  sessionId: external_exports.string(),
23520
23658
  workspaceId: external_exports.string(),
@@ -23647,146 +23785,6 @@ function buildPlanningSessionFollowUpAgentPrompt(userPrompt, existingTodos) {
23647
23785
  ].join("\n");
23648
23786
  }
23649
23787
 
23650
- // ../types/src/change-summary-path.ts
23651
- function normalizeRepoRelativePath(p) {
23652
- let t = p.trim().replace(/\\/g, "/");
23653
- while (t.startsWith("./")) t = t.slice(2);
23654
- return t.replace(/\/+/g, "/");
23655
- }
23656
- function resolveChangeSummaryPathAgainstAllowed(rawPath, allowed) {
23657
- const trimmed2 = rawPath.trim();
23658
- if (!trimmed2) return null;
23659
- if (allowed.has(trimmed2)) return trimmed2;
23660
- const n = normalizeRepoRelativePath(trimmed2);
23661
- if (allowed.has(n)) return n;
23662
- for (const a of allowed) {
23663
- if (normalizeRepoRelativePath(a) === n) return a;
23664
- }
23665
- return null;
23666
- }
23667
-
23668
- // ../types/src/parse-change-summary-json.ts
23669
- function clampSummaryToAtMostTwoLines(summary) {
23670
- const lines = summary.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0);
23671
- return lines.slice(0, 2).join("\n");
23672
- }
23673
- function parseChangeSummaryJson(raw, allowedPaths, options) {
23674
- if (raw == null || raw.trim() === "") return [];
23675
- let text = raw.trim();
23676
- const fence = text.match(/```(?:json)?\s*([\s\S]*?)```/i);
23677
- if (fence?.[1]) text = fence[1].trim();
23678
- let parsed;
23679
- try {
23680
- parsed = JSON.parse(text);
23681
- } catch {
23682
- const start = text.indexOf("[");
23683
- const end = text.lastIndexOf("]");
23684
- if (start < 0 || end <= start) return [];
23685
- try {
23686
- parsed = JSON.parse(text.slice(start, end + 1));
23687
- } catch {
23688
- return [];
23689
- }
23690
- }
23691
- const rows = [];
23692
- let arr = [];
23693
- if (Array.isArray(parsed)) {
23694
- arr = parsed;
23695
- } else if (parsed && typeof parsed === "object" && Array.isArray(parsed.files)) {
23696
- arr = parsed.files;
23697
- }
23698
- const skip = options?.skipPathAllowlist === true;
23699
- for (const item of arr) {
23700
- if (!item || typeof item !== "object") continue;
23701
- const o = item;
23702
- const rawPath = typeof o.path === "string" ? o.path.trim() : "";
23703
- const summary = typeof o.summary === "string" ? o.summary.trim() : "";
23704
- if (!rawPath || !summary) continue;
23705
- const path79 = skip ? normalizeRepoRelativePath(rawPath) || rawPath : resolveChangeSummaryPathAgainstAllowed(rawPath, allowedPaths);
23706
- if (!path79) continue;
23707
- rows.push({ path: path79, summary: clampSummaryToAtMostTwoLines(summary) });
23708
- }
23709
- return rows;
23710
- }
23711
-
23712
- // ../types/src/build-change-summary-prompt.ts
23713
- var PATCH_PREVIEW_MAX = 12e3;
23714
- function clip(s, max) {
23715
- if (s.length <= max) return s;
23716
- return `${s.slice(0, max)}
23717
-
23718
- \u2026(truncated, ${s.length - max} more characters)`;
23719
- }
23720
- function buildSessionChangeSummaryPrompt(files) {
23721
- const lines = [
23722
- "You are the same agent that produced the changes below. Summarize **your own** edits so a reader can scan them quickly.",
23723
- "",
23724
- "Write in second person (you / your): what you changed in each path and why it matters.",
23725
- "",
23726
- "Each summary must be **very concise**: **one line** of plain text, or **at most two short lines** (use a single line break between the two if needed). No bullets, no paragraphs.",
23727
- "",
23728
- "## How to format your reply (machine parsing)",
23729
- "",
23730
- "- Put the machine-readable part **only** inside a **markdown fenced code block** whose opening fence is exactly ```json on its own line. Close the block with ``` on its own line after the JSON.",
23731
- "- Inside that fence: **nothing except** one valid JSON value \u2014 the array described below. No trailing commentary inside the fence.",
23732
- "- **Do not** attach prose to the JSON on the same line (wrong: `Only one file\u2026page.tsx.[{\u2026}]`). Wrong: any sentence that ends with `.` immediately before `[`. Put a blank line before the ```json line.",
23733
- "- If you add optional plain English before the fence (e.g. one short sentence), keep it **separate**: end that sentence, blank line, then ```json.",
23734
- '- In each `"summary"` string, avoid raw double-quote characters, or escape them as `\\"` so the JSON parses.',
23735
- "",
23736
- "JSON shape **inside the fence** (array only):",
23737
- '[{"path":"<file path exactly as given>","summary":"<one line, or two short lines separated by \\n>"}]',
23738
- "",
23739
- "Rules:",
23740
- "- Include **exactly one** object per file path listed below (same path strings).",
23741
- "- If a path is a removed directory, state briefly what you removed.",
23742
- "- Do not invent paths; use only the paths provided.",
23743
- "",
23744
- "## Files you changed",
23745
- ""
23746
- ];
23747
- for (const f of files) {
23748
- lines.push(`### ${f.path}`);
23749
- if (f.directoryRemoved) {
23750
- lines.push("(directory removed)");
23751
- lines.push("");
23752
- continue;
23753
- }
23754
- if (f.patchContent && f.patchContent.trim() !== "") {
23755
- lines.push("```diff");
23756
- lines.push(clip(f.patchContent.trim(), PATCH_PREVIEW_MAX));
23757
- lines.push("```");
23758
- } else if (f.oldText != null || f.newText != null) {
23759
- const oldT = (f.oldText ?? "").trim();
23760
- const newT = (f.newText ?? "").trim();
23761
- lines.push("Previous snippet:", clip(oldT, 6e3));
23762
- lines.push("New snippet:", clip(newT, 6e3));
23763
- } else {
23764
- lines.push("(no diff body stored for this path)");
23765
- }
23766
- lines.push("");
23767
- }
23768
- return lines.join("\n");
23769
- }
23770
-
23771
- // ../types/src/dedupe-session-file-changes-by-path.ts
23772
- function defaultRichness(c) {
23773
- const patch = typeof c.patchContent === "string" ? c.patchContent.length : 0;
23774
- const nt = typeof c.newText === "string" ? c.newText.length : 0;
23775
- const ot = typeof c.oldText === "string" ? c.oldText.length : 0;
23776
- const dir = c.directoryRemoved === true ? 8 : 0;
23777
- return (patch > 0 ? 4 : 0) + (nt > 0 ? 2 : 0) + (ot > 0 ? 1 : 0) + dir;
23778
- }
23779
- function dedupeSessionFileChangesByPath(items, richness = (item) => defaultRichness(item)) {
23780
- const byPath = /* @__PURE__ */ new Map();
23781
- for (const item of items) {
23782
- const p = typeof item.path === "string" ? item.path.trim() : "";
23783
- if (!p) continue;
23784
- const prev = byPath.get(p);
23785
- if (!prev || richness(item) >= richness(prev)) byPath.set(p, item);
23786
- }
23787
- return Array.from(byPath.entries()).sort(([a], [b]) => a.localeCompare(b)).map(([, v]) => v);
23788
- }
23789
-
23790
23788
  // ../types/src/diff/line-diff.ts
23791
23789
  function normalizeDiffLineText(line) {
23792
23790
  return line.replace(/\r$/, "").replace(/\s*\\s*$/, "");
@@ -24175,11 +24173,11 @@ function createSdkStdioExtNotificationHandler(options) {
24175
24173
 
24176
24174
  // src/agents/acp/clients/sdk/sdk-stdio-permission-request-handshake.ts
24177
24175
  function awaitSdkStdioPermissionRequestHandshake(params) {
24178
- const { requestId, paramsRecord, pending: pending2, onRequest } = params;
24176
+ const { requestId, paramsRecord, pending, onRequest } = params;
24179
24177
  return new Promise((resolve35) => {
24180
- pending2.set(requestId, { resolve: resolve35, params: paramsRecord });
24178
+ pending.set(requestId, { resolve: resolve35, params: paramsRecord });
24181
24179
  if (onRequest == null) {
24182
- pending2.delete(requestId);
24180
+ pending.delete(requestId);
24183
24181
  resolve35({ outcome: { outcome: "denied" } });
24184
24182
  return;
24185
24183
  }
@@ -24195,9 +24193,9 @@ function awaitSdkStdioPermissionRequestHandshake(params) {
24195
24193
  }
24196
24194
 
24197
24195
  // src/agents/acp/clients/sdk/sdk-stdio-permission-pending.ts
24198
- function resolvePendingSdkStdioPermissionCancellations(pending2) {
24199
- for (const [id, entry] of [...pending2.entries()]) {
24200
- pending2.delete(id);
24196
+ function resolvePendingSdkStdioPermissionCancellations(pending) {
24197
+ for (const [id, entry] of [...pending.entries()]) {
24198
+ pending.delete(id);
24201
24199
  entry.resolve({ outcome: { outcome: "cancelled" } });
24202
24200
  }
24203
24201
  }
@@ -25079,6 +25077,7 @@ async function proxyToLocalStreaming(request, callbacks) {
25079
25077
  }
25080
25078
 
25081
25079
  // src/skills/preview.ts
25080
+ init_cwd();
25082
25081
  import { spawn as spawn2 } from "node:child_process";
25083
25082
  var PREVIEW_API_BASE_PATH = "/__preview";
25084
25083
  var PREVIEW_SECRET_HEADER = "X-Preview-Secret";
@@ -25099,8 +25098,8 @@ function randomSecret() {
25099
25098
  }
25100
25099
  return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
25101
25100
  }
25102
- async function requestPreviewApi(port, secret, method, path79, body) {
25103
- const url2 = `http://127.0.0.1:${port}${path79}`;
25101
+ async function requestPreviewApi(port, secret, method, path82, body) {
25102
+ const url2 = `http://127.0.0.1:${port}${path82}`;
25104
25103
  const headers = {
25105
25104
  [PREVIEW_SECRET_HEADER]: secret,
25106
25105
  "Content-Type": "application/json"
@@ -25112,7 +25111,7 @@ async function requestPreviewApi(port, secret, method, path79, body) {
25112
25111
  });
25113
25112
  const data = await res.json().catch(() => ({}));
25114
25113
  if (!res.ok) {
25115
- throw new Error(data?.error ?? `Preview API ${method} ${path79}: ${res.status}`);
25114
+ throw new Error(data?.error ?? `Preview API ${method} ${path82}: ${res.status}`);
25116
25115
  }
25117
25116
  return data;
25118
25117
  }
@@ -25327,7 +25326,7 @@ function installBridgeProcessResilience() {
25327
25326
  }
25328
25327
 
25329
25328
  // src/cli-version.ts
25330
- var CLI_VERSION = "0.1.62".length > 0 ? "0.1.62" : "0.0.0-dev";
25329
+ var CLI_VERSION = "0.1.64".length > 0 ? "0.1.64" : "0.0.0-dev";
25331
25330
 
25332
25331
  // src/connection/heartbeat/constants.ts
25333
25332
  var BRIDGE_APP_HEARTBEAT_INTERVAL_MS = 1e4;
@@ -26442,7 +26441,11 @@ function runPendingAuth(options) {
26442
26441
  };
26443
26442
  }
26444
26443
 
26444
+ // src/connection/create-bridge-connection.ts
26445
+ init_cwd();
26446
+
26445
26447
  // src/files/watch-file-index.ts
26448
+ init_cwd();
26446
26449
  import path25 from "node:path";
26447
26450
 
26448
26451
  // src/files/index/paths.ts
@@ -26452,7 +26455,7 @@ import crypto2 from "node:crypto";
26452
26455
  // src/files/index/constants.ts
26453
26456
  import path5 from "node:path";
26454
26457
  import os3 from "node:os";
26455
- var INDEX_WORK_YIELD_EVERY = 256;
26458
+ var INDEX_WORK_YIELD_EVERY = 128;
26456
26459
  var INDEX_DIR = path5.join(os3.homedir(), ".buildautomaton");
26457
26460
  var INDEX_HASH_LEN = 16;
26458
26461
 
@@ -26464,9 +26467,78 @@ function getCwdHashForFileIndex(resolvedCwd) {
26464
26467
  // src/files/index/build-file-index.ts
26465
26468
  import path15 from "node:path";
26466
26469
 
26467
- // src/runtime/yield-to-event-loop.ts
26468
- function yieldToEventLoop() {
26469
- return new Promise((resolve35) => setImmediate(resolve35));
26470
+ // src/files/browser/file-browser-in-flight.ts
26471
+ init_yield_to_event_loop();
26472
+
26473
+ // src/code-nav/symbol-index/deferred-indexing.ts
26474
+ var SymbolIndexDeferredError = class extends Error {
26475
+ constructor() {
26476
+ super("Symbol indexing deferred for file browser");
26477
+ this.name = "SymbolIndexDeferredError";
26478
+ }
26479
+ };
26480
+ function isSymbolIndexDeferredError(err) {
26481
+ return err instanceof SymbolIndexDeferredError;
26482
+ }
26483
+
26484
+ // src/files/browser/file-browser-in-flight.ts
26485
+ var BROWSE_INDEX_COOLDOWN_MS = 2500;
26486
+ var inFlightFileBrowserRequests = 0;
26487
+ var lastBrowseActivityAt = 0;
26488
+ var activityListeners = /* @__PURE__ */ new Set();
26489
+ var requestStartListeners = /* @__PURE__ */ new Set();
26490
+ function touchBrowseActivity() {
26491
+ lastBrowseActivityAt = Date.now();
26492
+ }
26493
+ function registerFileBrowserActivityListener(listener) {
26494
+ activityListeners.add(listener);
26495
+ return () => {
26496
+ activityListeners.delete(listener);
26497
+ };
26498
+ }
26499
+ function registerFileBrowserRequestStartListener(listener) {
26500
+ requestStartListeners.add(listener);
26501
+ return () => {
26502
+ requestStartListeners.delete(listener);
26503
+ };
26504
+ }
26505
+ function notifyFileBrowserActivity() {
26506
+ for (const listener of activityListeners) listener();
26507
+ }
26508
+ function notifyFileBrowserRequestStart() {
26509
+ for (const listener of requestStartListeners) listener();
26510
+ }
26511
+ function beginFileBrowserRequest() {
26512
+ inFlightFileBrowserRequests += 1;
26513
+ touchBrowseActivity();
26514
+ notifyFileBrowserRequestStart();
26515
+ notifyFileBrowserActivity();
26516
+ }
26517
+ function endFileBrowserRequest() {
26518
+ inFlightFileBrowserRequests = Math.max(0, inFlightFileBrowserRequests - 1);
26519
+ touchBrowseActivity();
26520
+ }
26521
+ function fileBrowserRequestInFlight() {
26522
+ return inFlightFileBrowserRequests > 0;
26523
+ }
26524
+ function isBridgeBrowseInteractiveActive() {
26525
+ if (fileBrowserRequestInFlight()) return true;
26526
+ return Date.now() - lastBrowseActivityAt < BROWSE_INDEX_COOLDOWN_MS;
26527
+ }
26528
+ function assertBackgroundIndexingAllowed() {
26529
+ if (isBridgeBrowseInteractiveActive()) throw new SymbolIndexDeferredError();
26530
+ }
26531
+ async function yieldUntilFileBrowserIdle(pollMs = 5) {
26532
+ while (isBridgeBrowseInteractiveActive()) {
26533
+ await yieldToEventLoop();
26534
+ if (isBridgeBrowseInteractiveActive()) {
26535
+ await new Promise((resolve35) => setTimeout(resolve35, pollMs));
26536
+ }
26537
+ }
26538
+ }
26539
+ async function yieldForBridgeInteractivePriority() {
26540
+ await yieldToEventLoop();
26541
+ await yieldUntilFileBrowserIdle();
26470
26542
  }
26471
26543
 
26472
26544
  // src/runtime/cli-process-interrupt.ts
@@ -26489,7 +26561,11 @@ async function delayMsUnlessShutdownRequested(ms) {
26489
26561
  return !isCliImmediateShutdownRequested();
26490
26562
  }
26491
26563
 
26564
+ // src/sqlite/code-nav-cache/code-nav-cache-database.ts
26565
+ init_yield_to_event_loop();
26566
+
26492
26567
  // src/sqlite/create-sqlite-database-access.ts
26568
+ init_yield_to_event_loop();
26493
26569
  import sqliteWasm from "node-sqlite3-wasm";
26494
26570
 
26495
26571
  // src/sqlite/sqlite-errors.ts
@@ -26534,6 +26610,7 @@ function applySqliteMemoryPragmas(db) {
26534
26610
  }
26535
26611
 
26536
26612
  // src/sqlite/sqlite-lock-retry.ts
26613
+ init_yield_to_event_loop();
26537
26614
  var SYNC_RETRY_MAX = 40;
26538
26615
  var ASYNC_RETRY_MAX = 60;
26539
26616
  var ASYNC_BASE_DELAY_MS = 20;
@@ -26695,7 +26772,7 @@ function readMigrationSql(filename, ...searchSubdirs) {
26695
26772
  join(moduleDir, "..", sub, filename),
26696
26773
  join(moduleDir, "..", "..", "dist", sub, filename)
26697
26774
  ]);
26698
- const resolved = candidates.find((path79) => existsSync(path79));
26775
+ const resolved = candidates.find((path82) => existsSync(path82));
26699
26776
  if (!resolved) {
26700
26777
  throw new Error(`Missing SQLite migration SQL: ${filename} (searched ${searchSubdirs.join(", ")})`);
26701
26778
  }
@@ -27084,14 +27161,14 @@ function legacyCliDiskMigrationIsPending() {
27084
27161
  return false;
27085
27162
  }
27086
27163
  function importCliSqliteLegacyDiskData(db, log2) {
27087
- const pending2 = legacyCliDiskMigrationIsPending();
27088
- if (pending2 && log2) {
27164
+ const pending = legacyCliDiskMigrationIsPending();
27165
+ if (pending && log2) {
27089
27166
  log2("Migrating legacy on-disk CLI data to SQLite\u2026");
27090
27167
  }
27091
27168
  archiveLegacyFileIndexJsonFiles();
27092
27169
  importLegacyAgentSessionsFromDisk(db);
27093
27170
  importLegacyPromptQueuesFromDisk(db);
27094
- if (pending2 && log2) {
27171
+ if (pending && log2) {
27095
27172
  log2("Legacy on-disk CLI data migration finished.");
27096
27173
  }
27097
27174
  }
@@ -27200,7 +27277,7 @@ async function walkWorkspaceTreeAsync(dir, baseDir, onFile, state) {
27200
27277
  if (shouldSkipWorkspaceWalkEntry(name)) continue;
27201
27278
  if (state.n > 0 && state.n % INDEX_WORK_YIELD_EVERY === 0) {
27202
27279
  if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();
27203
- await yieldToEventLoop();
27280
+ await yieldForBridgeInteractivePriority();
27204
27281
  if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();
27205
27282
  }
27206
27283
  state.n++;
@@ -27307,7 +27384,7 @@ async function persistFileIndexPathsAsync(resolved, paths) {
27307
27384
  assertFileIndexPersistNotShutdown();
27308
27385
  const batch = paths.slice(offset, offset + FILE_INDEX_INSERT_BUFFER);
27309
27386
  pathCount += await withCodeNavCacheSqlite((db) => insertFileIndexChildPathBatch(db, resolved, batch));
27310
- await yieldToEventLoop();
27387
+ await yieldForBridgeInteractivePriority();
27311
27388
  }
27312
27389
  return pathCount;
27313
27390
  }
@@ -27318,10 +27395,10 @@ function assertNotShutdown2() {
27318
27395
  }
27319
27396
  async function buildFileIndexAsync(cwd) {
27320
27397
  const resolved = path15.resolve(cwd);
27321
- await yieldToEventLoop();
27398
+ await yieldForBridgeInteractivePriority();
27322
27399
  assertNotShutdown2();
27323
27400
  const paths = await collectWorkspacePathsAsync(resolved);
27324
- await yieldToEventLoop();
27401
+ await yieldForBridgeInteractivePriority();
27325
27402
  assertNotShutdown2();
27326
27403
  return await withFileIndexSqliteLock(async () => {
27327
27404
  const pathCount = await persistFileIndexPathsAsync(resolved, paths);
@@ -27333,6 +27410,7 @@ async function buildFileIndexAsync(cwd) {
27333
27410
  import path16 from "node:path";
27334
27411
 
27335
27412
  // src/files/index/search-file-index.ts
27413
+ init_yield_to_event_loop();
27336
27414
  function escapeLikePattern(fragment) {
27337
27415
  return fragment.replace(/\\/g, "\\\\").replace(/%/g, "\\%").replace(/_/g, "\\_");
27338
27416
  }
@@ -27389,8 +27467,11 @@ async function ensureFileIndexAsync(cwd) {
27389
27467
  return { ...await buildFileIndexAsync(resolved), fromCache: false };
27390
27468
  }
27391
27469
 
27470
+ // src/code-nav/symbol-index/build/build-symbol-index.ts
27471
+ init_normalize_resolved_path();
27472
+
27392
27473
  // src/code-nav/yield-during-work.ts
27393
- var CODE_NAV_YIELD_EVERY = INDEX_WORK_YIELD_EVERY;
27474
+ var CODE_NAV_YIELD_EVERY = 64;
27394
27475
  function createCodeNavYieldState() {
27395
27476
  return { n: 0 };
27396
27477
  }
@@ -27398,7 +27479,7 @@ async function yieldDuringCodeNavWork(state) {
27398
27479
  state.n++;
27399
27480
  if (state.n % CODE_NAV_YIELD_EVERY !== 0) return;
27400
27481
  if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();
27401
- await yieldToEventLoop();
27482
+ await yieldForBridgeInteractivePriority();
27402
27483
  if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();
27403
27484
  }
27404
27485
 
@@ -27531,7 +27612,7 @@ async function walkCodeNavFilesInDirectory(dir, baseDir, relDir, filter, onFile,
27531
27612
  if (shouldSkipWorkspaceWalkEntry(name)) continue;
27532
27613
  if (state.n > 0 && state.n % INDEX_WORK_YIELD_EVERY === 0) {
27533
27614
  if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();
27534
- await yieldToEventLoop();
27615
+ await yieldForBridgeInteractivePriority();
27535
27616
  if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();
27536
27617
  }
27537
27618
  state.n++;
@@ -27565,6 +27646,8 @@ async function walkCodeNavFilesAsync(rootDir, onFile, state = createWalkYieldSta
27565
27646
  var SYMBOL_INDEX_VERSION = 11;
27566
27647
 
27567
27648
  // src/code-nav/symbol-index/sqlite/parent-path.ts
27649
+ init_bridge_root();
27650
+ init_normalize_resolved_path();
27568
27651
  function normalizeParentPath(resolved) {
27569
27652
  return normalizeResolvedPath(resolved);
27570
27653
  }
@@ -27859,128 +27942,11 @@ function withSymbolIndexSqliteLock(fn) {
27859
27942
  return withCodeNavCacheSqliteWorkLock(fn);
27860
27943
  }
27861
27944
 
27862
- // src/code-nav/symbol-index/imports/star-reexport-names.ts
27863
- var STAR_LOCAL_NAME = "*";
27864
- function isModuleLevelDef(tag) {
27865
- return tag.role === "def" && tag.parentScopeStartLine == null && tag.parentScopeStartColumn == null;
27866
- }
27867
- function collectExportableNamesFromTags(tags) {
27868
- const names = /* @__PURE__ */ new Map();
27869
- for (const tag of tags) {
27870
- if (!isModuleLevelDef(tag)) continue;
27871
- if (!names.has(tag.name)) names.set(tag.name, tag.name);
27872
- }
27873
- return names;
27874
- }
27875
- function existingLocalNames(imports) {
27876
- return new Set(imports.map((binding) => binding.localName));
27877
- }
27878
- function resolveExportableNames(filePath, entriesByPath, visited) {
27879
- if (visited.has(filePath)) return /* @__PURE__ */ new Map();
27880
- visited.add(filePath);
27881
- const entry = entriesByPath.get(filePath);
27882
- if (!entry) return /* @__PURE__ */ new Map();
27883
- const out = collectExportableNamesFromTags(entry.tags);
27884
- const resolved = /* @__PURE__ */ new Map();
27885
- for (const [name, sourceName] of out) {
27886
- resolved.set(name, { sourceName, sourceFilePath: filePath });
27887
- }
27888
- for (const binding of entry.imports) {
27889
- if (binding.importKind !== "star" || !binding.sourceFilePath) continue;
27890
- const upstream = resolveExportableNames(binding.sourceFilePath, entriesByPath, visited);
27891
- for (const [name, info] of upstream) {
27892
- if (!resolved.has(name)) resolved.set(name, info);
27893
- }
27894
- }
27895
- for (const binding of entry.imports) {
27896
- if (binding.importKind !== "reexport" && binding.importKind !== "type") continue;
27897
- if (!binding.sourceFilePath) continue;
27898
- if (!resolved.has(binding.localName)) {
27899
- resolved.set(binding.localName, {
27900
- sourceName: binding.sourceName,
27901
- sourceFilePath: binding.sourceFilePath
27902
- });
27903
- }
27904
- }
27905
- return resolved;
27906
- }
27907
-
27908
- // src/code-nav/symbol-index/imports/star-reexport-upstream.ts
27909
- function collectUpstreamEntries(entry, resolveEntry) {
27910
- const entriesByPath = /* @__PURE__ */ new Map();
27911
- entriesByPath.set(entry.relPath, entry);
27912
- const visit = (filePath, visited) => {
27913
- if (visited.has(filePath)) return;
27914
- visited.add(filePath);
27915
- const resolved = resolveEntry(filePath);
27916
- if (resolved == null) return;
27917
- entriesByPath.set(filePath, resolved);
27918
- for (const binding of resolved.imports) {
27919
- if (binding.sourceFilePath) visit(binding.sourceFilePath, visited);
27920
- }
27921
- };
27922
- for (const star of entry.imports) {
27923
- if (star.importKind !== "star" || !star.sourceFilePath) continue;
27924
- visit(star.sourceFilePath, /* @__PURE__ */ new Set());
27925
- }
27926
- return [...entriesByPath.values()];
27927
- }
27928
-
27929
- // src/code-nav/symbol-index/imports/expand-star-reexports.ts
27930
- function expandStarReexportForFile(entry, resolveEntry) {
27931
- const collected = collectUpstreamEntries(entry, resolveEntry);
27932
- return expandStarReexportBindings(collected).find((row) => row.relPath === entry.relPath) ?? entry;
27933
- }
27934
- function expandStarReexportBindings(collected) {
27935
- const entriesByPath = new Map(collected.map((entry) => [entry.relPath, entry]));
27936
- return collected.map((entry) => {
27937
- const stars = entry.imports.filter((binding) => binding.importKind === "star");
27938
- if (stars.length === 0) return entry;
27939
- const localNames = existingLocalNames(entry.imports);
27940
- const materialized = [];
27941
- for (const star of stars) {
27942
- if (!star.sourceFilePath) continue;
27943
- const exportable = resolveExportableNames(star.sourceFilePath, entriesByPath, /* @__PURE__ */ new Set());
27944
- for (const [localName, info] of exportable) {
27945
- if (localName === STAR_LOCAL_NAME || localNames.has(localName)) continue;
27946
- localNames.add(localName);
27947
- materialized.push({
27948
- localName,
27949
- sourceName: info.sourceName,
27950
- moduleSpecifier: star.moduleSpecifier,
27951
- sourceFilePath: info.sourceFilePath,
27952
- importKind: star.importKind === "type" ? "type" : "reexport",
27953
- startLine: star.startLine,
27954
- startColumn: star.startColumn
27955
- });
27956
- }
27957
- }
27958
- if (materialized.length === 0) return entry;
27959
- return { ...entry, imports: [...entry.imports, ...materialized] };
27960
- });
27961
- }
27945
+ // src/code-nav/symbol-index/build/ensure-symbol-index-file.ts
27946
+ init_normalize_resolved_path();
27962
27947
 
27963
- // src/code-nav/symbol-index/persistence/persist-single-file.ts
27964
- async function persistSymbolIndexFileAsync(resolved, relPath, source, tags, imports) {
27965
- await withCodeNavCacheSqlite(async (db) => {
27966
- runCodeNavCacheWriteTransaction(db, () => {
27967
- upsertSymbolIndexParentPath(db, resolved);
27968
- const ctx = getSymbolIndexParentContext(db, resolved);
27969
- if (ctx == null) throw new Error(`Failed to resolve symbol index parent: ${resolved}`);
27970
- persistSymbolIndexFileData(db, ctx, relPath, source, tags, imports);
27971
- });
27972
- });
27973
- }
27974
- async function removeSymbolIndexFileAsync(resolved, relPath) {
27975
- await withCodeNavCacheSqlite(async (db) => {
27976
- runCodeNavCacheWriteTransaction(db, () => {
27977
- upsertSymbolIndexParentPath(db, resolved);
27978
- const ctx = getSymbolIndexParentContext(db, resolved);
27979
- if (ctx == null) throw new Error(`Failed to resolve symbol index parent: ${resolved}`);
27980
- removeSymbolIndexFileData(db, ctx, relPath);
27981
- });
27982
- });
27983
- }
27948
+ // src/code-nav/symbol-index/query/list-direct-import-targets.ts
27949
+ init_normalize_resolved_path();
27984
27950
 
27985
27951
  // src/code-nav/symbol-index/query/tag-query-shared.ts
27986
27952
  var TAG_SELECT = `file_path, name, role, kind, start_line, start_column, end_line, end_column,
@@ -28130,6 +28096,7 @@ async function listDirectImportTargetsForFileAsync(parentPath, filePath) {
28130
28096
  }
28131
28097
 
28132
28098
  // src/code-nav/symbol-index/lifecycle/symbol-index-file-ready.ts
28099
+ init_normalize_resolved_path();
28133
28100
  function symbolIndexFileIsReadyWithDb(db, parentPath, filePath) {
28134
28101
  const normalizedParent = normalizeResolvedPath(parentPath);
28135
28102
  const normalizedFile = filePath.replace(/\\/g, "/").replace(/^\/+/, "");
@@ -28159,6 +28126,129 @@ async function loadSymbolIndexReadyFileSet(parentPath) {
28159
28126
  return new Set(paths);
28160
28127
  }
28161
28128
 
28129
+ // src/code-nav/symbol-index/imports/star-reexport-names.ts
28130
+ var STAR_LOCAL_NAME = "*";
28131
+ function isModuleLevelDef(tag) {
28132
+ return tag.role === "def" && tag.parentScopeStartLine == null && tag.parentScopeStartColumn == null;
28133
+ }
28134
+ function collectExportableNamesFromTags(tags) {
28135
+ const names = /* @__PURE__ */ new Map();
28136
+ for (const tag of tags) {
28137
+ if (!isModuleLevelDef(tag)) continue;
28138
+ if (!names.has(tag.name)) names.set(tag.name, tag.name);
28139
+ }
28140
+ return names;
28141
+ }
28142
+ function existingLocalNames(imports) {
28143
+ return new Set(imports.map((binding) => binding.localName));
28144
+ }
28145
+ function resolveExportableNames(filePath, entriesByPath, visited) {
28146
+ if (visited.has(filePath)) return /* @__PURE__ */ new Map();
28147
+ visited.add(filePath);
28148
+ const entry = entriesByPath.get(filePath);
28149
+ if (!entry) return /* @__PURE__ */ new Map();
28150
+ const out = collectExportableNamesFromTags(entry.tags);
28151
+ const resolved = /* @__PURE__ */ new Map();
28152
+ for (const [name, sourceName] of out) {
28153
+ resolved.set(name, { sourceName, sourceFilePath: filePath });
28154
+ }
28155
+ for (const binding of entry.imports) {
28156
+ if (binding.importKind !== "star" || !binding.sourceFilePath) continue;
28157
+ const upstream = resolveExportableNames(binding.sourceFilePath, entriesByPath, visited);
28158
+ for (const [name, info] of upstream) {
28159
+ if (!resolved.has(name)) resolved.set(name, info);
28160
+ }
28161
+ }
28162
+ for (const binding of entry.imports) {
28163
+ if (binding.importKind !== "reexport" && binding.importKind !== "type") continue;
28164
+ if (!binding.sourceFilePath) continue;
28165
+ if (!resolved.has(binding.localName)) {
28166
+ resolved.set(binding.localName, {
28167
+ sourceName: binding.sourceName,
28168
+ sourceFilePath: binding.sourceFilePath
28169
+ });
28170
+ }
28171
+ }
28172
+ return resolved;
28173
+ }
28174
+
28175
+ // src/code-nav/symbol-index/imports/star-reexport-upstream.ts
28176
+ function collectUpstreamEntries(entry, resolveEntry) {
28177
+ const entriesByPath = /* @__PURE__ */ new Map();
28178
+ entriesByPath.set(entry.relPath, entry);
28179
+ const visit = (filePath, visited) => {
28180
+ if (visited.has(filePath)) return;
28181
+ visited.add(filePath);
28182
+ const resolved = resolveEntry(filePath);
28183
+ if (resolved == null) return;
28184
+ entriesByPath.set(filePath, resolved);
28185
+ for (const binding of resolved.imports) {
28186
+ if (binding.sourceFilePath) visit(binding.sourceFilePath, visited);
28187
+ }
28188
+ };
28189
+ for (const star of entry.imports) {
28190
+ if (star.importKind !== "star" || !star.sourceFilePath) continue;
28191
+ visit(star.sourceFilePath, /* @__PURE__ */ new Set());
28192
+ }
28193
+ return [...entriesByPath.values()];
28194
+ }
28195
+
28196
+ // src/code-nav/symbol-index/imports/expand-star-reexports.ts
28197
+ function expandStarReexportForFile(entry, resolveEntry) {
28198
+ const collected = collectUpstreamEntries(entry, resolveEntry);
28199
+ return expandStarReexportBindings(collected).find((row) => row.relPath === entry.relPath) ?? entry;
28200
+ }
28201
+ function expandStarReexportBindings(collected) {
28202
+ const entriesByPath = new Map(collected.map((entry) => [entry.relPath, entry]));
28203
+ return collected.map((entry) => {
28204
+ const stars = entry.imports.filter((binding) => binding.importKind === "star");
28205
+ if (stars.length === 0) return entry;
28206
+ const localNames = existingLocalNames(entry.imports);
28207
+ const materialized = [];
28208
+ for (const star of stars) {
28209
+ if (!star.sourceFilePath) continue;
28210
+ const exportable = resolveExportableNames(star.sourceFilePath, entriesByPath, /* @__PURE__ */ new Set());
28211
+ for (const [localName, info] of exportable) {
28212
+ if (localName === STAR_LOCAL_NAME || localNames.has(localName)) continue;
28213
+ localNames.add(localName);
28214
+ materialized.push({
28215
+ localName,
28216
+ sourceName: info.sourceName,
28217
+ moduleSpecifier: star.moduleSpecifier,
28218
+ sourceFilePath: info.sourceFilePath,
28219
+ importKind: star.importKind === "type" ? "type" : "reexport",
28220
+ startLine: star.startLine,
28221
+ startColumn: star.startColumn
28222
+ });
28223
+ }
28224
+ }
28225
+ if (materialized.length === 0) return entry;
28226
+ return { ...entry, imports: [...entry.imports, ...materialized] };
28227
+ });
28228
+ }
28229
+
28230
+ // src/code-nav/symbol-index/persistence/persist-single-file.ts
28231
+ async function persistSymbolIndexFileAsync(resolved, relPath, source, tags, imports) {
28232
+ await withCodeNavCacheSqlite(async (db) => {
28233
+ runCodeNavCacheWriteTransaction(db, () => {
28234
+ upsertSymbolIndexParentPath(db, resolved);
28235
+ const ctx = getSymbolIndexParentContext(db, resolved);
28236
+ if (ctx == null) throw new Error(`Failed to resolve symbol index parent: ${resolved}`);
28237
+ persistSymbolIndexFileData(db, ctx, relPath, source, tags, imports);
28238
+ });
28239
+ });
28240
+ }
28241
+ async function removeSymbolIndexFileAsync(resolved, relPath) {
28242
+ await withCodeNavCacheSqlite(async (db) => {
28243
+ runCodeNavCacheWriteTransaction(db, () => {
28244
+ upsertSymbolIndexParentPath(db, resolved);
28245
+ const ctx = getSymbolIndexParentContext(db, resolved);
28246
+ if (ctx == null) throw new Error(`Failed to resolve symbol index parent: ${resolved}`);
28247
+ removeSymbolIndexFileData(db, ctx, relPath);
28248
+ });
28249
+ });
28250
+ }
28251
+
28162
28252
  // src/code-nav/symbol-index/build/extract-file-symbol-data.ts
28163
28253
  import fs19 from "node:fs";
28164
28254
  import path21 from "node:path";
@@ -28845,6 +28935,7 @@ async function parseSourceRoot(filePath, source) {
28845
28935
  const languageKey = getLanguageKeyForFilePath(filePath);
28846
28936
  if (!languageKey) return null;
28847
28937
  return withTreeSitterRuntimeLock(async () => {
28938
+ await yieldForBridgeInteractivePriority();
28848
28939
  let loaded;
28849
28940
  try {
28850
28941
  loaded = await loadLanguage(languageKey);
@@ -28856,7 +28947,11 @@ async function parseSourceRoot(filePath, source) {
28856
28947
  parser4.setLanguage(loaded.language);
28857
28948
  let tree = null;
28858
28949
  try {
28950
+ await yieldForBridgeInteractivePriority();
28951
+ assertBackgroundIndexingAllowed();
28859
28952
  tree = parser4.parse(source);
28953
+ assertBackgroundIndexingAllowed();
28954
+ await yieldForBridgeInteractivePriority();
28860
28955
  if (!tree) return null;
28861
28956
  return {
28862
28957
  root: tree.rootNode,
@@ -28866,9 +28961,10 @@ async function parseSourceRoot(filePath, source) {
28866
28961
  parser4.delete();
28867
28962
  }
28868
28963
  };
28869
- } catch {
28964
+ } catch (err) {
28870
28965
  tree?.delete();
28871
28966
  parser4.delete();
28967
+ if (isSymbolIndexDeferredError(err)) throw err;
28872
28968
  return null;
28873
28969
  }
28874
28970
  });
@@ -28876,9 +28972,11 @@ async function parseSourceRoot(filePath, source) {
28876
28972
 
28877
28973
  // src/code-nav/parser/run-tags-query.ts
28878
28974
  async function runTagsQuery(loaded, root) {
28879
- await yieldToEventLoop();
28975
+ await yieldForBridgeInteractivePriority();
28976
+ assertBackgroundIndexingAllowed();
28880
28977
  const matches = loaded.query.matches(root);
28881
- await yieldToEventLoop();
28978
+ assertBackgroundIndexingAllowed();
28979
+ await yieldForBridgeInteractivePriority();
28882
28980
  return matches;
28883
28981
  }
28884
28982
 
@@ -28959,7 +29057,7 @@ async function tagsFromMatchesAsync(matches, state) {
28959
29057
  // src/code-nav/parser/extract-tags.ts
28960
29058
  async function extractTagsFromSource(filePath, source) {
28961
29059
  const languageKey = getLanguageKeyForFilePath(filePath);
28962
- await yieldToEventLoop();
29060
+ await yieldForBridgeInteractivePriority();
28963
29061
  const parsed = await parseSourceRoot(filePath, source);
28964
29062
  if (!parsed) return [];
28965
29063
  try {
@@ -28975,13 +29073,17 @@ async function extractTagsFromSource(filePath, source) {
28975
29073
  const withReceivers = await augmentMemberReceiverTags(withFunctionTypeParamRefs, nameNodes, parsed.root, languageKey);
28976
29074
  await yieldDuringCodeNavWork(yieldState);
28977
29075
  return await enrichTagsWithEnclosingScope(withReceivers, nameNodes);
28978
- } catch {
29076
+ } catch (err) {
29077
+ if (isSymbolIndexDeferredError(err)) throw err;
28979
29078
  return [];
28980
29079
  } finally {
28981
29080
  parsed.cleanup();
28982
29081
  }
28983
29082
  }
28984
29083
 
29084
+ // src/code-nav/symbol-index/imports/index.ts
29085
+ init_yield_to_event_loop();
29086
+
28985
29087
  // src/code-nav/symbol-index/imports/shared.ts
28986
29088
  function pushBinding(out, filePath, workspaceFiles, moduleSpecifier, localName, sourceName, importKind, nameNode) {
28987
29089
  if (!localName) return;
@@ -29350,6 +29452,7 @@ async function extractImportBindingsFromSource(filePath, source, workspaceFiles)
29350
29452
  var MAX_INDEX_FILE_BYTES = 512 * 1024;
29351
29453
 
29352
29454
  // src/code-nav/symbol-index/build/workspace-files.ts
29455
+ init_normalize_resolved_path();
29353
29456
  function listWorkspaceFiles(db, workspacePath, includePath) {
29354
29457
  const files = /* @__PURE__ */ new Set([includePath.replace(/\\/g, "/")]);
29355
29458
  const normalizedWorkspace = normalizeResolvedPath(workspacePath);
@@ -29371,6 +29474,7 @@ function listWorkspaceFiles(db, workspacePath, includePath) {
29371
29474
 
29372
29475
  // src/code-nav/symbol-index/build/extract-file-symbol-data.ts
29373
29476
  async function extractFileSymbolData(resolved, relPath, workspaceFilesOverride) {
29477
+ await yieldForBridgeInteractivePriority();
29374
29478
  const absPath = path21.join(resolved, relPath);
29375
29479
  let tags = [];
29376
29480
  let source = null;
@@ -29379,15 +29483,16 @@ async function extractFileSymbolData(resolved, relPath, workspaceFilesOverride)
29379
29483
  const stat2 = await fs19.promises.stat(absPath);
29380
29484
  if (stat2.isFile() && stat2.size <= MAX_INDEX_FILE_BYTES) {
29381
29485
  source = await fs19.promises.readFile(absPath, "utf8");
29382
- await yieldToEventLoop();
29486
+ await yieldForBridgeInteractivePriority();
29383
29487
  tags = await extractTagsFromSource(relPath, source);
29384
29488
  }
29385
- } catch {
29489
+ } catch (err) {
29490
+ if (isSymbolIndexDeferredError(err)) throw err;
29386
29491
  tags = [];
29387
29492
  source = null;
29388
29493
  }
29389
29494
  }
29390
- await yieldToEventLoop();
29495
+ await yieldForBridgeInteractivePriority();
29391
29496
  const workspaceFiles = workspaceFilesOverride ?? await withCodeNavCacheSqlite((db) => listWorkspaceFiles(db, resolved, relPath));
29392
29497
  const imports = source != null ? await extractImportBindingsFromSource(relPath, source, workspaceFiles) : [];
29393
29498
  const yieldState = createCodeNavYieldState();
@@ -29398,12 +29503,9 @@ async function extractFileSymbolData(resolved, relPath, workspaceFilesOverride)
29398
29503
  };
29399
29504
  }
29400
29505
 
29401
- // src/code-nav/symbol-index/build/ensure-symbol-index-file.ts
29402
- var MAX_IMPORT_PREFETCH_COUNT = 8;
29403
- function normalizeRelPath3(filePath) {
29404
- return filePath.replace(/\\/g, "/").replace(/^\/+/, "");
29405
- }
29506
+ // src/code-nav/symbol-index/build/index-one-symbol-file-for-build.ts
29406
29507
  async function indexOneSymbolFileForBuild(resolved, relPath, workspaceFiles) {
29508
+ await yieldForBridgeInteractivePriority();
29407
29509
  const data = await extractFileSymbolData(resolved, relPath, workspaceFiles);
29408
29510
  let entry = {
29409
29511
  relPath,
@@ -29412,7 +29514,7 @@ async function indexOneSymbolFileForBuild(resolved, relPath, workspaceFiles) {
29412
29514
  imports: data.imports
29413
29515
  };
29414
29516
  if (data.imports.some((binding) => binding.importKind === "star")) {
29415
- await yieldToEventLoop();
29517
+ await yieldForBridgeInteractivePriority();
29416
29518
  entry = await withCodeNavCacheSqlite((db) => {
29417
29519
  const ctx = getSymbolIndexParentContext(db, resolved);
29418
29520
  if (ctx == null) return entry;
@@ -29422,13 +29524,30 @@ async function indexOneSymbolFileForBuild(resolved, relPath, workspaceFiles) {
29422
29524
  entry.source = data.source;
29423
29525
  }
29424
29526
  await withSymbolIndexSqliteLock(async () => {
29425
- await yieldToEventLoop();
29527
+ await yieldForBridgeInteractivePriority();
29426
29528
  await persistSymbolIndexFileAsync(resolved, relPath, entry.source, entry.tags, entry.imports);
29427
29529
  });
29428
29530
  }
29531
+
29532
+ // src/code-nav/symbol-index/build/normalize-symbol-index-rel-path.ts
29533
+ function normalizeSymbolIndexRelPath(filePath) {
29534
+ return filePath.replace(/\\/g, "/").replace(/^\/+/, "");
29535
+ }
29536
+
29537
+ // src/code-nav/symbol-index/build/register-symbol-index-parent.ts
29538
+ init_normalize_resolved_path();
29539
+ async function registerSymbolIndexParentAsync(parentPath) {
29540
+ const resolved = normalizeResolvedPath(parentPath);
29541
+ await withCodeNavCacheSqlite((db) => {
29542
+ upsertSymbolIndexParentPath(db, resolved);
29543
+ });
29544
+ }
29545
+
29546
+ // src/code-nav/symbol-index/build/ensure-symbol-index-file.ts
29547
+ var MAX_IMPORT_PREFETCH_COUNT = 8;
29429
29548
  async function ensureSymbolIndexFileAsync(parentPath, filePath, opts) {
29430
29549
  const resolved = normalizeResolvedPath(parentPath);
29431
- const relPath = normalizeRelPath3(filePath);
29550
+ const relPath = normalizeSymbolIndexRelPath(filePath);
29432
29551
  if (!relPath) return false;
29433
29552
  const importDepth = opts?.importDepth ?? 0;
29434
29553
  await withCodeNavCacheSqlite((db) => {
@@ -29443,7 +29562,7 @@ async function ensureSymbolIndexFileAsync(parentPath, filePath, opts) {
29443
29562
  MAX_IMPORT_PREFETCH_COUNT
29444
29563
  );
29445
29564
  for (const target of targets) {
29446
- await yieldToEventLoop();
29565
+ await yieldForBridgeInteractivePriority();
29447
29566
  if (!await symbolIndexFileIsReadyAsync(resolved, target)) {
29448
29567
  await ensureSymbolIndexFileAsync(resolved, target, { importDepth: importDepth - 1 });
29449
29568
  }
@@ -29451,18 +29570,12 @@ async function ensureSymbolIndexFileAsync(parentPath, filePath, opts) {
29451
29570
  }
29452
29571
  return await symbolIndexFileIsReadyAsync(resolved, relPath);
29453
29572
  }
29454
- async function registerSymbolIndexParentAsync(parentPath) {
29455
- const resolved = normalizeResolvedPath(parentPath);
29456
- await withCodeNavCacheSqlite((db) => {
29457
- upsertSymbolIndexParentPath(db, resolved);
29458
- });
29459
- }
29460
29573
 
29461
29574
  // src/code-nav/symbol-index/build/build-symbol-index.ts
29462
29575
  var SYMBOL_PARENT_CLEAR_BATCH_SIZE = 256;
29463
29576
  async function buildSymbolIndexAsync(parentPath) {
29464
29577
  const resolved = normalizeResolvedPath(parentPath);
29465
- await yieldToEventLoop();
29578
+ await yieldForBridgeInteractivePriority();
29466
29579
  let clearRemaining = true;
29467
29580
  while (clearRemaining) {
29468
29581
  await withSymbolIndexSqliteLock(async () => {
@@ -29474,7 +29587,7 @@ async function buildSymbolIndexAsync(parentPath) {
29474
29587
  })
29475
29588
  );
29476
29589
  });
29477
- if (clearRemaining) await yieldToEventLoop();
29590
+ if (clearRemaining) await yieldForBridgeInteractivePriority();
29478
29591
  }
29479
29592
  const workspaceFiles = /* @__PURE__ */ new Set();
29480
29593
  const walkState = createWalkYieldState();
@@ -29497,10 +29610,17 @@ async function buildSymbolIndexAsync(parentPath) {
29497
29610
  },
29498
29611
  walkState
29499
29612
  );
29500
- await yieldToEventLoop();
29613
+ await yieldForBridgeInteractivePriority();
29501
29614
  return { fileCount, tagCount: 0 };
29502
29615
  }
29503
29616
 
29617
+ // src/code-nav/symbol-index/build/ensure-symbol-index.ts
29618
+ init_bridge_root();
29619
+ init_normalize_resolved_path();
29620
+
29621
+ // src/code-nav/symbol-index/scheduler/task-queue-enqueue.ts
29622
+ init_normalize_resolved_path();
29623
+
29504
29624
  // src/code-nav/symbol-index/scheduler/task-priority-heap.ts
29505
29625
  function higherPriority(a, b) {
29506
29626
  return a.priority > b.priority;
@@ -29558,122 +29678,185 @@ function symbolIndexTaskKey(parentPath, filePath) {
29558
29678
  return `${parentPath}\0${filePath}`;
29559
29679
  }
29560
29680
 
29561
- // src/code-nav/symbol-index/scheduler/task-queue.ts
29562
- var pending = /* @__PURE__ */ new Map();
29563
- var heap = new SymbolIndexTaskPriorityHeap();
29681
+ // src/code-nav/symbol-index/scheduler/task-queue-store.ts
29682
+ var pendingSymbolIndexTasks = /* @__PURE__ */ new Map();
29683
+ var symbolIndexTaskHeap = new SymbolIndexTaskPriorityHeap();
29564
29684
  var latestActiveSequenceByParent = /* @__PURE__ */ new Map();
29565
- var workerRunning = false;
29685
+ var symbolIndexWorkerRunning = false;
29686
+ function setSymbolIndexWorkerRunning(running) {
29687
+ symbolIndexWorkerRunning = running;
29688
+ }
29689
+ function deferBackgroundSymbolIndexTasks() {
29690
+ if (pendingSymbolIndexTasks.size === 0) return;
29691
+ pendingSymbolIndexTasks.clear();
29692
+ symbolIndexTaskHeap.clear();
29693
+ }
29694
+ registerFileBrowserRequestStartListener(() => {
29695
+ deferBackgroundSymbolIndexTasks();
29696
+ });
29566
29697
  function taskMatchesCurrentPending(task) {
29567
- const current = pending.get(symbolIndexTaskKey(task.parentPath, task.filePath));
29698
+ const current = pendingSymbolIndexTasks.get(symbolIndexTaskKey(task.parentPath, task.filePath));
29568
29699
  return current === task;
29569
29700
  }
29570
- function pickNextTask() {
29571
- while (heap.size > 0) {
29572
- const task = heap.pop();
29701
+ function pickNextSymbolIndexTask() {
29702
+ while (symbolIndexTaskHeap.size > 0) {
29703
+ const task = symbolIndexTaskHeap.pop();
29573
29704
  if (task == null || !taskMatchesCurrentPending(task)) continue;
29574
29705
  return task;
29575
29706
  }
29576
29707
  return void 0;
29577
29708
  }
29709
+ function addPendingSymbolIndexTask(task) {
29710
+ const key = symbolIndexTaskKey(task.parentPath, task.filePath);
29711
+ const existing = pendingSymbolIndexTasks.get(key);
29712
+ if (existing != null && existing.priority >= task.priority) return false;
29713
+ pendingSymbolIndexTasks.set(key, task);
29714
+ symbolIndexTaskHeap.push(task);
29715
+ return true;
29716
+ }
29717
+ function clearSymbolIndexHeapIfEmpty() {
29718
+ if (pendingSymbolIndexTasks.size === 0) symbolIndexTaskHeap.clear();
29719
+ }
29720
+
29721
+ // src/code-nav/symbol-index/scheduler/task-queue-worker.ts
29578
29722
  async function runWorker() {
29579
- if (workerRunning) return;
29580
- workerRunning = true;
29723
+ if (symbolIndexWorkerRunning) return;
29724
+ setSymbolIndexWorkerRunning(true);
29581
29725
  try {
29582
29726
  const yieldState = createCodeNavYieldState();
29583
- while (pending.size > 0) {
29584
- const task = pickNextTask();
29727
+ while (pendingSymbolIndexTasks.size > 0) {
29728
+ await yieldForBridgeInteractivePriority();
29729
+ const task = pickNextSymbolIndexTask();
29585
29730
  if (task == null) break;
29586
- pending.delete(symbolIndexTaskKey(task.parentPath, task.filePath));
29731
+ pendingSymbolIndexTasks.delete(symbolIndexTaskKey(task.parentPath, task.filePath));
29587
29732
  await yieldDuringCodeNavWork(yieldState);
29588
29733
  const latestActiveSequence = latestActiveSequenceByParent.get(task.parentPath);
29589
29734
  if (latestActiveSequence != null && task.sequence != null && task.sequence < latestActiveSequence) {
29590
29735
  continue;
29591
29736
  }
29592
29737
  if (!await symbolIndexFileIsReadyAsync(task.parentPath, task.filePath)) {
29593
- await ensureSymbolIndexFileAsync(task.parentPath, task.filePath);
29738
+ try {
29739
+ await ensureSymbolIndexFileAsync(task.parentPath, task.filePath);
29740
+ } catch (err) {
29741
+ if (isSymbolIndexDeferredError(err)) {
29742
+ if (addPendingSymbolIndexTask(task)) void runWorker();
29743
+ continue;
29744
+ }
29745
+ throw err;
29746
+ }
29594
29747
  }
29595
- await yieldToEventLoop();
29748
+ await yieldForBridgeInteractivePriority();
29596
29749
  }
29597
29750
  } finally {
29598
- if (pending.size === 0) heap.clear();
29599
- workerRunning = false;
29600
- if (pending.size > 0) void runWorker();
29751
+ clearSymbolIndexHeapIfEmpty();
29752
+ setSymbolIndexWorkerRunning(false);
29753
+ if (pendingSymbolIndexTasks.size > 0) void runWorker();
29601
29754
  }
29602
29755
  }
29756
+ function kickSymbolIndexWorker() {
29757
+ void runWorker();
29758
+ }
29759
+
29760
+ // src/code-nav/symbol-index/scheduler/task-queue-enqueue.ts
29603
29761
  function enqueueSymbolIndexTask(parentPath, filePath, priority, sequence) {
29604
29762
  const normalizedParent = normalizeResolvedPath(parentPath);
29605
29763
  const normalizedFile = filePath.replace(/\\/g, "/").replace(/^\/+/, "");
29606
29764
  if (!normalizedFile) return;
29607
- const key = symbolIndexTaskKey(normalizedParent, normalizedFile);
29608
- const existing = pending.get(key);
29609
- if (existing != null && existing.priority >= priority) return;
29610
- const task = { parentPath: normalizedParent, filePath: normalizedFile, priority, sequence };
29611
- pending.set(key, task);
29612
- heap.push(task);
29613
- void runWorker();
29765
+ const added = addPendingSymbolIndexTask({
29766
+ parentPath: normalizedParent,
29767
+ filePath: normalizedFile,
29768
+ priority,
29769
+ sequence
29770
+ });
29771
+ if (added) kickSymbolIndexWorker();
29614
29772
  }
29615
29773
  function markLatestActiveSymbolIndexTask(parentPath, sequence) {
29616
29774
  const normalizedParent = normalizeResolvedPath(parentPath);
29617
29775
  const existing = latestActiveSequenceByParent.get(normalizedParent);
29618
29776
  if (existing != null && existing >= sequence) return;
29619
29777
  latestActiveSequenceByParent.set(normalizedParent, sequence);
29620
- for (const [key, task] of pending) {
29778
+ for (const [key, task] of pendingSymbolIndexTasks) {
29621
29779
  if (task.parentPath === normalizedParent && task.sequence != null && task.sequence < sequence) {
29622
- pending.delete(key);
29780
+ pendingSymbolIndexTasks.delete(key);
29623
29781
  }
29624
29782
  }
29625
- if (pending.size === 0) heap.clear();
29783
+ if (pendingSymbolIndexTasks.size === 0) symbolIndexTaskHeap.clear();
29626
29784
  }
29627
29785
 
29628
- // src/code-nav/symbol-index/scheduler/symbol-index-scheduler.ts
29786
+ // src/code-nav/symbol-index/scheduler/symbol-index-warmup.ts
29787
+ init_normalize_resolved_path();
29629
29788
  var requestSeq = 0;
29630
29789
  var warmupSeq = 0;
29631
- var warmupScheduled = /* @__PURE__ */ new Set();
29632
29790
  var warmupCompleted = /* @__PURE__ */ new Set();
29791
+ var pendingWarmupParents = /* @__PURE__ */ new Set();
29792
+ var warmupWalkInProgress = /* @__PURE__ */ new Set();
29793
+ var WARMUP_IDLE_MS = 3e3;
29794
+ var warmupIdleTimer = null;
29795
+ function scheduleWarmupWhenIdle() {
29796
+ if (warmupIdleTimer != null) clearTimeout(warmupIdleTimer);
29797
+ warmupIdleTimer = setTimeout(() => {
29798
+ warmupIdleTimer = null;
29799
+ if (fileBrowserRequestInFlight()) {
29800
+ scheduleWarmupWhenIdle();
29801
+ return;
29802
+ }
29803
+ for (const parentPath of [...pendingWarmupParents]) {
29804
+ void runWarmupWalk(parentPath);
29805
+ }
29806
+ }, WARMUP_IDLE_MS);
29807
+ }
29808
+ registerFileBrowserActivityListener(() => {
29809
+ if (pendingWarmupParents.size > 0) scheduleWarmupWhenIdle();
29810
+ });
29811
+ async function runWarmupWalk(resolved) {
29812
+ if (warmupCompleted.has(resolved) || warmupWalkInProgress.has(resolved)) {
29813
+ pendingWarmupParents.delete(resolved);
29814
+ return;
29815
+ }
29816
+ warmupWalkInProgress.add(resolved);
29817
+ pendingWarmupParents.delete(resolved);
29818
+ try {
29819
+ const readyFiles = await loadSymbolIndexReadyFileSet(resolved);
29820
+ const walkState = createWalkYieldState();
29821
+ const yieldState = createCodeNavYieldState();
29822
+ await walkCodeNavFilesAsync(
29823
+ resolved,
29824
+ async (relPath) => {
29825
+ await yieldDuringCodeNavWork(yieldState);
29826
+ if (!readyFiles.has(relPath)) {
29827
+ enqueueSymbolIndexTask(resolved, relPath, ++warmupSeq, requestSeq);
29828
+ }
29829
+ },
29830
+ walkState
29831
+ );
29832
+ warmupCompleted.add(resolved);
29833
+ } finally {
29834
+ warmupWalkInProgress.delete(resolved);
29835
+ }
29836
+ }
29837
+
29838
+ // src/code-nav/symbol-index/scheduler/symbol-index-scheduler.ts
29839
+ var requestSeq2 = 0;
29633
29840
  function scheduleSymbolIndexFile(parentPath, filePath) {
29634
- const sequence = ++requestSeq;
29841
+ const sequence = ++requestSeq2;
29635
29842
  markLatestActiveSymbolIndexTask(parentPath, sequence);
29636
29843
  enqueueSymbolIndexTask(parentPath, filePath, 1e6 + sequence, sequence);
29637
29844
  }
29638
29845
  function scheduleSymbolIndexImportNeighbors(parentPath, filePaths) {
29639
- let priority = 5e5 + requestSeq;
29846
+ let priority = 5e5 + requestSeq2;
29640
29847
  for (const filePath of filePaths) {
29641
- enqueueSymbolIndexTask(parentPath, filePath, priority, requestSeq);
29848
+ enqueueSymbolIndexTask(parentPath, filePath, priority, requestSeq2);
29642
29849
  priority -= 1;
29643
29850
  }
29644
29851
  }
29645
- function scheduleSymbolIndexWarmup(parentPath) {
29646
- const resolved = normalizeResolvedPath(parentPath);
29647
- if (warmupCompleted.has(resolved)) return;
29648
- if (warmupScheduled.has(resolved)) return;
29649
- warmupScheduled.add(resolved);
29650
- setImmediate(() => {
29651
- void (async () => {
29652
- try {
29653
- const readyFiles = await loadSymbolIndexReadyFileSet(resolved);
29654
- const walkState = createWalkYieldState();
29655
- const yieldState = createCodeNavYieldState();
29656
- await walkCodeNavFilesAsync(
29657
- resolved,
29658
- async (relPath) => {
29659
- await yieldDuringCodeNavWork(yieldState);
29660
- if (!readyFiles.has(relPath)) {
29661
- enqueueSymbolIndexTask(resolved, relPath, ++warmupSeq, requestSeq);
29662
- }
29663
- },
29664
- walkState
29665
- );
29666
- warmupCompleted.add(resolved);
29667
- } finally {
29668
- warmupScheduled.delete(resolved);
29669
- }
29670
- })();
29671
- });
29672
- }
29852
+
29853
+ // src/code-nav/symbol-index/build/update-symbol-index-file.ts
29854
+ init_normalize_resolved_path();
29855
+ init_yield_to_event_loop();
29673
29856
 
29674
29857
  // src/code-nav/symbol-index/lifecycle/normalize-symbol-index-path.ts
29675
29858
  import path22 from "node:path";
29676
- function normalizeSymbolIndexRelPath(parentPath, changedPath) {
29859
+ function normalizeSymbolIndexRelPath2(parentPath, changedPath) {
29677
29860
  const resolvedParent = path22.resolve(parentPath);
29678
29861
  const abs = path22.isAbsolute(changedPath) ? path22.resolve(changedPath) : path22.resolve(resolvedParent, changedPath);
29679
29862
  const rel = path22.relative(resolvedParent, abs).replace(/\\/g, "/");
@@ -29683,7 +29866,7 @@ function normalizeSymbolIndexRelPath(parentPath, changedPath) {
29683
29866
 
29684
29867
  // src/code-nav/symbol-index/build/update-symbol-index-file.ts
29685
29868
  async function updateSymbolIndexForFile(parentPath, changedPath) {
29686
- const relPath = normalizeSymbolIndexRelPath(parentPath, changedPath);
29869
+ const relPath = normalizeSymbolIndexRelPath2(parentPath, changedPath);
29687
29870
  if (relPath == null) return;
29688
29871
  const resolved = normalizeResolvedPath(parentPath);
29689
29872
  const { source, tags, imports } = await extractFileSymbolData(resolved, relPath);
@@ -29693,7 +29876,7 @@ async function updateSymbolIndexForFile(parentPath, changedPath) {
29693
29876
  });
29694
29877
  }
29695
29878
  async function removeSymbolIndexForFile(parentPath, changedPath) {
29696
- const relPath = normalizeSymbolIndexRelPath(parentPath, changedPath);
29879
+ const relPath = normalizeSymbolIndexRelPath2(parentPath, changedPath);
29697
29880
  if (relPath == null) return;
29698
29881
  const resolved = normalizeResolvedPath(parentPath);
29699
29882
  await withSymbolIndexSqliteLock(async () => {
@@ -29701,6 +29884,10 @@ async function removeSymbolIndexForFile(parentPath, changedPath) {
29701
29884
  });
29702
29885
  }
29703
29886
 
29887
+ // src/code-nav/symbol-index/query/query-definitions.ts
29888
+ init_normalize_resolved_path();
29889
+ init_yield_to_event_loop();
29890
+
29704
29891
  // src/code-nav/symbol-index/sqlite/symbol-index-import-sqlite.ts
29705
29892
  function prefersTypeImport(refKind) {
29706
29893
  return refKind === "type";
@@ -30201,6 +30388,8 @@ async function queryDefinitionAt(parentPath, filePath, line, column) {
30201
30388
  }
30202
30389
 
30203
30390
  // src/code-nav/symbol-index/query/query-references.ts
30391
+ init_normalize_resolved_path();
30392
+ init_yield_to_event_loop();
30204
30393
  async function queryReferencesAt(parentPath, filePath, line, column) {
30205
30394
  await yieldToEventLoop();
30206
30395
  const resolved = normalizeResolvedPath(parentPath);
@@ -30224,6 +30413,8 @@ async function queryReferencesAt(parentPath, filePath, line, column) {
30224
30413
  }
30225
30414
 
30226
30415
  // src/code-nav/symbol-index/query/query-symbols-in-file.ts
30416
+ init_normalize_resolved_path();
30417
+ init_yield_to_event_loop();
30227
30418
  function rowToSymbolSpan(row, clickable) {
30228
30419
  return {
30229
30420
  name: row.name,
@@ -30309,6 +30500,7 @@ function createFileIndexFsWatcher(resolved, schedule) {
30309
30500
  // src/files/index/file-index-incremental-symbol-updates.ts
30310
30501
  import fs20 from "node:fs";
30311
30502
  import path23 from "node:path";
30503
+ init_yield_to_event_loop();
30312
30504
  async function applyIncrementalSymbolIndexUpdates(resolved, relPaths) {
30313
30505
  for (const rel of relPaths) {
30314
30506
  const absPath = path23.join(resolved, rel);
@@ -30332,6 +30524,7 @@ async function applyIncrementalSymbolIndexUpdates(resolved, relPaths) {
30332
30524
 
30333
30525
  // src/files/index/file-index-initial-builds.ts
30334
30526
  import path24 from "node:path";
30527
+ init_cwd();
30335
30528
  async function runInitialIndexBuilds(cwd = getBridgeRoot()) {
30336
30529
  const resolved = path24.resolve(cwd);
30337
30530
  try {
@@ -30549,6 +30742,7 @@ import * as fs21 from "node:fs";
30549
30742
  import * as path29 from "node:path";
30550
30743
 
30551
30744
  // src/paths/session-layout-paths.ts
30745
+ init_cwd();
30552
30746
  import * as path26 from "node:path";
30553
30747
  function resolveIsolatedSessionParentPathFromCheckouts(worktreePaths) {
30554
30748
  const resolved = worktreePaths.map((p) => path26.resolve(p)).filter(Boolean);
@@ -30680,6 +30874,7 @@ __export(cursor_acp_client_exports, {
30680
30874
  createCursorAcpClient: () => createCursorAcpClient,
30681
30875
  detectLocalAgentPresence: () => detectLocalAgentPresence3
30682
30876
  });
30877
+ init_cwd();
30683
30878
 
30684
30879
  // src/agents/acp/clients/cursor/cursor-spawn-command.ts
30685
30880
  function buildCursorAcpSpawnCommand(base, sessionMode) {
@@ -30711,8 +30906,8 @@ function createCursorAcpSessionContext(options) {
30711
30906
 
30712
30907
  // src/agents/acp/clients/cursor/cancel-pending-cursor-permission-requests.ts
30713
30908
  function cancelPendingCursorPermissionRequests(pendingRequests, respond) {
30714
- for (const [reqId, pending2] of [...pendingRequests.entries()]) {
30715
- if (pending2.method === "session/request_permission") {
30909
+ for (const [reqId, pending] of [...pendingRequests.entries()]) {
30910
+ if (pending.method === "session/request_permission") {
30716
30911
  respond(reqId, { outcome: { outcome: "cancelled" } });
30717
30912
  pendingRequests.delete(reqId);
30718
30913
  }
@@ -30891,8 +31086,8 @@ function handleCursorIncomingPermissionRequest(id, method, msg, deps) {
30891
31086
 
30892
31087
  // src/agents/acp/clients/cursor/cursor-incoming-resolve-request.ts
30893
31088
  function resolveCursorIncomingRequest(pendingRequests, respond, requestId, result) {
30894
- const pending2 = pendingRequests.get(requestId);
30895
- const payload = pending2?.method === "session/request_permission" ? enrichAcpPermissionRpcResultFromRequestParams(result, pending2.params) : result;
31089
+ const pending = pendingRequests.get(requestId);
31090
+ const payload = pending?.method === "session/request_permission" ? enrichAcpPermissionRpcResultFromRequestParams(result, pending.params) : result;
30896
31091
  respond(requestId, payload);
30897
31092
  pendingRequests.delete(requestId);
30898
31093
  }
@@ -31029,25 +31224,25 @@ function createCursorJsonRpcInboundRespond(stdin) {
31029
31224
 
31030
31225
  // src/agents/acp/clients/cursor/cursor-json-rpc-outbound.ts
31031
31226
  function createCursorJsonRpcOutboundPending() {
31032
- const pending2 = /* @__PURE__ */ new Map();
31227
+ const pending = /* @__PURE__ */ new Map();
31033
31228
  let nextId = 1;
31034
31229
  function allocateId() {
31035
31230
  return nextId++;
31036
31231
  }
31037
31232
  function register(id, waiter) {
31038
- pending2.set(id, waiter);
31233
+ pending.set(id, waiter);
31039
31234
  }
31040
31235
  function settleResponse(id, msg) {
31041
- const waiter = pending2.get(id);
31236
+ const waiter = pending.get(id);
31042
31237
  if (!waiter) return false;
31043
- pending2.delete(id);
31238
+ pending.delete(id);
31044
31239
  if (msg.error) waiter.reject(msg.error);
31045
31240
  else waiter.resolve(msg.result);
31046
31241
  return true;
31047
31242
  }
31048
31243
  function rejectOnWriteError(id, err) {
31049
- const waiter = pending2.get(id);
31050
- pending2.delete(id);
31244
+ const waiter = pending.get(id);
31245
+ pending.delete(id);
31051
31246
  waiter?.reject(err);
31052
31247
  }
31053
31248
  return { allocateId, register, settleResponse, rejectOnWriteError };
@@ -32567,8 +32762,8 @@ async function execGitFile(args, options) {
32567
32762
  }
32568
32763
 
32569
32764
  // src/git/changes/parse/normalize-git-diff-path.ts
32570
- function normalizeGitDiffPath(path79) {
32571
- return path79.replace(/\\/g, "/").replace(/\/ +/g, "/").trim();
32765
+ function normalizeGitDiffPath(path82) {
32766
+ return path82.replace(/\\/g, "/").replace(/\/ +/g, "/").trim();
32572
32767
  }
32573
32768
 
32574
32769
  // src/git/changes/parse/parse-name-status-entries.ts
@@ -32852,102 +33047,6 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
32852
33047
  });
32853
33048
  }
32854
33049
 
32855
- // src/agents/acp/put-summarize-change-summaries.ts
32856
- async function putEncryptedChangeSummaryRows(params) {
32857
- const base = params.apiBaseUrl.replace(/\/+$/, "");
32858
- const entries = params.rows.map(({ path: path79, summary }) => {
32859
- const enc = params.e2ee.encryptFields({ summary }, ["summary"]);
32860
- return { path: path79, summary: JSON.stringify(enc) };
32861
- });
32862
- const res = await fetch(
32863
- `${base}/internal/sessions/${encodeURIComponent(params.sessionId)}/follow-ups/summarize-changes`,
32864
- {
32865
- method: "PUT",
32866
- headers: {
32867
- Authorization: `Bearer ${params.authToken}`,
32868
- "Content-Type": "application/json"
32869
- },
32870
- body: JSON.stringify({ entries })
32871
- }
32872
- );
32873
- if (!res.ok) {
32874
- const t = await res.text();
32875
- throw new Error(`PUT summarize-changes summaries failed ${res.status}: ${t.slice(0, 500)}`);
32876
- }
32877
- }
32878
-
32879
- // src/agents/acp/maybe-upload-e2ee-session-change-summaries.ts
32880
- async function maybeUploadE2eeSessionChangeSummariesAfterAgentSuccess(params) {
32881
- const {
32882
- sessionId,
32883
- runId,
32884
- resultSuccess,
32885
- output,
32886
- e2ee,
32887
- cloudApiBaseUrl,
32888
- getCloudAccessToken,
32889
- followUpCatalogPromptId,
32890
- sessionChangeSummaryFilePaths,
32891
- log: log2
32892
- } = params;
32893
- const outputStr = typeof output === "string" ? output : "";
32894
- if (!sessionId) {
32895
- return;
32896
- }
32897
- if (!runId) {
32898
- return;
32899
- }
32900
- if (!resultSuccess) {
32901
- return;
32902
- }
32903
- if (!e2ee) {
32904
- return;
32905
- }
32906
- if (!cloudApiBaseUrl) {
32907
- return;
32908
- }
32909
- if (!getCloudAccessToken) {
32910
- return;
32911
- }
32912
- if (followUpCatalogPromptId !== BUILTIN_SESSION_CHANGE_SUMMARY_FOLLOW_UP_CATALOG_PROMPT_ID) {
32913
- return;
32914
- }
32915
- if (!sessionChangeSummaryFilePaths || sessionChangeSummaryFilePaths.length === 0) {
32916
- return;
32917
- }
32918
- if (outputStr.trim() === "") {
32919
- return;
32920
- }
32921
- const allowed = /* @__PURE__ */ new Set();
32922
- for (const p of sessionChangeSummaryFilePaths) {
32923
- const t = p.trim();
32924
- if (!t) continue;
32925
- allowed.add(t);
32926
- allowed.add(normalizeRepoRelativePath(t));
32927
- }
32928
- const rows = parseChangeSummaryJson(outputStr, allowed);
32929
- if (rows.length === 0) {
32930
- return;
32931
- }
32932
- const token = getCloudAccessToken();
32933
- if (!token) {
32934
- return;
32935
- }
32936
- try {
32937
- await putEncryptedChangeSummaryRows({
32938
- apiBaseUrl: cloudApiBaseUrl,
32939
- authToken: token,
32940
- sessionId,
32941
- e2ee,
32942
- rows
32943
- });
32944
- } catch (uploadErr) {
32945
- log2(
32946
- `[Agent] Encrypted change summary upload failed: ${uploadErr instanceof Error ? uploadErr.message : String(uploadErr)}`
32947
- );
32948
- }
32949
- }
32950
-
32951
33050
  // src/agents/planning/submit-planning-todos-for-turn.ts
32952
33051
  async function submitPlanningTodosForTurn(params) {
32953
33052
  const token = params.getCloudAccessToken();
@@ -33016,10 +33115,8 @@ async function finalizeAndSendPromptResult(params) {
33016
33115
  agentCwd,
33017
33116
  isPlanningSession,
33018
33117
  followUpCatalogPromptId,
33019
- sessionChangeSummaryFilePaths,
33020
33118
  cloudApiBaseUrl,
33021
33119
  getCloudAccessToken,
33022
- e2ee,
33023
33120
  sendResult,
33024
33121
  sendSessionUpdate,
33025
33122
  log: log2
@@ -33033,18 +33130,6 @@ async function finalizeAndSendPromptResult(params) {
33033
33130
  log: log2
33034
33131
  });
33035
33132
  }
33036
- await maybeUploadE2eeSessionChangeSummariesAfterAgentSuccess({
33037
- sessionId,
33038
- runId,
33039
- resultSuccess: result.success === true,
33040
- output: result.output,
33041
- e2ee,
33042
- cloudApiBaseUrl,
33043
- getCloudAccessToken,
33044
- followUpCatalogPromptId,
33045
- sessionChangeSummaryFilePaths,
33046
- log: log2
33047
- });
33048
33133
  const planningTodosSubmit = await maybeSubmitPlanningTodosAfterAgentSuccess({
33049
33134
  sessionId,
33050
33135
  runId,
@@ -33580,7 +33665,6 @@ async function sendPromptToAgent(options) {
33580
33665
  sendSessionUpdate,
33581
33666
  log: log2,
33582
33667
  followUpCatalogPromptId,
33583
- sessionChangeSummaryFilePaths,
33584
33668
  cloudApiBaseUrl,
33585
33669
  getCloudAccessToken,
33586
33670
  e2ee,
@@ -33624,7 +33708,6 @@ async function sendPromptToAgent(options) {
33624
33708
  agentCwd,
33625
33709
  isPlanningSession,
33626
33710
  followUpCatalogPromptId,
33627
- sessionChangeSummaryFilePaths,
33628
33711
  cloudApiBaseUrl,
33629
33712
  getCloudAccessToken,
33630
33713
  e2ee,
@@ -33695,7 +33778,6 @@ async function runAcpPrompt(ctx, runCtx, opts) {
33695
33778
  sendResult,
33696
33779
  sendSessionUpdate,
33697
33780
  followUpCatalogPromptId,
33698
- sessionChangeSummaryFilePaths,
33699
33781
  cloudApiBaseUrl,
33700
33782
  getCloudAccessToken,
33701
33783
  e2ee,
@@ -33761,7 +33843,6 @@ async function runAcpPrompt(ctx, runCtx, opts) {
33761
33843
  sendSessionUpdate,
33762
33844
  log: ctx.log,
33763
33845
  followUpCatalogPromptId,
33764
- sessionChangeSummaryFilePaths,
33765
33846
  cloudApiBaseUrl,
33766
33847
  getCloudAccessToken,
33767
33848
  e2ee,
@@ -34298,8 +34379,10 @@ async function createBridgeAccessState(options = {}) {
34298
34379
 
34299
34380
  // src/agents/capabilities/warmup-agent-capabilities-on-connect.ts
34300
34381
  import * as path35 from "node:path";
34382
+ init_cwd();
34301
34383
 
34302
34384
  // src/agents/detect-local-agent-types.ts
34385
+ init_yield_to_event_loop();
34303
34386
  var LOCAL_AGENT_ACP_MODULES = [
34304
34387
  cursor_acp_client_exports,
34305
34388
  codex_acp_client_exports,
@@ -34328,6 +34411,9 @@ async function detectLocalAgentTypes() {
34328
34411
  }
34329
34412
  }
34330
34413
 
34414
+ // src/agents/capabilities/probe-agent-capabilities-for-types.ts
34415
+ init_yield_to_event_loop();
34416
+
34331
34417
  // src/sqlite/hash-json-sha256.ts
34332
34418
  import { createHash } from "node:crypto";
34333
34419
  function hashJsonUtf8Sha256(value) {
@@ -34504,6 +34590,9 @@ async function probeAgentCapabilitiesForDetectedTypes(params) {
34504
34590
  return changedCount;
34505
34591
  }
34506
34592
 
34593
+ // src/agents/capabilities/warmup-agent-capabilities-on-connect.ts
34594
+ init_yield_to_event_loop();
34595
+
34507
34596
  // src/agents/capabilities/agent-capability-warmup-run.ts
34508
34597
  var warmupEpoch = 0;
34509
34598
  function cancelInFlightAgentCapabilityWarmup() {
@@ -34645,6 +34734,7 @@ async function createBridgeAccessAndAcp(options) {
34645
34734
  }
34646
34735
 
34647
34736
  // src/connection/create-bridge-preview-stack.ts
34737
+ init_cwd();
34648
34738
  import * as path38 from "node:path";
34649
34739
 
34650
34740
  // src/preview-environments/manager/firehose-messages.ts
@@ -35933,11 +36023,11 @@ function tryConsumeBinaryProxyBody(raw, deps) {
35933
36023
  if (!PROXY_ID_RE.test(id)) return false;
35934
36024
  const body = raw.slice(PROXY_ID_BYTES);
35935
36025
  const bodyBytes = body.length > 0 ? new Uint8Array(body) : new Uint8Array(0);
35936
- const pending2 = deps.pendingProxyBody.get(id);
35937
- if (pending2) {
36026
+ const pending = deps.pendingProxyBody.get(id);
36027
+ if (pending) {
35938
36028
  deps.pendingProxyBody.delete(id);
35939
36029
  deps.startStreamingProxy({
35940
- ...pending2.pr,
36030
+ ...pending.pr,
35941
36031
  body: bodyBytes.length > 0 ? bodyBytes : void 0
35942
36032
  });
35943
36033
  return true;
@@ -36299,7 +36389,11 @@ function createBridgeMessageDeps(params) {
36299
36389
  };
36300
36390
  }
36301
36391
 
36392
+ // src/connection/create-bridge-local-reports.ts
36393
+ init_cwd();
36394
+
36302
36395
  // src/skills/discovery/skill-discovery-roots.ts
36396
+ init_yield_to_event_loop();
36303
36397
  var SKILL_DISCOVERY_ROOTS = [".agents/skills", ".claude/skills", ".cursor/skills", "skills"];
36304
36398
  async function yieldSkillDiscoveryWork(entryCount) {
36305
36399
  if (entryCount > 0 && entryCount % INDEX_WORK_YIELD_EVERY === 0) {
@@ -36490,9 +36584,9 @@ function createBridgeHeartbeatController(params) {
36490
36584
  if (awaitingSeq === null) return;
36491
36585
  if (!Number.isFinite(seq)) return;
36492
36586
  const ack = Math.trunc(seq);
36493
- const pending2 = awaitingSeq;
36494
- if (ack < pending2) return;
36495
- if (ack === pending2) {
36587
+ const pending = awaitingSeq;
36588
+ if (ack < pending) return;
36589
+ if (ack === pending) {
36496
36590
  const rtt = Date.now() - sentAtMs;
36497
36591
  if (Number.isFinite(rtt) && rtt >= 0 && rtt < 6e5) {
36498
36592
  rttSamples.push(rtt);
@@ -36624,6 +36718,7 @@ function allocateDirNameForLauncherCwd(layout, bridgeRootPath2) {
36624
36718
  }
36625
36719
 
36626
36720
  // src/worktrees/manager/session-worktree-cache.ts
36721
+ init_normalize_resolved_path();
36627
36722
  var SessionWorktreeCache = class {
36628
36723
  sessionRepoCheckoutPaths = /* @__PURE__ */ new Map();
36629
36724
  sessionParentPathBySession = /* @__PURE__ */ new Map();
@@ -36664,6 +36759,9 @@ function createSessionWorktreeManagerContext(options) {
36664
36759
  };
36665
36760
  }
36666
36761
 
36762
+ // src/worktrees/manager/git/commit-session-worktree.ts
36763
+ init_cwd();
36764
+
36667
36765
  // ../../node_modules/.pnpm/simple-git@3.32.3/node_modules/simple-git/dist/esm/index.js
36668
36766
  var import_file_exists = __toESM(require_dist(), 1);
36669
36767
  var import_debug = __toESM(require_src(), 1);
@@ -36701,8 +36799,8 @@ function pathspec(...paths) {
36701
36799
  cache.set(key, paths);
36702
36800
  return key;
36703
36801
  }
36704
- function isPathSpec(path79) {
36705
- return path79 instanceof String && cache.has(path79);
36802
+ function isPathSpec(path82) {
36803
+ return path82 instanceof String && cache.has(path82);
36706
36804
  }
36707
36805
  function toPaths(pathSpec) {
36708
36806
  return cache.get(pathSpec) || [];
@@ -36791,8 +36889,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
36791
36889
  function forEachLineWithContent(input, callback) {
36792
36890
  return toLinesWithContent(input, true).map((line) => callback(line));
36793
36891
  }
36794
- function folderExists(path79) {
36795
- return (0, import_file_exists.exists)(path79, import_file_exists.FOLDER);
36892
+ function folderExists(path82) {
36893
+ return (0, import_file_exists.exists)(path82, import_file_exists.FOLDER);
36796
36894
  }
36797
36895
  function append(target, item) {
36798
36896
  if (Array.isArray(target)) {
@@ -37196,8 +37294,8 @@ function checkIsRepoRootTask() {
37196
37294
  commands,
37197
37295
  format: "utf-8",
37198
37296
  onError,
37199
- parser(path79) {
37200
- return /^\.(git)?$/.test(path79.trim());
37297
+ parser(path82) {
37298
+ return /^\.(git)?$/.test(path82.trim());
37201
37299
  }
37202
37300
  };
37203
37301
  }
@@ -37631,11 +37729,11 @@ function parseGrep(grep) {
37631
37729
  const paths = /* @__PURE__ */ new Set();
37632
37730
  const results = {};
37633
37731
  forEachLineWithContent(grep, (input) => {
37634
- const [path79, line, preview] = input.split(NULL);
37635
- paths.add(path79);
37636
- (results[path79] = results[path79] || []).push({
37732
+ const [path82, line, preview] = input.split(NULL);
37733
+ paths.add(path82);
37734
+ (results[path82] = results[path82] || []).push({
37637
37735
  line: asNumber(line),
37638
- path: path79,
37736
+ path: path82,
37639
37737
  preview
37640
37738
  });
37641
37739
  });
@@ -38400,14 +38498,14 @@ var init_hash_object = __esm2({
38400
38498
  init_task();
38401
38499
  }
38402
38500
  });
38403
- function parseInit(bare, path79, text) {
38501
+ function parseInit(bare, path82, text) {
38404
38502
  const response = String(text).trim();
38405
38503
  let result;
38406
38504
  if (result = initResponseRegex.exec(response)) {
38407
- return new InitSummary(bare, path79, false, result[1]);
38505
+ return new InitSummary(bare, path82, false, result[1]);
38408
38506
  }
38409
38507
  if (result = reInitResponseRegex.exec(response)) {
38410
- return new InitSummary(bare, path79, true, result[1]);
38508
+ return new InitSummary(bare, path82, true, result[1]);
38411
38509
  }
38412
38510
  let gitDir = "";
38413
38511
  const tokens = response.split(" ");
@@ -38418,7 +38516,7 @@ function parseInit(bare, path79, text) {
38418
38516
  break;
38419
38517
  }
38420
38518
  }
38421
- return new InitSummary(bare, path79, /^re/i.test(response), gitDir);
38519
+ return new InitSummary(bare, path82, /^re/i.test(response), gitDir);
38422
38520
  }
38423
38521
  var InitSummary;
38424
38522
  var initResponseRegex;
@@ -38427,9 +38525,9 @@ var init_InitSummary = __esm2({
38427
38525
  "src/lib/responses/InitSummary.ts"() {
38428
38526
  "use strict";
38429
38527
  InitSummary = class {
38430
- constructor(bare, path79, existing, gitDir) {
38528
+ constructor(bare, path82, existing, gitDir) {
38431
38529
  this.bare = bare;
38432
- this.path = path79;
38530
+ this.path = path82;
38433
38531
  this.existing = existing;
38434
38532
  this.gitDir = gitDir;
38435
38533
  }
@@ -38441,7 +38539,7 @@ var init_InitSummary = __esm2({
38441
38539
  function hasBareCommand(command) {
38442
38540
  return command.includes(bareCommand);
38443
38541
  }
38444
- function initTask(bare = false, path79, customArgs) {
38542
+ function initTask(bare = false, path82, customArgs) {
38445
38543
  const commands = ["init", ...customArgs];
38446
38544
  if (bare && !hasBareCommand(commands)) {
38447
38545
  commands.splice(1, 0, bareCommand);
@@ -38450,7 +38548,7 @@ function initTask(bare = false, path79, customArgs) {
38450
38548
  commands,
38451
38549
  format: "utf-8",
38452
38550
  parser(text) {
38453
- return parseInit(commands.includes("--bare"), path79, text);
38551
+ return parseInit(commands.includes("--bare"), path82, text);
38454
38552
  }
38455
38553
  };
38456
38554
  }
@@ -39266,12 +39364,12 @@ var init_FileStatusSummary = __esm2({
39266
39364
  "use strict";
39267
39365
  fromPathRegex = /^(.+)\0(.+)$/;
39268
39366
  FileStatusSummary = class {
39269
- constructor(path79, index, working_dir) {
39270
- this.path = path79;
39367
+ constructor(path82, index, working_dir) {
39368
+ this.path = path82;
39271
39369
  this.index = index;
39272
39370
  this.working_dir = working_dir;
39273
39371
  if (index === "R" || working_dir === "R") {
39274
- const detail = fromPathRegex.exec(path79) || [null, path79, path79];
39372
+ const detail = fromPathRegex.exec(path82) || [null, path82, path82];
39275
39373
  this.from = detail[2] || "";
39276
39374
  this.path = detail[1] || "";
39277
39375
  }
@@ -39302,14 +39400,14 @@ function splitLine(result, lineStr) {
39302
39400
  default:
39303
39401
  return;
39304
39402
  }
39305
- function data(index, workingDir, path79) {
39403
+ function data(index, workingDir, path82) {
39306
39404
  const raw = `${index}${workingDir}`;
39307
39405
  const handler = parsers6.get(raw);
39308
39406
  if (handler) {
39309
- handler(result, path79);
39407
+ handler(result, path82);
39310
39408
  }
39311
39409
  if (raw !== "##" && raw !== "!!") {
39312
- result.files.push(new FileStatusSummary(path79, index, workingDir));
39410
+ result.files.push(new FileStatusSummary(path82, index, workingDir));
39313
39411
  }
39314
39412
  }
39315
39413
  }
@@ -39618,9 +39716,9 @@ var init_simple_git_api = __esm2({
39618
39716
  next
39619
39717
  );
39620
39718
  }
39621
- hashObject(path79, write) {
39719
+ hashObject(path82, write) {
39622
39720
  return this._runTask(
39623
- hashObjectTask(path79, write === true),
39721
+ hashObjectTask(path82, write === true),
39624
39722
  trailingFunctionArgument(arguments)
39625
39723
  );
39626
39724
  }
@@ -39973,8 +40071,8 @@ var init_branch = __esm2({
39973
40071
  }
39974
40072
  });
39975
40073
  function toPath(input) {
39976
- const path79 = input.trim().replace(/^["']|["']$/g, "");
39977
- return path79 && normalize3(path79);
40074
+ const path82 = input.trim().replace(/^["']|["']$/g, "");
40075
+ return path82 && normalize3(path82);
39978
40076
  }
39979
40077
  var parseCheckIgnore;
39980
40078
  var init_CheckIgnore = __esm2({
@@ -40288,8 +40386,8 @@ __export2(sub_module_exports, {
40288
40386
  subModuleTask: () => subModuleTask,
40289
40387
  updateSubModuleTask: () => updateSubModuleTask
40290
40388
  });
40291
- function addSubModuleTask(repo, path79) {
40292
- return subModuleTask(["add", repo, path79]);
40389
+ function addSubModuleTask(repo, path82) {
40390
+ return subModuleTask(["add", repo, path82]);
40293
40391
  }
40294
40392
  function initSubModuleTask(customArgs) {
40295
40393
  return subModuleTask(["init", ...customArgs]);
@@ -40622,8 +40720,8 @@ var require_git = __commonJS2({
40622
40720
  }
40623
40721
  return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
40624
40722
  };
40625
- Git2.prototype.submoduleAdd = function(repo, path79, then) {
40626
- return this._runTask(addSubModuleTask2(repo, path79), trailingFunctionArgument2(arguments));
40723
+ Git2.prototype.submoduleAdd = function(repo, path82, then) {
40724
+ return this._runTask(addSubModuleTask2(repo, path82), trailingFunctionArgument2(arguments));
40627
40725
  };
40628
40726
  Git2.prototype.submoduleUpdate = function(args, then) {
40629
40727
  return this._runTask(
@@ -41359,8 +41457,8 @@ function parseNumstatEntries(lines) {
41359
41457
  }
41360
41458
  function parseNumstat(lines) {
41361
41459
  const m = /* @__PURE__ */ new Map();
41362
- for (const [path79, entry] of parseNumstatEntries(lines)) {
41363
- m.set(path79, { additions: entry.additions, deletions: entry.deletions });
41460
+ for (const [path82, entry] of parseNumstatEntries(lines)) {
41461
+ m.set(path82, { additions: entry.additions, deletions: entry.deletions });
41364
41462
  }
41365
41463
  return m;
41366
41464
  }
@@ -41558,6 +41656,7 @@ async function pushAheadOfUpstreamForPaths(paths) {
41558
41656
  }
41559
41657
 
41560
41658
  // src/worktrees/manager/resolve-commit-targets.ts
41659
+ init_cwd();
41561
41660
  function bridgeRootBinding(bridgeRoot) {
41562
41661
  return {
41563
41662
  sessionParentPath: bridgeRoot,
@@ -41643,6 +41742,7 @@ function formatRemoteDisplayLabel(remoteUrl) {
41643
41742
  }
41644
41743
 
41645
41744
  // src/git/changes/repo/get-working-tree-change-repo-details.ts
41745
+ init_cwd();
41646
41746
  import * as path51 from "node:path";
41647
41747
 
41648
41748
  // src/git/changes/repo/build-working-tree-change-repo-detail.ts
@@ -41892,6 +41992,7 @@ function createHydrateSourceLines(options) {
41892
41992
  }
41893
41993
 
41894
41994
  // src/git/changes/patch/hydrate/create-hydrate-yield.ts
41995
+ init_yield_to_event_loop();
41895
41996
  function createHydrateYield() {
41896
41997
  let processedLines = 0;
41897
41998
  return async () => {
@@ -42655,6 +42756,7 @@ function parseWorkingTreeChangeKind(value) {
42655
42756
  }
42656
42757
 
42657
42758
  // src/worktrees/manager/git/get-session-working-tree-change-file-patch.ts
42759
+ init_cwd();
42658
42760
  import * as path53 from "node:path";
42659
42761
  async function getSessionWorkingTreeChangeFilePatch(cache2, sessionId, discover, opts) {
42660
42762
  const targets = await resolveCommitTargetsAsync(sessionId, cache2, discover);
@@ -42705,6 +42807,8 @@ import * as fs35 from "node:fs";
42705
42807
  import * as fs34 from "node:fs";
42706
42808
 
42707
42809
  // src/worktrees/is-removable-session-worktree-checkout-path.ts
42810
+ init_cwd();
42811
+ init_normalize_resolved_path();
42708
42812
  import path54 from "node:path";
42709
42813
  function isBridgeRootCheckoutPath(checkoutPath) {
42710
42814
  return normalizeResolvedPath(checkoutPath) === normalizeResolvedPath(getBridgeRoot());
@@ -42805,9 +42909,13 @@ async function renameSessionWorktreeBranch(cache2, sessionId, newBranch, log2) {
42805
42909
  await renameSessionWorktreeBranches(paths, newBranch, log2);
42806
42910
  }
42807
42911
 
42912
+ // src/worktrees/manager/discover-session-binding.ts
42913
+ init_cwd();
42914
+
42808
42915
  // src/worktrees/discovery/discover-session-worktree-on-disk.ts
42809
42916
  import * as fs39 from "node:fs";
42810
42917
  import * as path60 from "node:path";
42918
+ init_yield_to_event_loop();
42811
42919
 
42812
42920
  // src/worktrees/discovery/collect-worktree-paths.ts
42813
42921
  import * as fs37 from "node:fs";
@@ -42841,6 +42949,7 @@ function shouldSkipDiskWalkEntry(name) {
42841
42949
  // src/worktrees/discovery/disk-walk-utils.ts
42842
42950
  import * as fs36 from "node:fs";
42843
42951
  import * as path56 from "node:path";
42952
+ init_yield_to_event_loop();
42844
42953
  async function yieldDuringDiskWalk(state) {
42845
42954
  state.entries++;
42846
42955
  if (state.entries % DISK_WALK_YIELD_EVERY !== 0) return true;
@@ -43030,6 +43139,7 @@ import * as path62 from "node:path";
43030
43139
 
43031
43140
  // src/worktrees/discovery/discover-legacy-binding-ascending-from-checkout.ts
43032
43141
  import * as path61 from "node:path";
43142
+ init_yield_to_event_loop();
43033
43143
  async function discoverLegacyBindingAscendingFromCheckout(sessionId, checkoutPath) {
43034
43144
  const sid = sessionId.trim();
43035
43145
  if (!sid) return null;
@@ -43147,11 +43257,16 @@ function parseSessionParent(v) {
43147
43257
  return null;
43148
43258
  }
43149
43259
 
43260
+ // src/worktrees/manager/prepare-and-remember-session-worktrees.ts
43261
+ init_cwd();
43262
+
43150
43263
  // src/worktrees/prepare-new-isolated-worktrees.ts
43151
43264
  import * as fs42 from "node:fs";
43152
43265
  import * as path64 from "node:path";
43153
43266
 
43154
43267
  // src/git/discover-repos.ts
43268
+ init_cwd();
43269
+ init_yield_to_event_loop();
43155
43270
  import * as fs41 from "node:fs";
43156
43271
  import * as path63 from "node:path";
43157
43272
  var GIT_DISCOVER_YIELD_EVERY = 32;
@@ -43379,6 +43494,7 @@ async function resolveExistingSessionParentPath(sessionId, cache2, discover) {
43379
43494
 
43380
43495
  // src/worktrees/manager/resolve-explicit-session-parent-path.ts
43381
43496
  import * as path65 from "node:path";
43497
+ init_yield_to_event_loop();
43382
43498
  async function resolveExplicitSessionParentPath(params) {
43383
43499
  const resolved = path65.resolve(params.parentPathRaw);
43384
43500
  if (parseSessionParent(params.sessionParent) !== "worktrees_root") {
@@ -43544,7 +43660,12 @@ var SessionWorktreeManager = class {
43544
43660
  }
43545
43661
  };
43546
43662
 
43663
+ // src/worktrees/manager/preview-worktree-manager.ts
43664
+ init_cwd();
43665
+
43547
43666
  // src/worktrees/discovery/discover-preview-worktree-on-disk.ts
43667
+ init_cwd();
43668
+ init_yield_to_event_loop();
43548
43669
  import * as fs43 from "node:fs";
43549
43670
  import * as path66 from "node:path";
43550
43671
  async function discoverPreviewWorktreeOnDisk(options) {
@@ -43595,6 +43716,7 @@ async function discoverPreviewWorktreeForBridge(options) {
43595
43716
  }
43596
43717
 
43597
43718
  // src/worktrees/manager/preview-worktree-cache.ts
43719
+ init_normalize_resolved_path();
43598
43720
  var PreviewWorktreeCache = class {
43599
43721
  repoCheckoutPaths = /* @__PURE__ */ new Map();
43600
43722
  parentPathByEnvironment = /* @__PURE__ */ new Map();
@@ -43707,6 +43829,7 @@ var PreviewWorktreeManager = class {
43707
43829
  };
43708
43830
 
43709
43831
  // src/worktrees/deploy/deploy-session-to-preview-environment.ts
43832
+ init_cwd();
43710
43833
  import * as path70 from "node:path";
43711
43834
 
43712
43835
  // src/git/worktrees/reset-worktree-to-branch.ts
@@ -44266,8 +44389,6 @@ function dispatchLocalPrompt(next, deps) {
44266
44389
  ...sessionParentPath ? { sessionParentPath } : {},
44267
44390
  ...worktreeBaseBranches && Object.keys(worktreeBaseBranches).length > 0 ? { worktreeBaseBranches } : {},
44268
44391
  ...typeof pl.followUpCatalogPromptId === "string" ? { followUpCatalogPromptId: pl.followUpCatalogPromptId } : {},
44269
- ...Array.isArray(pl.sessionChangeSummaryFilePaths) ? { sessionChangeSummaryFilePaths: pl.sessionChangeSummaryFilePaths } : {},
44270
- ...Array.isArray(pl.sessionChangeSummaryFileSnapshots) ? { sessionChangeSummaryFileSnapshots: pl.sessionChangeSummaryFileSnapshots } : {},
44271
44392
  ...typeof pl.agentType === "string" && pl.agentType.trim() ? { agentType: pl.agentType.trim() } : {},
44272
44393
  ...pl.agentConfig != null && typeof pl.agentConfig === "object" && !Array.isArray(pl.agentConfig) && Object.keys(pl.agentConfig).length > 0 ? { agentConfig: pl.agentConfig } : {},
44273
44394
  ...Array.isArray(pl.attachments) && pl.attachments.length > 0 ? { attachments: pl.attachments } : {}
@@ -44406,6 +44527,7 @@ async function applyPreTurnSnapshot(filePath, log2) {
44406
44527
  }
44407
44528
 
44408
44529
  // src/prompt-turn-queue/runner/run-local-revert-before-queued-prompt.ts
44530
+ init_cwd();
44409
44531
  async function runLocalRevertBeforeQueuedPrompt(next, deps) {
44410
44532
  if (next.bridgeServerState !== "requeued_with_revert") return true;
44411
44533
  const sid = next.sessionId;
@@ -44530,8 +44652,7 @@ function createBridgePromptSenders(deps, getWs) {
44530
44652
  return true;
44531
44653
  };
44532
44654
  const sendResult = (result) => {
44533
- const skipEncryptForChangeSummaryFollowUp = result.type === "prompt_result" && result.followUpCatalogPromptId === BUILTIN_SESSION_CHANGE_SUMMARY_FOLLOW_UP_CATALOG_PROMPT_ID;
44534
- const encryptedFields = result.type === "prompt_result" && !skipEncryptForChangeSummaryFollowUp ? ["output", "error"] : [];
44655
+ const encryptedFields = result.type === "prompt_result" ? ["output", "error"] : [];
44535
44656
  sendBridgeMessage(result, encryptedFields);
44536
44657
  if (result.type === "prompt_result") {
44537
44658
  const pr = result;
@@ -44595,62 +44716,8 @@ function parseWorktreeBaseBranches(msg) {
44595
44716
  return Object.keys(out).length > 0 ? out : void 0;
44596
44717
  }
44597
44718
 
44598
- // src/agents/acp/change-summary/decrypt-change-summary-file-input.ts
44599
- function decryptChangeSummaryFileInput(row, e2ee) {
44600
- if (!e2ee) return row;
44601
- for (const field of ["path", "patchContent", "oldText", "newText"]) {
44602
- const raw = row[field];
44603
- if (typeof raw !== "string" || raw.trim() === "") continue;
44604
- let o;
44605
- try {
44606
- o = JSON.parse(raw);
44607
- } catch {
44608
- continue;
44609
- }
44610
- if (!isE2eeEnvelope(o.ee)) continue;
44611
- try {
44612
- const d = e2ee.decryptMessage(o);
44613
- const out = {
44614
- path: typeof d.path === "string" ? d.path : row.path
44615
- };
44616
- if (d.directoryRemoved === true) out.directoryRemoved = true;
44617
- else if (row.directoryRemoved === true) out.directoryRemoved = true;
44618
- if (typeof d.patchContent === "string") out.patchContent = d.patchContent;
44619
- else if (typeof row.patchContent === "string" && row.patchContent !== raw) out.patchContent = row.patchContent;
44620
- if (typeof d.oldText === "string") out.oldText = d.oldText;
44621
- else if (typeof row.oldText === "string") out.oldText = row.oldText;
44622
- if (typeof d.newText === "string") out.newText = d.newText;
44623
- else if (typeof row.newText === "string") out.newText = row.newText;
44624
- return out;
44625
- } catch {
44626
- return row;
44627
- }
44628
- }
44629
- return row;
44630
- }
44631
-
44632
- // src/agents/acp/change-summary/resolve-change-summary-prompt-for-agent.ts
44633
- function hasSummarizePayload(f) {
44634
- return f.directoryRemoved === true || f.patchContent != null && f.patchContent.trim() !== "" || f.oldText != null && f.oldText.trim() !== "" || f.newText != null && f.newText.trim() !== "";
44635
- }
44636
- function resolveChangeSummaryPromptForAgent(params) {
44637
- const isBuiltin = params.followUpCatalogPromptId === BUILTIN_SESSION_CHANGE_SUMMARY_FOLLOW_UP_CATALOG_PROMPT_ID;
44638
- const snaps = params.sessionChangeSummaryFileSnapshots;
44639
- if (!isBuiltin || !snaps || snaps.length === 0) {
44640
- return { promptText: params.bridgePromptText, sessionChangeSummaryFilePaths: void 0 };
44641
- }
44642
- const decrypted = dedupeSessionFileChangesByPath(snaps.map((row) => decryptChangeSummaryFileInput(row, params.e2ee)));
44643
- const withPayload = decrypted.filter(hasSummarizePayload);
44644
- if (withPayload.length === 0) {
44645
- return { promptText: params.bridgePromptText, sessionChangeSummaryFilePaths: void 0 };
44646
- }
44647
- return {
44648
- promptText: buildSessionChangeSummaryPrompt(withPayload),
44649
- sessionChangeSummaryFilePaths: withPayload.map((f) => f.path)
44650
- };
44651
- }
44652
-
44653
44719
  // src/agents/acp/from-bridge/bridge-prompt-preamble.ts
44720
+ init_cwd();
44654
44721
  import { execFile as execFile8 } from "node:child_process";
44655
44722
  import { promisify as promisify9 } from "node:util";
44656
44723
  var execFileAsync7 = promisify9(execFile8);
@@ -44696,29 +44763,9 @@ async function runBridgePromptPreamble(params) {
44696
44763
  });
44697
44764
  }
44698
44765
  }
44699
- function parseChangeSummarySnapshots(raw) {
44700
- if (!Array.isArray(raw) || raw.length === 0) return void 0;
44701
- const out = [];
44702
- for (const item of raw) {
44703
- if (!item || typeof item !== "object") continue;
44704
- const o = item;
44705
- const path79 = typeof o.path === "string" && o.path.trim() !== "" ? o.path.trim() : "";
44706
- if (!path79) continue;
44707
- const row = { path: path79 };
44708
- if (typeof o.patchContent === "string") row.patchContent = o.patchContent;
44709
- if (typeof o.oldText === "string") row.oldText = o.oldText;
44710
- if (typeof o.newText === "string") row.newText = o.newText;
44711
- if (o.directoryRemoved === true) row.directoryRemoved = true;
44712
- out.push(row);
44713
- }
44714
- return out.length > 0 ? out : void 0;
44715
- }
44716
44766
  function parseFollowUpFieldsFromPromptMessage(msg) {
44717
44767
  const followUpCatalogPromptId = typeof msg.followUpCatalogPromptId === "string" && msg.followUpCatalogPromptId.trim() !== "" ? msg.followUpCatalogPromptId.trim() : null;
44718
- const rawPaths = msg.sessionChangeSummaryFilePaths;
44719
- const sessionChangeSummaryFilePaths = Array.isArray(rawPaths) ? rawPaths.filter((p) => typeof p === "string" && p.trim() !== "").map((p) => p.trim()) : void 0;
44720
- const sessionChangeSummaryFileSnapshots = parseChangeSummarySnapshots(msg.sessionChangeSummaryFileSnapshots);
44721
- return { followUpCatalogPromptId, sessionChangeSummaryFilePaths, sessionChangeSummaryFileSnapshots };
44768
+ return { followUpCatalogPromptId };
44722
44769
  }
44723
44770
 
44724
44771
  // src/agents/acp/from-bridge/handle-bridge-prompt/run-preamble-and-prompt.ts
@@ -44749,25 +44796,9 @@ async function runPreambleAndPrompt(params) {
44749
44796
  runId,
44750
44797
  effectiveCwd
44751
44798
  });
44752
- const {
44753
- followUpCatalogPromptId,
44754
- sessionChangeSummaryFilePaths: pathsFromBridge,
44755
- sessionChangeSummaryFileSnapshots
44756
- } = parseFollowUpFieldsFromPromptMessage(msg);
44757
- const { promptText: resolvedPromptText, sessionChangeSummaryFilePaths } = resolveChangeSummaryPromptForAgent({
44758
- followUpCatalogPromptId,
44759
- sessionChangeSummaryFileSnapshots,
44760
- bridgePromptText: promptText,
44761
- e2ee: deps.e2ee
44762
- });
44763
- if (sessionChangeSummaryFileSnapshots && sessionChangeSummaryFileSnapshots.length > 0 && resolvedPromptText === promptText) {
44764
- deps.log(
44765
- "[Agent] Change-summary snapshots were present but the prompt was not rebuilt (decrypt failed or empty payloads); sending the bridge prompt as-is."
44766
- );
44767
- }
44768
- const pathsForUpload = sessionChangeSummaryFilePaths ?? pathsFromBridge;
44799
+ const { followUpCatalogPromptId } = parseFollowUpFieldsFromPromptMessage(msg);
44769
44800
  deps.acpManager.handlePrompt({
44770
- promptText: resolvedPromptText,
44801
+ promptText,
44771
44802
  promptId: msg.id,
44772
44803
  sessionId,
44773
44804
  runId,
@@ -44779,7 +44810,6 @@ async function runPreambleAndPrompt(params) {
44779
44810
  sendResult,
44780
44811
  sendSessionUpdate,
44781
44812
  followUpCatalogPromptId,
44782
- sessionChangeSummaryFilePaths: pathsForUpload,
44783
44813
  cloudApiBaseUrl: deps.cloudApiBaseUrl,
44784
44814
  getCloudAccessToken: deps.getCloudAccessToken,
44785
44815
  e2ee: deps.e2ee,
@@ -44919,6 +44949,8 @@ var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
44919
44949
  };
44920
44950
 
44921
44951
  // src/files/resolve-file-browser-session-parent.ts
44952
+ init_normalize_resolved_path();
44953
+ init_cwd();
44922
44954
  async function resolveFileBrowserSessionParent(sessionWorktreeManager, sessionId) {
44923
44955
  const sid = sessionId?.trim();
44924
44956
  if (sid) {
@@ -44929,301 +44961,18 @@ async function resolveFileBrowserSessionParent(sessionWorktreeManager, sessionId
44929
44961
  return getBridgeRoot();
44930
44962
  }
44931
44963
 
44932
- // src/files/list-dir/index.ts
44933
- import fs48 from "node:fs";
44934
-
44935
- // src/files/ensure-under-cwd.ts
44936
- import path73 from "node:path";
44937
- function ensureUnderCwd(relativePath, cwd = getBridgeRoot()) {
44938
- const normalized = path73.normalize(relativePath).replace(/^(\.\/)+/, "");
44939
- const resolved = path73.resolve(cwd, normalized);
44940
- if (!resolved.startsWith(cwd + path73.sep) && resolved !== cwd) {
44941
- return null;
44942
- }
44943
- return resolved;
44944
- }
44945
-
44946
- // src/files/list-dir/types.ts
44947
- var LIST_DIR_YIELD_EVERY = 256;
44948
-
44949
- // src/files/list-dir/map-dir-entry.ts
44950
- import path74 from "node:path";
44951
- import fs47 from "node:fs";
44952
- async function mapDirEntry(d, relativePath, resolved) {
44953
- const entryPath = path74.join(relativePath || ".", d.name).replace(/\\/g, "/");
44954
- const fullPath = path74.join(resolved, d.name);
44955
- let isDir = d.isDirectory();
44956
- if (d.isSymbolicLink()) {
44957
- try {
44958
- const targetStat = await fs47.promises.stat(fullPath);
44959
- isDir = targetStat.isDirectory();
44960
- } catch {
44961
- isDir = false;
44962
- }
44963
- }
44964
- return {
44965
- name: d.name,
44966
- path: entryPath,
44967
- isDir,
44968
- isSymlink: d.isSymbolicLink()
44969
- };
44970
- }
44971
-
44972
- // src/files/list-dir/sort-entries.ts
44973
- function sortListEntries(entries) {
44974
- return entries.sort((a, b) => {
44975
- if (a.isDir !== b.isDir) return a.isDir ? -1 : 1;
44976
- return a.name.localeCompare(b.name, void 0, { sensitivity: "base" });
44977
- });
44978
- }
44979
-
44980
- // src/files/list-dir/index.ts
44981
- async function listDirAsync(relativePath, sessionParentPath = getBridgeRoot()) {
44982
- await yieldToEventLoop();
44983
- const resolved = ensureUnderCwd(relativePath || ".", sessionParentPath);
44984
- if (!resolved) {
44985
- return { error: "Path is outside working directory" };
44986
- }
44987
- try {
44988
- const names = await fs48.promises.readdir(resolved, { withFileTypes: true });
44989
- const entries = [];
44990
- for (let i = 0; i < names.length; i++) {
44991
- if (i > 0 && i % LIST_DIR_YIELD_EVERY === 0) {
44992
- await yieldToEventLoop();
44993
- }
44994
- entries.push(await mapDirEntry(names[i], relativePath, resolved));
44995
- }
44996
- return { entries: sortListEntries(entries) };
44997
- } catch (err) {
44998
- const message = err instanceof Error ? err.message : String(err);
44999
- return { error: message };
45000
- }
45001
- }
45002
-
45003
- // src/files/handle-file-browser-search.ts
45004
- import path75 from "node:path";
45005
- var SEARCH_LIMIT = 100;
45006
- function handleFileBrowserSearch(msg, socket, e2ee, sessionWorktreeManager) {
45007
- void (async () => {
45008
- await yieldToEventLoop();
45009
- const q = typeof msg.q === "string" ? msg.q : "";
45010
- const sessionParentPath = path75.resolve(
45011
- sessionWorktreeManager != null ? await resolveFileBrowserSessionParent(sessionWorktreeManager, msg.sessionId) : getBridgeRoot()
45012
- );
45013
- if (!await bridgeFileIndexIsPopulated(sessionParentPath)) {
45014
- const payload2 = {
45015
- type: "file_browser_search_response",
45016
- id: msg.id,
45017
- paths: [],
45018
- indexReady: false
45019
- };
45020
- sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload2, ["paths"]) : payload2);
45021
- return;
45022
- }
45023
- const results = await searchBridgeFilePathsAsync(sessionParentPath, q, SEARCH_LIMIT);
45024
- const payload = {
45025
- type: "file_browser_search_response",
45026
- id: msg.id,
45027
- paths: results,
45028
- indexReady: true
45029
- };
45030
- sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload, ["paths"]) : payload);
45031
- })();
45032
- }
45033
- function triggerFileIndexBuild(sessionParentPath = getBridgeRoot()) {
45034
- setImmediate(() => {
45035
- void ensureFileIndexAsync(sessionParentPath).catch((e) => {
45036
- console.error("[file-index] Background build failed:", e);
45037
- });
45038
- });
45039
- }
45040
-
45041
- // src/code-nav/handlers/send-code-nav-response.ts
45042
- var ENCRYPTED_FIELDS = ["definition", "definitions", "references", "symbols", "confidentTarget"];
45043
- function sendCodeNavResponse(socket, e2ee, payload) {
45044
- const fieldsToEncrypt = ENCRYPTED_FIELDS.filter((field) => field in payload && payload[field] !== void 0);
45045
- sendWsMessage(
45046
- socket,
45047
- e2ee && fieldsToEncrypt.length > 0 ? e2ee.encryptFields(payload, [...fieldsToEncrypt]) : payload
45048
- );
45049
- }
45050
-
45051
- // src/code-nav/handlers/handle-definition-op.ts
45052
- async function handleDefinitionOp(ctx) {
45053
- const definition = await queryDefinitionAt(ctx.sessionParentPath, ctx.reqPath, ctx.line, ctx.column);
45054
- sendCodeNavResponse(ctx.socket, ctx.e2ee, {
45055
- type: "code_nav_response",
45056
- id: ctx.msg.id,
45057
- indexReady: true,
45058
- definition
45059
- });
45060
- }
45061
-
45062
- // src/code-nav/handlers/handle-definitions-op.ts
45063
- async function handleDefinitionsOp(ctx) {
45064
- const { definitions, confidentTarget } = await queryDefinitionsNavigation(
45065
- ctx.sessionParentPath,
45066
- ctx.reqPath,
45067
- ctx.line,
45068
- ctx.column
45069
- );
45070
- sendCodeNavResponse(ctx.socket, ctx.e2ee, {
45071
- type: "code_nav_response",
45072
- id: ctx.msg.id,
45073
- indexReady: true,
45074
- definitions,
45075
- confidentTarget
45076
- });
45077
- }
45078
-
45079
- // src/code-nav/handlers/handle-references-op.ts
45080
- async function handleReferencesOp(ctx) {
45081
- const references = await queryReferencesAt(ctx.sessionParentPath, ctx.reqPath, ctx.line, ctx.column);
45082
- sendCodeNavResponse(ctx.socket, ctx.e2ee, {
45083
- type: "code_nav_response",
45084
- id: ctx.msg.id,
45085
- indexReady: true,
45086
- references
45087
- });
45088
- }
45089
-
45090
- // src/code-nav/handlers/handle-symbols-op.ts
45091
- async function handleSymbolsOp(ctx) {
45092
- const symbols = await querySymbolsInFile(ctx.sessionParentPath, ctx.reqPath);
45093
- sendCodeNavResponse(ctx.socket, ctx.e2ee, {
45094
- type: "code_nav_response",
45095
- id: ctx.msg.id,
45096
- indexReady: true,
45097
- symbols
45098
- });
45099
- }
45100
-
45101
- // src/code-nav/handlers/code-nav-op-context.ts
45102
- function normalizeCodeNavOp(op) {
45103
- if (op === "references" || op === "symbols" || op === "definitions") return op;
45104
- return "definition";
45105
- }
45106
-
45107
- // src/code-nav/handlers/resolve-code-nav-parent.ts
45108
- async function resolveCodeNavParentPath(sessionWorktreeManager, sessionId) {
45109
- const parent = sessionWorktreeManager != null ? await resolveFileBrowserSessionParent(sessionWorktreeManager, sessionId) : getBridgeRoot();
45110
- return normalizeResolvedPath(parent);
45111
- }
45112
-
45113
- // src/code-nav/handlers/prepare-code-nav-request.ts
45114
- var CODE_NAV_INDEX_READY_WAIT_MS = 75;
45115
- var CODE_NAV_INDEX_READY_POLL_MS = 15;
45116
- function delay2(ms) {
45117
- return new Promise((resolve35) => setTimeout(resolve35, ms));
45118
- }
45119
- async function waitForSymbolIndexReady(sessionParentPath, reqPath) {
45120
- const deadline = Date.now() + CODE_NAV_INDEX_READY_WAIT_MS;
45121
- do {
45122
- if (await symbolIndexFileIsReadyAsync(sessionParentPath, reqPath)) return true;
45123
- await delay2(CODE_NAV_INDEX_READY_POLL_MS);
45124
- } while (Date.now() < deadline);
45125
- return await symbolIndexFileIsReadyAsync(sessionParentPath, reqPath);
45126
- }
45127
- async function prepareCodeNavRequest(msg, socket, e2ee, sessionWorktreeManager) {
45128
- await yieldToEventLoop();
45129
- const reqPath = msg.path.replace(/^\/+/, "") || "";
45130
- if (!reqPath) {
45131
- sendCodeNavResponse(socket, e2ee, {
45132
- type: "code_nav_response",
45133
- id: msg.id,
45134
- error: "Path required"
45135
- });
45136
- return null;
45137
- }
45138
- const sessionParentPath = await resolveCodeNavParentPath(sessionWorktreeManager, msg.sessionId);
45139
- await registerSymbolIndexParentAsync(sessionParentPath);
45140
- scheduleSymbolIndexFile(sessionParentPath, reqPath);
45141
- const indexReady = await waitForSymbolIndexReady(sessionParentPath, reqPath);
45142
- if (indexReady) {
45143
- const importTargets = await listDirectImportTargetsForFileAsync(sessionParentPath, reqPath);
45144
- scheduleSymbolIndexImportNeighbors(sessionParentPath, importTargets);
45145
- }
45146
- scheduleSymbolIndexWarmup(sessionParentPath);
45147
- await yieldToEventLoop();
45148
- return {
45149
- socket,
45150
- e2ee,
45151
- msg,
45152
- reqPath,
45153
- sessionParentPath,
45154
- line: typeof msg.line === "number" ? msg.line : 1,
45155
- column: typeof msg.column === "number" ? msg.column : 0,
45156
- indexReady
45157
- };
45158
- }
45159
- function sendIndexNotReadyResponse(ctx) {
45160
- sendCodeNavResponse(ctx.socket, ctx.e2ee, {
45161
- type: "code_nav_response",
45162
- id: ctx.msg.id,
45163
- indexReady: false,
45164
- definition: null,
45165
- definitions: [],
45166
- references: [],
45167
- symbols: []
45168
- });
45169
- }
45170
- function preparedOpContext(ctx) {
45171
- return {
45172
- socket: ctx.socket,
45173
- e2ee: ctx.e2ee,
45174
- msg: { ...ctx.msg, op: normalizeCodeNavOp(ctx.msg.op) },
45175
- reqPath: ctx.reqPath,
45176
- sessionParentPath: ctx.sessionParentPath,
45177
- line: ctx.line,
45178
- column: ctx.column
45179
- };
45180
- }
45181
-
45182
- // src/code-nav/handlers/handle-code-nav-request.ts
45183
- function handleCodeNavRequest(msg, socket, e2ee, sessionWorktreeManager) {
45184
- void (async () => {
45185
- const prepared = await prepareCodeNavRequest(msg, socket, e2ee, sessionWorktreeManager);
45186
- if (prepared == null) return;
45187
- if (!prepared.indexReady) {
45188
- sendIndexNotReadyResponse(prepared);
45189
- return;
45190
- }
45191
- const ctx = preparedOpContext(prepared);
45192
- switch (ctx.msg.op) {
45193
- case "symbols":
45194
- await handleSymbolsOp(ctx);
45195
- return;
45196
- case "references":
45197
- await handleReferencesOp(ctx);
45198
- return;
45199
- case "definitions":
45200
- await handleDefinitionsOp(ctx);
45201
- return;
45202
- default:
45203
- await handleDefinitionOp(ctx);
45204
- }
45205
- })();
45206
- }
45207
-
45208
- // src/code-nav/handlers/trigger-symbol-index-build.ts
45209
- function triggerSymbolIndexBuild(parentPath) {
45210
- setImmediate(() => {
45211
- void (async () => {
45212
- const resolved = normalizeResolvedPath(parentPath);
45213
- await registerSymbolIndexParentAsync(resolved);
45214
- scheduleSymbolIndexWarmup(resolved);
45215
- })();
45216
- });
45217
- }
44964
+ // src/files/browser/handle-file-browser-list.ts
44965
+ init_list_dir();
45218
44966
 
45219
44967
  // src/git/tree/resolve-repo-abs-path.ts
45220
- import * as path76 from "node:path";
44968
+ init_cwd();
44969
+ import * as path75 from "node:path";
45221
44970
  function resolveRepoAbsPathFromBridge(repoRelPath, bridgeRoot = getBridgeRoot()) {
45222
- const bridgeResolved = path76.resolve(bridgeRoot);
44971
+ const bridgeResolved = path75.resolve(bridgeRoot);
45223
44972
  const rel = repoRelPath.trim() === "." ? "" : repoRelPath.trim().replace(/\\/g, "/");
45224
- const repoPath = rel === "" ? bridgeResolved : path76.join(bridgeResolved, rel);
45225
- const resolved = path76.resolve(repoPath);
45226
- if (!resolved.startsWith(bridgeResolved + path76.sep) && resolved !== bridgeResolved) {
44973
+ const repoPath = rel === "" ? bridgeResolved : path75.join(bridgeResolved, rel);
44974
+ const resolved = path75.resolve(repoPath);
44975
+ if (!resolved.startsWith(bridgeResolved + path75.sep) && resolved !== bridgeResolved) {
45227
44976
  return null;
45228
44977
  }
45229
44978
  return resolved;
@@ -45241,6 +44990,9 @@ async function resolveBranchCommit(repoAbsPath, branch) {
45241
44990
  }
45242
44991
 
45243
44992
  // src/git/tree/list-git-tree-dir.ts
44993
+ init_yield_to_event_loop();
44994
+ init_types2();
44995
+ init_sort_entries();
45244
44996
  function parseLsTreeLine(line) {
45245
44997
  const tab = line.indexOf(" ");
45246
44998
  if (tab < 0) return null;
@@ -45303,6 +45055,9 @@ async function listGitTreeDirAsync(repoAbsPath, branch, relativePath) {
45303
45055
  }
45304
45056
  }
45305
45057
 
45058
+ // src/git/tree/file/index.ts
45059
+ init_yield_to_event_loop();
45060
+
45306
45061
  // src/files/read-file/types.ts
45307
45062
  var LINE_CHUNK_SIZE = 64 * 1024;
45308
45063
  var READ_RANGE_YIELD_EVERY_BYTES = 256 * 1024;
@@ -45339,6 +45094,7 @@ function guessMimeType(filePath) {
45339
45094
  }
45340
45095
 
45341
45096
  // src/git/tree/file/git-blob-ref.ts
45097
+ init_yield_to_event_loop();
45342
45098
  async function gitBlobRef(repoAbsPath, branch, relativePath) {
45343
45099
  const commit = await resolveBranchCommit(repoAbsPath, branch);
45344
45100
  await yieldToEventLoop();
@@ -45358,6 +45114,7 @@ function isBinaryBuffer(buf) {
45358
45114
  }
45359
45115
 
45360
45116
  // src/git/tree/file/read-git-blob-text-async.ts
45117
+ init_yield_to_event_loop();
45361
45118
  import { StringDecoder } from "node:string_decoder";
45362
45119
  async function countGitBlobLinesAsync(buf) {
45363
45120
  if (buf.length === 0) return 1;
@@ -45606,6 +45363,145 @@ function sendFileBrowserMessage(socket, e2ee, payload) {
45606
45363
  sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload, ["entries", "content", "totalLines", "size", "lineOffset"]) : payload);
45607
45364
  }
45608
45365
 
45366
+ // src/files/read-file/resolve-file-cache-warmup.ts
45367
+ init_yield_to_event_loop();
45368
+ import path77 from "node:path";
45369
+
45370
+ // src/files/read-file/resolve-file-cache.ts
45371
+ import fs49 from "node:fs";
45372
+ import path76 from "node:path";
45373
+ var RESOLVE_CACHE_MAX = 4096;
45374
+ var resolveCache = /* @__PURE__ */ new Map();
45375
+ var warmedDirectories = /* @__PURE__ */ new Set();
45376
+ function resolveCacheKey(sessionParentPath, relativePath) {
45377
+ return `${sessionParentPath}\0${relativePath}`;
45378
+ }
45379
+ function warmedDirectoryKey(sessionParentPath, directoryRelativePath) {
45380
+ const dir = directoryRelativePath.replace(/^\/+/, "") || ".";
45381
+ return `${path76.resolve(sessionParentPath)}\0${dir}`;
45382
+ }
45383
+ function pathStaysUnderParent(filePath, sessionParentPath) {
45384
+ const parent = path76.resolve(sessionParentPath);
45385
+ const resolved = path76.resolve(filePath);
45386
+ return resolved === parent || resolved.startsWith(`${parent}${path76.sep}`);
45387
+ }
45388
+ async function statMatchesCache(entry) {
45389
+ try {
45390
+ const stat2 = await fs49.promises.stat(entry.path);
45391
+ return stat2.isFile() && stat2.mtimeMs === entry.mtimeMs && stat2.size === entry.size;
45392
+ } catch {
45393
+ return false;
45394
+ }
45395
+ }
45396
+ function getResolveCacheEntry(cacheKey) {
45397
+ return resolveCache.get(cacheKey);
45398
+ }
45399
+ function deleteResolveCacheEntry(cacheKey) {
45400
+ resolveCache.delete(cacheKey);
45401
+ }
45402
+ function storeResolveCacheEntry(cacheKey, entry) {
45403
+ if (resolveCache.size >= RESOLVE_CACHE_MAX) resolveCache.clear();
45404
+ resolveCache.set(cacheKey, entry);
45405
+ return entry;
45406
+ }
45407
+ function hasResolveCacheEntry(cacheKey) {
45408
+ return resolveCache.has(cacheKey);
45409
+ }
45410
+ function markDirectoryWarmed(dirKey) {
45411
+ if (warmedDirectories.has(dirKey)) return false;
45412
+ warmedDirectories.add(dirKey);
45413
+ return true;
45414
+ }
45415
+ function unmarkDirectoryWarmed(dirKey) {
45416
+ warmedDirectories.delete(dirKey);
45417
+ }
45418
+
45419
+ // src/files/read-file/resolve-file-path.ts
45420
+ init_ensure_under_cwd();
45421
+ init_cwd();
45422
+ import fs50 from "node:fs";
45423
+ async function resolveFileForReadAsync(relativePath, sessionParentPath = getBridgeRoot()) {
45424
+ const cacheKey = resolveCacheKey(sessionParentPath, relativePath);
45425
+ const cached2 = getResolveCacheEntry(cacheKey);
45426
+ if (cached2 != null && await statMatchesCache(cached2)) {
45427
+ return { path: cached2.path, size: cached2.size };
45428
+ }
45429
+ if (cached2 != null) deleteResolveCacheEntry(cacheKey);
45430
+ const resolved = ensureUnderCwd(relativePath, sessionParentPath);
45431
+ if (!resolved) return { error: "Path is outside working directory" };
45432
+ let real;
45433
+ let size;
45434
+ let mtimeMs;
45435
+ try {
45436
+ const lstat = await fs50.promises.lstat(resolved);
45437
+ if (lstat.isSymbolicLink()) {
45438
+ real = await fs50.promises.realpath(resolved);
45439
+ if (!pathStaysUnderParent(real, sessionParentPath)) {
45440
+ return { error: "Path is outside working directory" };
45441
+ }
45442
+ const stat2 = await fs50.promises.stat(real);
45443
+ if (!stat2.isFile()) return { error: "Not a file" };
45444
+ size = stat2.size;
45445
+ mtimeMs = stat2.mtimeMs;
45446
+ } else if (lstat.isFile()) {
45447
+ real = resolved;
45448
+ size = lstat.size;
45449
+ mtimeMs = lstat.mtimeMs;
45450
+ } else {
45451
+ return { error: "Not a file" };
45452
+ }
45453
+ } catch (err) {
45454
+ return { error: err instanceof Error ? err.message : String(err) };
45455
+ }
45456
+ const entry = storeResolveCacheEntry(cacheKey, { path: real, size, mtimeMs });
45457
+ return { path: entry.path, size: entry.size };
45458
+ }
45459
+ async function resolveFilePathAsync(relativePath, sessionParentPath = getBridgeRoot()) {
45460
+ const result = await resolveFileForReadAsync(relativePath, sessionParentPath);
45461
+ if ("error" in result) return result;
45462
+ return result.path;
45463
+ }
45464
+
45465
+ // src/files/read-file/resolve-file-cache-warmup.ts
45466
+ var WARMED_DIRECTORY_TTL_MS = 6e4;
45467
+ async function warmDirectoryResolveCache(sessionParentPath, directoryRelativePath) {
45468
+ const { listDirAsync: listDirAsync2 } = await Promise.resolve().then(() => (init_list_dir(), list_dir_exports));
45469
+ const result = await listDirAsync2(directoryRelativePath, sessionParentPath);
45470
+ if ("error" in result) return;
45471
+ for (const entry of result.entries) {
45472
+ if (entry.isDir) continue;
45473
+ if (fileBrowserRequestInFlight()) return;
45474
+ const cacheKey = resolveCacheKey(sessionParentPath, entry.path);
45475
+ if (hasResolveCacheEntry(cacheKey)) continue;
45476
+ await resolveFileForReadAsync(entry.path, sessionParentPath).catch(() => void 0);
45477
+ await yieldToEventLoop();
45478
+ }
45479
+ }
45480
+ function scheduleDirectoryResolveCacheWarmup(sessionParentPath, directoryRelativePath) {
45481
+ const parent = path77.resolve(sessionParentPath);
45482
+ const dirKey = warmedDirectoryKey(parent, directoryRelativePath);
45483
+ if (!markDirectoryWarmed(dirKey)) return;
45484
+ setTimeout(() => unmarkDirectoryWarmed(dirKey), WARMED_DIRECTORY_TTL_MS);
45485
+ setImmediate(() => {
45486
+ void warmDirectoryResolveCache(parent, directoryRelativePath.replace(/^\/+/, "") || ".");
45487
+ });
45488
+ }
45489
+ function scheduleResolveCacheWarmupForListedEntries(sessionParentPath, listRelativePath, entries) {
45490
+ scheduleDirectoryResolveCacheWarmup(sessionParentPath, listRelativePath);
45491
+ setImmediate(() => {
45492
+ void (async () => {
45493
+ for (const entry of entries) {
45494
+ if (entry.isDir) continue;
45495
+ if (fileBrowserRequestInFlight()) return;
45496
+ const cacheKey = resolveCacheKey(sessionParentPath, entry.path);
45497
+ if (hasResolveCacheEntry(cacheKey)) continue;
45498
+ await resolveFileForReadAsync(entry.path, sessionParentPath).catch(() => void 0);
45499
+ await yieldToEventLoop();
45500
+ }
45501
+ })();
45502
+ });
45503
+ }
45504
+
45609
45505
  // src/files/browser/handle-file-browser-list.ts
45610
45506
  async function handleFileBrowserList(socket, e2ee, id, reqPath, sessionParentPath, gitScope) {
45611
45507
  const result = gitScope ? await listGitTreeDirAsync(gitScope.repoAbsPath, gitScope.branch, reqPath) : await listDirAsync(reqPath, sessionParentPath);
@@ -45614,38 +45510,138 @@ async function handleFileBrowserList(socket, e2ee, id, reqPath, sessionParentPat
45614
45510
  return;
45615
45511
  }
45616
45512
  sendFileBrowserMessage(socket, e2ee, { type: "file_browser_response", id, entries: result.entries });
45617
- if (!gitScope && (reqPath === "." || reqPath === "")) {
45618
- triggerFileIndexBuild(sessionParentPath);
45619
- if (sessionParentPath) triggerSymbolIndexBuild(sessionParentPath);
45513
+ if (!gitScope && sessionParentPath) {
45514
+ scheduleResolveCacheWarmupForListedEntries(sessionParentPath, reqPath, result.entries);
45620
45515
  }
45621
45516
  }
45622
45517
 
45623
- // src/files/read-file/resolve-file-path.ts
45624
- import fs49 from "node:fs";
45625
- async function resolveFilePathAsync(relativePath, sessionParentPath = getBridgeRoot()) {
45626
- const resolved = ensureUnderCwd(relativePath, sessionParentPath);
45627
- if (!resolved) return { error: "Path is outside working directory" };
45628
- let real;
45629
- try {
45630
- real = await fs49.promises.realpath(resolved);
45631
- } catch {
45632
- real = resolved;
45518
+ // src/files/browser/handle-file-browser-read.ts
45519
+ import path78 from "node:path";
45520
+ init_cwd();
45521
+
45522
+ // src/files/read-file/index.ts
45523
+ init_cwd();
45524
+ init_yield_to_event_loop();
45525
+ import fs54 from "node:fs";
45526
+
45527
+ // src/files/read-file/read-file-range-async.ts
45528
+ init_yield_to_event_loop();
45529
+ import fs51 from "node:fs";
45530
+ import { StringDecoder as StringDecoder2 } from "node:string_decoder";
45531
+
45532
+ // src/files/read-file/read-file-range-line-zero.ts
45533
+ function createLineZeroStreamState(lineOffsetIn) {
45534
+ return {
45535
+ line0Accum: "",
45536
+ skipLine0Chars: typeof lineOffsetIn === "number" ? lineOffsetIn : 0,
45537
+ line0CharsReturned: 0
45538
+ };
45539
+ }
45540
+ function shouldTrackLineZero(startLine, lineOffsetIn) {
45541
+ return startLine === 0 || lineOffsetIn !== void 0;
45542
+ }
45543
+ function stripCarriageReturn(lineContent) {
45544
+ return lineContent.endsWith("\r") ? lineContent.slice(0, -1) : lineContent;
45545
+ }
45546
+ function lineContentBeforeNewline(text, lineStart, newlineIndex) {
45547
+ let lineEnd = newlineIndex;
45548
+ if (lineEnd > lineStart && text[lineEnd - 1] === "\r") lineEnd--;
45549
+ return text.slice(lineStart, lineEnd);
45550
+ }
45551
+ function buildLineZeroChunkResult(resultLines, fileSize, lineOffset, totalLines = 1) {
45552
+ return {
45553
+ content: resultLines.join("\n"),
45554
+ size: fileSize,
45555
+ lineOffset,
45556
+ totalLines
45557
+ };
45558
+ }
45559
+ function tryFinishLineZeroOnCompleteLine(state, lineContent, resultLines, fileSize, lineChunkSize, lineOffsetIn, endLine, currentLine) {
45560
+ state.line0Accum += lineContent;
45561
+ const totalLine0 = state.line0Accum.length;
45562
+ if (state.skipLine0Chars > 0) {
45563
+ if (totalLine0 <= state.skipLine0Chars) {
45564
+ state.skipLine0Chars -= totalLine0;
45565
+ state.line0Accum = "";
45566
+ return currentLine + 1 > endLine ? "done" : "continue";
45567
+ }
45568
+ const from = state.skipLine0Chars;
45569
+ const take = Math.min(lineChunkSize, totalLine0 - from);
45570
+ resultLines.push(state.line0Accum.slice(from, from + take));
45571
+ state.line0CharsReturned += take;
45572
+ if (from + take < totalLine0) {
45573
+ return buildLineZeroChunkResult(
45574
+ resultLines,
45575
+ fileSize,
45576
+ (lineOffsetIn ?? 0) + state.line0CharsReturned
45577
+ );
45578
+ }
45579
+ state.line0Accum = "";
45580
+ state.skipLine0Chars = 0;
45581
+ state.line0CharsReturned = 0;
45582
+ return "continue";
45583
+ }
45584
+ if (totalLine0 > lineChunkSize) {
45585
+ resultLines.push(state.line0Accum.slice(0, lineChunkSize));
45586
+ return buildLineZeroChunkResult(resultLines, fileSize, lineChunkSize);
45587
+ }
45588
+ resultLines.push(state.line0Accum);
45589
+ state.line0Accum = "";
45590
+ return "continue";
45591
+ }
45592
+ function tryFinishLineZeroPartial(state, partialLine, resultLines, fileSize, lineChunkSize, lineOffsetIn) {
45593
+ state.line0Accum += partialLine;
45594
+ const totalLine0 = state.line0Accum.length;
45595
+ if (state.skipLine0Chars > 0) {
45596
+ if (totalLine0 <= state.skipLine0Chars) {
45597
+ state.skipLine0Chars -= totalLine0;
45598
+ state.line0Accum = "";
45599
+ return null;
45600
+ }
45601
+ const from = state.skipLine0Chars;
45602
+ const take = Math.min(lineChunkSize, totalLine0 - from);
45603
+ resultLines.push(state.line0Accum.slice(from, from + take));
45604
+ return buildLineZeroChunkResult(resultLines, fileSize, (lineOffsetIn ?? 0) + take);
45633
45605
  }
45634
- try {
45635
- const stat2 = await fs49.promises.stat(real);
45636
- if (!stat2.isFile()) return { error: "Not a file" };
45637
- return real;
45638
- } catch (err) {
45639
- return { error: err instanceof Error ? err.message : String(err) };
45606
+ if (totalLine0 > lineChunkSize) {
45607
+ resultLines.push(state.line0Accum.slice(0, lineChunkSize));
45608
+ return buildLineZeroChunkResult(resultLines, fileSize, lineChunkSize);
45609
+ }
45610
+ return null;
45611
+ }
45612
+ function finishLineZeroTail(state, tail, resultLines, fileSize, lineChunkSize, lineOffsetIn) {
45613
+ if (tail.length === 0) return null;
45614
+ state.line0Accum += stripCarriageReturn(tail);
45615
+ const totalLine0 = state.line0Accum.length;
45616
+ if (state.skipLine0Chars > 0) {
45617
+ if (totalLine0 <= state.skipLine0Chars) {
45618
+ return { content: resultLines.join("\n"), size: fileSize };
45619
+ }
45620
+ const from = state.skipLine0Chars;
45621
+ const take = Math.min(lineChunkSize, totalLine0 - from);
45622
+ resultLines.push(state.line0Accum.slice(from, from + take));
45623
+ state.line0CharsReturned += take;
45624
+ if (from + take < totalLine0) {
45625
+ return buildLineZeroChunkResult(
45626
+ resultLines,
45627
+ fileSize,
45628
+ (lineOffsetIn ?? 0) + state.line0CharsReturned
45629
+ );
45630
+ }
45631
+ return null;
45640
45632
  }
45633
+ if (totalLine0 > lineChunkSize) {
45634
+ resultLines.push(state.line0Accum.slice(0, lineChunkSize));
45635
+ return buildLineZeroChunkResult(resultLines, fileSize, lineChunkSize);
45636
+ }
45637
+ resultLines.push(state.line0Accum);
45638
+ return null;
45641
45639
  }
45642
45640
 
45643
45641
  // src/files/read-file/read-file-range-async.ts
45644
- import fs50 from "node:fs";
45645
- import { StringDecoder as StringDecoder2 } from "node:string_decoder";
45646
- async function readFileRangeAsync(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
45647
- const fileSize = (await fs50.promises.stat(filePath)).size;
45648
- const fd = await fs50.promises.open(filePath, "r");
45642
+ async function readFileRangeAsync(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE, fileSizeIn) {
45643
+ const fileSize = fileSizeIn ?? (await fs51.promises.stat(filePath)).size;
45644
+ const fd = await fs51.promises.open(filePath, "r");
45649
45645
  const bufSize = 64 * 1024;
45650
45646
  const buf = Buffer.alloc(bufSize);
45651
45647
  const decoder = new StringDecoder2("utf8");
@@ -45653,9 +45649,8 @@ async function readFileRangeAsync(filePath, startLine, endLine, lineOffsetIn, li
45653
45649
  const resultLines = [];
45654
45650
  let partial2 = "";
45655
45651
  let done = false;
45656
- let skipLine0Chars = typeof lineOffsetIn === "number" ? lineOffsetIn : 0;
45657
- let line0CharsReturned = 0;
45658
- let line0Accum = "";
45652
+ const trackLineZero = shouldTrackLineZero(startLine, lineOffsetIn);
45653
+ const lineZeroState = createLineZeroStreamState(lineOffsetIn);
45659
45654
  let bytesSinceYield = 0;
45660
45655
  try {
45661
45656
  let position = 0;
@@ -45672,130 +45667,70 @@ async function readFileRangeAsync(filePath, startLine, endLine, lineOffsetIn, li
45672
45667
  partial2 = "";
45673
45668
  let lineStart = 0;
45674
45669
  for (let i = 0; i < text.length; i++) {
45675
- if (text[i] === "\n") {
45676
- const lineContent = (() => {
45677
- let lineEnd = i;
45678
- if (lineEnd > lineStart && text[lineEnd - 1] === "\r") lineEnd--;
45679
- return text.slice(lineStart, lineEnd);
45680
- })();
45681
- if (currentLine === 0 && (startLine === 0 || lineOffsetIn !== void 0)) {
45682
- line0Accum += lineContent;
45683
- const totalLine0 = line0Accum.length;
45684
- if (skipLine0Chars > 0) {
45685
- if (totalLine0 <= skipLine0Chars) {
45686
- skipLine0Chars -= totalLine0;
45687
- line0Accum = "";
45688
- currentLine++;
45689
- lineStart = i + 1;
45690
- if (currentLine > endLine) {
45691
- done = true;
45692
- break;
45693
- }
45694
- continue;
45695
- }
45696
- const from = skipLine0Chars;
45697
- const take = Math.min(lineChunkSize, totalLine0 - from);
45698
- resultLines.push(line0Accum.slice(from, from + take));
45699
- line0CharsReturned += take;
45700
- if (from + take < totalLine0) {
45701
- return {
45702
- content: resultLines.join("\n"),
45703
- size: fileSize,
45704
- lineOffset: lineOffsetIn + line0CharsReturned,
45705
- totalLines: 1
45706
- };
45707
- }
45708
- line0Accum = "";
45709
- skipLine0Chars = 0;
45710
- line0CharsReturned = 0;
45711
- } else if (totalLine0 > lineChunkSize) {
45712
- resultLines.push(line0Accum.slice(0, lineChunkSize));
45713
- return {
45714
- content: resultLines.join("\n"),
45715
- size: fileSize,
45716
- lineOffset: lineChunkSize,
45717
- totalLines: 1
45718
- };
45719
- } else {
45720
- resultLines.push(line0Accum);
45721
- line0Accum = "";
45722
- }
45723
- } else if (currentLine >= startLine && currentLine <= endLine) {
45724
- resultLines.push(lineContent);
45670
+ if (text[i] !== "\n") continue;
45671
+ const lineContent2 = lineContentBeforeNewline(text, lineStart, i);
45672
+ if (currentLine === 0 && trackLineZero) {
45673
+ const lineZeroResult = tryFinishLineZeroOnCompleteLine(
45674
+ lineZeroState,
45675
+ lineContent2,
45676
+ resultLines,
45677
+ fileSize,
45678
+ lineChunkSize,
45679
+ lineOffsetIn,
45680
+ endLine,
45681
+ currentLine
45682
+ );
45683
+ if (lineZeroResult === "done") {
45684
+ done = true;
45685
+ break;
45725
45686
  }
45687
+ if (lineZeroResult !== "continue") return lineZeroResult;
45726
45688
  currentLine++;
45727
45689
  lineStart = i + 1;
45728
45690
  if (currentLine > endLine) {
45729
45691
  done = true;
45730
45692
  break;
45731
45693
  }
45694
+ continue;
45732
45695
  }
45733
- }
45734
- if (!done) {
45735
- const lineContent = text.slice(lineStart);
45736
- if (currentLine === 0 && (startLine === 0 || lineOffsetIn !== void 0)) {
45737
- line0Accum += lineContent;
45738
- const totalLine0 = line0Accum.length;
45739
- if (skipLine0Chars > 0) {
45740
- if (totalLine0 <= skipLine0Chars) {
45741
- skipLine0Chars -= totalLine0;
45742
- line0Accum = "";
45743
- } else {
45744
- const from = skipLine0Chars;
45745
- const take = Math.min(lineChunkSize, totalLine0 - from);
45746
- resultLines.push(line0Accum.slice(from, from + take));
45747
- return {
45748
- content: resultLines.join("\n"),
45749
- size: fileSize,
45750
- lineOffset: (lineOffsetIn ?? 0) + take,
45751
- totalLines: 1
45752
- };
45753
- }
45754
- } else if (totalLine0 > lineChunkSize) {
45755
- resultLines.push(line0Accum.slice(0, lineChunkSize));
45756
- return {
45757
- content: resultLines.join("\n"),
45758
- size: fileSize,
45759
- lineOffset: lineChunkSize,
45760
- totalLines: 1
45761
- };
45762
- }
45696
+ if (currentLine >= startLine && currentLine <= endLine) {
45697
+ resultLines.push(lineContent2);
45698
+ }
45699
+ currentLine++;
45700
+ lineStart = i + 1;
45701
+ if (currentLine > endLine) {
45702
+ done = true;
45703
+ break;
45763
45704
  }
45764
- partial2 = text.slice(lineStart);
45705
+ }
45706
+ if (done) continue;
45707
+ const lineContent = text.slice(lineStart);
45708
+ if (currentLine === 0 && trackLineZero) {
45709
+ const partialResult = tryFinishLineZeroPartial(
45710
+ lineZeroState,
45711
+ lineContent,
45712
+ resultLines,
45713
+ fileSize,
45714
+ lineChunkSize,
45715
+ lineOffsetIn
45716
+ );
45717
+ if (partialResult != null) return partialResult;
45718
+ } else {
45719
+ partial2 = lineContent;
45765
45720
  }
45766
45721
  }
45767
45722
  if (!done) {
45768
45723
  const tail = partial2 + decoder.end();
45769
- if (currentLine === 0 && (startLine === 0 || lineOffsetIn !== void 0) && tail.length > 0) {
45770
- line0Accum += tail.endsWith("\r") ? tail.slice(0, -1) : tail;
45771
- const totalLine0 = line0Accum.length;
45772
- if (skipLine0Chars > 0) {
45773
- if (totalLine0 <= skipLine0Chars) {
45774
- return { content: resultLines.join("\n"), size: fileSize };
45775
- }
45776
- const from = skipLine0Chars;
45777
- const take = Math.min(lineChunkSize, totalLine0 - from);
45778
- resultLines.push(line0Accum.slice(from, from + take));
45779
- line0CharsReturned += take;
45780
- if (from + take < totalLine0) {
45781
- return {
45782
- content: resultLines.join("\n"),
45783
- size: fileSize,
45784
- lineOffset: (lineOffsetIn ?? 0) + line0CharsReturned,
45785
- totalLines: 1
45786
- };
45787
- }
45788
- } else if (totalLine0 > lineChunkSize) {
45789
- resultLines.push(line0Accum.slice(0, lineChunkSize));
45790
- return {
45791
- content: resultLines.join("\n"),
45792
- size: fileSize,
45793
- lineOffset: lineChunkSize,
45794
- totalLines: 1
45795
- };
45796
- } else {
45797
- resultLines.push(line0Accum);
45798
- }
45724
+ if (currentLine === 0 && trackLineZero) {
45725
+ const tailResult = finishLineZeroTail(
45726
+ lineZeroState,
45727
+ tail,
45728
+ resultLines,
45729
+ fileSize,
45730
+ lineChunkSize,
45731
+ lineOffsetIn
45732
+ );
45733
+ if (tailResult != null) return tailResult;
45799
45734
  } else if (tail.length > 0 && currentLine >= startLine && currentLine <= endLine) {
45800
45735
  resultLines.push(tail.endsWith("\r") ? tail.slice(0, -1) : tail);
45801
45736
  }
@@ -45806,12 +45741,48 @@ async function readFileRangeAsync(filePath, startLine, endLine, lineOffsetIn, li
45806
45741
  }
45807
45742
  }
45808
45743
 
45744
+ // src/files/read-file/read-small-file-range-async.ts
45745
+ import fs52 from "node:fs";
45746
+ var SMALL_FILE_RANGE_MAX_BYTES = 512 * 1024;
45747
+ function sliceLineRange(lines, startLine, endLine, lineOffsetIn, lineChunkSize, fileSize) {
45748
+ if (startLine === 0 && lineOffsetIn == null && lines[0] != null && lines[0].length > lineChunkSize) {
45749
+ return {
45750
+ content: lines[0].slice(0, lineChunkSize),
45751
+ size: fileSize,
45752
+ lineOffset: lineChunkSize,
45753
+ totalLines: lines.length
45754
+ };
45755
+ }
45756
+ if (startLine === 0 && typeof lineOffsetIn === "number") {
45757
+ const line0 = lines[0] ?? "";
45758
+ const from = lineOffsetIn;
45759
+ const take = Math.min(lineChunkSize, Math.max(0, line0.length - from));
45760
+ return {
45761
+ content: line0.slice(from, from + take),
45762
+ size: fileSize,
45763
+ ...from + take < line0.length ? { lineOffset: from + take, totalLines: lines.length } : { totalLines: lines.length }
45764
+ };
45765
+ }
45766
+ const slice = lines.slice(startLine, endLine + 1);
45767
+ return {
45768
+ content: slice.join("\n"),
45769
+ size: fileSize,
45770
+ totalLines: lines.length
45771
+ };
45772
+ }
45773
+ async function readSmallFileRangeAsync(filePath, fileSize, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
45774
+ const raw = await fs52.promises.readFile(filePath, "utf8");
45775
+ const lines = raw.split(/\r?\n/);
45776
+ return sliceLineRange(lines, startLine, endLine, lineOffsetIn, lineChunkSize, fileSize);
45777
+ }
45778
+
45809
45779
  // src/files/read-file/read-file-buffer-full-async.ts
45810
- import fs51 from "node:fs";
45780
+ init_yield_to_event_loop();
45781
+ import fs53 from "node:fs";
45811
45782
  var READ_CHUNK_BYTES = 256 * 1024;
45812
45783
  async function readFileBufferFullAsync(filePath) {
45813
- const stat2 = await fs51.promises.stat(filePath);
45814
- const fd = await fs51.promises.open(filePath, "r");
45784
+ const stat2 = await fs53.promises.stat(filePath);
45785
+ const fd = await fs53.promises.open(filePath, "r");
45815
45786
  const chunks = [];
45816
45787
  let position = 0;
45817
45788
  let bytesSinceYield = 0;
@@ -45853,12 +45824,23 @@ async function readFileBinaryFullAsync(filePath) {
45853
45824
  }
45854
45825
 
45855
45826
  // src/files/read-file/index.ts
45856
- async function readFileAsync(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE, sessionParentPath = getBridgeRoot(), encoding = "utf8") {
45857
- await yieldToEventLoop();
45827
+ async function readFileAsync(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE, sessionParentPath = getBridgeRoot(), encoding = "utf8", options) {
45828
+ if (!options?.skipInitialYield) {
45829
+ await yieldToEventLoop();
45830
+ }
45858
45831
  try {
45859
- const result = await resolveFilePathAsync(relativePath, sessionParentPath);
45860
- if (typeof result === "object") return result;
45861
- const resolvedPath = result;
45832
+ let resolvedPath;
45833
+ let fileSize;
45834
+ if (options?.useResolvedSize) {
45835
+ const resolved = await resolveFileForReadAsync(relativePath, sessionParentPath);
45836
+ if ("error" in resolved) return resolved;
45837
+ resolvedPath = resolved.path;
45838
+ fileSize = resolved.size;
45839
+ } else {
45840
+ const result = await resolveFilePathAsync(relativePath, sessionParentPath);
45841
+ if (typeof result === "object") return result;
45842
+ resolvedPath = result;
45843
+ }
45862
45844
  const hasRange = typeof startLine === "number" && typeof endLine === "number";
45863
45845
  if (encoding === "base64") {
45864
45846
  if (hasRange) return { error: "base64 encoding requires a full file read (no line range)" };
@@ -45866,7 +45848,26 @@ async function readFileAsync(relativePath, startLine, endLine, lineOffset, lineC
45866
45848
  return { ...read2, resolvedPath };
45867
45849
  }
45868
45850
  if (hasRange) {
45869
- return readFileRangeAsync(resolvedPath, startLine, endLine, lineOffset, lineChunkSize);
45851
+ if (fileSize == null) {
45852
+ const stat2 = await fs54.promises.stat(resolvedPath);
45853
+ fileSize = stat2.size;
45854
+ }
45855
+ const read2 = fileSize <= SMALL_FILE_RANGE_MAX_BYTES ? await readSmallFileRangeAsync(
45856
+ resolvedPath,
45857
+ fileSize,
45858
+ startLine,
45859
+ endLine,
45860
+ lineOffset,
45861
+ lineChunkSize
45862
+ ) : await readFileRangeAsync(
45863
+ resolvedPath,
45864
+ startLine,
45865
+ endLine,
45866
+ lineOffset,
45867
+ lineChunkSize,
45868
+ fileSize
45869
+ );
45870
+ return read2;
45870
45871
  }
45871
45872
  const read = await readFileFullAsync(resolvedPath);
45872
45873
  return { ...read, resolvedPath };
@@ -45875,6 +45876,17 @@ async function readFileAsync(relativePath, startLine, endLine, lineOffset, lineC
45875
45876
  }
45876
45877
  }
45877
45878
 
45879
+ // src/files/browser/file-browser-read-queue.ts
45880
+ var readChain = Promise.resolve();
45881
+ function withFileBrowserReadQueue(fn) {
45882
+ const next = readChain.then(() => fn());
45883
+ readChain = next.then(
45884
+ () => void 0,
45885
+ () => void 0
45886
+ );
45887
+ return next;
45888
+ }
45889
+
45878
45890
  // src/files/browser/handle-file-browser-read.ts
45879
45891
  async function handleFileBrowserRead(socket, e2ee, msg, reqPath, sessionParentPath, gitScope) {
45880
45892
  const startLine = typeof msg.startLine === "number" ? msg.startLine : void 0;
@@ -45891,14 +45903,17 @@ async function handleFileBrowserRead(socket, e2ee, msg, reqPath, sessionParentPa
45891
45903
  lineOffset,
45892
45904
  lineChunkSize,
45893
45905
  encoding
45894
- ) : await readFileAsync(
45895
- reqPath,
45896
- startLine,
45897
- endLine,
45898
- lineOffset,
45899
- lineChunkSize,
45900
- sessionParentPath,
45901
- encoding
45906
+ ) : await withFileBrowserReadQueue(
45907
+ () => readFileAsync(
45908
+ reqPath,
45909
+ startLine,
45910
+ endLine,
45911
+ lineOffset,
45912
+ lineChunkSize,
45913
+ sessionParentPath,
45914
+ encoding,
45915
+ { skipInitialYield: true, useResolvedSize: true }
45916
+ )
45902
45917
  );
45903
45918
  if ("error" in result) {
45904
45919
  sendWsMessage(socket, { type: "file_browser_response", id: msg.id, error: result.error });
@@ -45915,6 +45930,10 @@ async function handleFileBrowserRead(socket, e2ee, msg, reqPath, sessionParentPa
45915
45930
  if (result.mimeType != null) payload.mimeType = result.mimeType;
45916
45931
  if (result.resolvedPath != null) payload.resolvedPath = result.resolvedPath;
45917
45932
  sendFileBrowserMessage(socket, e2ee, payload);
45933
+ if (!gitScope) {
45934
+ const parentDir = path78.dirname(reqPath.replace(/^\/+/, "") || ".");
45935
+ scheduleDirectoryResolveCacheWarmup(sessionParentPath ?? getBridgeRoot(), parentDir === "" ? "." : parentDir);
45936
+ }
45918
45937
  }
45919
45938
 
45920
45939
  // src/files/browser/resolve-git-branch-scope.ts
@@ -45928,22 +45947,67 @@ function resolveGitBranchScope(msg) {
45928
45947
 
45929
45948
  // src/files/browser/index.ts
45930
45949
  function handleFileBrowserRequest(msg, socket, e2ee, sessionWorktreeManager) {
45950
+ beginFileBrowserRequest();
45931
45951
  void (async () => {
45932
- const reqPath = msg.path.replace(/^\/+/, "") || ".";
45933
- const op = msg.op === "read" ? "read" : "list";
45934
- const sessionParentPath = sessionWorktreeManager != null ? await resolveFileBrowserSessionParent(sessionWorktreeManager, msg.sessionId) : void 0;
45935
- const gitScope = resolveGitBranchScope(msg);
45936
- if (msg.source === "git_branch" && typeof msg.repoRelPath === "string" && typeof msg.branch === "string" && msg.branch.trim().length > 0 && !gitScope) {
45937
- sendWsMessage(socket, { type: "file_browser_response", id: msg.id, error: "Invalid repository path" });
45938
- return;
45952
+ try {
45953
+ const reqPath = msg.path.replace(/^\/+/, "") || ".";
45954
+ const sessionParentPath = sessionWorktreeManager != null ? await resolveFileBrowserSessionParent(sessionWorktreeManager, msg.sessionId) : void 0;
45955
+ const gitScope = resolveGitBranchScope(msg);
45956
+ if (msg.source === "git_branch" && typeof msg.repoRelPath === "string" && typeof msg.branch === "string" && msg.branch.trim().length > 0 && !gitScope) {
45957
+ sendWsMessage(socket, { type: "file_browser_response", id: msg.id, error: "Invalid repository path" });
45958
+ return;
45959
+ }
45960
+ if (msg.op === "read") {
45961
+ await handleFileBrowserRead(socket, e2ee, msg, reqPath, sessionParentPath, gitScope);
45962
+ } else {
45963
+ await handleFileBrowserList(socket, e2ee, msg.id, reqPath, sessionParentPath, gitScope);
45964
+ }
45965
+ } finally {
45966
+ endFileBrowserRequest();
45939
45967
  }
45940
- if (op === "list") {
45941
- await handleFileBrowserList(socket, e2ee, msg.id, reqPath, sessionParentPath, gitScope);
45942
- } else {
45943
- await handleFileBrowserRead(socket, e2ee, msg, reqPath, sessionParentPath, gitScope);
45968
+ })();
45969
+ }
45970
+
45971
+ // src/files/handle-file-browser-search.ts
45972
+ init_cwd();
45973
+ init_yield_to_event_loop();
45974
+ import path79 from "node:path";
45975
+ var SEARCH_LIMIT = 100;
45976
+ function handleFileBrowserSearch(msg, socket, e2ee, sessionWorktreeManager) {
45977
+ void (async () => {
45978
+ await yieldToEventLoop();
45979
+ const q = typeof msg.q === "string" ? msg.q : "";
45980
+ const sessionParentPath = path79.resolve(
45981
+ sessionWorktreeManager != null ? await resolveFileBrowserSessionParent(sessionWorktreeManager, msg.sessionId) : getBridgeRoot()
45982
+ );
45983
+ if (!await bridgeFileIndexIsPopulated(sessionParentPath)) {
45984
+ triggerFileIndexBuild(sessionParentPath);
45985
+ const payload2 = {
45986
+ type: "file_browser_search_response",
45987
+ id: msg.id,
45988
+ paths: [],
45989
+ indexReady: false
45990
+ };
45991
+ sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload2, ["paths"]) : payload2);
45992
+ return;
45944
45993
  }
45994
+ const results = await searchBridgeFilePathsAsync(sessionParentPath, q, SEARCH_LIMIT);
45995
+ const payload = {
45996
+ type: "file_browser_search_response",
45997
+ id: msg.id,
45998
+ paths: results,
45999
+ indexReady: true
46000
+ };
46001
+ sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload, ["paths"]) : payload);
45945
46002
  })();
45946
46003
  }
46004
+ function triggerFileIndexBuild(sessionParentPath = getBridgeRoot()) {
46005
+ setImmediate(() => {
46006
+ void ensureFileIndexAsync(sessionParentPath).catch((e) => {
46007
+ console.error("[file-index] Background build failed:", e);
46008
+ });
46009
+ });
46010
+ }
45947
46011
 
45948
46012
  // src/routing/handlers/file-browser-messages.ts
45949
46013
  function handleFileBrowserRequestMessage(msg, { getWs, e2ee, sessionWorktreeManager }) {
@@ -45964,6 +46028,235 @@ function handleFileBrowserSearchMessage(msg, { getWs, e2ee, sessionWorktreeManag
45964
46028
  );
45965
46029
  }
45966
46030
 
46031
+ // src/code-nav/handlers/send-code-nav-response.ts
46032
+ var ENCRYPTED_FIELDS = ["definition", "definitions", "references", "symbols", "confidentTarget"];
46033
+ function sendCodeNavResponse(socket, e2ee, payload) {
46034
+ const fieldsToEncrypt = ENCRYPTED_FIELDS.filter((field) => field in payload && payload[field] !== void 0);
46035
+ sendWsMessage(
46036
+ socket,
46037
+ e2ee && fieldsToEncrypt.length > 0 ? e2ee.encryptFields(payload, [...fieldsToEncrypt]) : payload
46038
+ );
46039
+ }
46040
+
46041
+ // src/code-nav/handlers/handle-definition-op.ts
46042
+ async function handleDefinitionOp(ctx) {
46043
+ const definition = await queryDefinitionAt(ctx.sessionParentPath, ctx.reqPath, ctx.line, ctx.column);
46044
+ sendCodeNavResponse(ctx.socket, ctx.e2ee, {
46045
+ type: "code_nav_response",
46046
+ id: ctx.msg.id,
46047
+ indexReady: true,
46048
+ definition
46049
+ });
46050
+ }
46051
+
46052
+ // src/code-nav/handlers/handle-definitions-op.ts
46053
+ async function handleDefinitionsOp(ctx) {
46054
+ const { definitions, confidentTarget } = await queryDefinitionsNavigation(
46055
+ ctx.sessionParentPath,
46056
+ ctx.reqPath,
46057
+ ctx.line,
46058
+ ctx.column
46059
+ );
46060
+ sendCodeNavResponse(ctx.socket, ctx.e2ee, {
46061
+ type: "code_nav_response",
46062
+ id: ctx.msg.id,
46063
+ indexReady: true,
46064
+ definitions,
46065
+ confidentTarget
46066
+ });
46067
+ }
46068
+
46069
+ // src/code-nav/handlers/handle-references-op.ts
46070
+ async function handleReferencesOp(ctx) {
46071
+ const references = await queryReferencesAt(ctx.sessionParentPath, ctx.reqPath, ctx.line, ctx.column);
46072
+ sendCodeNavResponse(ctx.socket, ctx.e2ee, {
46073
+ type: "code_nav_response",
46074
+ id: ctx.msg.id,
46075
+ indexReady: true,
46076
+ references
46077
+ });
46078
+ }
46079
+
46080
+ // src/code-nav/handlers/handle-symbols-op.ts
46081
+ async function handleSymbolsOp(ctx) {
46082
+ const symbols = await querySymbolsInFile(ctx.sessionParentPath, ctx.reqPath);
46083
+ sendCodeNavResponse(ctx.socket, ctx.e2ee, {
46084
+ type: "code_nav_response",
46085
+ id: ctx.msg.id,
46086
+ indexReady: true,
46087
+ symbols
46088
+ });
46089
+ }
46090
+
46091
+ // src/code-nav/handlers/prepare-code-nav-request.ts
46092
+ init_yield_to_event_loop();
46093
+
46094
+ // src/code-nav/handlers/deferred-code-nav-index.ts
46095
+ var latestSeqBySession = /* @__PURE__ */ new Map();
46096
+ var pendingBySession = /* @__PURE__ */ new Map();
46097
+ var flushPromise = null;
46098
+ function scheduleDeferredCodeNavIndex(sessionKey, sessionParentPath, reqPath) {
46099
+ const seq = (latestSeqBySession.get(sessionKey) ?? 0) + 1;
46100
+ latestSeqBySession.set(sessionKey, seq);
46101
+ pendingBySession.set(sessionKey, { sessionParentPath, reqPath, seq });
46102
+ scheduleFlushWhenIdle();
46103
+ }
46104
+ function scheduleFlushWhenIdle() {
46105
+ if (flushPromise != null) return;
46106
+ flushPromise = runFlushWhenIdle().finally(() => {
46107
+ flushPromise = null;
46108
+ if (pendingBySession.size > 0) scheduleFlushWhenIdle();
46109
+ });
46110
+ }
46111
+ async function runFlushWhenIdle() {
46112
+ await yieldUntilFileBrowserIdle();
46113
+ const entries = [];
46114
+ for (const [sessionKey, entry] of pendingBySession) {
46115
+ pendingBySession.delete(sessionKey);
46116
+ if (entry.seq === latestSeqBySession.get(sessionKey)) entries.push(entry);
46117
+ }
46118
+ for (const entry of entries) {
46119
+ scheduleSymbolIndexFile(entry.sessionParentPath, entry.reqPath);
46120
+ }
46121
+ }
46122
+ registerFileBrowserActivityListener(() => {
46123
+ if (pendingBySession.size > 0 && !isBridgeBrowseInteractiveActive()) {
46124
+ scheduleFlushWhenIdle();
46125
+ }
46126
+ });
46127
+
46128
+ // src/code-nav/handlers/code-nav-session-key.ts
46129
+ function codeNavSessionKey(sessionId, sessionParentPath) {
46130
+ const trimmed2 = sessionId?.trim();
46131
+ return trimmed2 ? trimmed2 : sessionParentPath;
46132
+ }
46133
+
46134
+ // src/code-nav/handlers/wait-for-symbol-index-ready.ts
46135
+ var CODE_NAV_INDEX_READY_WAIT_MS = 75;
46136
+ var CODE_NAV_INDEX_READY_POLL_MS = 15;
46137
+ function delay2(ms) {
46138
+ return new Promise((resolve35) => setTimeout(resolve35, ms));
46139
+ }
46140
+ async function waitForSymbolIndexReady(sessionParentPath, reqPath, maxWaitMs = CODE_NAV_INDEX_READY_WAIT_MS) {
46141
+ const deadline = Date.now() + maxWaitMs;
46142
+ do {
46143
+ if (await symbolIndexFileIsReadyAsync(sessionParentPath, reqPath)) return true;
46144
+ await delay2(CODE_NAV_INDEX_READY_POLL_MS);
46145
+ } while (Date.now() < deadline);
46146
+ return await symbolIndexFileIsReadyAsync(sessionParentPath, reqPath);
46147
+ }
46148
+
46149
+ // src/code-nav/handlers/prepare-code-nav-base-context.ts
46150
+ function buildPreparedCodeNavBaseContext(msg, socket, e2ee, reqPath, sessionParentPath) {
46151
+ return {
46152
+ socket,
46153
+ e2ee,
46154
+ msg,
46155
+ reqPath,
46156
+ sessionParentPath,
46157
+ line: typeof msg.line === "number" ? msg.line : 1,
46158
+ column: typeof msg.column === "number" ? msg.column : 0
46159
+ };
46160
+ }
46161
+
46162
+ // src/code-nav/handlers/code-nav-op-context.ts
46163
+ function normalizeCodeNavOp(op) {
46164
+ if (op === "references" || op === "symbols" || op === "definitions") return op;
46165
+ return "definition";
46166
+ }
46167
+
46168
+ // src/code-nav/handlers/resolve-code-nav-parent.ts
46169
+ init_cwd();
46170
+ init_normalize_resolved_path();
46171
+ async function resolveCodeNavParentPath(sessionWorktreeManager, sessionId) {
46172
+ const parent = sessionWorktreeManager != null ? await resolveFileBrowserSessionParent(sessionWorktreeManager, sessionId) : getBridgeRoot();
46173
+ return normalizeResolvedPath(parent);
46174
+ }
46175
+
46176
+ // src/code-nav/handlers/prepare-code-nav-request.ts
46177
+ async function prepareCodeNavRequest(msg, socket, e2ee, sessionWorktreeManager) {
46178
+ await yieldToEventLoop();
46179
+ const reqPath = msg.path.replace(/^\/+/, "") || "";
46180
+ if (!reqPath) {
46181
+ sendCodeNavResponse(socket, e2ee, {
46182
+ type: "code_nav_response",
46183
+ id: msg.id,
46184
+ error: "Path required"
46185
+ });
46186
+ return null;
46187
+ }
46188
+ const sessionParentPath = await resolveCodeNavParentPath(sessionWorktreeManager, msg.sessionId);
46189
+ await registerSymbolIndexParentAsync(sessionParentPath);
46190
+ const sessionKey = codeNavSessionKey(msg.sessionId, sessionParentPath);
46191
+ const baseContext = buildPreparedCodeNavBaseContext(msg, socket, e2ee, reqPath, sessionParentPath);
46192
+ if (isBridgeBrowseInteractiveActive()) {
46193
+ scheduleDeferredCodeNavIndex(sessionKey, sessionParentPath, reqPath);
46194
+ return { ...baseContext, indexReady: false };
46195
+ }
46196
+ scheduleSymbolIndexFile(sessionParentPath, reqPath);
46197
+ const indexReady = await waitForSymbolIndexReady(sessionParentPath, reqPath);
46198
+ if (indexReady) {
46199
+ const importTargets = await listDirectImportTargetsForFileAsync(sessionParentPath, reqPath);
46200
+ scheduleSymbolIndexImportNeighbors(sessionParentPath, importTargets);
46201
+ }
46202
+ await yieldToEventLoop();
46203
+ return {
46204
+ ...baseContext,
46205
+ indexReady
46206
+ };
46207
+ }
46208
+ function sendIndexNotReadyResponse(ctx) {
46209
+ sendCodeNavResponse(ctx.socket, ctx.e2ee, {
46210
+ type: "code_nav_response",
46211
+ id: ctx.msg.id,
46212
+ indexReady: false,
46213
+ definition: null,
46214
+ definitions: [],
46215
+ references: [],
46216
+ symbols: []
46217
+ });
46218
+ }
46219
+ function preparedOpContext(ctx) {
46220
+ return {
46221
+ socket: ctx.socket,
46222
+ e2ee: ctx.e2ee,
46223
+ msg: { ...ctx.msg, op: normalizeCodeNavOp(ctx.msg.op) },
46224
+ reqPath: ctx.reqPath,
46225
+ sessionParentPath: ctx.sessionParentPath,
46226
+ line: ctx.line,
46227
+ column: ctx.column
46228
+ };
46229
+ }
46230
+
46231
+ // src/code-nav/handlers/handle-code-nav-request.ts
46232
+ function handleCodeNavRequest(msg, socket, e2ee, sessionWorktreeManager) {
46233
+ void (async () => {
46234
+ const prepared = await prepareCodeNavRequest(msg, socket, e2ee, sessionWorktreeManager);
46235
+ if (prepared == null) return;
46236
+ if (!prepared.indexReady) {
46237
+ sendIndexNotReadyResponse(prepared);
46238
+ return;
46239
+ }
46240
+ const ctx = preparedOpContext(prepared);
46241
+ switch (ctx.msg.op) {
46242
+ case "symbols":
46243
+ await handleSymbolsOp(ctx);
46244
+ return;
46245
+ case "references":
46246
+ await handleReferencesOp(ctx);
46247
+ return;
46248
+ case "definitions":
46249
+ await handleDefinitionsOp(ctx);
46250
+ return;
46251
+ default:
46252
+ await handleDefinitionOp(ctx);
46253
+ }
46254
+ })();
46255
+ }
46256
+
46257
+ // src/code-nav/handlers/trigger-symbol-index-build.ts
46258
+ init_normalize_resolved_path();
46259
+
45967
46260
  // src/routing/handlers/code-nav-messages.ts
45968
46261
  function handleFileBrowserCodeNavMessage(msg, { getWs, e2ee, sessionWorktreeManager }) {
45969
46262
  if (typeof msg.id !== "string" || typeof msg.path !== "string") return;
@@ -45986,6 +46279,7 @@ function handleFileBrowserCodeNavMessage(msg, { getWs, e2ee, sessionWorktreeMana
45986
46279
  }
45987
46280
 
45988
46281
  // src/routing/handlers/skill-layout-request.ts
46282
+ init_cwd();
45989
46283
  function handleSkillLayoutRequest(msg, deps) {
45990
46284
  const id = typeof msg.id === "string" ? msg.id : "";
45991
46285
  void (async () => {
@@ -45997,6 +46291,9 @@ function handleSkillLayoutRequest(msg, deps) {
45997
46291
  })();
45998
46292
  }
45999
46293
 
46294
+ // src/routing/handlers/install-skills.ts
46295
+ init_cwd();
46296
+
46000
46297
  // src/skills/install/is-valid-install-item.ts
46001
46298
  function isValidRemoteSkillInstallItem(item) {
46002
46299
  if (item === null || typeof item !== "object") return false;
@@ -46005,8 +46302,9 @@ function isValidRemoteSkillInstallItem(item) {
46005
46302
  }
46006
46303
 
46007
46304
  // src/skills/install/install-remote-skills-async.ts
46008
- import fs52 from "node:fs";
46009
- import path77 from "node:path";
46305
+ init_yield_to_event_loop();
46306
+ import fs55 from "node:fs";
46307
+ import path80 from "node:path";
46010
46308
 
46011
46309
  // src/skills/install/constants.ts
46012
46310
  var INSTALL_SKILLS_YIELD_EVERY = 16;
@@ -46017,12 +46315,12 @@ async function writeInstallFileAsync(skillDir, f, filesWritten) {
46017
46315
  if (++filesWritten.count % INSTALL_SKILLS_YIELD_EVERY === 0) {
46018
46316
  await yieldToEventLoop();
46019
46317
  }
46020
- const dest = path77.join(skillDir, f.path);
46021
- await fs52.promises.mkdir(path77.dirname(dest), { recursive: true });
46318
+ const dest = path80.join(skillDir, f.path);
46319
+ await fs55.promises.mkdir(path80.dirname(dest), { recursive: true });
46022
46320
  if (f.text !== void 0) {
46023
- await fs52.promises.writeFile(dest, f.text, "utf8");
46321
+ await fs55.promises.writeFile(dest, f.text, "utf8");
46024
46322
  } else if (f.base64) {
46025
- await fs52.promises.writeFile(dest, Buffer.from(f.base64, "base64"));
46323
+ await fs55.promises.writeFile(dest, Buffer.from(f.base64, "base64"));
46026
46324
  }
46027
46325
  }
46028
46326
  async function installRemoteSkillsAsync(cwd, targetDir, items) {
@@ -46034,7 +46332,7 @@ async function installRemoteSkillsAsync(cwd, targetDir, items) {
46034
46332
  try {
46035
46333
  for (const item of items) {
46036
46334
  if (!isValidRemoteSkillInstallItem(item)) continue;
46037
- const skillDir = path77.join(cwd, targetDir, item.skillName);
46335
+ const skillDir = path80.join(cwd, targetDir, item.skillName);
46038
46336
  for (const f of item.files) {
46039
46337
  await writeInstallFileAsync(skillDir, f, filesWritten);
46040
46338
  }
@@ -46316,7 +46614,8 @@ var handleSessionDiscardedMessage = (msg, deps) => {
46316
46614
  };
46317
46615
 
46318
46616
  // src/routing/handlers/revert-turn-snapshot.ts
46319
- import * as fs53 from "node:fs";
46617
+ init_cwd();
46618
+ import * as fs56 from "node:fs";
46320
46619
  var handleRevertTurnSnapshotMessage = (msg, deps) => {
46321
46620
  const id = typeof msg.id === "string" ? msg.id : "";
46322
46621
  const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
@@ -46329,7 +46628,7 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
46329
46628
  const agentBase = sessionWorktreeManager.getSessionWorktreeRootForSession(sessionId) ?? getBridgeRoot();
46330
46629
  const file2 = snapshotFilePath(agentBase, turnId);
46331
46630
  try {
46332
- await fs53.promises.access(file2, fs53.constants.F_OK);
46631
+ await fs56.promises.access(file2, fs56.constants.F_OK);
46333
46632
  } catch {
46334
46633
  sendWsMessage(s, {
46335
46634
  type: "revert_turn_snapshot_result",
@@ -46414,7 +46713,9 @@ var handleDeploySessionToPreviewMessage = (msg, deps) => {
46414
46713
  };
46415
46714
 
46416
46715
  // src/git/bridge-git-context.ts
46417
- import * as path78 from "node:path";
46716
+ init_cwd();
46717
+ init_yield_to_event_loop();
46718
+ import * as path81 from "node:path";
46418
46719
 
46419
46720
  // src/git/branches/get-current-branch.ts
46420
46721
  async function getCurrentBranch(repoPath) {
@@ -46464,12 +46765,12 @@ async function listRepoBranchRefs(repoPath) {
46464
46765
  // src/git/bridge-git-context.ts
46465
46766
  function folderNameForRelPath(relPath, bridgeRoot) {
46466
46767
  if (relPath === "." || relPath === "") {
46467
- return path78.basename(path78.resolve(bridgeRoot)) || "repo";
46768
+ return path81.basename(path81.resolve(bridgeRoot)) || "repo";
46468
46769
  }
46469
- return path78.basename(relPath) || relPath;
46770
+ return path81.basename(relPath) || relPath;
46470
46771
  }
46471
46772
  async function discoverGitReposForBridgeContext(bridgeRoot) {
46472
- const root = path78.resolve(bridgeRoot);
46773
+ const root = path81.resolve(bridgeRoot);
46473
46774
  if (await isGitRepoDirectory(root)) {
46474
46775
  const remoteUrl = await getRemoteOriginUrl(root);
46475
46776
  return [{ absolutePath: root, remoteUrl }];
@@ -46477,19 +46778,19 @@ async function discoverGitReposForBridgeContext(bridgeRoot) {
46477
46778
  const [deep, shallow] = await Promise.all([discoverGitReposUnderRoot(root), discoverGitRepos(root)]);
46478
46779
  const byPath = /* @__PURE__ */ new Map();
46479
46780
  for (const repo of [...deep, ...shallow]) {
46480
- byPath.set(path78.resolve(repo.absolutePath), repo);
46781
+ byPath.set(path81.resolve(repo.absolutePath), repo);
46481
46782
  }
46482
46783
  return [...byPath.values()];
46483
46784
  }
46484
46785
  async function getBridgeGitContext(bridgeRoot = getBridgeRoot()) {
46485
- const bridgeResolved = path78.resolve(bridgeRoot);
46786
+ const bridgeResolved = path81.resolve(bridgeRoot);
46486
46787
  const repos = await discoverGitReposForBridgeContext(bridgeResolved);
46487
46788
  const rows = [];
46488
46789
  for (let i = 0; i < repos.length; i++) {
46489
46790
  if (i > 0) await yieldToEventLoop();
46490
46791
  const repo = repos[i];
46491
- let rel = path78.relative(bridgeResolved, repo.absolutePath);
46492
- if (rel.startsWith("..") || path78.isAbsolute(rel)) continue;
46792
+ let rel = path81.relative(bridgeResolved, repo.absolutePath);
46793
+ if (rel.startsWith("..") || path81.isAbsolute(rel)) continue;
46493
46794
  const relPath = rel === "" ? "." : rel.replace(/\\/g, "/");
46494
46795
  const currentBranch = await getCurrentBranch(repo.absolutePath);
46495
46796
  const remoteUrl = repo.remoteUrl.trim() || null;
@@ -46504,11 +46805,11 @@ async function getBridgeGitContext(bridgeRoot = getBridgeRoot()) {
46504
46805
  return rows;
46505
46806
  }
46506
46807
  async function listRepoBranchesForBridge(repoRelPath, bridgeRoot = getBridgeRoot()) {
46507
- const bridgeResolved = path78.resolve(bridgeRoot);
46808
+ const bridgeResolved = path81.resolve(bridgeRoot);
46508
46809
  const rel = repoRelPath.trim() === "." ? "" : repoRelPath.trim().replace(/\\/g, "/");
46509
- const repoPath = rel === "" ? bridgeResolved : path78.join(bridgeResolved, rel);
46510
- const resolved = path78.resolve(repoPath);
46511
- if (!resolved.startsWith(bridgeResolved + path78.sep) && resolved !== bridgeResolved) {
46810
+ const repoPath = rel === "" ? bridgeResolved : path81.join(bridgeResolved, rel);
46811
+ const resolved = path81.resolve(repoPath);
46812
+ if (!resolved.startsWith(bridgeResolved + path81.sep) && resolved !== bridgeResolved) {
46512
46813
  return [];
46513
46814
  }
46514
46815
  return listRepoBranchRefs(resolved);