fss-link 1.5.4 → 1.5.6

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.
@@ -397,14 +397,14 @@ async function authWithUserCode(client) {
397
397
  console.log("");
398
398
  console.log(authUrl);
399
399
  console.log("");
400
- const code = await new Promise((resolve20) => {
400
+ const code = await new Promise((resolve19) => {
401
401
  const rl = readline.createInterface({
402
402
  input: process.stdin,
403
403
  output: process.stdout
404
404
  });
405
405
  rl.question("Enter the authorization code: ", (code2) => {
406
406
  rl.close();
407
- resolve20(code2.trim());
407
+ resolve19(code2.trim());
408
408
  });
409
409
  });
410
410
  if (!code) {
@@ -434,7 +434,7 @@ async function authWithWeb(client) {
434
434
  scope: OAUTH_SCOPE,
435
435
  state
436
436
  });
437
- const loginCompletePromise = new Promise((resolve20, reject) => {
437
+ const loginCompletePromise = new Promise((resolve19, reject) => {
438
438
  const server = http.createServer(async (req, res) => {
439
439
  try {
440
440
  if (req.url.indexOf("/oauth2callback") === -1) {
@@ -463,7 +463,7 @@ async function authWithWeb(client) {
463
463
  }
464
464
  res.writeHead(HTTP_REDIRECT, { Location: SIGN_IN_SUCCESS_URL });
465
465
  res.end();
466
- resolve20();
466
+ resolve19();
467
467
  } else {
468
468
  reject(new Error("No code found in request"));
469
469
  }
@@ -481,7 +481,7 @@ async function authWithWeb(client) {
481
481
  };
482
482
  }
483
483
  function getAvailablePort() {
484
- return new Promise((resolve20, reject) => {
484
+ return new Promise((resolve19, reject) => {
485
485
  let port = 0;
486
486
  try {
487
487
  const portStr = process.env["OAUTH_CALLBACK_PORT"];
@@ -490,7 +490,7 @@ function getAvailablePort() {
490
490
  if (isNaN(port) || port <= 0 || port > 65535) {
491
491
  return reject(new Error(`Invalid value for OAUTH_CALLBACK_PORT: "${portStr}"`));
492
492
  }
493
- return resolve20(port);
493
+ return resolve19(port);
494
494
  }
495
495
  const server = net.createServer();
496
496
  server.listen(0, () => {
@@ -502,7 +502,7 @@ function getAvailablePort() {
502
502
  server.unref();
503
503
  });
504
504
  server.on("error", (e2) => reject(e2));
505
- server.on("close", () => resolve20(port));
505
+ server.on("close", () => resolve19(port));
506
506
  } catch (e2) {
507
507
  reject(e2);
508
508
  }
@@ -3981,7 +3981,7 @@ var require_compile = __commonJS({
3981
3981
  const schOrFunc = root.refs[ref];
3982
3982
  if (schOrFunc)
3983
3983
  return schOrFunc;
3984
- let _sch = resolve20.call(this, root, ref);
3984
+ let _sch = resolve19.call(this, root, ref);
3985
3985
  if (_sch === void 0) {
3986
3986
  const schema2 = (_a4 = root.localRefs) === null || _a4 === void 0 ? void 0 : _a4[ref];
3987
3987
  const { schemaId } = this.opts;
@@ -4008,7 +4008,7 @@ var require_compile = __commonJS({
4008
4008
  function sameSchemaEnv(s1, s2) {
4009
4009
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
4010
4010
  }
4011
- function resolve20(root, ref) {
4011
+ function resolve19(root, ref) {
4012
4012
  let sch;
4013
4013
  while (typeof (sch = this.refs[ref]) == "string")
4014
4014
  ref = sch;
@@ -4583,7 +4583,7 @@ var require_fast_uri = __commonJS({
4583
4583
  }
4584
4584
  return uri;
4585
4585
  }
4586
- function resolve20(baseURI, relativeURI, options2) {
4586
+ function resolve19(baseURI, relativeURI, options2) {
4587
4587
  const schemelessOptions = options2 ? Object.assign({ scheme: "null" }, options2) : { scheme: "null" };
4588
4588
  const resolved = resolveComponent(parse6(baseURI, schemelessOptions), parse6(relativeURI, schemelessOptions), schemelessOptions, true);
4589
4589
  schemelessOptions.skipEscape = true;
@@ -4810,7 +4810,7 @@ var require_fast_uri = __commonJS({
4810
4810
  var fastUri = {
4811
4811
  SCHEMES,
4812
4812
  normalize: normalize8,
4813
- resolve: resolve20,
4813
+ resolve: resolve19,
4814
4814
  resolveComponent,
4815
4815
  equal,
4816
4816
  serialize: serialize2,
@@ -8855,7 +8855,7 @@ function defaultShouldRetry(error) {
8855
8855
  return false;
8856
8856
  }
8857
8857
  function delay(ms) {
8858
- return new Promise((resolve20) => setTimeout(resolve20, ms));
8858
+ return new Promise((resolve19) => setTimeout(resolve19, ms));
8859
8859
  }
8860
8860
  async function retryWithBackoff(fn, options2) {
8861
8861
  const { maxAttempts, initialDelayMs, maxDelayMs, onPersistent429, authType, shouldRetry } = {
@@ -10539,7 +10539,7 @@ var init_qwen_logger = __esm({
10539
10539
  this.events.clear();
10540
10540
  const rumPayload = await this.createRumPayload();
10541
10541
  rumPayload.events = eventsToSend;
10542
- const flushFn = () => new Promise((resolve20, reject) => {
10542
+ const flushFn = () => new Promise((resolve19, reject) => {
10543
10543
  const body = safeJsonStringify(rumPayload);
10544
10544
  const options2 = {
10545
10545
  hostname: USAGE_STATS_HOSTNAME,
@@ -10562,7 +10562,7 @@ var init_qwen_logger = __esm({
10562
10562
  return reject(err);
10563
10563
  }
10564
10564
  res.on("data", (buf) => bufs.push(buf));
10565
- res.on("end", () => resolve20(Buffer2.concat(bufs)));
10565
+ res.on("end", () => resolve19(Buffer2.concat(bufs)));
10566
10566
  });
10567
10567
  req.on("error", reject);
10568
10568
  req.end(body);
@@ -10891,8 +10891,8 @@ var init_file_exporters = __esm({
10891
10891
  return JSON.stringify(data, null, 2) + "\n";
10892
10892
  }
10893
10893
  shutdown() {
10894
- return new Promise((resolve20) => {
10895
- this.writeStream.end(resolve20);
10894
+ return new Promise((resolve19) => {
10895
+ this.writeStream.end(resolve19);
10896
10896
  });
10897
10897
  }
10898
10898
  };
@@ -11961,7 +11961,7 @@ var init_values = __esm({
11961
11961
  var sleep;
11962
11962
  var init_sleep = __esm({
11963
11963
  "node_modules/openai/internal/utils/sleep.mjs"() {
11964
- sleep = (ms) => new Promise((resolve20) => setTimeout(resolve20, ms));
11964
+ sleep = (ms) => new Promise((resolve19) => setTimeout(resolve19, ms));
11965
11965
  }
11966
11966
  });
11967
11967
 
@@ -13116,8 +13116,8 @@ var init_api_promise = __esm({
13116
13116
  init_parse();
13117
13117
  APIPromise = class _APIPromise extends Promise {
13118
13118
  constructor(client, responsePromise, parseResponse2 = defaultParseResponse) {
13119
- super((resolve20) => {
13120
- resolve20(null);
13119
+ super((resolve19) => {
13120
+ resolve19(null);
13121
13121
  });
13122
13122
  this.responsePromise = responsePromise;
13123
13123
  this.parseResponse = parseResponse2;
@@ -13587,12 +13587,12 @@ var init_EventStream = __esm({
13587
13587
  _EventStream_errored.set(this, false);
13588
13588
  _EventStream_aborted.set(this, false);
13589
13589
  _EventStream_catchingPromiseCreated.set(this, false);
13590
- __classPrivateFieldSet(this, _EventStream_connectedPromise, new Promise((resolve20, reject) => {
13591
- __classPrivateFieldSet(this, _EventStream_resolveConnectedPromise, resolve20, "f");
13590
+ __classPrivateFieldSet(this, _EventStream_connectedPromise, new Promise((resolve19, reject) => {
13591
+ __classPrivateFieldSet(this, _EventStream_resolveConnectedPromise, resolve19, "f");
13592
13592
  __classPrivateFieldSet(this, _EventStream_rejectConnectedPromise, reject, "f");
13593
13593
  }), "f");
13594
- __classPrivateFieldSet(this, _EventStream_endPromise, new Promise((resolve20, reject) => {
13595
- __classPrivateFieldSet(this, _EventStream_resolveEndPromise, resolve20, "f");
13594
+ __classPrivateFieldSet(this, _EventStream_endPromise, new Promise((resolve19, reject) => {
13595
+ __classPrivateFieldSet(this, _EventStream_resolveEndPromise, resolve19, "f");
13596
13596
  __classPrivateFieldSet(this, _EventStream_rejectEndPromise, reject, "f");
13597
13597
  }), "f");
13598
13598
  __classPrivateFieldGet(this, _EventStream_connectedPromise, "f").catch(() => {
@@ -13676,11 +13676,11 @@ var init_EventStream = __esm({
13676
13676
  * const message = await stream.emitted('message') // rejects if the stream errors
13677
13677
  */
13678
13678
  emitted(event) {
13679
- return new Promise((resolve20, reject) => {
13679
+ return new Promise((resolve19, reject) => {
13680
13680
  __classPrivateFieldSet(this, _EventStream_catchingPromiseCreated, true, "f");
13681
13681
  if (event !== "error")
13682
13682
  this.once("error", reject);
13683
- this.once(event, resolve20);
13683
+ this.once(event, resolve19);
13684
13684
  });
13685
13685
  }
13686
13686
  async done() {
@@ -14826,7 +14826,7 @@ var init_ChatCompletionStream = __esm({
14826
14826
  if (done) {
14827
14827
  return { value: void 0, done: true };
14828
14828
  }
14829
- return new Promise((resolve20, reject) => readQueue.push({ resolve: resolve20, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
14829
+ return new Promise((resolve19, reject) => readQueue.push({ resolve: resolve19, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
14830
14830
  }
14831
14831
  const chunk = pushQueue.shift();
14832
14832
  return { value: chunk, done: false };
@@ -15634,7 +15634,7 @@ var init_AssistantStream = __esm({
15634
15634
  if (done) {
15635
15635
  return { value: void 0, done: true };
15636
15636
  }
15637
- return new Promise((resolve20, reject) => readQueue.push({ resolve: resolve20, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
15637
+ return new Promise((resolve19, reject) => readQueue.push({ resolve: resolve19, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
15638
15638
  }
15639
15639
  const chunk = pushQueue.shift();
15640
15640
  return { value: chunk, done: false };
@@ -17598,7 +17598,7 @@ var init_ResponseStream = __esm({
17598
17598
  if (done) {
17599
17599
  return { value: void 0, done: true };
17600
17600
  }
17601
- return new Promise((resolve20, reject) => readQueue.push({ resolve: resolve20, reject })).then((event2) => event2 ? { value: event2, done: false } : { value: void 0, done: true });
17601
+ return new Promise((resolve19, reject) => readQueue.push({ resolve: resolve19, reject })).then((event2) => event2 ? { value: event2, done: false } : { value: void 0, done: true });
17602
17602
  }
17603
17603
  const event = pushQueue.shift();
17604
17604
  return { value: event, done: false };
@@ -20707,11 +20707,20 @@ Streaming setup timeout troubleshooting:
20707
20707
  const functionCalls = [];
20708
20708
  const functionResponses = [];
20709
20709
  const textParts = [];
20710
+ const imageParts = [];
20710
20711
  for (const part of content.parts || []) {
20711
20712
  if (typeof part === "string") {
20712
20713
  textParts.push(part);
20713
20714
  } else if ("text" in part && part.text) {
20714
20715
  textParts.push(part.text);
20716
+ } else if ("inlineData" in part && part.inlineData) {
20717
+ imageParts.push({
20718
+ type: "image_url",
20719
+ image_url: {
20720
+ url: `data:${part.inlineData.mimeType};base64,${part.inlineData.data}`,
20721
+ detail: "auto"
20722
+ }
20723
+ });
20715
20724
  } else if ("functionCall" in part && part.functionCall) {
20716
20725
  functionCalls.push(part.functionCall);
20717
20726
  } else if ("functionResponse" in part && part.functionResponse) {
@@ -20726,6 +20735,14 @@ Streaming setup timeout troubleshooting:
20726
20735
  content: typeof funcResponse.response === "string" ? funcResponse.response : JSON.stringify(funcResponse.response)
20727
20736
  });
20728
20737
  }
20738
+ if (imageParts.length > 0) {
20739
+ const contentParts = [];
20740
+ const text = textParts.join("");
20741
+ if (text)
20742
+ contentParts.push({ type: "text", text });
20743
+ contentParts.push(...imageParts);
20744
+ messages.push({ role: "user", content: contentParts });
20745
+ }
20729
20746
  } else if (content.role === "model" && functionCalls.length > 0) {
20730
20747
  const toolCalls = functionCalls.map((fc, index) => ({
20731
20748
  id: fc.id || `call_${index}`,
@@ -20743,7 +20760,13 @@ Streaming setup timeout troubleshooting:
20743
20760
  } else {
20744
20761
  const role = content.role === "model" ? "assistant" : "user";
20745
20762
  const text = textParts.join("");
20746
- if (text) {
20763
+ if (role === "user" && imageParts.length > 0) {
20764
+ const contentParts = [];
20765
+ if (text)
20766
+ contentParts.push({ type: "text", text });
20767
+ contentParts.push(...imageParts);
20768
+ messages.push({ role, content: contentParts });
20769
+ } else if (text) {
20747
20770
  messages.push({ role, content: text });
20748
20771
  }
20749
20772
  }
@@ -21652,7 +21675,7 @@ var init_sharedTokenManager = __esm({
21652
21675
  } catch (statError) {
21653
21676
  console.warn(`Failed to stat lock file ${lockPath}: ${statError instanceof Error ? statError.message : String(statError)}`);
21654
21677
  }
21655
- await new Promise((resolve20) => setTimeout(resolve20, attemptInterval));
21678
+ await new Promise((resolve19) => setTimeout(resolve19, attemptInterval));
21656
21679
  } else {
21657
21680
  throw new TokenManagerError(TokenError.FILE_ACCESS_ERROR, `Failed to create lock file: ${error instanceof Error ? error.message : String(error)}`, error);
21658
21681
  }
@@ -21928,19 +21951,19 @@ Server requested to slow down, increasing poll interval to ${pollInterval}ms'`);
21928
21951
  }
21929
21952
  qwenOAuth2Events.emit(QwenOAuth2Event.AuthProgress, "polling", `Polling... (attempt ${attempt + 1}/${maxAttempts})`);
21930
21953
  process.stdout.write(".");
21931
- await new Promise((resolve20) => {
21954
+ await new Promise((resolve19) => {
21932
21955
  const checkInterval = 100;
21933
21956
  let elapsedTime = 0;
21934
21957
  const intervalId = setInterval(() => {
21935
21958
  elapsedTime += checkInterval;
21936
21959
  if (isCancelled) {
21937
21960
  clearInterval(intervalId);
21938
- resolve20();
21961
+ resolve19();
21939
21962
  return;
21940
21963
  }
21941
21964
  if (elapsedTime >= pollInterval) {
21942
21965
  clearInterval(intervalId);
21943
- resolve20();
21966
+ resolve19();
21944
21967
  return;
21945
21968
  }
21946
21969
  }, checkInterval);
@@ -21975,7 +21998,7 @@ Server requested to slow down, increasing poll interval to ${pollInterval}ms'`);
21975
21998
  if (isCancelled) {
21976
21999
  return { success: false, reason: "cancelled" };
21977
22000
  }
21978
- await new Promise((resolve20) => setTimeout(resolve20, pollInterval));
22001
+ await new Promise((resolve19) => setTimeout(resolve19, pollInterval));
21979
22002
  }
21980
22003
  }
21981
22004
  const timeoutMessage = "Authorization timeout, please restart the process.";
@@ -22495,7 +22518,7 @@ async function createContentGeneratorConfig(config, authType) {
22495
22518
  async function createContentGenerator(config, gcConfig, sessionId2) {
22496
22519
  if (DEBUG_CONTENT)
22497
22520
  console.log(`\u{1F41B} DEBUG createContentGenerator: authType=${config.authType}, apiKey=${config.apiKey}, baseUrl=${config.baseUrl}`);
22498
- const version = "1.5.4";
22521
+ const version = "1.5.6";
22499
22522
  const userAgent = `FSS-Link/${version} (${process.platform}; ${process.arch})`;
22500
22523
  const baseHeaders = {
22501
22524
  "User-Agent": userAgent
@@ -23448,7 +23471,7 @@ var init_oauth_provider = __esm({
23448
23471
  * @returns Promise that resolves with the authorization code
23449
23472
  */
23450
23473
  static async startCallbackServer(expectedState) {
23451
- return new Promise((resolve20, reject) => {
23474
+ return new Promise((resolve19, reject) => {
23452
23475
  const server = http2.createServer(async (req, res) => {
23453
23476
  try {
23454
23477
  const url2 = new URL3(req.url, `http://localhost:${this.REDIRECT_PORT}`);
@@ -23499,7 +23522,7 @@ var init_oauth_provider = __esm({
23499
23522
  </html>
23500
23523
  `);
23501
23524
  server.close();
23502
- resolve20({ code, state });
23525
+ resolve19({ code, state });
23503
23526
  } catch (error) {
23504
23527
  server.close();
23505
23528
  reject(error);
@@ -24729,7 +24752,7 @@ var init_tool_registry = __esm({
24729
24752
  let error = null;
24730
24753
  let code = null;
24731
24754
  let signal = null;
24732
- await new Promise((resolve20) => {
24755
+ await new Promise((resolve19) => {
24733
24756
  const onStdout = (data) => {
24734
24757
  stdout += data?.toString();
24735
24758
  };
@@ -24743,7 +24766,7 @@ var init_tool_registry = __esm({
24743
24766
  code = _code;
24744
24767
  signal = _signal2;
24745
24768
  cleanup();
24746
- resolve20();
24769
+ resolve19();
24747
24770
  };
24748
24771
  const cleanup = () => {
24749
24772
  child.stdout.removeListener("data", onStdout);
@@ -24945,7 +24968,7 @@ Signal: Signal number or \`(none)\` if no signal was received.
24945
24968
  stderrByteLength += data.length;
24946
24969
  stderr += stderrDecoder.write(data);
24947
24970
  });
24948
- await new Promise((resolve20, reject) => {
24971
+ await new Promise((resolve19, reject) => {
24949
24972
  proc2.on("error", reject);
24950
24973
  proc2.on("close", (code) => {
24951
24974
  stdout += stdoutDecoder.end();
@@ -24958,7 +24981,7 @@ Signal: Signal number or \`(none)\` if no signal was received.
24958
24981
  console.error(stderr);
24959
24982
  return reject(new Error(`Tool discovery command failed with exit code ${code}`));
24960
24983
  }
24961
- resolve20();
24984
+ resolve19();
24962
24985
  });
24963
24986
  });
24964
24987
  const functions = [];
@@ -25245,32 +25268,22 @@ async function processSingleFileContent(filePath, rootDirectory, fileSystemServi
25245
25268
  }
25246
25269
  case "image": {
25247
25270
  const sizeStr = formatFileSize(fileSizeInBytes);
25248
- const mimeType = mime.lookup(filePath) || "image/*";
25271
+ const mimeType = mime.lookup(filePath) || "image/jpeg";
25272
+ const imageBuffer = await fs9.promises.readFile(filePath);
25273
+ const base64Data = imageBuffer.toString("base64");
25249
25274
  return {
25250
- llmContent: `Cannot read image file with this tool: ${relativePathForDisplay}
25251
-
25252
- File details:
25253
- - Type: ${mimeType}
25254
- - Size: ${sizeStr}
25255
- - Path: ${filePath}
25256
-
25257
- Images cannot be read with the read_file tool to prevent context overflow.
25258
- Use a vision-capable model or bash tools (e.g., base64, file, identify) if available.`,
25259
- returnDisplay: `Skipped image file (${sizeStr}): ${relativePathForDisplay}`
25275
+ llmContent: { inlineData: { mimeType, data: base64Data } },
25276
+ returnDisplay: `Read image file (${sizeStr}): ${relativePathForDisplay}`
25260
25277
  };
25261
25278
  }
25262
25279
  case "pdf": {
25263
25280
  const sizeStr = formatFileSize(fileSizeInBytes);
25281
+ const mimeType = "application/pdf";
25282
+ const pdfBuffer = await fs9.promises.readFile(filePath);
25283
+ const base64Data = pdfBuffer.toString("base64");
25264
25284
  return {
25265
- llmContent: `Cannot read PDF file with this tool: ${relativePathForDisplay}
25266
-
25267
- File details:
25268
- - Type: PDF Document
25269
- - Size: ${sizeStr}
25270
- - Path: ${filePath}
25271
-
25272
- PDFs cannot be read with the read_file tool. Use the PDF parser tool for proper content extraction.`,
25273
- returnDisplay: `Skipped PDF file (${sizeStr}): ${relativePathForDisplay}`
25285
+ llmContent: { inlineData: { mimeType, data: base64Data } },
25286
+ returnDisplay: `Read pdf file (${sizeStr}): ${relativePathForDisplay}`
25274
25287
  };
25275
25288
  }
25276
25289
  case "audio":
@@ -25349,7 +25362,7 @@ function getFileTypeIcon(filePath, fileType) {
25349
25362
  return "\u{1F4C4}";
25350
25363
  }
25351
25364
  async function countLinesEfficiently(filePath, maxLines = 1e4) {
25352
- return new Promise((resolve20) => {
25365
+ return new Promise((resolve19) => {
25353
25366
  let lineCount = 0;
25354
25367
  const stream2 = fs9.createReadStream(filePath, { encoding: "utf-8" });
25355
25368
  let remainder = "";
@@ -25360,16 +25373,16 @@ async function countLinesEfficiently(filePath, maxLines = 1e4) {
25360
25373
  lineCount += lines.length;
25361
25374
  if (lineCount > maxLines) {
25362
25375
  stream2.destroy();
25363
- resolve20(void 0);
25376
+ resolve19(void 0);
25364
25377
  }
25365
25378
  });
25366
25379
  stream2.on("end", () => {
25367
25380
  if (remainder)
25368
25381
  lineCount++;
25369
- resolve20(lineCount);
25382
+ resolve19(lineCount);
25370
25383
  });
25371
25384
  stream2.on("error", () => {
25372
- resolve20(void 0);
25385
+ resolve19(void 0);
25373
25386
  });
25374
25387
  });
25375
25388
  }
@@ -25925,31 +25938,6 @@ Output budget: ${budgetUsagePercent}% of ${(MAX_LS_OUTPUT_SIZE / 1024).toFixed(0
25925
25938
  });
25926
25939
  this.config = config;
25927
25940
  }
25928
- /**
25929
- * Check if execution needs user confirmation (e.g., for workspace boundary violations)
25930
- * @param abortSignal Signal to handle request cancellation
25931
- * @returns Confirmation details if needed, false otherwise
25932
- */
25933
- async shouldConfirmExecute(abortSignal) {
25934
- const workspaceContext = this.config.getWorkspaceContext();
25935
- const params = this.pendingToolCall?.params;
25936
- if (params?.path) {
25937
- const targetPath = path13.resolve(params.path);
25938
- if (!workspaceContext.isPathWithinWorkspace(targetPath)) {
25939
- const details = {
25940
- attemptedPath: targetPath,
25941
- toolName: "list_directory",
25942
- operation: "list directory"
25943
- };
25944
- return createWorkspaceConfirmation(details, workspaceContext, async (outcome) => {
25945
- if (outcome === ToolConfirmationOutcome.ProceedAlways) {
25946
- workspaceContext.addDirectory(targetPath);
25947
- }
25948
- });
25949
- }
25950
- }
25951
- return false;
25952
- }
25953
25941
  /**
25954
25942
  * Validates the parameters for the tool
25955
25943
  * @param params Parameters to validate
@@ -29875,10 +29863,10 @@ var init_esm4 = __esm({
29875
29863
  * Return a void Promise that resolves once the stream ends.
29876
29864
  */
29877
29865
  async promise() {
29878
- return new Promise((resolve20, reject) => {
29866
+ return new Promise((resolve19, reject) => {
29879
29867
  this.on(DESTROYED, () => reject(new Error("stream destroyed")));
29880
29868
  this.on("error", (er) => reject(er));
29881
- this.on("end", () => resolve20());
29869
+ this.on("end", () => resolve19());
29882
29870
  });
29883
29871
  }
29884
29872
  /**
@@ -29902,7 +29890,7 @@ var init_esm4 = __esm({
29902
29890
  return Promise.resolve({ done: false, value: res });
29903
29891
  if (this[EOF])
29904
29892
  return stop();
29905
- let resolve20;
29893
+ let resolve19;
29906
29894
  let reject;
29907
29895
  const onerr = (er) => {
29908
29896
  this.off("data", ondata);
@@ -29916,19 +29904,19 @@ var init_esm4 = __esm({
29916
29904
  this.off("end", onend);
29917
29905
  this.off(DESTROYED, ondestroy);
29918
29906
  this.pause();
29919
- resolve20({ value, done: !!this[EOF] });
29907
+ resolve19({ value, done: !!this[EOF] });
29920
29908
  };
29921
29909
  const onend = () => {
29922
29910
  this.off("error", onerr);
29923
29911
  this.off("data", ondata);
29924
29912
  this.off(DESTROYED, ondestroy);
29925
29913
  stop();
29926
- resolve20({ done: true, value: void 0 });
29914
+ resolve19({ done: true, value: void 0 });
29927
29915
  };
29928
29916
  const ondestroy = () => onerr(new Error("stream destroyed"));
29929
29917
  return new Promise((res2, rej) => {
29930
29918
  reject = rej;
29931
- resolve20 = res2;
29919
+ resolve19 = res2;
29932
29920
  this.once(DESTROYED, ondestroy);
29933
29921
  this.once("error", onerr);
29934
29922
  this.once("end", onend);
@@ -30908,9 +30896,9 @@ var init_esm5 = __esm({
30908
30896
  if (this.#asyncReaddirInFlight) {
30909
30897
  await this.#asyncReaddirInFlight;
30910
30898
  } else {
30911
- let resolve20 = () => {
30899
+ let resolve19 = () => {
30912
30900
  };
30913
- this.#asyncReaddirInFlight = new Promise((res) => resolve20 = res);
30901
+ this.#asyncReaddirInFlight = new Promise((res) => resolve19 = res);
30914
30902
  try {
30915
30903
  for (const e2 of await this.#fs.promises.readdir(fullpath, {
30916
30904
  withFileTypes: true
@@ -30923,7 +30911,7 @@ var init_esm5 = __esm({
30923
30911
  children.provisional = 0;
30924
30912
  }
30925
30913
  this.#asyncReaddirInFlight = void 0;
30926
- resolve20();
30914
+ resolve19();
30927
30915
  }
30928
30916
  return children.slice(0, children.provisional);
30929
30917
  }
@@ -31153,8 +31141,8 @@ var init_esm5 = __esm({
31153
31141
  *
31154
31142
  * @internal
31155
31143
  */
31156
- constructor(cwd3 = process.cwd(), pathImpl, sep6, { nocase, childrenCacheSize = 16 * 1024, fs: fs73 = defaultFS } = {}) {
31157
- this.#fs = fsFromOption(fs73);
31144
+ constructor(cwd3 = process.cwd(), pathImpl, sep6, { nocase, childrenCacheSize = 16 * 1024, fs: fs76 = defaultFS } = {}) {
31145
+ this.#fs = fsFromOption(fs76);
31158
31146
  if (cwd3 instanceof URL || cwd3.startsWith("file://")) {
31159
31147
  cwd3 = fileURLToPath(cwd3);
31160
31148
  }
@@ -31712,8 +31700,8 @@ var init_esm5 = __esm({
31712
31700
  /**
31713
31701
  * @internal
31714
31702
  */
31715
- newRoot(fs73) {
31716
- return new PathWin32(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs73 });
31703
+ newRoot(fs76) {
31704
+ return new PathWin32(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs76 });
31717
31705
  }
31718
31706
  /**
31719
31707
  * Return true if the provided path string is an absolute path
@@ -31741,8 +31729,8 @@ var init_esm5 = __esm({
31741
31729
  /**
31742
31730
  * @internal
31743
31731
  */
31744
- newRoot(fs73) {
31745
- return new PathPosix(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs73 });
31732
+ newRoot(fs76) {
31733
+ return new PathPosix(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs76 });
31746
31734
  }
31747
31735
  /**
31748
31736
  * Return true if the provided path string is an absolute path
@@ -33401,7 +33389,7 @@ NOTE: Search stopped after processing ${processedMB} MB of content (approaching
33401
33389
  * @returns {Promise<boolean>} True if the command is available, false otherwise.
33402
33390
  */
33403
33391
  isCommandAvailable(command) {
33404
- return new Promise((resolve20) => {
33392
+ return new Promise((resolve19) => {
33405
33393
  const checkCommand = process.platform === "win32" ? "where" : "command";
33406
33394
  const checkArgs = process.platform === "win32" ? [command] : ["-v", command];
33407
33395
  try {
@@ -33409,10 +33397,10 @@ NOTE: Search stopped after processing ${processedMB} MB of content (approaching
33409
33397
  stdio: "ignore",
33410
33398
  shell: process.platform === "win32"
33411
33399
  });
33412
- child.on("close", (code) => resolve20(code === 0));
33413
- child.on("error", () => resolve20(false));
33400
+ child.on("close", (code) => resolve19(code === 0));
33401
+ child.on("error", () => resolve19(false));
33414
33402
  } catch {
33415
- resolve20(false);
33403
+ resolve19(false);
33416
33404
  }
33417
33405
  });
33418
33406
  }
@@ -33550,7 +33538,7 @@ NOTE: Search stopped after processing ${processedMB} MB of content (approaching
33550
33538
  gitArgs.push("--", include);
33551
33539
  }
33552
33540
  try {
33553
- const output = await new Promise((resolve20, reject) => {
33541
+ const output = await new Promise((resolve19, reject) => {
33554
33542
  const child = spawn2("git", gitArgs, {
33555
33543
  cwd: absolutePath,
33556
33544
  windowsHide: true
@@ -33572,9 +33560,9 @@ NOTE: Search stopped after processing ${processedMB} MB of content (approaching
33572
33560
  const stdoutData = Buffer.concat(stdoutChunks).toString("utf8");
33573
33561
  const stderrData = Buffer.concat(stderrChunks).toString("utf8");
33574
33562
  if (code === 0)
33575
- resolve20(stdoutData);
33563
+ resolve19(stdoutData);
33576
33564
  else if (code === 1)
33577
- resolve20("");
33565
+ resolve19("");
33578
33566
  else
33579
33567
  reject(new Error(`git grep exited with code ${code}: ${stderrData}`));
33580
33568
  });
@@ -33610,7 +33598,7 @@ NOTE: Search stopped after processing ${processedMB} MB of content (approaching
33610
33598
  grepArgs.push(pattern);
33611
33599
  grepArgs.push(".");
33612
33600
  try {
33613
- const output = await new Promise((resolve20, reject) => {
33601
+ const output = await new Promise((resolve19, reject) => {
33614
33602
  const child = spawn2("grep", grepArgs, {
33615
33603
  cwd: absolutePath,
33616
33604
  windowsHide: true
@@ -33639,14 +33627,14 @@ NOTE: Search stopped after processing ${processedMB} MB of content (approaching
33639
33627
  const stderrData = Buffer.concat(stderrChunks).toString("utf8").trim();
33640
33628
  cleanup();
33641
33629
  if (code === 0)
33642
- resolve20(stdoutData);
33630
+ resolve19(stdoutData);
33643
33631
  else if (code === 1)
33644
- resolve20("");
33632
+ resolve19("");
33645
33633
  else {
33646
33634
  if (stderrData)
33647
33635
  reject(new Error(`System grep exited with code ${code}: ${stderrData}`));
33648
33636
  else
33649
- resolve20("");
33637
+ resolve19("");
33650
33638
  }
33651
33639
  };
33652
33640
  const cleanup = () => {
@@ -33792,7 +33780,7 @@ NOTE: Search stopped after processing ${processedMB} MB of content (approaching
33792
33780
  gitArgs.splice(4, 0, `-B${contextBefore}`);
33793
33781
  if (contextAfter > 0)
33794
33782
  gitArgs.splice(4, 0, `-A${contextAfter}`);
33795
- const output = await new Promise((resolve20, reject) => {
33783
+ const output = await new Promise((resolve19, reject) => {
33796
33784
  const child = spawn2("git", gitArgs, { cwd: fileDir, windowsHide: true });
33797
33785
  const stdoutChunks = [];
33798
33786
  const stderrChunks = [];
@@ -33811,9 +33799,9 @@ NOTE: Search stopped after processing ${processedMB} MB of content (approaching
33811
33799
  const stdoutData = Buffer.concat(stdoutChunks).toString("utf8");
33812
33800
  const stderrData = Buffer.concat(stderrChunks).toString("utf8");
33813
33801
  if (code === 0)
33814
- resolve20(stdoutData);
33802
+ resolve19(stdoutData);
33815
33803
  else if (code === 1)
33816
- resolve20("");
33804
+ resolve19("");
33817
33805
  else
33818
33806
  reject(new Error(`git grep exited with code ${code}: ${stderrData}`));
33819
33807
  });
@@ -33834,7 +33822,7 @@ NOTE: Search stopped after processing ${processedMB} MB of content (approaching
33834
33822
  grepArgs.push(`-A${contextAfter}`);
33835
33823
  grepArgs.push(pattern);
33836
33824
  grepArgs.push(filePath);
33837
- const output = await new Promise((resolve20, reject) => {
33825
+ const output = await new Promise((resolve19, reject) => {
33838
33826
  const child = spawn2("grep", grepArgs, { windowsHide: true });
33839
33827
  const stdoutChunks = [];
33840
33828
  const stderrChunks = [];
@@ -33853,9 +33841,9 @@ NOTE: Search stopped after processing ${processedMB} MB of content (approaching
33853
33841
  const stdoutData = Buffer.concat(stdoutChunks).toString("utf8");
33854
33842
  const stderrData = Buffer.concat(stderrChunks).toString("utf8");
33855
33843
  if (code === 0)
33856
- resolve20(stdoutData);
33844
+ resolve19(stdoutData);
33857
33845
  else if (code === 1)
33858
- resolve20("");
33846
+ resolve19("");
33859
33847
  else
33860
33848
  reject(new Error(`grep exited with code ${code}: ${stderrData}`));
33861
33849
  });
@@ -39851,8 +39839,8 @@ var init_ide_client = __esm({
39851
39839
  * - Closes the file
39852
39840
  */
39853
39841
  async openDiff(filePath, newContent) {
39854
- return new Promise((resolve20, reject) => {
39855
- this.diffResponses.set(filePath, resolve20);
39842
+ return new Promise((resolve19, reject) => {
39843
+ this.diffResponses.set(filePath, resolve19);
39856
39844
  this.client?.callTool({
39857
39845
  name: `openDiff`,
39858
39846
  arguments: {
@@ -40469,32 +40457,6 @@ Expectation for required parameters:
40469
40457
  });
40470
40458
  this.config = config;
40471
40459
  }
40472
- /**
40473
- * Check if execution needs user confirmation (e.g., for workspace boundary violations)
40474
- * @param abortSignal Signal to handle request cancellation
40475
- * @returns Confirmation details if needed, false otherwise
40476
- */
40477
- async shouldConfirmExecute(abortSignal) {
40478
- const workspaceContext = this.config.getWorkspaceContext();
40479
- const params = this.pendingToolCall?.params;
40480
- if (params?.file_path) {
40481
- const targetPath = path21.resolve(params.file_path);
40482
- if (!workspaceContext.isPathWithinWorkspace(targetPath)) {
40483
- const details = {
40484
- attemptedPath: targetPath,
40485
- toolName: "replace",
40486
- operation: "edit file"
40487
- };
40488
- return createWorkspaceConfirmation(details, workspaceContext, async (outcome) => {
40489
- if (outcome === ToolConfirmationOutcome.ProceedAlways) {
40490
- const parentDir = path21.dirname(targetPath);
40491
- workspaceContext.addDirectory(parentDir);
40492
- }
40493
- });
40494
- }
40495
- }
40496
- return false;
40497
- }
40498
40460
  /**
40499
40461
  * Validates the parameters for the Edit tool
40500
40462
  * @param params Parameters to validate
@@ -46249,40 +46211,40 @@ var require_lib = __commonJS({
46249
46211
  return matches;
46250
46212
  };
46251
46213
  exports.analyse = analyse;
46252
- var detectFile = (filepath, opts = {}) => new Promise((resolve20, reject) => {
46214
+ var detectFile = (filepath, opts = {}) => new Promise((resolve19, reject) => {
46253
46215
  let fd;
46254
- const fs73 = (0, node_1.default)();
46216
+ const fs76 = (0, node_1.default)();
46255
46217
  const handler = (err, buffer) => {
46256
46218
  if (fd) {
46257
- fs73.closeSync(fd);
46219
+ fs76.closeSync(fd);
46258
46220
  }
46259
46221
  if (err) {
46260
46222
  reject(err);
46261
46223
  } else {
46262
- resolve20((0, exports.detect)(buffer));
46224
+ resolve19((0, exports.detect)(buffer));
46263
46225
  }
46264
46226
  };
46265
46227
  if (opts && opts.sampleSize) {
46266
- fd = fs73.openSync(filepath, "r");
46228
+ fd = fs76.openSync(filepath, "r");
46267
46229
  const sample = Buffer.allocUnsafe(opts.sampleSize);
46268
- fs73.read(fd, sample, 0, opts.sampleSize, opts.offset, (err) => {
46230
+ fs76.read(fd, sample, 0, opts.sampleSize, opts.offset, (err) => {
46269
46231
  handler(err, sample);
46270
46232
  });
46271
46233
  return;
46272
46234
  }
46273
- fs73.readFile(filepath, handler);
46235
+ fs76.readFile(filepath, handler);
46274
46236
  });
46275
46237
  exports.detectFile = detectFile;
46276
46238
  var detectFileSync = (filepath, opts = {}) => {
46277
- const fs73 = (0, node_1.default)();
46239
+ const fs76 = (0, node_1.default)();
46278
46240
  if (opts && opts.sampleSize) {
46279
- const fd = fs73.openSync(filepath, "r");
46241
+ const fd = fs76.openSync(filepath, "r");
46280
46242
  const sample = Buffer.allocUnsafe(opts.sampleSize);
46281
- fs73.readSync(fd, sample, 0, opts.sampleSize, opts.offset);
46282
- fs73.closeSync(fd);
46243
+ fs76.readSync(fd, sample, 0, opts.sampleSize, opts.offset);
46244
+ fs76.closeSync(fd);
46283
46245
  return (0, exports.detect)(sample);
46284
46246
  }
46285
- return (0, exports.detect)(fs73.readFileSync(filepath));
46247
+ return (0, exports.detect)(fs76.readFileSync(filepath));
46286
46248
  };
46287
46249
  exports.detectFileSync = detectFileSync;
46288
46250
  exports.default = {
@@ -49895,7 +49857,7 @@ var init_shellExecutionService = __esm({
49895
49857
  PAGER: "cat"
49896
49858
  }
49897
49859
  });
49898
- const result = new Promise((resolve20) => {
49860
+ const result = new Promise((resolve19) => {
49899
49861
  let stdoutDecoder = null;
49900
49862
  let stderrDecoder = null;
49901
49863
  let stdout = "";
@@ -49948,7 +49910,7 @@ var init_shellExecutionService = __esm({
49948
49910
  const { finalBuffer } = cleanup();
49949
49911
  const separator = stdout.endsWith("\n") ? "" : "\n";
49950
49912
  const combinedOutput = stdout + (stderr ? (stdout ? separator : "") + stderr : "");
49951
- resolve20({
49913
+ resolve19({
49952
49914
  rawOutput: finalBuffer,
49953
49915
  output: combinedOutput.trim(),
49954
49916
  exitCode: code,
@@ -50044,7 +50006,7 @@ var init_shellExecutionService = __esm({
50044
50006
  },
50045
50007
  handleFlowControl: true
50046
50008
  });
50047
- const result = new Promise((resolve20) => {
50009
+ const result = new Promise((resolve19) => {
50048
50010
  const headlessTerminal = new Terminal({
50049
50011
  allowProposedApi: true,
50050
50012
  cols,
@@ -50060,7 +50022,7 @@ var init_shellExecutionService = __esm({
50060
50022
  const MAX_SNIFF_SIZE = 4096;
50061
50023
  let sniffedBytes = 0;
50062
50024
  const handleOutput = (data) => {
50063
- processingChain = processingChain.then(() => new Promise((resolve21) => {
50025
+ processingChain = processingChain.then(() => new Promise((resolve20) => {
50064
50026
  if (!decoder) {
50065
50027
  const encoding = getCachedEncodingForBuffer(data);
50066
50028
  try {
@@ -50084,7 +50046,7 @@ var init_shellExecutionService = __esm({
50084
50046
  const newStrippedOutput = getFullText(headlessTerminal);
50085
50047
  output = newStrippedOutput;
50086
50048
  onOutputEvent({ type: "data", chunk: newStrippedOutput });
50087
- resolve21();
50049
+ resolve20();
50088
50050
  });
50089
50051
  } else {
50090
50052
  const totalBytes = outputChunks.reduce((sum, chunk) => sum + chunk.length, 0);
@@ -50092,7 +50054,7 @@ var init_shellExecutionService = __esm({
50092
50054
  type: "binary_progress",
50093
50055
  bytesReceived: totalBytes
50094
50056
  });
50095
- resolve21();
50057
+ resolve20();
50096
50058
  }
50097
50059
  }));
50098
50060
  };
@@ -50105,7 +50067,7 @@ var init_shellExecutionService = __esm({
50105
50067
  abortSignal.removeEventListener("abort", abortHandler);
50106
50068
  processingChain.then(() => {
50107
50069
  const finalBuffer = Buffer.concat(outputChunks);
50108
- resolve20({
50070
+ resolve19({
50109
50071
  rawOutput: finalBuffer,
50110
50072
  output,
50111
50073
  exitCode,
@@ -51148,31 +51110,12 @@ Size change: ${sizeDelta > 0 ? "+" : ""}${sizeDelta} characters (${oldSize} \u21
51148
51110
  });
51149
51111
  this.config = config;
51150
51112
  }
51151
- /**
51152
- * Check if execution needs user confirmation (e.g., for workspace boundary violations)
51153
- * @param abortSignal Signal to handle request cancellation
51154
- * @returns Confirmation details if needed, false otherwise
51155
- */
51156
- async shouldConfirmExecute(abortSignal) {
51157
- const workspaceContext = this.config.getWorkspaceContext();
51158
- const params = this.pendingToolCall?.params;
51159
- if (params?.file_path) {
51160
- const targetPath = path23.resolve(params.file_path);
51161
- if (!workspaceContext.isPathWithinWorkspace(targetPath)) {
51162
- const details = {
51163
- attemptedPath: targetPath,
51164
- toolName: "write_file",
51165
- operation: "write file"
51166
- };
51167
- return createWorkspaceConfirmation(details, workspaceContext, async (outcome) => {
51168
- if (outcome === ToolConfirmationOutcome.ProceedAlways) {
51169
- const parentDir = path23.dirname(targetPath);
51170
- workspaceContext.addDirectory(parentDir);
51171
- }
51172
- });
51173
- }
51113
+ validateToolParams(params) {
51114
+ const raw = params;
51115
+ if (raw["content"] !== void 0 && typeof raw["content"] !== "string") {
51116
+ raw["content"] = typeof raw["content"] === "object" ? JSON.stringify(raw["content"], null, 2) : String(raw["content"]);
51174
51117
  }
51175
- return false;
51118
+ return super.validateToolParams(params);
51176
51119
  }
51177
51120
  validateToolParamValues(params) {
51178
51121
  const filePath = params.file_path;
@@ -58064,19 +58007,19 @@ function pLimit(concurrency) {
58064
58007
  queue.dequeue()();
58065
58008
  }
58066
58009
  };
58067
- const run = async (function_, resolve20, arguments_) => {
58010
+ const run = async (function_, resolve19, arguments_) => {
58068
58011
  activeCount++;
58069
58012
  const result = (async () => function_(...arguments_))();
58070
- resolve20(result);
58013
+ resolve19(result);
58071
58014
  try {
58072
58015
  await result;
58073
58016
  } catch {
58074
58017
  }
58075
58018
  next();
58076
58019
  };
58077
- const enqueue = (function_, resolve20, arguments_) => {
58020
+ const enqueue = (function_, resolve19, arguments_) => {
58078
58021
  queue.enqueue(
58079
- AsyncResource.bind(run.bind(void 0, function_, resolve20, arguments_))
58022
+ AsyncResource.bind(run.bind(void 0, function_, resolve19, arguments_))
58080
58023
  );
58081
58024
  (async () => {
58082
58025
  await Promise.resolve();
@@ -58085,8 +58028,8 @@ function pLimit(concurrency) {
58085
58028
  }
58086
58029
  })();
58087
58030
  };
58088
- const generator = (function_, ...arguments_) => new Promise((resolve20) => {
58089
- enqueue(function_, resolve20, arguments_);
58031
+ const generator = (function_, ...arguments_) => new Promise((resolve19) => {
58032
+ enqueue(function_, resolve19, arguments_);
58090
58033
  });
58091
58034
  Object.defineProperties(generator, {
58092
58035
  activeCount: {
@@ -60570,7 +60513,7 @@ var init_webScraperService = __esm({
60570
60513
  }
60571
60514
  if (attempt < maxRetries) {
60572
60515
  const backoffMs = Math.min(1e3 * Math.pow(2, attempt - 1), 1e4);
60573
- await new Promise((resolve20) => setTimeout(resolve20, backoffMs));
60516
+ await new Promise((resolve19) => setTimeout(resolve19, backoffMs));
60574
60517
  }
60575
60518
  }
60576
60519
  }
@@ -60720,7 +60663,7 @@ ${content.content}`;
60720
60663
  const timeSinceLastRequest = now - lastRequest;
60721
60664
  if (timeSinceLastRequest < minDelay) {
60722
60665
  const waitTime = minDelay - timeSinceLastRequest;
60723
- await new Promise((resolve20) => setTimeout(resolve20, waitTime));
60666
+ await new Promise((resolve19) => setTimeout(resolve19, waitTime));
60724
60667
  }
60725
60668
  this.rateLimiter.set(domain, Date.now());
60726
60669
  }
@@ -61300,7 +61243,7 @@ var init_tts_tool = __esm({
61300
61243
  if (process.env["FSS_DEBUG"] === "true") {
61301
61244
  console.log(`[TTS DEBUG] Request body: ${JSON.stringify(requestBody, null, 2)}`);
61302
61245
  }
61303
- const response = await fetch("http://192.168.1.5:11450/api/v1/synthesize", {
61246
+ const response = await fetch("http://tts.internal.bobai.com.au:11450/api/v1/synthesize", {
61304
61247
  method: "POST",
61305
61248
  headers: {
61306
61249
  "Content-Type": "application/json"
@@ -67920,7 +67863,7 @@ var init_memory_tracker = __esm({
67920
67863
  async forceGC() {
67921
67864
  if (global.gc) {
67922
67865
  global.gc();
67923
- await new Promise((resolve20) => setTimeout(resolve20, 10));
67866
+ await new Promise((resolve19) => setTimeout(resolve19, 10));
67924
67867
  }
67925
67868
  }
67926
67869
  /**
@@ -68496,7 +68439,7 @@ var init_excel_parser = __esm({
68496
68439
  }
68497
68440
  }
68498
68441
  async parseCsvFile(filePath, delimiter2 = ",") {
68499
- return new Promise((resolve20, reject) => {
68442
+ return new Promise((resolve19, reject) => {
68500
68443
  const data = [];
68501
68444
  const fileStream = fs27.createReadStream(filePath);
68502
68445
  fileStream.pipe(parse3({
@@ -68517,7 +68460,7 @@ var init_excel_parser = __esm({
68517
68460
  rowCount: data.length,
68518
68461
  columnCount: data[0]?.length || 0
68519
68462
  };
68520
- resolve20({
68463
+ resolve19({
68521
68464
  sheets: { "Sheet1": sheetData }
68522
68465
  });
68523
68466
  }).on("error", reject);
@@ -68856,7 +68799,7 @@ Perfect for:
68856
68799
  }
68857
68800
  async validateFile(filePath) {
68858
68801
  const config = DEFAULT_PARSER_CONFIGS["excel"];
68859
- const stats = await import("fs/promises").then((fs73) => fs73.stat(filePath));
68802
+ const stats = await import("fs/promises").then((fs76) => fs76.stat(filePath));
68860
68803
  if (!stats.isFile()) {
68861
68804
  throw new Error(`Path is not a file: ${filePath}`);
68862
68805
  }
@@ -68878,8 +68821,8 @@ Perfect for:
68878
68821
  }
68879
68822
  const backupPath = `${filePath}.backup.${Date.now()}`;
68880
68823
  try {
68881
- const fs73 = await import("fs/promises");
68882
- await fs73.copyFile(filePath, backupPath);
68824
+ const fs76 = await import("fs/promises");
68825
+ await fs76.copyFile(filePath, backupPath);
68883
68826
  return backupPath;
68884
68827
  } catch (error) {
68885
68828
  console.warn(`Failed to create backup: ${error}`);
@@ -68887,8 +68830,8 @@ Perfect for:
68887
68830
  }
68888
68831
  }
68889
68832
  async getFileSize(filePath) {
68890
- const fs73 = await import("fs/promises");
68891
- const stats = await fs73.stat(filePath);
68833
+ const fs76 = await import("fs/promises");
68834
+ const stats = await fs76.stat(filePath);
68892
68835
  return stats.size;
68893
68836
  }
68894
68837
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -69145,7 +69088,7 @@ var init_word_parser = __esm({
69145
69088
  return result;
69146
69089
  }
69147
69090
  async extractDocxContent(filePath) {
69148
- return new Promise((resolve20, reject) => {
69091
+ return new Promise((resolve19, reject) => {
69149
69092
  const content = {};
69150
69093
  yauzl.open(filePath, { lazyEntries: true }, (err, zipfile) => {
69151
69094
  if (err || !zipfile) {
@@ -69176,7 +69119,7 @@ var init_word_parser = __esm({
69176
69119
  }
69177
69120
  });
69178
69121
  zipfile.on("end", () => {
69179
- resolve20(content);
69122
+ resolve19(content);
69180
69123
  });
69181
69124
  zipfile.on("error", (err2) => {
69182
69125
  reject(err2);
@@ -69308,8 +69251,8 @@ var init_word_parser = __esm({
69308
69251
  throw new Error(`Failed to parse document: ${result.errors?.join("; ")}`);
69309
69252
  }
69310
69253
  const convertedContent = await this.convertToFormat(result.content || "", format, result.metadata);
69311
- const fs73 = await import("fs/promises");
69312
- await fs73.writeFile(outputPath, convertedContent, "utf8");
69254
+ const fs76 = await import("fs/promises");
69255
+ await fs76.writeFile(outputPath, convertedContent, "utf8");
69313
69256
  }
69314
69257
  /**
69315
69258
  * Read and convert document to markdown file
@@ -69534,7 +69477,7 @@ Perfect for:
69534
69477
  }
69535
69478
  async validateFile(filePath) {
69536
69479
  const config = DEFAULT_PARSER_CONFIGS["word"];
69537
- const stats = await import("fs/promises").then((fs73) => fs73.stat(filePath));
69480
+ const stats = await import("fs/promises").then((fs76) => fs76.stat(filePath));
69538
69481
  if (!stats.isFile()) {
69539
69482
  throw new Error(`Path is not a file: ${filePath}`);
69540
69483
  }
@@ -69556,8 +69499,8 @@ Perfect for:
69556
69499
  }
69557
69500
  const backupPath = `${filePath}.backup.${Date.now()}`;
69558
69501
  try {
69559
- const fs73 = await import("fs/promises");
69560
- await fs73.copyFile(filePath, backupPath);
69502
+ const fs76 = await import("fs/promises");
69503
+ await fs76.copyFile(filePath, backupPath);
69561
69504
  return backupPath;
69562
69505
  } catch (error) {
69563
69506
  console.warn(`Failed to create backup: ${error}`);
@@ -69565,8 +69508,8 @@ Perfect for:
69565
69508
  }
69566
69509
  }
69567
69510
  async getFileSize(filePath) {
69568
- const fs73 = await import("fs/promises");
69569
- const stats = await fs73.stat(filePath);
69511
+ const fs76 = await import("fs/promises");
69512
+ const stats = await fs76.stat(filePath);
69570
69513
  return stats.size;
69571
69514
  }
69572
69515
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -69693,7 +69636,7 @@ Perfect for:
69693
69636
  this.validateFormat(this.params.file_path);
69694
69637
  const backupPath = await this.createBackup(this.params.file_path);
69695
69638
  const pdfParse = await import("pdf-parse");
69696
- const fs73 = await import("fs/promises");
69639
+ const fs76 = await import("fs/promises");
69697
69640
  const parseOptions = {};
69698
69641
  if (this.params.options?.password) {
69699
69642
  parseOptions.password = this.params.options.password;
@@ -69701,7 +69644,7 @@ Perfect for:
69701
69644
  if (this.params.options?.max_pages) {
69702
69645
  parseOptions.max = this.params.options.max_pages;
69703
69646
  }
69704
- const pdfBuffer = await fs73.readFile(this.params.file_path);
69647
+ const pdfBuffer = await fs76.readFile(this.params.file_path);
69705
69648
  const pdfData = await pdfParse.default(pdfBuffer, parseOptions);
69706
69649
  const metadata = {
69707
69650
  pageCount: pdfData.numpages,
@@ -69756,7 +69699,7 @@ Perfect for:
69756
69699
  }
69757
69700
  async validateFile(filePath) {
69758
69701
  const config = DEFAULT_PARSER_CONFIGS["pdf"];
69759
- const stats = await import("fs/promises").then((fs73) => fs73.stat(filePath));
69702
+ const stats = await import("fs/promises").then((fs76) => fs76.stat(filePath));
69760
69703
  if (!stats.isFile()) {
69761
69704
  throw new Error(`Path is not a file: ${filePath}`);
69762
69705
  }
@@ -69778,8 +69721,8 @@ Perfect for:
69778
69721
  }
69779
69722
  const backupPath = `${filePath}.backup.${Date.now()}`;
69780
69723
  try {
69781
- const fs73 = await import("fs/promises");
69782
- await fs73.copyFile(filePath, backupPath);
69724
+ const fs76 = await import("fs/promises");
69725
+ await fs76.copyFile(filePath, backupPath);
69783
69726
  return backupPath;
69784
69727
  } catch (error) {
69785
69728
  console.warn(`Failed to create backup: ${error}`);
@@ -69787,8 +69730,8 @@ Perfect for:
69787
69730
  }
69788
69731
  }
69789
69732
  async getFileSize(filePath) {
69790
- const fs73 = await import("fs/promises");
69791
- const stats = await fs73.stat(filePath);
69733
+ const fs76 = await import("fs/promises");
69734
+ const stats = await fs76.stat(filePath);
69792
69735
  return stats.size;
69793
69736
  }
69794
69737
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -71358,8 +71301,8 @@ var init_geminiChat = __esm({
71358
71301
  async sendMessageStream(params, prompt_id) {
71359
71302
  await this.sendPromise;
71360
71303
  let streamDoneResolver;
71361
- const streamDonePromise = new Promise((resolve20) => {
71362
- streamDoneResolver = resolve20;
71304
+ const streamDonePromise = new Promise((resolve19) => {
71305
+ streamDoneResolver = resolve19;
71363
71306
  });
71364
71307
  this.sendPromise = streamDonePromise;
71365
71308
  const userContent = createUserContent(params.message);
@@ -73213,12 +73156,12 @@ var init_gitService = __esm({
73213
73156
  this.setupShadowGitRepository();
73214
73157
  }
73215
73158
  verifyGitAvailability() {
73216
- return new Promise((resolve20) => {
73159
+ return new Promise((resolve19) => {
73217
73160
  exec2("git --version", (error) => {
73218
73161
  if (error) {
73219
- resolve20(false);
73162
+ resolve19(false);
73220
73163
  } else {
73221
- resolve20(true);
73164
+ resolve19(true);
73222
73165
  }
73223
73166
  });
73224
73167
  });
@@ -74662,14 +74605,14 @@ async function openDiff(oldPath, newPath, editor, onEditorClose) {
74662
74605
  case "windsurf":
74663
74606
  case "cursor":
74664
74607
  case "zed":
74665
- return new Promise((resolve20, reject) => {
74608
+ return new Promise((resolve19, reject) => {
74666
74609
  const childProcess2 = spawn3(diffCommand.command, diffCommand.args, {
74667
74610
  stdio: "inherit",
74668
74611
  shell: true
74669
74612
  });
74670
74613
  childProcess2.on("close", (code) => {
74671
74614
  if (code === 0) {
74672
- resolve20();
74615
+ resolve19();
74673
74616
  } else {
74674
74617
  reject(new Error(`${editor} exited with code ${code}`));
74675
74618
  }
@@ -75027,7 +74970,7 @@ var init_coreToolScheduler = __esm({
75027
74970
  }
75028
74971
  schedule(request2, signal) {
75029
74972
  if (this.isRunning() || this.isScheduling) {
75030
- return new Promise((resolve20, reject) => {
74973
+ return new Promise((resolve19, reject) => {
75031
74974
  const abortHandler = () => {
75032
74975
  const index = this.requestQueue.findIndex((item) => item.request === request2);
75033
74976
  if (index > -1) {
@@ -75041,7 +74984,7 @@ var init_coreToolScheduler = __esm({
75041
74984
  signal,
75042
74985
  resolve: () => {
75043
74986
  signal.removeEventListener("abort", abortHandler);
75044
- resolve20();
74987
+ resolve19();
75045
74988
  },
75046
74989
  reject: (reason) => {
75047
74990
  signal.removeEventListener("abort", abortHandler);
@@ -80145,7 +80088,7 @@ var init_result_cache = __esm({
80145
80088
 
80146
80089
  // node_modules/fdir/dist/index.mjs
80147
80090
  import { createRequire } from "module";
80148
- import { basename as basename14, dirname as dirname9, normalize as normalize4, relative as relative5, resolve as resolve14, sep as sep4 } from "path";
80091
+ import { basename as basename14, dirname as dirname9, normalize as normalize4, relative as relative5, resolve as resolve13, sep as sep4 } from "path";
80149
80092
  import * as nativeFs from "fs";
80150
80093
  function cleanPath(path84) {
80151
80094
  let normalized2 = normalize4(path84);
@@ -80161,7 +80104,7 @@ function isRootDirectory(path84) {
80161
80104
  function normalizePath(path84, options2) {
80162
80105
  const { resolvePaths, normalizePath: normalizePath$1, pathSeparator } = options2;
80163
80106
  const pathNeedsCleaning = process.platform === "win32" && path84.includes("/") || path84.startsWith(".");
80164
- if (resolvePaths) path84 = resolve14(path84);
80107
+ if (resolvePaths) path84 = resolve13(path84);
80165
80108
  if (normalizePath$1 || pathNeedsCleaning) path84 = cleanPath(path84);
80166
80109
  if (path84 === ".") return "";
80167
80110
  const needsSeperator = path84[path84.length - 1] !== pathSeparator;
@@ -80312,11 +80255,11 @@ var init_dist = __esm({
80312
80255
  empty = () => {
80313
80256
  };
80314
80257
  resolveSymlinksAsync = function(path84, state, callback$1) {
80315
- const { queue, fs: fs73, options: { suppressErrors } } = state;
80258
+ const { queue, fs: fs76, options: { suppressErrors } } = state;
80316
80259
  queue.enqueue();
80317
- fs73.realpath(path84, (error, resolvedPath) => {
80260
+ fs76.realpath(path84, (error, resolvedPath) => {
80318
80261
  if (error) return queue.dequeue(suppressErrors ? null : error, state);
80319
- fs73.stat(resolvedPath, (error$1, stat7) => {
80262
+ fs76.stat(resolvedPath, (error$1, stat7) => {
80320
80263
  if (error$1) return queue.dequeue(suppressErrors ? null : error$1, state);
80321
80264
  if (stat7.isDirectory() && isRecursive(path84, resolvedPath, state)) return queue.dequeue(null, state);
80322
80265
  callback$1(stat7, resolvedPath);
@@ -80325,11 +80268,11 @@ var init_dist = __esm({
80325
80268
  });
80326
80269
  };
80327
80270
  resolveSymlinks = function(path84, state, callback$1) {
80328
- const { queue, fs: fs73, options: { suppressErrors } } = state;
80271
+ const { queue, fs: fs76, options: { suppressErrors } } = state;
80329
80272
  queue.enqueue();
80330
80273
  try {
80331
- const resolvedPath = fs73.realpathSync(path84);
80332
- const stat7 = fs73.statSync(resolvedPath);
80274
+ const resolvedPath = fs76.realpathSync(path84);
80275
+ const stat7 = fs76.statSync(resolvedPath);
80333
80276
  if (stat7.isDirectory() && isRecursive(path84, resolvedPath, state)) return;
80334
80277
  callback$1(stat7, resolvedPath);
80335
80278
  } catch (e2) {
@@ -80368,22 +80311,22 @@ var init_dist = __esm({
80368
80311
  walkAsync = (state, crawlPath, directoryPath, currentDepth, callback$1) => {
80369
80312
  state.queue.enqueue();
80370
80313
  if (currentDepth < 0) return state.queue.dequeue(null, state);
80371
- const { fs: fs73 } = state;
80314
+ const { fs: fs76 } = state;
80372
80315
  state.visited.push(crawlPath);
80373
80316
  state.counts.directories++;
80374
- fs73.readdir(crawlPath || ".", readdirOpts, (error, entries = []) => {
80317
+ fs76.readdir(crawlPath || ".", readdirOpts, (error, entries = []) => {
80375
80318
  callback$1(entries, directoryPath, currentDepth);
80376
80319
  state.queue.dequeue(state.options.suppressErrors ? null : error, state);
80377
80320
  });
80378
80321
  };
80379
80322
  walkSync = (state, crawlPath, directoryPath, currentDepth, callback$1) => {
80380
- const { fs: fs73 } = state;
80323
+ const { fs: fs76 } = state;
80381
80324
  if (currentDepth < 0) return;
80382
80325
  state.visited.push(crawlPath);
80383
80326
  state.counts.directories++;
80384
80327
  let entries = [];
80385
80328
  try {
80386
- entries = fs73.readdirSync(crawlPath || ".", readdirOpts);
80329
+ entries = fs76.readdirSync(crawlPath || ".", readdirOpts);
80387
80330
  } catch (e2) {
80388
80331
  if (!state.options.suppressErrors) throw e2;
80389
80332
  }
@@ -80997,7 +80940,7 @@ function basicMatch(query) {
80997
80940
  return getResultFromScoreMap(scoreMap, this.opts.limit);
80998
80941
  }
80999
80942
  function asyncMatcher(token2, len, iter2, onFinish) {
81000
- return new Promise((resolve20, reject) => {
80943
+ return new Promise((resolve19, reject) => {
81001
80944
  const INCREMENT = 1e3;
81002
80945
  let i = 0, end = Math.min(INCREMENT, len);
81003
80946
  const step = () => {
@@ -81010,7 +80953,7 @@ function asyncMatcher(token2, len, iter2, onFinish) {
81010
80953
  end = Math.min(end + INCREMENT, len);
81011
80954
  isNode ? setImmediate(step) : setTimeout(step);
81012
80955
  } else {
81013
- resolve20(onFinish());
80956
+ resolve19(onFinish());
81014
80957
  }
81015
80958
  };
81016
80959
  step();
@@ -81709,7 +81652,7 @@ async function filter3(allPaths, pattern, signal) {
81709
81652
  const results = [];
81710
81653
  for (const [i, p] of allPaths.entries()) {
81711
81654
  if (i % 1e3 === 0) {
81712
- await new Promise((resolve20) => setImmediate(resolve20));
81655
+ await new Promise((resolve19) => setImmediate(resolve19));
81713
81656
  if (signal?.aborted) {
81714
81657
  throw new AbortError();
81715
81658
  }
@@ -81792,7 +81735,7 @@ var init_fileSearch = __esm({
81792
81735
  const results = [];
81793
81736
  for (const [i, candidate] of filteredCandidates.entries()) {
81794
81737
  if (i % 1e3 === 0) {
81795
- await new Promise((resolve20) => setImmediate(resolve20));
81738
+ await new Promise((resolve19) => setImmediate(resolve19));
81796
81739
  if (options2.signal?.aborted) {
81797
81740
  throw new AbortError();
81798
81741
  }
@@ -84109,8 +84052,8 @@ var init_databasePool = __esm({
84109
84052
  this.connections.push(connection);
84110
84053
  return connection;
84111
84054
  }
84112
- return new Promise((resolve20) => {
84113
- this.pendingRequests.push(resolve20);
84055
+ return new Promise((resolve19) => {
84056
+ this.pendingRequests.push(resolve19);
84114
84057
  });
84115
84058
  }
84116
84059
  /**
@@ -84332,6 +84275,55 @@ var init_databaseMigrations = __esm({
84332
84275
  db.exec("DROP TABLE IF EXISTS model_configs");
84333
84276
  }
84334
84277
  });
84278
+ this.migrations.push({
84279
+ version: 2,
84280
+ name: "lock_metrics_tracking",
84281
+ up: (db) => {
84282
+ console.log("Creating lock_metrics table...");
84283
+ db.exec(`
84284
+ CREATE TABLE IF NOT EXISTS lock_metrics (
84285
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
84286
+ operation TEXT NOT NULL,
84287
+ lock_acquired_at DATETIME NOT NULL,
84288
+ lock_released_at DATETIME,
84289
+ wait_time_ms INTEGER DEFAULT 0,
84290
+ hold_time_ms INTEGER,
84291
+ timeout_occurred BOOLEAN DEFAULT 0,
84292
+ conflict_detected BOOLEAN DEFAULT 0,
84293
+ error_message TEXT,
84294
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP
84295
+ )
84296
+ `);
84297
+ db.exec(`
84298
+ CREATE INDEX IF NOT EXISTS idx_lock_metrics_recent
84299
+ ON lock_metrics(created_at DESC)
84300
+ `);
84301
+ db.exec(`
84302
+ CREATE INDEX IF NOT EXISTS idx_lock_metrics_timeouts
84303
+ ON lock_metrics(timeout_occurred, created_at DESC)
84304
+ WHERE timeout_occurred = 1
84305
+ `);
84306
+ db.exec(`
84307
+ CREATE INDEX IF NOT EXISTS idx_lock_metrics_conflicts
84308
+ ON lock_metrics(conflict_detected, created_at DESC)
84309
+ WHERE conflict_detected = 1
84310
+ `);
84311
+ const now = (/* @__PURE__ */ new Date()).toISOString();
84312
+ db.exec(`
84313
+ INSERT OR REPLACE INTO schema_info (key, value, updated_at)
84314
+ VALUES
84315
+ ('lock_metrics_enabled', '1', '${now}')
84316
+ `);
84317
+ console.log("lock_metrics table created successfully");
84318
+ },
84319
+ down: (db) => {
84320
+ db.exec("DROP INDEX IF EXISTS idx_lock_metrics_conflicts");
84321
+ db.exec("DROP INDEX IF EXISTS idx_lock_metrics_timeouts");
84322
+ db.exec("DROP INDEX IF EXISTS idx_lock_metrics_recent");
84323
+ db.exec("DROP TABLE IF EXISTS lock_metrics");
84324
+ db.exec(`DELETE FROM schema_info WHERE key = 'lock_metrics_enabled'`);
84325
+ }
84326
+ });
84335
84327
  }
84336
84328
  /**
84337
84329
  * Get current schema version from database
@@ -84842,17 +84834,17 @@ var init_async_mutex = __esm({
84842
84834
  * @returns Promise that resolves to a release function
84843
84835
  */
84844
84836
  async acquire() {
84845
- return new Promise((resolve20) => {
84837
+ return new Promise((resolve19) => {
84846
84838
  if (!this.locked) {
84847
84839
  this.locked = true;
84848
84840
  this.debugLog("\u{1F512} Mutex acquired immediately");
84849
- resolve20(() => this.release());
84841
+ resolve19(() => this.release());
84850
84842
  } else {
84851
84843
  this.debugLog(`\u23F3 Mutex busy, joining queue (position: ${this.waitQueue.length + 1})`);
84852
84844
  this.waitQueue.push(() => {
84853
84845
  this.locked = true;
84854
84846
  this.debugLog("\u{1F512} Mutex acquired from queue");
84855
- resolve20(() => this.release());
84847
+ resolve19(() => this.release());
84856
84848
  });
84857
84849
  }
84858
84850
  });
@@ -85010,7 +85002,7 @@ var init_database_queue = __esm({
85010
85002
  */
85011
85003
  async waitForIdle() {
85012
85004
  while (this.mutex.isLocked() || this.mutex.getQueueLength() > 0) {
85013
- await new Promise((resolve20) => setTimeout(resolve20, 10));
85005
+ await new Promise((resolve19) => setTimeout(resolve19, 10));
85014
85006
  }
85015
85007
  this.debugLog("\u{1F3C1} [DB-QUEUE] All operations completed - queue is idle");
85016
85008
  }
@@ -85074,9 +85066,344 @@ var init_database_queue = __esm({
85074
85066
  }
85075
85067
  });
85076
85068
 
85069
+ // packages/cli/src/config/database-lock.ts
85070
+ import lockfile from "proper-lockfile";
85071
+ import * as fs52 from "fs";
85072
+ var DatabaseLockManager;
85073
+ var init_database_lock = __esm({
85074
+ "packages/cli/src/config/database-lock.ts"() {
85075
+ DatabaseLockManager = class {
85076
+ lockPath;
85077
+ dbPath;
85078
+ options;
85079
+ db = null;
85080
+ currentMetrics = null;
85081
+ constructor(dbPath, customTimeout) {
85082
+ this.dbPath = dbPath;
85083
+ this.lockPath = `${dbPath}.lock`;
85084
+ const envTimeout = process.env["FSS_LOCK_TIMEOUT"];
85085
+ const timeout = customTimeout || (envTimeout ? parseInt(envTimeout, 10) : 5e3);
85086
+ this.options = {
85087
+ stale: 1e4,
85088
+ // 10 seconds - if process hasn't updated lock, consider stale
85089
+ retries: 10,
85090
+ // Try 10 times
85091
+ retryInterval: 100,
85092
+ // Start with 100ms
85093
+ timeout
85094
+ // Configurable via FSS_LOCK_TIMEOUT env var (default 5000ms)
85095
+ };
85096
+ }
85097
+ /**
85098
+ * Set database instance for metrics tracking
85099
+ */
85100
+ setDatabase(db) {
85101
+ this.db = db;
85102
+ }
85103
+ /**
85104
+ * Acquire exclusive lock for database write operation
85105
+ *
85106
+ * Returns an unlock function that must be called to release the lock.
85107
+ * Uses exponential backoff for retries if lock is held by another process.
85108
+ *
85109
+ * @throws Error if lock cannot be acquired within timeout
85110
+ * @returns Unlock function
85111
+ */
85112
+ async acquireLock(operationName = "database_save") {
85113
+ const startTime = Date.now();
85114
+ let attempt = 0;
85115
+ let conflictDetected = false;
85116
+ this.currentMetrics = {
85117
+ operation: operationName,
85118
+ lockAcquiredAt: /* @__PURE__ */ new Date(),
85119
+ waitTimeMs: 0,
85120
+ timeoutOccurred: false,
85121
+ conflictDetected: false
85122
+ };
85123
+ while (Date.now() - startTime < this.options.timeout) {
85124
+ try {
85125
+ await lockfile.lock(this.dbPath, {
85126
+ stale: this.options.stale,
85127
+ retries: {
85128
+ retries: 0,
85129
+ // We handle retries manually for better control
85130
+ minTimeout: this.options.retryInterval
85131
+ },
85132
+ lockfilePath: this.lockPath
85133
+ });
85134
+ const waitTime = Date.now() - startTime;
85135
+ this.currentMetrics.waitTimeMs = waitTime;
85136
+ this.currentMetrics.conflictDetected = conflictDetected;
85137
+ if (process.env["FSS_DEBUG"] === "true") {
85138
+ console.log(`[DB-LOCK] Lock acquired (attempt ${attempt + 1}, waited ${waitTime}ms)`);
85139
+ }
85140
+ return async () => {
85141
+ const unlockStartTime = Date.now();
85142
+ try {
85143
+ await lockfile.unlock(this.dbPath, {
85144
+ lockfilePath: this.lockPath
85145
+ });
85146
+ if (this.currentMetrics) {
85147
+ this.currentMetrics.lockReleasedAt = /* @__PURE__ */ new Date();
85148
+ this.currentMetrics.holdTimeMs = Date.now() - unlockStartTime;
85149
+ await this.recordMetrics(this.currentMetrics);
85150
+ }
85151
+ if (process.env["FSS_DEBUG"] === "true") {
85152
+ console.log("[DB-LOCK] Lock released");
85153
+ }
85154
+ } catch (err) {
85155
+ const errorMsg = `Failed to unlock: ${err instanceof Error ? err.message : String(err)}`;
85156
+ console.warn("[DB-LOCK]", errorMsg);
85157
+ if (this.currentMetrics) {
85158
+ this.currentMetrics.errorMessage = errorMsg;
85159
+ await this.recordMetrics(this.currentMetrics);
85160
+ }
85161
+ }
85162
+ };
85163
+ } catch (err) {
85164
+ if (err.code === "ELOCKED") {
85165
+ conflictDetected = true;
85166
+ attempt++;
85167
+ const backoff = Math.min(
85168
+ this.options.retryInterval * Math.pow(2, attempt),
85169
+ 1e3
85170
+ // Max 1 second between retries
85171
+ );
85172
+ if (process.env["FSS_DEBUG"] === "true") {
85173
+ console.log(`[DB-LOCK] Lock held by another process, retrying in ${backoff}ms (attempt ${attempt}/${this.options.retries})...`);
85174
+ }
85175
+ await this.sleep(backoff);
85176
+ continue;
85177
+ }
85178
+ const errorMsg = this.getUserFriendlyErrorMessage(err);
85179
+ if (this.currentMetrics) {
85180
+ this.currentMetrics.timeoutOccurred = true;
85181
+ this.currentMetrics.errorMessage = errorMsg;
85182
+ await this.recordMetrics(this.currentMetrics);
85183
+ }
85184
+ throw new Error(errorMsg);
85185
+ }
85186
+ }
85187
+ const timeoutMsg = this.getTimeoutErrorMessage();
85188
+ if (this.currentMetrics) {
85189
+ this.currentMetrics.timeoutOccurred = true;
85190
+ this.currentMetrics.conflictDetected = conflictDetected;
85191
+ this.currentMetrics.waitTimeMs = Date.now() - startTime;
85192
+ this.currentMetrics.errorMessage = timeoutMsg;
85193
+ await this.recordMetrics(this.currentMetrics);
85194
+ }
85195
+ throw new Error(timeoutMsg);
85196
+ }
85197
+ /**
85198
+ * Check if database is currently locked by another process
85199
+ *
85200
+ * @returns true if locked, false if available or stale
85201
+ */
85202
+ async isLocked() {
85203
+ try {
85204
+ return await lockfile.check(this.dbPath, {
85205
+ lockfilePath: this.lockPath,
85206
+ stale: this.options.stale
85207
+ });
85208
+ } catch (err) {
85209
+ return false;
85210
+ }
85211
+ }
85212
+ /**
85213
+ * Force remove stale lock file
85214
+ *
85215
+ * Use with caution! Only call this if you're certain the lock is stale
85216
+ * (e.g., from a crashed process).
85217
+ */
85218
+ async forceUnlock() {
85219
+ try {
85220
+ if (fs52.existsSync(this.lockPath)) {
85221
+ const stat7 = fs52.statSync(this.lockPath);
85222
+ const age = Date.now() - stat7.mtimeMs;
85223
+ if (age > this.options.stale) {
85224
+ console.warn(`[DB-LOCK] Removing stale lock (${age}ms old)`);
85225
+ fs52.unlinkSync(this.lockPath);
85226
+ } else {
85227
+ console.warn(`[DB-LOCK] Lock is not stale (${age}ms old), not removing`);
85228
+ }
85229
+ }
85230
+ } catch (err) {
85231
+ console.warn("[DB-LOCK] Failed to force unlock:", err);
85232
+ }
85233
+ }
85234
+ /**
85235
+ * Get lock file path (for debugging)
85236
+ */
85237
+ getLockPath() {
85238
+ return this.lockPath;
85239
+ }
85240
+ /**
85241
+ * Sleep for specified milliseconds
85242
+ */
85243
+ sleep(ms) {
85244
+ return new Promise((resolve19) => setTimeout(resolve19, ms));
85245
+ }
85246
+ /**
85247
+ * Record lock metrics to database
85248
+ */
85249
+ async recordMetrics(metrics2) {
85250
+ if (!this.db) {
85251
+ return;
85252
+ }
85253
+ try {
85254
+ const stmt = this.db.prepare(`
85255
+ INSERT INTO lock_metrics (
85256
+ operation,
85257
+ lock_acquired_at,
85258
+ lock_released_at,
85259
+ wait_time_ms,
85260
+ hold_time_ms,
85261
+ timeout_occurred,
85262
+ conflict_detected,
85263
+ error_message
85264
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
85265
+ `);
85266
+ stmt.run([
85267
+ metrics2.operation,
85268
+ metrics2.lockAcquiredAt.toISOString(),
85269
+ metrics2.lockReleasedAt?.toISOString() || null,
85270
+ metrics2.waitTimeMs,
85271
+ metrics2.holdTimeMs || null,
85272
+ metrics2.timeoutOccurred ? 1 : 0,
85273
+ metrics2.conflictDetected ? 1 : 0,
85274
+ metrics2.errorMessage || null
85275
+ ]);
85276
+ stmt.free();
85277
+ } catch (err) {
85278
+ if (process.env["FSS_DEBUG"] === "true") {
85279
+ console.warn("[DB-LOCK] Failed to record metrics:", err);
85280
+ }
85281
+ }
85282
+ }
85283
+ /**
85284
+ * Get user-friendly error message for lock errors
85285
+ */
85286
+ getUserFriendlyErrorMessage(err) {
85287
+ if (err.code === "EACCES" || err.code === "EPERM") {
85288
+ return "Cannot save database: Permission denied. Please check file permissions for your FSS Link database.";
85289
+ }
85290
+ if (err.code === "ENOENT") {
85291
+ return "Cannot save database: Database directory not found. The database folder may have been deleted.";
85292
+ }
85293
+ if (err.code === "ENOSPC") {
85294
+ return "Cannot save database: No space left on disk. Please free up disk space and try again.";
85295
+ }
85296
+ if (err.code === "EROFS") {
85297
+ return "Cannot save database: File system is read-only. The disk may be mounted as read-only.";
85298
+ }
85299
+ return `Cannot save database: ${err.message || "Unknown error"}. Please check your system and try again.`;
85300
+ }
85301
+ /**
85302
+ * Get user-friendly timeout error message
85303
+ */
85304
+ getTimeoutErrorMessage() {
85305
+ const timeoutSeconds = Math.round(this.options.timeout / 1e3);
85306
+ return `Cannot save database: Another FSS Link instance is currently saving data. Waited ${timeoutSeconds} seconds but the lock is still held. Please wait for the other instance to complete, or use 'fss-link db:force-unlock' if you're certain no other instance is running.`;
85307
+ }
85308
+ /**
85309
+ * Get recent lock metrics for diagnostics
85310
+ */
85311
+ async getMetrics(limit2 = 10) {
85312
+ if (!this.db) {
85313
+ return [];
85314
+ }
85315
+ try {
85316
+ const stmt = this.db.prepare(`
85317
+ SELECT
85318
+ id,
85319
+ operation,
85320
+ lock_acquired_at,
85321
+ lock_released_at,
85322
+ wait_time_ms,
85323
+ hold_time_ms,
85324
+ timeout_occurred,
85325
+ conflict_detected,
85326
+ error_message,
85327
+ created_at
85328
+ FROM lock_metrics
85329
+ ORDER BY created_at DESC
85330
+ LIMIT ?
85331
+ `);
85332
+ stmt.bind([limit2]);
85333
+ const results = [];
85334
+ while (stmt.step()) {
85335
+ const row = stmt.getAsObject();
85336
+ results.push({
85337
+ id: row["id"],
85338
+ operation: row["operation"],
85339
+ lockAcquiredAt: row["lock_acquired_at"],
85340
+ lockReleasedAt: row["lock_released_at"],
85341
+ waitTimeMs: row["wait_time_ms"],
85342
+ holdTimeMs: row["hold_time_ms"],
85343
+ timeoutOccurred: Boolean(row["timeout_occurred"]),
85344
+ conflictDetected: Boolean(row["conflict_detected"]),
85345
+ errorMessage: row["error_message"],
85346
+ createdAt: row["created_at"]
85347
+ });
85348
+ }
85349
+ stmt.free();
85350
+ return results;
85351
+ } catch (err) {
85352
+ console.warn("[DB-LOCK] Failed to get metrics:", err);
85353
+ return [];
85354
+ }
85355
+ }
85356
+ /**
85357
+ * Get lock statistics summary
85358
+ */
85359
+ async getStatistics() {
85360
+ if (!this.db) {
85361
+ return {
85362
+ totalOperations: 0,
85363
+ totalTimeouts: 0,
85364
+ totalConflicts: 0,
85365
+ averageWaitTime: 0,
85366
+ averageHoldTime: 0
85367
+ };
85368
+ }
85369
+ try {
85370
+ const stmt = this.db.prepare(`
85371
+ SELECT
85372
+ COUNT(*) as total_operations,
85373
+ SUM(CASE WHEN timeout_occurred = 1 THEN 1 ELSE 0 END) as total_timeouts,
85374
+ SUM(CASE WHEN conflict_detected = 1 THEN 1 ELSE 0 END) as total_conflicts,
85375
+ AVG(wait_time_ms) as avg_wait_time,
85376
+ AVG(hold_time_ms) as avg_hold_time
85377
+ FROM lock_metrics
85378
+ `);
85379
+ stmt.step();
85380
+ const row = stmt.getAsObject();
85381
+ stmt.free();
85382
+ return {
85383
+ totalOperations: row["total_operations"] || 0,
85384
+ totalTimeouts: row["total_timeouts"] || 0,
85385
+ totalConflicts: row["total_conflicts"] || 0,
85386
+ averageWaitTime: row["avg_wait_time"] || 0,
85387
+ averageHoldTime: row["avg_hold_time"] || 0
85388
+ };
85389
+ } catch (err) {
85390
+ console.warn("[DB-LOCK] Failed to get statistics:", err);
85391
+ return {
85392
+ totalOperations: 0,
85393
+ totalTimeouts: 0,
85394
+ totalConflicts: 0,
85395
+ averageWaitTime: 0,
85396
+ averageHoldTime: 0
85397
+ };
85398
+ }
85399
+ }
85400
+ };
85401
+ }
85402
+ });
85403
+
85077
85404
  // packages/cli/src/config/core-database.ts
85078
85405
  import * as path58 from "path";
85079
- import * as fs52 from "fs";
85406
+ import * as fs53 from "fs";
85080
85407
  function getCoreDatabase() {
85081
85408
  if (!coreDatabase) {
85082
85409
  const dbPath = path58.join(USER_SETTINGS_DIR, "fss-link.db");
@@ -85092,12 +85419,14 @@ var init_core_database = __esm({
85092
85419
  init_databaseMigrations();
85093
85420
  init_queryOptimizer();
85094
85421
  init_database_queue();
85422
+ init_database_lock();
85095
85423
  CoreDatabase = class {
85096
85424
  constructor(dbPath) {
85097
85425
  this.dbPath = dbPath;
85098
85426
  this.migrationManager = new MigrationManager();
85099
85427
  this.queryOptimizer = new QueryOptimizer();
85100
85428
  this.pool = getDatabasePool(dbPath);
85429
+ this.lockManager = new DatabaseLockManager(dbPath);
85101
85430
  }
85102
85431
  db = null;
85103
85432
  isInitialized = false;
@@ -85105,6 +85434,7 @@ var init_core_database = __esm({
85105
85434
  migrationManager;
85106
85435
  queryOptimizer;
85107
85436
  pool;
85437
+ lockManager;
85108
85438
  /**
85109
85439
  * Get the database instance (for delegation to other managers)
85110
85440
  */
@@ -85128,10 +85458,18 @@ var init_core_database = __esm({
85128
85458
  */
85129
85459
  async initialize() {
85130
85460
  try {
85461
+ const isLocked = await this.lockManager.isLocked();
85462
+ if (isLocked) {
85463
+ console.warn("[DB-INIT] Database is locked by another process");
85464
+ console.warn("[DB-INIT] This might indicate:");
85465
+ console.warn("[DB-INIT] 1. Another FSS Link instance is currently saving");
85466
+ console.warn("[DB-INIT] 2. Previous instance crashed during save operation");
85467
+ console.warn("[DB-INIT] Waiting for lock to be released or expire (10s)...");
85468
+ }
85131
85469
  await this.pool.initialize();
85132
- if (fs52.existsSync(this.dbPath)) {
85470
+ if (fs53.existsSync(this.dbPath)) {
85133
85471
  try {
85134
- const buffer = fs52.readFileSync(this.dbPath).slice(0, 100);
85472
+ const buffer = fs53.readFileSync(this.dbPath).slice(0, 100);
85135
85473
  if (!buffer.toString("ascii", 0, 16).includes("SQLite format 3")) {
85136
85474
  console.warn("Database file appears corrupted, attempting recovery...");
85137
85475
  await this.recoverFromCorruption();
@@ -85144,6 +85482,7 @@ var init_core_database = __esm({
85144
85482
  this.db = await this.createPrimaryConnection();
85145
85483
  await this.initializeSchema(this.db);
85146
85484
  await this.ensureDefaultConfigurations(this.db);
85485
+ this.lockManager.setDatabase(this.db);
85147
85486
  this.isInitialized = true;
85148
85487
  this.setupAutoSave();
85149
85488
  } catch (error) {
@@ -85153,6 +85492,7 @@ var init_core_database = __esm({
85153
85492
  this.db = await this.createPrimaryConnection();
85154
85493
  await this.initializeSchema(this.db);
85155
85494
  await this.ensureDefaultConfigurations(this.db);
85495
+ this.lockManager.setDatabase(this.db);
85156
85496
  this.isInitialized = true;
85157
85497
  this.setupAutoSave();
85158
85498
  console.log("Database recovery successful");
@@ -85175,8 +85515,8 @@ var init_core_database = __esm({
85175
85515
  */
85176
85516
  async createPrimaryConnection() {
85177
85517
  const dbDir = path58.dirname(this.dbPath);
85178
- if (!fs52.existsSync(dbDir)) {
85179
- fs52.mkdirSync(dbDir, { recursive: true });
85518
+ if (!fs53.existsSync(dbDir)) {
85519
+ fs53.mkdirSync(dbDir, { recursive: true });
85180
85520
  }
85181
85521
  const connection = await this.pool.getConnection();
85182
85522
  return connection;
@@ -85239,10 +85579,15 @@ var init_core_database = __esm({
85239
85579
  }, "forceSave");
85240
85580
  }
85241
85581
  /**
85242
- * Perform database save operation
85582
+ * Perform database save operation with file locking
85583
+ *
85584
+ * Acquires an exclusive lock before writing to disk to prevent concurrent
85585
+ * writes from multiple FSS Link instances. The lock is automatically released
85586
+ * after the write completes (or fails).
85243
85587
  */
85244
85588
  async performSave() {
85245
85589
  if (!this.db) return;
85590
+ const unlock = await this.lockManager.acquireLock();
85246
85591
  try {
85247
85592
  console.log("[DB-SAVE] About to export - DB instance:", this.db.constructor.name);
85248
85593
  console.log("[DB-SAVE] DB has", this.db.exec("SELECT COUNT(*) FROM user_preferences")[0]?.values[0][0] || 0, "preferences in memory");
@@ -85255,22 +85600,38 @@ var init_core_database = __esm({
85255
85600
  console.log("[DB-SAVE] Exporting database from memory...");
85256
85601
  const data = this.db.export();
85257
85602
  console.log("[DB-SAVE] Exported", data.length, "bytes");
85258
- if (fs52.existsSync(this.dbPath)) {
85603
+ if (fs53.existsSync(this.dbPath)) {
85259
85604
  const backupPath2 = `${this.dbPath}.backup`;
85260
85605
  console.log("[DB-SAVE] Creating backup:", backupPath2);
85261
- fs52.copyFileSync(this.dbPath, backupPath2);
85606
+ fs53.copyFileSync(this.dbPath, backupPath2);
85262
85607
  }
85263
85608
  console.log("[DB-SAVE] Writing to:", this.dbPath);
85264
- fs52.writeFileSync(this.dbPath, Buffer.from(data));
85609
+ fs53.writeFileSync(this.dbPath, Buffer.from(data));
85265
85610
  console.log("[DB-SAVE] Write completed successfully");
85611
+ const written = fs53.readFileSync(this.dbPath);
85612
+ if (written.length !== data.length) {
85613
+ throw new Error("Write verification failed: size mismatch");
85614
+ }
85266
85615
  const backupPath = `${this.dbPath}.backup`;
85267
- if (fs52.existsSync(backupPath)) {
85616
+ if (fs53.existsSync(backupPath)) {
85268
85617
  console.log("[DB-SAVE] Removing backup");
85269
- fs52.unlinkSync(backupPath);
85618
+ fs53.unlinkSync(backupPath);
85270
85619
  }
85271
85620
  } catch (error) {
85272
85621
  console.error("[DB-SAVE] ERROR: Database save failed:", error);
85622
+ const backupPath = `${this.dbPath}.backup`;
85623
+ if (fs53.existsSync(backupPath)) {
85624
+ console.log("[DB-SAVE] Restoring from backup...");
85625
+ try {
85626
+ fs53.copyFileSync(backupPath, this.dbPath);
85627
+ console.log("[DB-SAVE] Backup restored successfully");
85628
+ } catch (restoreError) {
85629
+ console.error("[DB-SAVE] Failed to restore backup:", restoreError);
85630
+ }
85631
+ }
85273
85632
  throw error;
85633
+ } finally {
85634
+ await unlock();
85274
85635
  }
85275
85636
  }
85276
85637
  /**
@@ -85280,13 +85641,13 @@ var init_core_database = __esm({
85280
85641
  console.log("Attempting database corruption recovery...");
85281
85642
  const backupPath = `${this.dbPath}.backup`;
85282
85643
  const corruptedPath = `${this.dbPath}.corrupted.${Date.now()}`;
85283
- if (fs52.existsSync(this.dbPath)) {
85284
- fs52.renameSync(this.dbPath, corruptedPath);
85644
+ if (fs53.existsSync(this.dbPath)) {
85645
+ fs53.renameSync(this.dbPath, corruptedPath);
85285
85646
  console.log(`Moved corrupted database to: ${corruptedPath}`);
85286
85647
  }
85287
- if (fs52.existsSync(backupPath)) {
85648
+ if (fs53.existsSync(backupPath)) {
85288
85649
  try {
85289
- fs52.copyFileSync(backupPath, this.dbPath);
85650
+ fs53.copyFileSync(backupPath, this.dbPath);
85290
85651
  console.log("Restored database from backup file");
85291
85652
  return;
85292
85653
  } catch (backupError) {
@@ -85304,6 +85665,7 @@ var init_core_database = __esm({
85304
85665
  throw new Error("Database not available for default configuration setup");
85305
85666
  }
85306
85667
  const stmt = database.prepare("SELECT COUNT(*) as count FROM model_configs");
85668
+ stmt.step();
85307
85669
  const result = stmt.getAsObject();
85308
85670
  stmt.free();
85309
85671
  if (result.count > 0) {
@@ -85417,6 +85779,12 @@ var init_core_database = __esm({
85417
85779
  getMigrationManager() {
85418
85780
  return this.migrationManager;
85419
85781
  }
85782
+ /**
85783
+ * Get lock manager instance
85784
+ */
85785
+ getLockManager() {
85786
+ return this.lockManager;
85787
+ }
85420
85788
  };
85421
85789
  coreDatabase = null;
85422
85790
  }
@@ -87189,7 +87557,7 @@ var init_unified_database = __esm({
87189
87557
 
87190
87558
  // packages/cli/src/config/database.ts
87191
87559
  import * as path59 from "path";
87192
- import * as fs53 from "fs";
87560
+ import * as fs54 from "fs";
87193
87561
  import * as crypto13 from "crypto";
87194
87562
  function debugLog(message) {
87195
87563
  if (process.env["FSS_DEBUG"] === "true") {
@@ -87206,8 +87574,8 @@ async function getFSSLinkDatabase() {
87206
87574
  }
87207
87575
  if (initializationLock) {
87208
87576
  debugLog("Database initialization locked, queuing request...");
87209
- return new Promise((resolve20, reject) => {
87210
- waitingQueue.push({ resolve: resolve20, reject });
87577
+ return new Promise((resolve19, reject) => {
87578
+ waitingQueue.push({ resolve: resolve19, reject });
87211
87579
  });
87212
87580
  }
87213
87581
  initializationLock = true;
@@ -87221,7 +87589,7 @@ async function getFSSLinkDatabase() {
87221
87589
  databaseInstance = instance;
87222
87590
  const queue = [...waitingQueue];
87223
87591
  waitingQueue = [];
87224
- queue.forEach(({ resolve: resolve20 }) => resolve20(instance));
87592
+ queue.forEach(({ resolve: resolve19 }) => resolve19(instance));
87225
87593
  return instance;
87226
87594
  } catch (error) {
87227
87595
  const queue = [...waitingQueue];
@@ -87247,14 +87615,14 @@ var init_database = __esm({
87247
87615
  constructor() {
87248
87616
  this.unifiedDb = getUnifiedDatabase();
87249
87617
  const keyPath = path59.join(USER_SETTINGS_DIR, "db.key");
87250
- if (fs53.existsSync(keyPath)) {
87251
- this.encryptionKey = fs53.readFileSync(keyPath);
87618
+ if (fs54.existsSync(keyPath)) {
87619
+ this.encryptionKey = fs54.readFileSync(keyPath);
87252
87620
  } else {
87253
87621
  this.encryptionKey = crypto13.randomBytes(32);
87254
- if (!fs53.existsSync(USER_SETTINGS_DIR)) {
87255
- fs53.mkdirSync(USER_SETTINGS_DIR, { recursive: true });
87622
+ if (!fs54.existsSync(USER_SETTINGS_DIR)) {
87623
+ fs54.mkdirSync(USER_SETTINGS_DIR, { recursive: true });
87256
87624
  }
87257
- fs53.writeFileSync(keyPath, this.encryptionKey);
87625
+ fs54.writeFileSync(keyPath, this.encryptionKey);
87258
87626
  }
87259
87627
  }
87260
87628
  /**
@@ -87558,14 +87926,14 @@ var init_database = __esm({
87558
87926
  */
87559
87927
  static getEncryptionKey() {
87560
87928
  const keyPath = path59.join(USER_SETTINGS_DIR, "db.key");
87561
- if (fs53.existsSync(keyPath)) {
87562
- return fs53.readFileSync(keyPath);
87929
+ if (fs54.existsSync(keyPath)) {
87930
+ return fs54.readFileSync(keyPath);
87563
87931
  } else {
87564
87932
  const key = crypto13.randomBytes(32);
87565
- if (!fs53.existsSync(USER_SETTINGS_DIR)) {
87566
- fs53.mkdirSync(USER_SETTINGS_DIR, { recursive: true });
87933
+ if (!fs54.existsSync(USER_SETTINGS_DIR)) {
87934
+ fs54.mkdirSync(USER_SETTINGS_DIR, { recursive: true });
87567
87935
  }
87568
- fs53.writeFileSync(keyPath, key);
87936
+ fs54.writeFileSync(keyPath, key);
87569
87937
  return key;
87570
87938
  }
87571
87939
  }
@@ -91057,13 +91425,13 @@ var isAtCommand = (query) => (
91057
91425
  );
91058
91426
  var isSlashCommand = (query) => query.startsWith("/");
91059
91427
  var copyToClipboard = async (text) => {
91060
- const run = (cmd, args) => new Promise((resolve20, reject) => {
91428
+ const run = (cmd, args) => new Promise((resolve19, reject) => {
91061
91429
  const child = spawn4(cmd, args);
91062
91430
  let stderr = "";
91063
91431
  child.stderr.on("data", (chunk) => stderr += chunk.toString());
91064
91432
  child.on("error", reject);
91065
91433
  child.on("close", (code) => {
91066
- if (code === 0) return resolve20();
91434
+ if (code === 0) return resolve19();
91067
91435
  const errorMsg = stderr.trim();
91068
91436
  reject(
91069
91437
  new Error(
@@ -91621,7 +91989,7 @@ var useShellCommandProcessor = (addItemToHistory, setPendingHistoryItem, onExec,
91621
91989
  }
91622
91990
  commandToExecute = `{ ${command} }; __code=$?; pwd > "${pwdFilePath}"; exit $__code`;
91623
91991
  }
91624
- const executeCommand = async (resolve20) => {
91992
+ const executeCommand = async (resolve19) => {
91625
91993
  let lastUpdateTime = Date.now();
91626
91994
  let cumulativeStdout = "";
91627
91995
  let isBinaryStream = false;
@@ -91764,7 +92132,7 @@ ${finalOutput}`;
91764
92132
  if (pwdFilePath && fs47.existsSync(pwdFilePath)) {
91765
92133
  fs47.unlinkSync(pwdFilePath);
91766
92134
  }
91767
- resolve20();
92135
+ resolve19();
91768
92136
  });
91769
92137
  } catch (err) {
91770
92138
  setPendingHistoryItem(null);
@@ -91779,11 +92147,11 @@ ${finalOutput}`;
91779
92147
  if (pwdFilePath && fs47.existsSync(pwdFilePath)) {
91780
92148
  fs47.unlinkSync(pwdFilePath);
91781
92149
  }
91782
- resolve20();
92150
+ resolve19();
91783
92151
  }
91784
92152
  };
91785
- const execPromise = new Promise((resolve20) => {
91786
- executeCommand(resolve20);
92153
+ const execPromise = new Promise((resolve19) => {
92154
+ executeCommand(resolve19);
91787
92155
  });
91788
92156
  onExec(execPromise);
91789
92157
  return true;
@@ -96485,7 +96853,7 @@ var FolderTrustDialog = ({
96485
96853
  // packages/cli/src/config/trustedFolders.ts
96486
96854
  init_dist2();
96487
96855
  var import_strip_json_comments2 = __toESM(require_strip_json_comments(), 1);
96488
- import * as fs54 from "fs";
96856
+ import * as fs55 from "fs";
96489
96857
  import * as path60 from "path";
96490
96858
  import { homedir as homedir13 } from "os";
96491
96859
  var TRUSTED_FOLDERS_FILENAME = "trustedFolders.json";
@@ -96516,8 +96884,8 @@ function loadTrustedFolders() {
96516
96884
  const userConfig = {};
96517
96885
  const userPath = USER_TRUSTED_FOLDERS_PATH;
96518
96886
  try {
96519
- if (fs54.existsSync(userPath)) {
96520
- const content = fs54.readFileSync(userPath, "utf-8");
96887
+ if (fs55.existsSync(userPath)) {
96888
+ const content = fs55.readFileSync(userPath, "utf-8");
96521
96889
  const parsed = JSON.parse((0, import_strip_json_comments2.default)(content));
96522
96890
  if (parsed) {
96523
96891
  Object.assign(userConfig, parsed);
@@ -96537,10 +96905,10 @@ function loadTrustedFolders() {
96537
96905
  function saveTrustedFolders(trustedFoldersFile) {
96538
96906
  try {
96539
96907
  const dirPath = path60.dirname(trustedFoldersFile.path);
96540
- if (!fs54.existsSync(dirPath)) {
96541
- fs54.mkdirSync(dirPath, { recursive: true });
96908
+ if (!fs55.existsSync(dirPath)) {
96909
+ fs55.mkdirSync(dirPath, { recursive: true });
96542
96910
  }
96543
- fs54.writeFileSync(
96911
+ fs55.writeFileSync(
96544
96912
  trustedFoldersFile.path,
96545
96913
  JSON.stringify(trustedFoldersFile.config, null, 2),
96546
96914
  "utf-8"
@@ -96789,7 +97157,7 @@ async function getPackageJson() {
96789
97157
  // packages/cli/src/utils/version.ts
96790
97158
  async function getCliVersion() {
96791
97159
  const pkgJson = await getPackageJson();
96792
- return "1.5.4";
97160
+ return "1.5.6";
96793
97161
  }
96794
97162
 
96795
97163
  // packages/cli/src/ui/commands/aboutCommand.ts
@@ -96841,7 +97209,7 @@ import open4 from "open";
96841
97209
  import process11 from "node:process";
96842
97210
 
96843
97211
  // packages/cli/src/generated/git-commit.ts
96844
- var GIT_COMMIT_INFO = "ff600884";
97212
+ var GIT_COMMIT_INFO = "5a5d9179";
96845
97213
 
96846
97214
  // packages/cli/src/ui/commands/bugCommand.ts
96847
97215
  init_dist2();
@@ -97680,7 +98048,7 @@ var ideCommand = (config) => {
97680
98048
  if (ideClient.getConnectionStatus().status === IDEConnectionStatus.Connected) {
97681
98049
  break;
97682
98050
  }
97683
- await new Promise((resolve20) => setTimeout(resolve20, 500));
98051
+ await new Promise((resolve19) => setTimeout(resolve19, 500));
97684
98052
  }
97685
98053
  const { messageType, content } = getIdeStatusMessage(ideClient);
97686
98054
  if (messageType === "error") {
@@ -97752,7 +98120,7 @@ var ideCommand = (config) => {
97752
98120
  };
97753
98121
 
97754
98122
  // packages/cli/src/ui/commands/initCommand.ts
97755
- import * as fs55 from "fs";
98123
+ import * as fs56 from "fs";
97756
98124
  import * as path65 from "path";
97757
98125
  init_dist2();
97758
98126
  var initCommand = {
@@ -97771,9 +98139,9 @@ var initCommand = {
97771
98139
  const contextFileName = getCurrentGeminiMdFilename();
97772
98140
  const contextFilePath = path65.join(targetDir, contextFileName);
97773
98141
  try {
97774
- if (fs55.existsSync(contextFilePath)) {
98142
+ if (fs56.existsSync(contextFilePath)) {
97775
98143
  try {
97776
- const existing = fs55.readFileSync(contextFilePath, "utf8");
98144
+ const existing = fs56.readFileSync(contextFilePath, "utf8");
97777
98145
  if (existing && existing.trim().length > 0) {
97778
98146
  return {
97779
98147
  type: "message",
@@ -97785,7 +98153,7 @@ var initCommand = {
97785
98153
  }
97786
98154
  }
97787
98155
  try {
97788
- fs55.writeFileSync(contextFilePath, "", "utf8");
98156
+ fs56.writeFileSync(contextFilePath, "", "utf8");
97789
98157
  context.ui.addItem(
97790
98158
  {
97791
98159
  type: "info",
@@ -98264,7 +98632,7 @@ var mcpCommand = {
98264
98632
  init_dist2();
98265
98633
  import path66 from "node:path";
98266
98634
  import os22 from "os";
98267
- import fs56 from "fs/promises";
98635
+ import fs57 from "fs/promises";
98268
98636
  var memoryCommand = {
98269
98637
  name: "memory",
98270
98638
  description: "Commands for interacting with memory.",
@@ -98298,7 +98666,7 @@ ${memoryContent}
98298
98666
  action: async (context) => {
98299
98667
  try {
98300
98668
  const projectMemoryPath = path66.join(process.cwd(), "LINK.md");
98301
- const memoryContent = await fs56.readFile(
98669
+ const memoryContent = await fs57.readFile(
98302
98670
  projectMemoryPath,
98303
98671
  "utf-8"
98304
98672
  );
@@ -98336,7 +98704,7 @@ ${memoryContent}
98336
98704
  FSS_LINK_DIR,
98337
98705
  "LINK.md"
98338
98706
  );
98339
- const globalMemoryContent = await fs56.readFile(
98707
+ const globalMemoryContent = await fs57.readFile(
98340
98708
  globalMemoryPath,
98341
98709
  "utf-8"
98342
98710
  );
@@ -98575,7 +98943,7 @@ var quitCommand = {
98575
98943
  };
98576
98944
 
98577
98945
  // packages/cli/src/ui/commands/restoreCommand.ts
98578
- import * as fs57 from "fs/promises";
98946
+ import * as fs58 from "fs/promises";
98579
98947
  import path67 from "path";
98580
98948
  async function restoreAction(context, args) {
98581
98949
  const { services, ui } = context;
@@ -98590,8 +98958,8 @@ async function restoreAction(context, args) {
98590
98958
  };
98591
98959
  }
98592
98960
  try {
98593
- await fs57.mkdir(checkpointDir, { recursive: true });
98594
- const files = await fs57.readdir(checkpointDir);
98961
+ await fs58.mkdir(checkpointDir, { recursive: true });
98962
+ const files = await fs58.readdir(checkpointDir);
98595
98963
  const jsonFiles = files.filter((file) => file.endsWith(".json"));
98596
98964
  if (!args) {
98597
98965
  if (jsonFiles.length === 0) {
@@ -98627,7 +98995,7 @@ ${fileList}`
98627
98995
  };
98628
98996
  }
98629
98997
  const filePath = path67.join(checkpointDir, selectedFile);
98630
- const data = await fs57.readFile(filePath, "utf-8");
98998
+ const data = await fs58.readFile(filePath, "utf-8");
98631
98999
  const toolCallData = JSON.parse(data);
98632
99000
  if (toolCallData.history) {
98633
99001
  if (!loadHistory) {
@@ -98673,7 +99041,7 @@ async function completion(context, _partialArg) {
98673
99041
  return [];
98674
99042
  }
98675
99043
  try {
98676
- const files = await fs57.readdir(checkpointDir);
99044
+ const files = await fs58.readdir(checkpointDir);
98677
99045
  return files.filter((file) => file.endsWith(".json")).map((file) => file.replace(".json", ""));
98678
99046
  } catch (_err) {
98679
99047
  return [];
@@ -98839,7 +99207,7 @@ var vimCommand = {
98839
99207
 
98840
99208
  // packages/cli/src/ui/commands/setupGithubCommand.ts
98841
99209
  import path68 from "node:path";
98842
- import * as fs58 from "node:fs";
99210
+ import * as fs59 from "node:fs";
98843
99211
  import { Writable } from "node:stream";
98844
99212
  import { ProxyAgent as ProxyAgent4 } from "undici";
98845
99213
 
@@ -98940,20 +99308,20 @@ async function updateGitignore(gitRepoRoot) {
98940
99308
  let existingContent = "";
98941
99309
  let fileExists = true;
98942
99310
  try {
98943
- existingContent = await fs58.promises.readFile(gitignorePath, "utf8");
99311
+ existingContent = await fs59.promises.readFile(gitignorePath, "utf8");
98944
99312
  } catch (_error) {
98945
99313
  fileExists = false;
98946
99314
  }
98947
99315
  if (!fileExists) {
98948
99316
  const contentToWrite = gitignoreEntries.join("\n") + "\n";
98949
- await fs58.promises.writeFile(gitignorePath, contentToWrite);
99317
+ await fs59.promises.writeFile(gitignorePath, contentToWrite);
98950
99318
  } else {
98951
99319
  const missingEntries = gitignoreEntries.filter(
98952
99320
  (entry) => !existingContent.split(/\r?\n/).some((line) => line.split("#")[0].trim() === entry)
98953
99321
  );
98954
99322
  if (missingEntries.length > 0) {
98955
99323
  const contentToAdd = "\n" + missingEntries.join("\n") + "\n";
98956
- await fs58.promises.appendFile(gitignorePath, contentToAdd);
99324
+ await fs59.promises.appendFile(gitignorePath, contentToAdd);
98957
99325
  }
98958
99326
  }
98959
99327
  } catch (error) {
@@ -98985,7 +99353,7 @@ var setupGithubCommand = {
98985
99353
  const readmeUrl = `https://github.com/google-github-actions/run-gemini-cli/blob/${releaseTag}/README.md#quick-start`;
98986
99354
  const githubWorkflowsDir = path68.join(gitRepoRoot, ".github", "workflows");
98987
99355
  try {
98988
- await fs58.promises.mkdir(githubWorkflowsDir, { recursive: true });
99356
+ await fs59.promises.mkdir(githubWorkflowsDir, { recursive: true });
98989
99357
  } catch (_error) {
98990
99358
  console.debug(
98991
99359
  `Failed to create ${githubWorkflowsDir} directory:`,
@@ -99023,7 +99391,7 @@ var setupGithubCommand = {
99023
99391
  githubWorkflowsDir,
99024
99392
  path68.basename(workflow)
99025
99393
  );
99026
- const fileStream = fs58.createWriteStream(destination, {
99394
+ const fileStream = fs59.createWriteStream(destination, {
99027
99395
  mode: 420,
99028
99396
  // -rw-r--r--, user(rw), group(r), other(r)
99029
99397
  flags: "w",
@@ -99057,7 +99425,7 @@ var setupGithubCommand = {
99057
99425
  };
99058
99426
 
99059
99427
  // packages/cli/src/ui/utils/terminalSetup.ts
99060
- import { promises as fs59 } from "fs";
99428
+ import { promises as fs60 } from "fs";
99061
99429
  import * as os23 from "os";
99062
99430
  import * as path69 from "path";
99063
99431
  import { exec as exec4 } from "child_process";
@@ -99071,10 +99439,10 @@ async function detectAndEnableKittyProtocol() {
99071
99439
  if (detectionComplete) {
99072
99440
  return protocolSupported;
99073
99441
  }
99074
- return new Promise((resolve20) => {
99442
+ return new Promise((resolve19) => {
99075
99443
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
99076
99444
  detectionComplete = true;
99077
- resolve20(false);
99445
+ resolve19(false);
99078
99446
  return;
99079
99447
  }
99080
99448
  const originalRawMode = process.stdin.isRaw;
@@ -99104,7 +99472,7 @@ async function detectAndEnableKittyProtocol() {
99104
99472
  process.on("SIGTERM", disableProtocol);
99105
99473
  }
99106
99474
  detectionComplete = true;
99107
- resolve20(protocolSupported);
99475
+ resolve19(protocolSupported);
99108
99476
  }
99109
99477
  }
99110
99478
  };
@@ -99118,7 +99486,7 @@ async function detectAndEnableKittyProtocol() {
99118
99486
  process.stdin.setRawMode(false);
99119
99487
  }
99120
99488
  detectionComplete = true;
99121
- resolve20(false);
99489
+ resolve19(false);
99122
99490
  }
99123
99491
  }, 50);
99124
99492
  });
@@ -99172,7 +99540,7 @@ async function backupFile(filePath) {
99172
99540
  try {
99173
99541
  const timestamp2 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
99174
99542
  const backupPath = `${filePath}.backup.${timestamp2}`;
99175
- await fs59.copyFile(filePath, backupPath);
99543
+ await fs60.copyFile(filePath, backupPath);
99176
99544
  } catch (error) {
99177
99545
  console.warn(`Failed to create backup of ${filePath}:`, error);
99178
99546
  }
@@ -99206,10 +99574,10 @@ async function configureVSCodeStyle(terminalName, appName) {
99206
99574
  }
99207
99575
  const keybindingsFile = path69.join(configDir, "keybindings.json");
99208
99576
  try {
99209
- await fs59.mkdir(configDir, { recursive: true });
99577
+ await fs60.mkdir(configDir, { recursive: true });
99210
99578
  let keybindings = [];
99211
99579
  try {
99212
- const content = await fs59.readFile(keybindingsFile, "utf8");
99580
+ const content = await fs60.readFile(keybindingsFile, "utf8");
99213
99581
  await backupFile(keybindingsFile);
99214
99582
  try {
99215
99583
  const cleanContent = stripJsonComments3(content);
@@ -99279,7 +99647,7 @@ Please check and modify manually if needed: ${keybindingsFile}`
99279
99647
  if (!hasOurShiftEnter || !hasOurCtrlEnter) {
99280
99648
  if (!hasOurShiftEnter) keybindings.unshift(shiftEnterBinding);
99281
99649
  if (!hasOurCtrlEnter) keybindings.unshift(ctrlEnterBinding);
99282
- await fs59.writeFile(keybindingsFile, JSON.stringify(keybindings, null, 4));
99650
+ await fs60.writeFile(keybindingsFile, JSON.stringify(keybindings, null, 4));
99283
99651
  return {
99284
99652
  success: true,
99285
99653
  message: `Added Shift+Enter and Ctrl+Enter keybindings to ${terminalName}.
@@ -99510,11 +99878,11 @@ function cleanTextForSpeech2(text) {
99510
99878
  async function executeSpeech(text, voice, progress) {
99511
99879
  try {
99512
99880
  progress?.setPhase("cleaning");
99513
- await new Promise((resolve20) => setTimeout(resolve20, 300));
99881
+ await new Promise((resolve19) => setTimeout(resolve19, 300));
99514
99882
  const cleanedText = cleanTextForSpeech2(text);
99515
99883
  progress?.setPhase("sending");
99516
- await new Promise((resolve20) => setTimeout(resolve20, 200));
99517
- const response = await fetch("http://192.168.1.5:11450/api/v1/synthesize", {
99884
+ await new Promise((resolve19) => setTimeout(resolve19, 200));
99885
+ const response = await fetch("http://tts.internal.bobai.com.au:11450/api/v1/synthesize", {
99518
99886
  method: "POST",
99519
99887
  headers: {
99520
99888
  "Content-Type": "application/json"
@@ -99533,10 +99901,10 @@ async function executeSpeech(text, voice, progress) {
99533
99901
  }
99534
99902
  progress?.setPhase("processing");
99535
99903
  await response.json();
99536
- await new Promise((resolve20) => setTimeout(resolve20, 400));
99904
+ await new Promise((resolve19) => setTimeout(resolve19, 400));
99537
99905
  progress?.setPhase("speaking");
99538
99906
  const estimatedDuration = Math.max(1e3, Math.min(text.length * 50, 5e3));
99539
- await new Promise((resolve20) => setTimeout(resolve20, estimatedDuration));
99907
+ await new Promise((resolve19) => setTimeout(resolve19, estimatedDuration));
99540
99908
  progress?.setPhase("completed");
99541
99909
  } catch (error) {
99542
99910
  progress?.setError(error instanceof Error ? error.message : "Unknown error");
@@ -99689,7 +100057,7 @@ var ttsCommand = {
99689
100057
  let serverAvailable = false;
99690
100058
  let serverInfo = "";
99691
100059
  try {
99692
- const response = await fetch("http://192.168.1.5:11450/health", {
100060
+ const response = await fetch("http://tts.internal.bobai.com.au:11450/health", {
99693
100061
  method: "GET"
99694
100062
  });
99695
100063
  serverAvailable = response.ok;
@@ -99725,7 +100093,7 @@ var ttsCommand = {
99725
100093
  `;
99726
100094
  status += `Server Status:
99727
100095
  `;
99728
- status += ` \u{1F310} Endpoint: http://192.168.1.5:11450
100096
+ status += ` \u{1F310} Endpoint: http://tts.internal.bobai.com.au:11450
99729
100097
  `;
99730
100098
  status += ` \u{1F4E1} Connection: ${serverAvailable ? "\u2705 Connected" : "\u274C Failed"}
99731
100099
  `;
@@ -99921,7 +100289,7 @@ var BuiltinCommandLoader = class {
99921
100289
  init_esm6();
99922
100290
  init_zod();
99923
100291
  init_dist2();
99924
- import { promises as fs60 } from "fs";
100292
+ import { promises as fs61 } from "fs";
99925
100293
  import path70 from "path";
99926
100294
  import toml from "@iarna/toml";
99927
100295
 
@@ -100192,7 +100560,7 @@ var FileCommandLoader = class {
100192
100560
  async parseAndAdaptFile(filePath, baseDir, extensionName) {
100193
100561
  let fileContent;
100194
100562
  try {
100195
- fileContent = await fs60.readFile(filePath, "utf-8");
100563
+ fileContent = await fs61.readFile(filePath, "utf-8");
100196
100564
  } catch (error) {
100197
100565
  console.error(
100198
100566
  `[FileCommandLoader] Failed to read file ${filePath}:`,
@@ -100792,12 +101160,12 @@ var useSlashCommandProcessor = (config, settings, addItem, clearItems, loadHisto
100792
101160
  content: result.content
100793
101161
  };
100794
101162
  case "confirm_shell_commands": {
100795
- const { outcome, approvedCommands } = await new Promise((resolve20) => {
101163
+ const { outcome, approvedCommands } = await new Promise((resolve19) => {
100796
101164
  setShellConfirmationRequest({
100797
101165
  commands: result.commandsToConfirm,
100798
101166
  onConfirm: (resolvedOutcome, resolvedApprovedCommands) => {
100799
101167
  setShellConfirmationRequest(null);
100800
- resolve20({
101168
+ resolve19({
100801
101169
  outcome: resolvedOutcome,
100802
101170
  approvedCommands: resolvedApprovedCommands
100803
101171
  });
@@ -100819,12 +101187,12 @@ var useSlashCommandProcessor = (config, settings, addItem, clearItems, loadHisto
100819
101187
  );
100820
101188
  }
100821
101189
  case "confirm_action": {
100822
- const { confirmed } = await new Promise((resolve20) => {
101190
+ const { confirmed } = await new Promise((resolve19) => {
100823
101191
  setConfirmationRequest({
100824
101192
  prompt: result.prompt,
100825
101193
  onConfirm: (resolvedConfirmed) => {
100826
101194
  setConfirmationRequest(null);
100827
- resolve20({ confirmed: resolvedConfirmed });
101195
+ resolve19({ confirmed: resolvedConfirmed });
100828
101196
  }
100829
101197
  });
100830
101198
  });
@@ -101493,7 +101861,7 @@ function useInputHistory({
101493
101861
  init_strip_ansi();
101494
101862
  import { stripVTControlCharacters } from "util";
101495
101863
  import { spawnSync } from "child_process";
101496
- import fs61 from "fs";
101864
+ import fs62 from "fs";
101497
101865
  import os24 from "os";
101498
101866
  import pathMod from "path";
101499
101867
  import { useState as useState21, useCallback as useCallback15, useEffect as useEffect20, useMemo as useMemo5, useReducer as useReducer2 } from "react";
@@ -103361,9 +103729,9 @@ function useTextBuffer({
103361
103729
  const openInExternalEditor = useCallback15(
103362
103730
  async (opts = {}) => {
103363
103731
  const editor = opts.editor ?? process.env["VISUAL"] ?? process.env["EDITOR"] ?? (process.platform === "win32" ? "notepad" : "vi");
103364
- const tmpDir = fs61.mkdtempSync(pathMod.join(os24.tmpdir(), "gemini-edit-"));
103732
+ const tmpDir = fs62.mkdtempSync(pathMod.join(os24.tmpdir(), "gemini-edit-"));
103365
103733
  const filePath = pathMod.join(tmpDir, "buffer.txt");
103366
- fs61.writeFileSync(filePath, text, "utf8");
103734
+ fs62.writeFileSync(filePath, text, "utf8");
103367
103735
  dispatch({ type: "create_undo_snapshot" });
103368
103736
  const wasRaw = stdin?.isRaw ?? false;
103369
103737
  try {
@@ -103374,7 +103742,7 @@ function useTextBuffer({
103374
103742
  if (error) throw error;
103375
103743
  if (typeof status === "number" && status !== 0)
103376
103744
  throw new Error(`External editor exited with status ${status}`);
103377
- let newText = fs61.readFileSync(filePath, "utf8");
103745
+ let newText = fs62.readFileSync(filePath, "utf8");
103378
103746
  newText = newText.replace(/\r\n?/g, "\n");
103379
103747
  dispatch({ type: "set_text", payload: newText, pushToUndo: false });
103380
103748
  } catch (err) {
@@ -103382,11 +103750,11 @@ function useTextBuffer({
103382
103750
  } finally {
103383
103751
  if (wasRaw) setRawMode?.(true);
103384
103752
  try {
103385
- fs61.unlinkSync(filePath);
103753
+ fs62.unlinkSync(filePath);
103386
103754
  } catch {
103387
103755
  }
103388
103756
  try {
103389
- fs61.rmdirSync(tmpDir);
103757
+ fs62.rmdirSync(tmpDir);
103390
103758
  } catch {
103391
103759
  }
103392
103760
  }
@@ -103525,7 +103893,7 @@ import chalk from "chalk";
103525
103893
  // packages/cli/src/ui/hooks/useShellHistory.ts
103526
103894
  init_dist2();
103527
103895
  import { useState as useState22, useEffect as useEffect21, useCallback as useCallback16 } from "react";
103528
- import * as fs62 from "fs/promises";
103896
+ import * as fs63 from "fs/promises";
103529
103897
  import * as path71 from "path";
103530
103898
  var HISTORY_FILE = "shell_history";
103531
103899
  var MAX_HISTORY_LENGTH2 = 100;
@@ -103535,7 +103903,7 @@ async function getHistoryFilePath(projectRoot) {
103535
103903
  }
103536
103904
  async function readHistoryFile(filePath) {
103537
103905
  try {
103538
- const text = await fs62.readFile(filePath, "utf-8");
103906
+ const text = await fs63.readFile(filePath, "utf-8");
103539
103907
  const result = [];
103540
103908
  let cur = "";
103541
103909
  for (const raw of text.split(/\r?\n/)) {
@@ -103559,8 +103927,8 @@ async function readHistoryFile(filePath) {
103559
103927
  }
103560
103928
  async function writeHistoryFile(filePath, history) {
103561
103929
  try {
103562
- await fs62.mkdir(path71.dirname(filePath), { recursive: true });
103563
- await fs62.writeFile(filePath, history.join("\n"));
103930
+ await fs63.mkdir(path71.dirname(filePath), { recursive: true });
103931
+ await fs63.writeFile(filePath, history.join("\n"));
103564
103932
  } catch (error) {
103565
103933
  console.error("Error writing shell history:", error);
103566
103934
  }
@@ -104389,7 +104757,7 @@ var keyMatchers = createKeyMatchers(defaultKeyBindings);
104389
104757
  // packages/cli/src/ui/utils/clipboardUtils.ts
104390
104758
  import { exec as exec5 } from "child_process";
104391
104759
  import { promisify as promisify5 } from "util";
104392
- import * as fs63 from "fs/promises";
104760
+ import * as fs64 from "fs/promises";
104393
104761
  import * as path72 from "path";
104394
104762
  var execAsync4 = promisify5(exec5);
104395
104763
  async function clipboardHasImage() {
@@ -104413,7 +104781,7 @@ async function saveClipboardImage(targetDir) {
104413
104781
  try {
104414
104782
  const baseDir = targetDir || process.cwd();
104415
104783
  const tempDir = path72.join(baseDir, ".gemini-clipboard");
104416
- await fs63.mkdir(tempDir, { recursive: true });
104784
+ await fs64.mkdir(tempDir, { recursive: true });
104417
104785
  const timestamp2 = (/* @__PURE__ */ new Date()).getTime();
104418
104786
  const formats = [
104419
104787
  { class: "PNGf", extension: "png" },
@@ -104443,7 +104811,7 @@ async function saveClipboardImage(targetDir) {
104443
104811
  const { stdout } = await execAsync4(`osascript -e '${script}'`);
104444
104812
  if (stdout.trim() === "success") {
104445
104813
  try {
104446
- const stats = await fs63.stat(tempFilePath);
104814
+ const stats = await fs64.stat(tempFilePath);
104447
104815
  if (stats.size > 0) {
104448
104816
  return tempFilePath;
104449
104817
  }
@@ -104451,7 +104819,7 @@ async function saveClipboardImage(targetDir) {
104451
104819
  }
104452
104820
  }
104453
104821
  try {
104454
- await fs63.unlink(tempFilePath);
104822
+ await fs64.unlink(tempFilePath);
104455
104823
  } catch {
104456
104824
  }
104457
104825
  }
@@ -104465,14 +104833,14 @@ async function cleanupOldClipboardImages(targetDir) {
104465
104833
  try {
104466
104834
  const baseDir = targetDir || process.cwd();
104467
104835
  const tempDir = path72.join(baseDir, ".gemini-clipboard");
104468
- const files = await fs63.readdir(tempDir);
104836
+ const files = await fs64.readdir(tempDir);
104469
104837
  const oneHourAgo = Date.now() - 60 * 60 * 1e3;
104470
104838
  for (const file of files) {
104471
104839
  if (file.startsWith("clipboard-") && (file.endsWith(".png") || file.endsWith(".jpg") || file.endsWith(".tiff") || file.endsWith(".gif"))) {
104472
104840
  const filePath = path72.join(tempDir, file);
104473
- const stats = await fs63.stat(filePath);
104841
+ const stats = await fs64.stat(filePath);
104474
104842
  if (stats.mtimeMs < oneHourAgo) {
104475
- await fs63.unlink(filePath);
104843
+ await fs64.unlink(filePath);
104476
104844
  }
104477
104845
  }
104478
104846
  }
@@ -122108,7 +122476,7 @@ function ProviderEndpointSelectionDialog({
122108
122476
  const modelManager = getModelManager();
122109
122477
  modelManager.switchToModel(selected.modelId).then(async (success) => {
122110
122478
  if (success) {
122111
- await new Promise((resolve20) => setTimeout(resolve20, 300));
122479
+ await new Promise((resolve19) => setTimeout(resolve19, 300));
122112
122480
  onCancel();
122113
122481
  } else {
122114
122482
  setError("Failed to switch model - model not found");
@@ -123315,7 +123683,7 @@ var ShellConfirmationDialog = ({ request: request2 }) => {
123315
123683
  };
123316
123684
 
123317
123685
  // packages/cli/src/config/config.ts
123318
- import * as fs65 from "fs";
123686
+ import * as fs68 from "fs";
123319
123687
  import * as path77 from "path";
123320
123688
  import { homedir as homedir18 } from "node:os";
123321
123689
  import yargs from "yargs/yargs";
@@ -123538,7 +123906,7 @@ init_dist2();
123538
123906
  import { Client as Client3 } from "@modelcontextprotocol/sdk/client/index.js";
123539
123907
 
123540
123908
  // packages/cli/src/config/extension.ts
123541
- import * as fs64 from "fs";
123909
+ import * as fs65 from "fs";
123542
123910
  import * as path75 from "path";
123543
123911
  import * as os25 from "os";
123544
123912
  var EXTENSIONS_DIRECTORY_NAME = path75.join(".fss-link", "extensions");
@@ -123559,11 +123927,11 @@ function loadExtensions(workspaceDir) {
123559
123927
  }
123560
123928
  function loadExtensionsFromDir(dir) {
123561
123929
  const extensionsDir = path75.join(dir, EXTENSIONS_DIRECTORY_NAME);
123562
- if (!fs64.existsSync(extensionsDir)) {
123930
+ if (!fs65.existsSync(extensionsDir)) {
123563
123931
  return [];
123564
123932
  }
123565
123933
  const extensions = [];
123566
- for (const subdir of fs64.readdirSync(extensionsDir)) {
123934
+ for (const subdir of fs65.readdirSync(extensionsDir)) {
123567
123935
  const extensionDir = path75.join(extensionsDir, subdir);
123568
123936
  const extension = loadExtension(extensionDir);
123569
123937
  if (extension != null) {
@@ -123573,19 +123941,19 @@ function loadExtensionsFromDir(dir) {
123573
123941
  return extensions;
123574
123942
  }
123575
123943
  function loadExtension(extensionDir) {
123576
- if (!fs64.statSync(extensionDir).isDirectory()) {
123944
+ if (!fs65.statSync(extensionDir).isDirectory()) {
123577
123945
  console.error(
123578
123946
  `Warning: unexpected file ${extensionDir} in extensions directory.`
123579
123947
  );
123580
123948
  return null;
123581
123949
  }
123582
123950
  let configFilePath = path75.join(extensionDir, EXTENSIONS_CONFIG_FILENAME);
123583
- if (!fs64.existsSync(configFilePath)) {
123951
+ if (!fs65.existsSync(configFilePath)) {
123584
123952
  const oldConfigFilePath = path75.join(
123585
123953
  extensionDir,
123586
123954
  EXTENSIONS_CONFIG_FILENAME_OLD
123587
123955
  );
123588
- if (!fs64.existsSync(oldConfigFilePath)) {
123956
+ if (!fs65.existsSync(oldConfigFilePath)) {
123589
123957
  console.error(
123590
123958
  `Warning: extension directory ${extensionDir} does not contain a config file ${configFilePath}.`
123591
123959
  );
@@ -123594,7 +123962,7 @@ function loadExtension(extensionDir) {
123594
123962
  configFilePath = oldConfigFilePath;
123595
123963
  }
123596
123964
  try {
123597
- const configContent = fs64.readFileSync(configFilePath, "utf-8");
123965
+ const configContent = fs65.readFileSync(configFilePath, "utf-8");
123598
123966
  const config = JSON.parse(configContent);
123599
123967
  if (!config.name || !config.version) {
123600
123968
  console.error(
@@ -123602,7 +123970,7 @@ function loadExtension(extensionDir) {
123602
123970
  );
123603
123971
  return null;
123604
123972
  }
123605
- const contextFiles = getContextFileNames(config).map((contextFileName) => path75.join(extensionDir, contextFileName)).filter((contextFilePath) => fs64.existsSync(contextFilePath));
123973
+ const contextFiles = getContextFileNames(config).map((contextFileName) => path75.join(extensionDir, contextFileName)).filter((contextFilePath) => fs65.existsSync(contextFilePath));
123606
123974
  return {
123607
123975
  path: extensionDir,
123608
123976
  config,
@@ -123770,6 +124138,171 @@ var mcpCommand2 = {
123770
124138
  }
123771
124139
  };
123772
124140
 
124141
+ // packages/cli/src/commands/db/lock-status.ts
124142
+ init_core_database();
124143
+ import * as fs66 from "fs";
124144
+ var lockStatusCommand = {
124145
+ command: "lock-status",
124146
+ describe: "Show database lock status and metrics",
124147
+ handler: async () => {
124148
+ try {
124149
+ const coreDb = getCoreDatabase();
124150
+ await coreDb.ensureInitialized();
124151
+ await coreDb.forceSave();
124152
+ const lockManager = coreDb.getLockManager();
124153
+ const lockPath = lockManager.getLockPath();
124154
+ console.log("\u{1F4CA} FSS Link Database Lock Status\n");
124155
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n");
124156
+ const isLocked = await lockManager.isLocked();
124157
+ if (isLocked) {
124158
+ console.log("\u{1F512} Status: LOCKED");
124159
+ console.log(` Another FSS Link instance is currently saving data.
124160
+ `);
124161
+ if (fs66.existsSync(lockPath)) {
124162
+ const stat7 = fs66.statSync(lockPath);
124163
+ const age = Date.now() - stat7.mtimeMs;
124164
+ const ageSeconds = Math.round(age / 1e3);
124165
+ console.log(` Lock file: ${lockPath}`);
124166
+ console.log(` Lock age: ${ageSeconds} seconds`);
124167
+ if (age > 1e4) {
124168
+ console.log(` \u26A0\uFE0F WARNING: Lock is stale (older than 10 seconds)`);
124169
+ console.log(` This may indicate a crashed process.`);
124170
+ console.log(` Use 'fss-link db:force-unlock' to remove it.
124171
+ `);
124172
+ } else {
124173
+ console.log();
124174
+ }
124175
+ }
124176
+ } else {
124177
+ console.log("\u2705 Status: UNLOCKED");
124178
+ console.log(` Database is available for writing.
124179
+ `);
124180
+ }
124181
+ const stats = await lockManager.getStatistics();
124182
+ if (stats.totalOperations > 0) {
124183
+ console.log("\u{1F4C8} Lock Statistics:\n");
124184
+ console.log(` Total operations: ${stats.totalOperations}`);
124185
+ console.log(` Total conflicts: ${stats.totalConflicts}`);
124186
+ console.log(` Total timeouts: ${stats.totalTimeouts}`);
124187
+ console.log(` Avg wait time: ${Math.round(stats.averageWaitTime)}ms`);
124188
+ console.log(` Avg hold time: ${Math.round(stats.averageHoldTime)}ms
124189
+ `);
124190
+ } else {
124191
+ console.log("\u{1F4C8} Lock Statistics:\n");
124192
+ console.log(` No lock operations recorded yet.
124193
+ `);
124194
+ }
124195
+ const recentMetrics = await lockManager.getMetrics(5);
124196
+ if (recentMetrics.length > 0) {
124197
+ console.log("\u{1F4CB} Recent Operations (last 5):\n");
124198
+ for (const metric of recentMetrics) {
124199
+ const date = new Date(metric.createdAt);
124200
+ const timeStr = date.toLocaleTimeString();
124201
+ const status = metric.timeoutOccurred ? "\u274C TIMEOUT" : metric.conflictDetected ? "\u26A0\uFE0F CONFLICT" : "\u2705 SUCCESS";
124202
+ console.log(` ${timeStr} - ${status}`);
124203
+ console.log(` Operation: ${metric.operation}`);
124204
+ console.log(` Wait: ${metric.waitTimeMs}ms, Hold: ${metric.holdTimeMs || "N/A"}ms`);
124205
+ if (metric.errorMessage) {
124206
+ console.log(` Error: ${metric.errorMessage}`);
124207
+ }
124208
+ console.log();
124209
+ }
124210
+ }
124211
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
124212
+ } catch (error) {
124213
+ console.error("Error getting lock status:", error);
124214
+ process.exit(1);
124215
+ }
124216
+ }
124217
+ };
124218
+
124219
+ // packages/cli/src/commands/db/force-unlock.ts
124220
+ init_core_database();
124221
+ import * as fs67 from "fs";
124222
+ import * as readline4 from "readline";
124223
+ async function confirm(question) {
124224
+ const rl = readline4.createInterface({
124225
+ input: process.stdin,
124226
+ output: process.stdout
124227
+ });
124228
+ return new Promise((resolve19) => {
124229
+ rl.question(question, (answer) => {
124230
+ rl.close();
124231
+ resolve19(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
124232
+ });
124233
+ });
124234
+ }
124235
+ var forceUnlockCommand = {
124236
+ command: "force-unlock",
124237
+ describe: "Force remove database lock file (use with caution)",
124238
+ builder: (yargs2) => yargs2.option("yes", {
124239
+ alias: "y",
124240
+ type: "boolean",
124241
+ description: "Skip confirmation prompt",
124242
+ default: false
124243
+ }),
124244
+ handler: async (argv) => {
124245
+ try {
124246
+ const coreDb = getCoreDatabase();
124247
+ await coreDb.ensureInitialized();
124248
+ await coreDb.forceSave();
124249
+ const lockManager = coreDb.getLockManager();
124250
+ const lockPath = lockManager.getLockPath();
124251
+ console.log("\u26A0\uFE0F Force Unlock Database\n");
124252
+ if (!fs67.existsSync(lockPath)) {
124253
+ console.log("\u2705 No lock file found - database is not locked.\n");
124254
+ return;
124255
+ }
124256
+ const stat7 = fs67.statSync(lockPath);
124257
+ const age = Date.now() - stat7.mtimeMs;
124258
+ const ageSeconds = Math.round(age / 1e3);
124259
+ console.log(`Lock file: ${lockPath}`);
124260
+ console.log(`Lock age: ${ageSeconds} seconds
124261
+ `);
124262
+ if (age < 1e4) {
124263
+ console.log("\u26A0\uFE0F WARNING: Lock is NOT stale (less than 10 seconds old)");
124264
+ console.log(" This lock may belong to an active FSS Link instance.\n");
124265
+ console.log(" Force removing it could cause database corruption if another");
124266
+ console.log(" instance is currently saving data.\n");
124267
+ } else {
124268
+ console.log("\u2139\uFE0F Lock appears to be stale (older than 10 seconds)");
124269
+ console.log(" This is likely from a crashed process.\n");
124270
+ }
124271
+ if (!argv.yes) {
124272
+ console.log("This will forcefully remove the lock file.");
124273
+ console.log("Only do this if you are certain no other FSS Link instance is running.\n");
124274
+ const confirmed = await confirm("Are you sure you want to continue? (y/N): ");
124275
+ if (!confirmed) {
124276
+ console.log("\n\u274C Cancelled - lock file not removed.\n");
124277
+ return;
124278
+ }
124279
+ }
124280
+ await lockManager.forceUnlock();
124281
+ if (fs67.existsSync(lockPath)) {
124282
+ console.log("\n\u26A0\uFE0F Lock file still exists after force unlock.");
124283
+ console.log(" It may have been recently updated by another instance.\n");
124284
+ console.log(` Lock age is now: ${Math.round((Date.now() - fs67.statSync(lockPath).mtimeMs) / 1e3)} seconds
124285
+ `);
124286
+ } else {
124287
+ console.log("\n\u2705 Lock file removed successfully.\n");
124288
+ console.log(" Database is now unlocked and ready for use.\n");
124289
+ }
124290
+ } catch (error) {
124291
+ console.error("Error forcing unlock:", error);
124292
+ process.exit(1);
124293
+ }
124294
+ }
124295
+ };
124296
+
124297
+ // packages/cli/src/commands/db.ts
124298
+ var dbCommand = {
124299
+ command: "db",
124300
+ describe: "Database management and diagnostics",
124301
+ builder: (yargs2) => yargs2.command(lockStatusCommand).command(forceUnlockCommand).demandCommand(1, "You need at least one command before continuing.").version(false),
124302
+ handler: () => {
124303
+ }
124304
+ };
124305
+
123773
124306
  // packages/cli/src/config/config.ts
123774
124307
  init_dist2();
123775
124308
 
@@ -124027,7 +124560,7 @@ async function parseArguments() {
124027
124560
  }
124028
124561
  return true;
124029
124562
  })
124030
- ).command(mcpCommand2).version(await getCliVersion()).alias("v", "version").help().alias("h", "help").strict().demandCommand(0, 0);
124563
+ ).command(mcpCommand2).command(dbCommand).version(await getCliVersion()).alias("v", "version").help().alias("h", "help").strict().demandCommand(0, 0);
124031
124564
  yargsInstance.wrap(yargsInstance.terminalWidth());
124032
124565
  const result = await yargsInstance.parse();
124033
124566
  if (result._.length > 0 && result._[0] === "mcp") {
@@ -124036,8 +124569,8 @@ async function parseArguments() {
124036
124569
  return result;
124037
124570
  }
124038
124571
  async function loadHierarchicalGeminiMemory(currentWorkingDirectory, includeDirectoriesToReadGemini = [], debugMode, fileService, settings, extensionContextFilePaths = [], memoryImportFormat = "tree", fileFilteringOptions) {
124039
- const realCwd = fs65.realpathSync(path77.resolve(currentWorkingDirectory));
124040
- const realHome = fs65.realpathSync(path77.resolve(homedir18()));
124572
+ const realCwd = fs68.realpathSync(path77.resolve(currentWorkingDirectory));
124573
+ const realHome = fs68.realpathSync(path77.resolve(homedir18()));
124041
124574
  const isHomeDirectory = realCwd === realHome;
124042
124575
  const effectiveCwd = isHomeDirectory ? "" : currentWorkingDirectory;
124043
124576
  if (debugMode) {
@@ -126576,7 +127109,7 @@ function IdeIntegrationNudge({
126576
127109
  // packages/cli/src/ui/hooks/useGitBranchName.ts
126577
127110
  import { useState as useState42, useEffect as useEffect38, useCallback as useCallback24 } from "react";
126578
127111
  import { exec as exec6 } from "node:child_process";
126579
- import fs66 from "node:fs";
127112
+ import fs69 from "node:fs";
126580
127113
  import fsPromises3 from "node:fs/promises";
126581
127114
  import path78 from "path";
126582
127115
  function useGitBranchName(cwd3) {
@@ -126616,8 +127149,8 @@ function useGitBranchName(cwd3) {
126616
127149
  let watcher;
126617
127150
  const setupWatcher = async () => {
126618
127151
  try {
126619
- await fsPromises3.access(gitLogsHeadPath, fs66.constants.F_OK);
126620
- watcher = fs66.watch(gitLogsHeadPath, (eventType) => {
127152
+ await fsPromises3.access(gitLogsHeadPath, fs69.constants.F_OK);
127153
+ watcher = fs69.watch(gitLogsHeadPath, (eventType) => {
126621
127154
  if (eventType === "change" || eventType === "rename") {
126622
127155
  fetchBranchName();
126623
127156
  }
@@ -127261,7 +127794,7 @@ function useKittyKeyboardProtocol() {
127261
127794
  }
127262
127795
 
127263
127796
  // packages/cli/src/ui/App.tsx
127264
- import * as fs68 from "fs";
127797
+ import * as fs71 from "fs";
127265
127798
 
127266
127799
  // packages/cli/src/ui/components/UpdateNotification.tsx
127267
127800
  import { Box as Box52, Text as Text57 } from "ink";
@@ -128347,7 +128880,7 @@ function SettingsDialog({
128347
128880
 
128348
128881
  // packages/cli/src/utils/installationInfo.ts
128349
128882
  init_dist2();
128350
- import * as fs67 from "fs";
128883
+ import * as fs70 from "fs";
128351
128884
  import * as path79 from "path";
128352
128885
  import * as childProcess from "child_process";
128353
128886
  function getInstallationInfo(projectRoot, isAutoUpdateDisabled) {
@@ -128356,7 +128889,7 @@ function getInstallationInfo(projectRoot, isAutoUpdateDisabled) {
128356
128889
  return { packageManager: "unknown" /* UNKNOWN */, isGlobal: false };
128357
128890
  }
128358
128891
  try {
128359
- const realPath = fs67.realpathSync(cliPath).replace(/\\/g, "/");
128892
+ const realPath = fs70.realpathSync(cliPath).replace(/\\/g, "/");
128360
128893
  const normalizedProjectRoot = projectRoot?.replace(/\\/g, "/");
128361
128894
  const isGit = isGitRepository(process.cwd());
128362
128895
  if (isGit && normalizedProjectRoot && realPath.startsWith(normalizedProjectRoot) && !realPath.includes("/node_modules/")) {
@@ -128367,8 +128900,8 @@ function getInstallationInfo(projectRoot, isAutoUpdateDisabled) {
128367
128900
  updateMessage: 'Running from a local git clone. Please update with "git pull".'
128368
128901
  };
128369
128902
  }
128370
- if (realPath.includes("/node_modules/") && fs67.existsSync(cliPath) && fs67.lstatSync(cliPath).isSymbolicLink()) {
128371
- const symlinkTarget = fs67.readlinkSync(cliPath);
128903
+ if (realPath.includes("/node_modules/") && fs70.existsSync(cliPath) && fs70.lstatSync(cliPath).isSymbolicLink()) {
128904
+ const symlinkTarget = fs70.readlinkSync(cliPath);
128372
128905
  const absoluteTarget = path79.isAbsolute(symlinkTarget) ? symlinkTarget : path79.resolve(path79.dirname(cliPath), symlinkTarget);
128373
128906
  if (isGitRepository(absoluteTarget)) {
128374
128907
  return {
@@ -128441,11 +128974,11 @@ function getInstallationInfo(projectRoot, isAutoUpdateDisabled) {
128441
128974
  }
128442
128975
  if (normalizedProjectRoot && realPath.startsWith(`${normalizedProjectRoot}/node_modules`)) {
128443
128976
  let pm2 = "npm" /* NPM */;
128444
- if (fs67.existsSync(path79.join(projectRoot, "yarn.lock"))) {
128977
+ if (fs70.existsSync(path79.join(projectRoot, "yarn.lock"))) {
128445
128978
  pm2 = "yarn" /* YARN */;
128446
- } else if (fs67.existsSync(path79.join(projectRoot, "pnpm-lock.yaml"))) {
128979
+ } else if (fs70.existsSync(path79.join(projectRoot, "pnpm-lock.yaml"))) {
128447
128980
  pm2 = "pnpm" /* PNPM */;
128448
- } else if (fs67.existsSync(path79.join(projectRoot, "bun.lockb"))) {
128981
+ } else if (fs70.existsSync(path79.join(projectRoot, "bun.lockb"))) {
128449
128982
  pm2 = "bun" /* BUN */;
128450
128983
  }
128451
128984
  return {
@@ -128476,13 +129009,13 @@ import { spawn as spawn5 } from "child_process";
128476
129009
  var spawnWrapper = spawn5;
128477
129010
 
128478
129011
  // packages/cli/src/utils/handleAutoUpdate.ts
128479
- import { existsSync as existsSync20 } from "fs";
129012
+ import { existsSync as existsSync23 } from "fs";
128480
129013
  import os28 from "os";
128481
129014
  import path80 from "path";
128482
129015
  function hasSudoAskpass() {
128483
129016
  const homeDir2 = os28.homedir();
128484
129017
  const sudoGuiPath = path80.join(homeDir2, ".local", "bin", "sudo-gui");
128485
- return existsSync20(sudoGuiPath);
129018
+ return existsSync23(sudoGuiPath);
128486
129019
  }
128487
129020
  function shouldAttemptAutoUpdate(installationInfo, isGlobal) {
128488
129021
  if (!isGlobal) {
@@ -128931,7 +129464,7 @@ var App = ({ config, settings, startupWarnings = [], version }) => {
128931
129464
  const suggestionsWidth = Math.max(20, Math.floor(terminalWidth * 0.8));
128932
129465
  const isValidPath = useCallback29((filePath) => {
128933
129466
  try {
128934
- return fs68.existsSync(filePath) && fs68.statSync(filePath).isFile();
129467
+ return fs71.existsSync(filePath) && fs71.statSync(filePath).isFile();
128935
129468
  } catch (_e) {
128936
129469
  return false;
128937
129470
  }
@@ -129629,7 +130162,7 @@ ${queuedText}` : queuedText;
129629
130162
  // packages/cli/src/utils/readStdin.ts
129630
130163
  async function readStdin() {
129631
130164
  const MAX_STDIN_SIZE = 8 * 1024 * 1024;
129632
- return new Promise((resolve20, reject) => {
130165
+ return new Promise((resolve19, reject) => {
129633
130166
  let data = "";
129634
130167
  let totalSize = 0;
129635
130168
  process.stdin.setEncoding("utf8");
@@ -129651,7 +130184,7 @@ async function readStdin() {
129651
130184
  };
129652
130185
  const onEnd = () => {
129653
130186
  cleanup();
129654
- resolve20(data);
130187
+ resolve19(data);
129655
130188
  };
129656
130189
  const onError = (err) => {
129657
130190
  cleanup();
@@ -129681,7 +130214,7 @@ init_settings();
129681
130214
  import { exec as exec7, execSync as execSync7, spawn as spawn6 } from "node:child_process";
129682
130215
  import os29 from "node:os";
129683
130216
  import path81 from "node:path";
129684
- import fs69 from "node:fs";
130217
+ import fs72 from "node:fs";
129685
130218
  import { readFile as readFile12 } from "node:fs/promises";
129686
130219
  import { promisify as promisify6 } from "util";
129687
130220
  var execAsync5 = promisify6(exec7);
@@ -129776,7 +130309,7 @@ function entrypoint(workdir) {
129776
130309
  SETTINGS_DIRECTORY_NAME,
129777
130310
  "sandbox.bashrc"
129778
130311
  );
129779
- if (fs69.existsSync(projectSandboxBashrc)) {
130312
+ if (fs72.existsSync(projectSandboxBashrc)) {
129780
130313
  shellCmds.push(`source ${getContainerPath(projectSandboxBashrc)};`);
129781
130314
  }
129782
130315
  ports().forEach(
@@ -129809,7 +130342,7 @@ async function start_sandbox(config, nodeArgs = [], cliConfig) {
129809
130342
  `sandbox-macos-${profile}.sb`
129810
130343
  );
129811
130344
  }
129812
- if (!fs69.existsSync(profileFile)) {
130345
+ if (!fs72.existsSync(profileFile)) {
129813
130346
  console.error(
129814
130347
  `ERROR: missing macos seatbelt profile file '${profileFile}'`
129815
130348
  );
@@ -129822,22 +130355,22 @@ async function start_sandbox(config, nodeArgs = [], cliConfig) {
129822
130355
  ].join(" ");
129823
130356
  const args2 = [
129824
130357
  "-D",
129825
- `TARGET_DIR=${fs69.realpathSync(process.cwd())}`,
130358
+ `TARGET_DIR=${fs72.realpathSync(process.cwd())}`,
129826
130359
  "-D",
129827
- `TMP_DIR=${fs69.realpathSync(os29.tmpdir())}`,
130360
+ `TMP_DIR=${fs72.realpathSync(os29.tmpdir())}`,
129828
130361
  "-D",
129829
- `HOME_DIR=${fs69.realpathSync(os29.homedir())}`,
130362
+ `HOME_DIR=${fs72.realpathSync(os29.homedir())}`,
129830
130363
  "-D",
129831
- `CACHE_DIR=${fs69.realpathSync(execSync7(`getconf DARWIN_USER_CACHE_DIR`).toString().trim())}`
130364
+ `CACHE_DIR=${fs72.realpathSync(execSync7(`getconf DARWIN_USER_CACHE_DIR`).toString().trim())}`
129832
130365
  ];
129833
130366
  const MAX_INCLUDE_DIRS = 5;
129834
- const targetDir = fs69.realpathSync(cliConfig?.getTargetDir() || "");
130367
+ const targetDir = fs72.realpathSync(cliConfig?.getTargetDir() || "");
129835
130368
  const includedDirs = [];
129836
130369
  if (cliConfig) {
129837
130370
  const workspaceContext = cliConfig.getWorkspaceContext();
129838
130371
  const directories = workspaceContext.getDirectories();
129839
130372
  for (const dir of directories) {
129840
- const realDir = fs69.realpathSync(dir);
130373
+ const realDir = fs72.realpathSync(dir);
129841
130374
  if (realDir !== targetDir) {
129842
130375
  includedDirs.push(realDir);
129843
130376
  }
@@ -129910,16 +130443,16 @@ async function start_sandbox(config, nodeArgs = [], cliConfig) {
129910
130443
  sandboxProcess2 = spawn6(config.command, args2, {
129911
130444
  stdio: "inherit"
129912
130445
  });
129913
- await new Promise((resolve20) => sandboxProcess2?.on("close", resolve20));
130446
+ await new Promise((resolve19) => sandboxProcess2?.on("close", resolve19));
129914
130447
  return;
129915
130448
  }
129916
130449
  console.error(`hopping into sandbox (command: ${config.command}) ...`);
129917
- const gcPath = fs69.realpathSync(process.argv[1]);
130450
+ const gcPath = fs72.realpathSync(process.argv[1]);
129918
130451
  const projectSandboxDockerfile = path81.join(
129919
130452
  SETTINGS_DIRECTORY_NAME,
129920
130453
  "sandbox.Dockerfile"
129921
130454
  );
129922
- const isCustomProjectSandbox = fs69.existsSync(projectSandboxDockerfile);
130455
+ const isCustomProjectSandbox = fs72.existsSync(projectSandboxDockerfile);
129923
130456
  const image2 = config.image;
129924
130457
  const workdir = path81.resolve(process.cwd());
129925
130458
  const containerWorkdir = getContainerPath(workdir);
@@ -129976,8 +130509,8 @@ async function start_sandbox(config, nodeArgs = [], cliConfig) {
129976
130509
  const userSettingsDirInSandbox = getContainerPath(
129977
130510
  `/home/node/${SETTINGS_DIRECTORY_NAME}`
129978
130511
  );
129979
- if (!fs69.existsSync(userSettingsDirOnHost)) {
129980
- fs69.mkdirSync(userSettingsDirOnHost);
130512
+ if (!fs72.existsSync(userSettingsDirOnHost)) {
130513
+ fs72.mkdirSync(userSettingsDirOnHost);
129981
130514
  }
129982
130515
  args.push(
129983
130516
  "--volume",
@@ -129991,7 +130524,7 @@ async function start_sandbox(config, nodeArgs = [], cliConfig) {
129991
130524
  }
129992
130525
  args.push("--volume", `${os29.tmpdir()}:${getContainerPath(os29.tmpdir())}`);
129993
130526
  const gcloudConfigDir = path81.join(os29.homedir(), ".config", "gcloud");
129994
- if (fs69.existsSync(gcloudConfigDir)) {
130527
+ if (fs72.existsSync(gcloudConfigDir)) {
129995
130528
  args.push(
129996
130529
  "--volume",
129997
130530
  `${gcloudConfigDir}:${getContainerPath(gcloudConfigDir)}:ro`
@@ -129999,7 +130532,7 @@ async function start_sandbox(config, nodeArgs = [], cliConfig) {
129999
130532
  }
130000
130533
  if (process.env["GOOGLE_APPLICATION_CREDENTIALS"]) {
130001
130534
  const adcFile = process.env["GOOGLE_APPLICATION_CREDENTIALS"];
130002
- if (fs69.existsSync(adcFile)) {
130535
+ if (fs72.existsSync(adcFile)) {
130003
130536
  args.push("--volume", `${adcFile}:${getContainerPath(adcFile)}:ro`);
130004
130537
  args.push(
130005
130538
  "--env",
@@ -130020,7 +130553,7 @@ async function start_sandbox(config, nodeArgs = [], cliConfig) {
130020
130553
  );
130021
130554
  process.exit(1);
130022
130555
  }
130023
- if (!fs69.existsSync(from)) {
130556
+ if (!fs72.existsSync(from)) {
130024
130557
  console.error(
130025
130558
  `ERROR: missing mount path '${from}' listed in SANDBOX_MOUNTS`
130026
130559
  );
@@ -130126,8 +130659,8 @@ async function start_sandbox(config, nodeArgs = [], cliConfig) {
130126
130659
  SETTINGS_DIRECTORY_NAME,
130127
130660
  "sandbox.venv"
130128
130661
  );
130129
- if (!fs69.existsSync(sandboxVenvPath)) {
130130
- fs69.mkdirSync(sandboxVenvPath, { recursive: true });
130662
+ if (!fs72.existsSync(sandboxVenvPath)) {
130663
+ fs72.mkdirSync(sandboxVenvPath, { recursive: true });
130131
130664
  }
130132
130665
  args.push(
130133
130666
  "--volume",
@@ -130164,7 +130697,7 @@ async function start_sandbox(config, nodeArgs = [], cliConfig) {
130164
130697
  args.push("--env", `SANDBOX=${containerName}`);
130165
130698
  if (config.command === "podman") {
130166
130699
  const emptyAuthFilePath = path81.join(os29.tmpdir(), "empty_auth.json");
130167
- fs69.writeFileSync(emptyAuthFilePath, "{}", "utf-8");
130700
+ fs72.writeFileSync(emptyAuthFilePath, "{}", "utf-8");
130168
130701
  args.push("--authfile", emptyAuthFilePath);
130169
130702
  }
130170
130703
  let userFlag = "";
@@ -130235,14 +130768,14 @@ async function start_sandbox(config, nodeArgs = [], cliConfig) {
130235
130768
  sandboxProcess.on("error", (err) => {
130236
130769
  console.error("Sandbox process error:", err);
130237
130770
  });
130238
- await new Promise((resolve20) => {
130771
+ await new Promise((resolve19) => {
130239
130772
  sandboxProcess?.on("close", (code, signal) => {
130240
130773
  if (code !== 0) {
130241
130774
  console.log(
130242
130775
  `Sandbox process exited with code: ${code}, signal: ${signal}`
130243
130776
  );
130244
130777
  }
130245
- resolve20();
130778
+ resolve19();
130246
130779
  });
130247
130780
  });
130248
130781
  } finally {
@@ -130250,7 +130783,7 @@ async function start_sandbox(config, nodeArgs = [], cliConfig) {
130250
130783
  }
130251
130784
  }
130252
130785
  async function imageExists(sandbox, image2) {
130253
- return new Promise((resolve20) => {
130786
+ return new Promise((resolve19) => {
130254
130787
  const args = ["images", "-q", image2];
130255
130788
  const checkProcess = spawn6(sandbox, args);
130256
130789
  let stdoutData = "";
@@ -130263,18 +130796,18 @@ async function imageExists(sandbox, image2) {
130263
130796
  console.warn(
130264
130797
  `Failed to start '${sandbox}' command for image check: ${err.message}`
130265
130798
  );
130266
- resolve20(false);
130799
+ resolve19(false);
130267
130800
  });
130268
130801
  checkProcess.on("close", (code) => {
130269
130802
  if (code !== 0) {
130270
130803
  }
130271
- resolve20(stdoutData.trim() !== "");
130804
+ resolve19(stdoutData.trim() !== "");
130272
130805
  });
130273
130806
  });
130274
130807
  }
130275
130808
  async function pullImage(sandbox, image2) {
130276
130809
  console.info(`Attempting to pull image ${image2} using ${sandbox}...`);
130277
- return new Promise((resolve20) => {
130810
+ return new Promise((resolve19) => {
130278
130811
  const args = ["pull", image2];
130279
130812
  const pullProcess = spawn6(sandbox, args, { stdio: "pipe" });
130280
130813
  let stderrData = "";
@@ -130290,13 +130823,13 @@ async function pullImage(sandbox, image2) {
130290
130823
  `Failed to start '${sandbox} pull ${image2}' command: ${err.message}`
130291
130824
  );
130292
130825
  cleanup();
130293
- resolve20(false);
130826
+ resolve19(false);
130294
130827
  };
130295
130828
  const onClose = (code) => {
130296
130829
  if (code === 0) {
130297
130830
  console.info(`Successfully pulled image ${image2}.`);
130298
130831
  cleanup();
130299
- resolve20(true);
130832
+ resolve19(true);
130300
130833
  } else {
130301
130834
  console.warn(
130302
130835
  `Failed to pull image ${image2}. '${sandbox} pull ${image2}' exited with code ${code}.`
@@ -130304,7 +130837,7 @@ async function pullImage(sandbox, image2) {
130304
130837
  if (stderrData.trim()) {
130305
130838
  }
130306
130839
  cleanup();
130307
- resolve20(false);
130840
+ resolve19(false);
130308
130841
  }
130309
130842
  };
130310
130843
  const cleanup = () => {
@@ -130362,17 +130895,17 @@ init_settings();
130362
130895
 
130363
130896
  // packages/cli/src/utils/startupWarnings.ts
130364
130897
  init_dist2();
130365
- import fs70 from "fs/promises";
130898
+ import fs73 from "fs/promises";
130366
130899
  import os30 from "os";
130367
130900
  import { join as pathJoin } from "node:path";
130368
130901
  var warningsFilePath = pathJoin(os30.tmpdir(), "fss-link-warnings.txt");
130369
130902
  async function getStartupWarnings() {
130370
130903
  try {
130371
- await fs70.access(warningsFilePath);
130372
- const warningsContent = await fs70.readFile(warningsFilePath, "utf-8");
130904
+ await fs73.access(warningsFilePath);
130905
+ const warningsContent = await fs73.readFile(warningsFilePath, "utf-8");
130373
130906
  const warnings = warningsContent.split("\n").filter((line) => line.trim() !== "");
130374
130907
  try {
130375
- await fs70.unlink(warningsFilePath);
130908
+ await fs73.unlink(warningsFilePath);
130376
130909
  } catch {
130377
130910
  warnings.push("Warning: Could not delete temporary warnings file.");
130378
130911
  }
@@ -130386,7 +130919,7 @@ async function getStartupWarnings() {
130386
130919
  }
130387
130920
 
130388
130921
  // packages/cli/src/utils/userStartupWarnings.ts
130389
- import fs71 from "fs/promises";
130922
+ import fs74 from "fs/promises";
130390
130923
  import * as os31 from "os";
130391
130924
  import path82 from "path";
130392
130925
  var homeDirectoryCheck = {
@@ -130394,8 +130927,8 @@ var homeDirectoryCheck = {
130394
130927
  check: async (workspaceRoot) => {
130395
130928
  try {
130396
130929
  const [workspaceRealPath, homeRealPath] = await Promise.all([
130397
- fs71.realpath(workspaceRoot),
130398
- fs71.realpath(os31.homedir())
130930
+ fs74.realpath(workspaceRoot),
130931
+ fs74.realpath(os31.homedir())
130399
130932
  ]);
130400
130933
  if (workspaceRealPath === homeRealPath) {
130401
130934
  return "You are running FSS Link in your home directory. It is recommended to run in a project-specific directory.";
@@ -130410,7 +130943,7 @@ var rootDirectoryCheck = {
130410
130943
  id: "root-directory",
130411
130944
  check: async (workspaceRoot) => {
130412
130945
  try {
130413
- const workspaceRealPath = await fs71.realpath(workspaceRoot);
130946
+ const workspaceRealPath = await fs74.realpath(workspaceRoot);
130414
130947
  const errorMessage = "Warning: You are running FSS Link in the root directory. Your entire folder structure will be used for context. It is strongly recommended to run in a project-specific directory.";
130415
130948
  if (path82.dirname(workspaceRealPath) === workspaceRealPath) {
130416
130949
  return errorMessage;
@@ -130694,7 +131227,7 @@ var AcpFileSystemService = class {
130694
131227
  // packages/cli/src/zed-integration/zedIntegration.ts
130695
131228
  init_zod();
130696
131229
  init_settings();
130697
- import * as fs72 from "fs/promises";
131230
+ import * as fs75 from "fs/promises";
130698
131231
  import { Readable, Writable as Writable2 } from "node:stream";
130699
131232
  import * as path83 from "path";
130700
131233
 
@@ -131161,8 +131694,8 @@ var Connection = class {
131161
131694
  }
131162
131695
  async sendRequest(method, params) {
131163
131696
  const id = this.#nextRequestId++;
131164
- const responsePromise = new Promise((resolve20, reject) => {
131165
- this.#pendingResponses.set(id, { resolve: resolve20, reject });
131697
+ const responsePromise = new Promise((resolve19, reject) => {
131698
+ this.#pendingResponses.set(id, { resolve: resolve19, reject });
131166
131699
  });
131167
131700
  await this.#sendMessage({ jsonrpc: "2.0", id, method, params });
131168
131701
  return responsePromise;
@@ -131646,7 +132179,7 @@ var Session = class {
131646
132179
  try {
131647
132180
  const absolutePath = path83.resolve(this.config.getTargetDir(), pathName);
131648
132181
  if (isWithinRoot(absolutePath, this.config.getTargetDir())) {
131649
- const stats = await fs72.stat(absolutePath);
132182
+ const stats = await fs75.stat(absolutePath);
131650
132183
  if (stats.isDirectory()) {
131651
132184
  currentPathSpec = pathName.endsWith("/") ? `${pathName}**` : `${pathName}/**`;
131652
132185
  this.debug(
@@ -132011,7 +132544,7 @@ async function relaunchWithAdditionalArgs(additionalArgs) {
132011
132544
  stdio: "inherit",
132012
132545
  env: newEnv
132013
132546
  });
132014
- await new Promise((resolve20) => child.on("close", resolve20));
132547
+ await new Promise((resolve19) => child.on("close", resolve19));
132015
132548
  process.exit(0);
132016
132549
  }
132017
132550
  function setupUnhandledRejectionHandler() {
@@ -132271,6 +132804,11 @@ main().catch((error) => {
132271
132804
  * Copyright 2025 FSS Coding
132272
132805
  * SPDX-License-Identifier: Apache-2.0
132273
132806
  */
132807
+ /**
132808
+ * @license
132809
+ * Copyright 2026 Google LLC
132810
+ * SPDX-License-Identifier: Apache-2.0
132811
+ */
132274
132812
  /**
132275
132813
  * @license
132276
132814
  * Copyright 2025 Google LLC