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.
- package/README.md +2 -2
- package/bundle/fss-link.js +968 -430
- package/package.json +1 -1
package/bundle/fss-link.js
CHANGED
|
@@ -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((
|
|
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
|
-
|
|
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((
|
|
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
|
-
|
|
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((
|
|
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
|
|
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", () =>
|
|
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 =
|
|
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
|
|
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
|
|
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:
|
|
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((
|
|
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((
|
|
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", () =>
|
|
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((
|
|
10895
|
-
this.writeStream.end(
|
|
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((
|
|
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((
|
|
13120
|
-
|
|
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((
|
|
13591
|
-
__classPrivateFieldSet(this, _EventStream_resolveConnectedPromise,
|
|
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((
|
|
13595
|
-
__classPrivateFieldSet(this, _EventStream_resolveEndPromise,
|
|
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((
|
|
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,
|
|
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((
|
|
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((
|
|
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((
|
|
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 (
|
|
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((
|
|
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((
|
|
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
|
-
|
|
21961
|
+
resolve19();
|
|
21939
21962
|
return;
|
|
21940
21963
|
}
|
|
21941
21964
|
if (elapsedTime >= pollInterval) {
|
|
21942
21965
|
clearInterval(intervalId);
|
|
21943
|
-
|
|
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((
|
|
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.
|
|
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((
|
|
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
|
-
|
|
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((
|
|
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
|
-
|
|
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((
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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((
|
|
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
|
-
|
|
25376
|
+
resolve19(void 0);
|
|
25364
25377
|
}
|
|
25365
25378
|
});
|
|
25366
25379
|
stream2.on("end", () => {
|
|
25367
25380
|
if (remainder)
|
|
25368
25381
|
lineCount++;
|
|
25369
|
-
|
|
25382
|
+
resolve19(lineCount);
|
|
25370
25383
|
});
|
|
25371
25384
|
stream2.on("error", () => {
|
|
25372
|
-
|
|
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((
|
|
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", () =>
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
30899
|
+
let resolve19 = () => {
|
|
30912
30900
|
};
|
|
30913
|
-
this.#asyncReaddirInFlight = new Promise((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
|
-
|
|
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:
|
|
31157
|
-
this.#fs = fsFromOption(
|
|
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(
|
|
31716
|
-
return new PathWin32(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs:
|
|
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(
|
|
31745
|
-
return new PathPosix(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs:
|
|
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((
|
|
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) =>
|
|
33413
|
-
child.on("error", () =>
|
|
33400
|
+
child.on("close", (code) => resolve19(code === 0));
|
|
33401
|
+
child.on("error", () => resolve19(false));
|
|
33414
33402
|
} catch {
|
|
33415
|
-
|
|
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((
|
|
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
|
-
|
|
33563
|
+
resolve19(stdoutData);
|
|
33576
33564
|
else if (code === 1)
|
|
33577
|
-
|
|
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((
|
|
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
|
-
|
|
33630
|
+
resolve19(stdoutData);
|
|
33643
33631
|
else if (code === 1)
|
|
33644
|
-
|
|
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
|
-
|
|
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((
|
|
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
|
-
|
|
33802
|
+
resolve19(stdoutData);
|
|
33815
33803
|
else if (code === 1)
|
|
33816
|
-
|
|
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((
|
|
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
|
-
|
|
33844
|
+
resolve19(stdoutData);
|
|
33857
33845
|
else if (code === 1)
|
|
33858
|
-
|
|
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((
|
|
39855
|
-
this.diffResponses.set(filePath,
|
|
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((
|
|
46214
|
+
var detectFile = (filepath, opts = {}) => new Promise((resolve19, reject) => {
|
|
46253
46215
|
let fd;
|
|
46254
|
-
const
|
|
46216
|
+
const fs76 = (0, node_1.default)();
|
|
46255
46217
|
const handler = (err, buffer) => {
|
|
46256
46218
|
if (fd) {
|
|
46257
|
-
|
|
46219
|
+
fs76.closeSync(fd);
|
|
46258
46220
|
}
|
|
46259
46221
|
if (err) {
|
|
46260
46222
|
reject(err);
|
|
46261
46223
|
} else {
|
|
46262
|
-
|
|
46224
|
+
resolve19((0, exports.detect)(buffer));
|
|
46263
46225
|
}
|
|
46264
46226
|
};
|
|
46265
46227
|
if (opts && opts.sampleSize) {
|
|
46266
|
-
fd =
|
|
46228
|
+
fd = fs76.openSync(filepath, "r");
|
|
46267
46229
|
const sample = Buffer.allocUnsafe(opts.sampleSize);
|
|
46268
|
-
|
|
46230
|
+
fs76.read(fd, sample, 0, opts.sampleSize, opts.offset, (err) => {
|
|
46269
46231
|
handler(err, sample);
|
|
46270
46232
|
});
|
|
46271
46233
|
return;
|
|
46272
46234
|
}
|
|
46273
|
-
|
|
46235
|
+
fs76.readFile(filepath, handler);
|
|
46274
46236
|
});
|
|
46275
46237
|
exports.detectFile = detectFile;
|
|
46276
46238
|
var detectFileSync = (filepath, opts = {}) => {
|
|
46277
|
-
const
|
|
46239
|
+
const fs76 = (0, node_1.default)();
|
|
46278
46240
|
if (opts && opts.sampleSize) {
|
|
46279
|
-
const fd =
|
|
46241
|
+
const fd = fs76.openSync(filepath, "r");
|
|
46280
46242
|
const sample = Buffer.allocUnsafe(opts.sampleSize);
|
|
46281
|
-
|
|
46282
|
-
|
|
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)(
|
|
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((
|
|
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
|
-
|
|
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((
|
|
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((
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
51153
|
-
|
|
51154
|
-
|
|
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
|
|
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_,
|
|
58010
|
+
const run = async (function_, resolve19, arguments_) => {
|
|
58068
58011
|
activeCount++;
|
|
58069
58012
|
const result = (async () => function_(...arguments_))();
|
|
58070
|
-
|
|
58013
|
+
resolve19(result);
|
|
58071
58014
|
try {
|
|
58072
58015
|
await result;
|
|
58073
58016
|
} catch {
|
|
58074
58017
|
}
|
|
58075
58018
|
next();
|
|
58076
58019
|
};
|
|
58077
|
-
const enqueue = (function_,
|
|
58020
|
+
const enqueue = (function_, resolve19, arguments_) => {
|
|
58078
58021
|
queue.enqueue(
|
|
58079
|
-
AsyncResource.bind(run.bind(void 0, function_,
|
|
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((
|
|
58089
|
-
enqueue(function_,
|
|
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((
|
|
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((
|
|
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://
|
|
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((
|
|
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((
|
|
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
|
-
|
|
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((
|
|
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
|
|
68882
|
-
await
|
|
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
|
|
68891
|
-
const stats = await
|
|
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((
|
|
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
|
-
|
|
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
|
|
69312
|
-
await
|
|
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((
|
|
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
|
|
69560
|
-
await
|
|
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
|
|
69569
|
-
const stats = await
|
|
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
|
|
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
|
|
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((
|
|
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
|
|
69782
|
-
await
|
|
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
|
|
69791
|
-
const stats = await
|
|
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((
|
|
71362
|
-
streamDoneResolver =
|
|
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((
|
|
73159
|
+
return new Promise((resolve19) => {
|
|
73217
73160
|
exec2("git --version", (error) => {
|
|
73218
73161
|
if (error) {
|
|
73219
|
-
|
|
73162
|
+
resolve19(false);
|
|
73220
73163
|
} else {
|
|
73221
|
-
|
|
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((
|
|
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
|
-
|
|
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((
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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:
|
|
80258
|
+
const { queue, fs: fs76, options: { suppressErrors } } = state;
|
|
80316
80259
|
queue.enqueue();
|
|
80317
|
-
|
|
80260
|
+
fs76.realpath(path84, (error, resolvedPath) => {
|
|
80318
80261
|
if (error) return queue.dequeue(suppressErrors ? null : error, state);
|
|
80319
|
-
|
|
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:
|
|
80271
|
+
const { queue, fs: fs76, options: { suppressErrors } } = state;
|
|
80329
80272
|
queue.enqueue();
|
|
80330
80273
|
try {
|
|
80331
|
-
const resolvedPath =
|
|
80332
|
-
const stat7 =
|
|
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:
|
|
80314
|
+
const { fs: fs76 } = state;
|
|
80372
80315
|
state.visited.push(crawlPath);
|
|
80373
80316
|
state.counts.directories++;
|
|
80374
|
-
|
|
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:
|
|
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 =
|
|
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((
|
|
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
|
-
|
|
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((
|
|
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((
|
|
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((
|
|
84113
|
-
this.pendingRequests.push(
|
|
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((
|
|
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
|
-
|
|
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
|
-
|
|
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((
|
|
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
|
|
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 (
|
|
85470
|
+
if (fs53.existsSync(this.dbPath)) {
|
|
85133
85471
|
try {
|
|
85134
|
-
const buffer =
|
|
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 (!
|
|
85179
|
-
|
|
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 (
|
|
85603
|
+
if (fs53.existsSync(this.dbPath)) {
|
|
85259
85604
|
const backupPath2 = `${this.dbPath}.backup`;
|
|
85260
85605
|
console.log("[DB-SAVE] Creating backup:", backupPath2);
|
|
85261
|
-
|
|
85606
|
+
fs53.copyFileSync(this.dbPath, backupPath2);
|
|
85262
85607
|
}
|
|
85263
85608
|
console.log("[DB-SAVE] Writing to:", this.dbPath);
|
|
85264
|
-
|
|
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 (
|
|
85616
|
+
if (fs53.existsSync(backupPath)) {
|
|
85268
85617
|
console.log("[DB-SAVE] Removing backup");
|
|
85269
|
-
|
|
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 (
|
|
85284
|
-
|
|
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 (
|
|
85648
|
+
if (fs53.existsSync(backupPath)) {
|
|
85288
85649
|
try {
|
|
85289
|
-
|
|
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
|
|
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((
|
|
87210
|
-
waitingQueue.push({ resolve:
|
|
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:
|
|
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 (
|
|
87251
|
-
this.encryptionKey =
|
|
87618
|
+
if (fs54.existsSync(keyPath)) {
|
|
87619
|
+
this.encryptionKey = fs54.readFileSync(keyPath);
|
|
87252
87620
|
} else {
|
|
87253
87621
|
this.encryptionKey = crypto13.randomBytes(32);
|
|
87254
|
-
if (!
|
|
87255
|
-
|
|
87622
|
+
if (!fs54.existsSync(USER_SETTINGS_DIR)) {
|
|
87623
|
+
fs54.mkdirSync(USER_SETTINGS_DIR, { recursive: true });
|
|
87256
87624
|
}
|
|
87257
|
-
|
|
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 (
|
|
87562
|
-
return
|
|
87929
|
+
if (fs54.existsSync(keyPath)) {
|
|
87930
|
+
return fs54.readFileSync(keyPath);
|
|
87563
87931
|
} else {
|
|
87564
87932
|
const key = crypto13.randomBytes(32);
|
|
87565
|
-
if (!
|
|
87566
|
-
|
|
87933
|
+
if (!fs54.existsSync(USER_SETTINGS_DIR)) {
|
|
87934
|
+
fs54.mkdirSync(USER_SETTINGS_DIR, { recursive: true });
|
|
87567
87935
|
}
|
|
87568
|
-
|
|
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((
|
|
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
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
92150
|
+
resolve19();
|
|
91783
92151
|
}
|
|
91784
92152
|
};
|
|
91785
|
-
const execPromise = new Promise((
|
|
91786
|
-
executeCommand(
|
|
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
|
|
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 (
|
|
96520
|
-
const content =
|
|
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 (!
|
|
96541
|
-
|
|
96908
|
+
if (!fs55.existsSync(dirPath)) {
|
|
96909
|
+
fs55.mkdirSync(dirPath, { recursive: true });
|
|
96542
96910
|
}
|
|
96543
|
-
|
|
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.
|
|
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 = "
|
|
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((
|
|
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
|
|
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 (
|
|
98142
|
+
if (fs56.existsSync(contextFilePath)) {
|
|
97775
98143
|
try {
|
|
97776
|
-
const existing =
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
98594
|
-
const files = await
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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((
|
|
99442
|
+
return new Promise((resolve19) => {
|
|
99075
99443
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
99076
99444
|
detectionComplete = true;
|
|
99077
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
99577
|
+
await fs60.mkdir(configDir, { recursive: true });
|
|
99210
99578
|
let keybindings = [];
|
|
99211
99579
|
try {
|
|
99212
|
-
const content = await
|
|
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
|
|
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((
|
|
99881
|
+
await new Promise((resolve19) => setTimeout(resolve19, 300));
|
|
99514
99882
|
const cleanedText = cleanTextForSpeech2(text);
|
|
99515
99883
|
progress?.setPhase("sending");
|
|
99516
|
-
await new Promise((
|
|
99517
|
-
const response = await fetch("http://
|
|
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((
|
|
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((
|
|
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://
|
|
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://
|
|
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
|
|
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
|
|
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((
|
|
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
|
-
|
|
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((
|
|
101190
|
+
const { confirmed } = await new Promise((resolve19) => {
|
|
100823
101191
|
setConfirmationRequest({
|
|
100824
101192
|
prompt: result.prompt,
|
|
100825
101193
|
onConfirm: (resolvedConfirmed) => {
|
|
100826
101194
|
setConfirmationRequest(null);
|
|
100827
|
-
|
|
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
|
|
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 =
|
|
103732
|
+
const tmpDir = fs62.mkdtempSync(pathMod.join(os24.tmpdir(), "gemini-edit-"));
|
|
103365
103733
|
const filePath = pathMod.join(tmpDir, "buffer.txt");
|
|
103366
|
-
|
|
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 =
|
|
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
|
-
|
|
103753
|
+
fs62.unlinkSync(filePath);
|
|
103386
103754
|
} catch {
|
|
103387
103755
|
}
|
|
103388
103756
|
try {
|
|
103389
|
-
|
|
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
|
|
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
|
|
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
|
|
103563
|
-
await
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
104841
|
+
const stats = await fs64.stat(filePath);
|
|
104474
104842
|
if (stats.mtimeMs < oneHourAgo) {
|
|
104475
|
-
await
|
|
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((
|
|
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
|
|
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
|
|
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 (!
|
|
123930
|
+
if (!fs65.existsSync(extensionsDir)) {
|
|
123563
123931
|
return [];
|
|
123564
123932
|
}
|
|
123565
123933
|
const extensions = [];
|
|
123566
|
-
for (const subdir of
|
|
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 (!
|
|
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 (!
|
|
123951
|
+
if (!fs65.existsSync(configFilePath)) {
|
|
123584
123952
|
const oldConfigFilePath = path75.join(
|
|
123585
123953
|
extensionDir,
|
|
123586
123954
|
EXTENSIONS_CONFIG_FILENAME_OLD
|
|
123587
123955
|
);
|
|
123588
|
-
if (!
|
|
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 =
|
|
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) =>
|
|
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 =
|
|
124040
|
-
const realHome =
|
|
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
|
|
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,
|
|
126620
|
-
watcher =
|
|
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
|
|
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
|
|
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 =
|
|
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/") &&
|
|
128371
|
-
const symlinkTarget =
|
|
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 (
|
|
128977
|
+
if (fs70.existsSync(path79.join(projectRoot, "yarn.lock"))) {
|
|
128445
128978
|
pm2 = "yarn" /* YARN */;
|
|
128446
|
-
} else if (
|
|
128979
|
+
} else if (fs70.existsSync(path79.join(projectRoot, "pnpm-lock.yaml"))) {
|
|
128447
128980
|
pm2 = "pnpm" /* PNPM */;
|
|
128448
|
-
} else if (
|
|
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
|
|
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
|
|
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
|
|
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((
|
|
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
|
-
|
|
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
|
|
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 (
|
|
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 (!
|
|
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=${
|
|
130358
|
+
`TARGET_DIR=${fs72.realpathSync(process.cwd())}`,
|
|
129826
130359
|
"-D",
|
|
129827
|
-
`TMP_DIR=${
|
|
130360
|
+
`TMP_DIR=${fs72.realpathSync(os29.tmpdir())}`,
|
|
129828
130361
|
"-D",
|
|
129829
|
-
`HOME_DIR=${
|
|
130362
|
+
`HOME_DIR=${fs72.realpathSync(os29.homedir())}`,
|
|
129830
130363
|
"-D",
|
|
129831
|
-
`CACHE_DIR=${
|
|
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 =
|
|
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 =
|
|
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((
|
|
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 =
|
|
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 =
|
|
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 (!
|
|
129980
|
-
|
|
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 (
|
|
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 (
|
|
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 (!
|
|
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 (!
|
|
130130
|
-
|
|
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
|
-
|
|
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((
|
|
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
|
-
|
|
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((
|
|
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
|
-
|
|
130799
|
+
resolve19(false);
|
|
130267
130800
|
});
|
|
130268
130801
|
checkProcess.on("close", (code) => {
|
|
130269
130802
|
if (code !== 0) {
|
|
130270
130803
|
}
|
|
130271
|
-
|
|
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((
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
130372
|
-
const warningsContent = await
|
|
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
|
|
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
|
|
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
|
-
|
|
130398
|
-
|
|
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
|
|
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
|
|
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((
|
|
131165
|
-
this.#pendingResponses.set(id, { resolve:
|
|
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
|
|
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((
|
|
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
|