bitfab-cli 0.2.97 → 0.2.98
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +75 -15
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9834,7 +9834,7 @@ async function createStudioSession({ serviceUrl, apiKey, sessionId, initialPath
|
|
|
9834
9834
|
import net2 from "net";
|
|
9835
9835
|
|
|
9836
9836
|
// ../bitfab-plugin-lib/dist/daemon/ensure.js
|
|
9837
|
-
import { fork } from "child_process";
|
|
9837
|
+
import { execFileSync as execFileSync4, fork } from "child_process";
|
|
9838
9838
|
import crypto5 from "crypto";
|
|
9839
9839
|
import fs9 from "fs";
|
|
9840
9840
|
import net from "net";
|
|
@@ -9921,6 +9921,21 @@ async function waitForSocket(socketPath, timeoutMs) {
|
|
|
9921
9921
|
}
|
|
9922
9922
|
throw new Error(`daemon did not become ready within ${timeoutMs}ms`);
|
|
9923
9923
|
}
|
|
9924
|
+
async function waitForLockHolderDaemon(socketPath, timeoutMs, localBuild = localBuildFingerprint()) {
|
|
9925
|
+
const deadline = Date.now() + timeoutMs;
|
|
9926
|
+
while (Date.now() < deadline) {
|
|
9927
|
+
const ping = await pingSocket(socketPath);
|
|
9928
|
+
if (ping.alive && (localBuild === "unknown" || !ping.build || ping.build === localBuild)) {
|
|
9929
|
+
return;
|
|
9930
|
+
}
|
|
9931
|
+
await new Promise((r) => setTimeout(r, ENSURE_POLL_INTERVAL_MS));
|
|
9932
|
+
}
|
|
9933
|
+
const finalPing = await pingSocket(socketPath);
|
|
9934
|
+
if (finalPing.alive) {
|
|
9935
|
+
return;
|
|
9936
|
+
}
|
|
9937
|
+
throw new Error(`daemon did not become ready within ${timeoutMs}ms`);
|
|
9938
|
+
}
|
|
9924
9939
|
function localBuildFingerprint() {
|
|
9925
9940
|
try {
|
|
9926
9941
|
const thisDir = path8.dirname(fileURLToPath2(import.meta.url));
|
|
@@ -9931,17 +9946,63 @@ function localBuildFingerprint() {
|
|
|
9931
9946
|
return "unknown";
|
|
9932
9947
|
}
|
|
9933
9948
|
}
|
|
9934
|
-
|
|
9935
|
-
|
|
9936
|
-
|
|
9949
|
+
function findDaemonPids(socketPath) {
|
|
9950
|
+
let out;
|
|
9951
|
+
try {
|
|
9952
|
+
out = execFileSync4("ps", ["-axww", "-o", "pid=,command="], {
|
|
9953
|
+
encoding: "utf-8"
|
|
9954
|
+
});
|
|
9955
|
+
} catch {
|
|
9956
|
+
return [];
|
|
9957
|
+
}
|
|
9958
|
+
const pids = [];
|
|
9959
|
+
for (const line of out.split("\n")) {
|
|
9960
|
+
const match = line.trim().match(/^(\d+)\s+(.*)$/);
|
|
9961
|
+
if (!match) {
|
|
9962
|
+
continue;
|
|
9963
|
+
}
|
|
9964
|
+
const pid = Number.parseInt(match[1], 10);
|
|
9965
|
+
const command = match[2];
|
|
9966
|
+
if (pid === process.pid || Number.isNaN(pid)) {
|
|
9967
|
+
continue;
|
|
9968
|
+
}
|
|
9969
|
+
if (command.includes("daemon/main.js") && commandTargetsSocket(command, socketPath)) {
|
|
9970
|
+
pids.push(pid);
|
|
9971
|
+
}
|
|
9972
|
+
}
|
|
9973
|
+
return pids;
|
|
9974
|
+
}
|
|
9975
|
+
function commandTargetsSocket(command, socketPath) {
|
|
9976
|
+
let idx = command.indexOf(socketPath);
|
|
9977
|
+
while (idx !== -1) {
|
|
9978
|
+
const after = command[idx + socketPath.length];
|
|
9979
|
+
if (after === void 0 || after === " ") {
|
|
9980
|
+
return true;
|
|
9981
|
+
}
|
|
9982
|
+
idx = command.indexOf(socketPath, idx + 1);
|
|
9983
|
+
}
|
|
9984
|
+
return false;
|
|
9985
|
+
}
|
|
9986
|
+
async function reapAllDaemons(socketPath, pidPath) {
|
|
9987
|
+
const pids = new Set(findDaemonPids(socketPath));
|
|
9988
|
+
const pidfilePid = readPid(pidPath);
|
|
9989
|
+
if (pidfilePid !== null) {
|
|
9990
|
+
pids.add(pidfilePid);
|
|
9991
|
+
}
|
|
9992
|
+
for (const pid of pids) {
|
|
9937
9993
|
try {
|
|
9938
9994
|
process.kill(pid, "SIGTERM");
|
|
9939
9995
|
} catch {
|
|
9940
9996
|
}
|
|
9941
|
-
|
|
9942
|
-
|
|
9943
|
-
|
|
9997
|
+
}
|
|
9998
|
+
const deadline = Date.now() + 5e3;
|
|
9999
|
+
while (Date.now() < deadline) {
|
|
10000
|
+
if (![...pids].some(processIsAlive)) {
|
|
10001
|
+
break;
|
|
9944
10002
|
}
|
|
10003
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
10004
|
+
}
|
|
10005
|
+
for (const pid of pids) {
|
|
9945
10006
|
if (processIsAlive(pid)) {
|
|
9946
10007
|
try {
|
|
9947
10008
|
process.kill(pid, "SIGKILL");
|
|
@@ -10015,18 +10076,17 @@ async function ensureDaemon(socketPath = SOCKET_PATH, pidPath = PID_FILE_PATH) {
|
|
|
10015
10076
|
const localBuild = localBuildFingerprint();
|
|
10016
10077
|
if (ping.build && ping.build !== localBuild && localBuild !== "unknown") {
|
|
10017
10078
|
console.error(`[daemon] build mismatch (running: ${ping.build}, local: ${localBuild}), restarting`);
|
|
10018
|
-
await killDaemon(pidPath, socketPath);
|
|
10019
10079
|
} else {
|
|
10020
10080
|
return;
|
|
10021
10081
|
}
|
|
10022
10082
|
}
|
|
10023
10083
|
}
|
|
10024
10084
|
if (!acquireLock(socketPath)) {
|
|
10025
|
-
await
|
|
10085
|
+
await waitForLockHolderDaemon(socketPath, ENSURE_TIMEOUT_MS);
|
|
10026
10086
|
return;
|
|
10027
10087
|
}
|
|
10028
10088
|
try {
|
|
10029
|
-
|
|
10089
|
+
await reapAllDaemons(socketPath, pidPath);
|
|
10030
10090
|
spawnDaemon(socketPath, pidPath);
|
|
10031
10091
|
await waitForSocket(socketPath, ENSURE_TIMEOUT_MS);
|
|
10032
10092
|
} finally {
|
|
@@ -10453,13 +10513,13 @@ async function reportHandoff(apiKey, pluginVersion, platform2, body) {
|
|
|
10453
10513
|
import crypto7 from "crypto";
|
|
10454
10514
|
|
|
10455
10515
|
// ../bitfab-plugin-lib/dist/frontmostApp.js
|
|
10456
|
-
import { execFileSync as
|
|
10516
|
+
import { execFileSync as execFileSync5, spawn as spawn2 } from "child_process";
|
|
10457
10517
|
import os10 from "os";
|
|
10458
10518
|
function findAncestorApp() {
|
|
10459
10519
|
try {
|
|
10460
10520
|
let pid = process.ppid;
|
|
10461
10521
|
while (pid > 1) {
|
|
10462
|
-
const output =
|
|
10522
|
+
const output = execFileSync5("ps", ["-o", "ppid=,comm=", "-p", String(pid)], { stdio: "pipe", encoding: "utf-8" }).trim();
|
|
10463
10523
|
const match = output.match(/^\s*(\d+)\s+(.+)$/);
|
|
10464
10524
|
if (!match) {
|
|
10465
10525
|
break;
|
|
@@ -10518,19 +10578,19 @@ function getFrontmostApp() {
|
|
|
10518
10578
|
const platform2 = os10.platform();
|
|
10519
10579
|
try {
|
|
10520
10580
|
if (platform2 === "darwin") {
|
|
10521
|
-
return
|
|
10581
|
+
return execFileSync5("osascript", [
|
|
10522
10582
|
"-e",
|
|
10523
10583
|
'tell application "System Events" to get name of first process whose frontmost is true'
|
|
10524
10584
|
], { stdio: "pipe", encoding: "utf-8" }).trim();
|
|
10525
10585
|
}
|
|
10526
10586
|
if (platform2 === "linux") {
|
|
10527
|
-
return
|
|
10587
|
+
return execFileSync5("xdotool", ["getactivewindow"], {
|
|
10528
10588
|
stdio: "pipe",
|
|
10529
10589
|
encoding: "utf-8"
|
|
10530
10590
|
}).trim();
|
|
10531
10591
|
}
|
|
10532
10592
|
if (platform2 === "win32") {
|
|
10533
|
-
return
|
|
10593
|
+
return execFileSync5("powershell.exe", [
|
|
10534
10594
|
"-NoProfile",
|
|
10535
10595
|
"-Command",
|
|
10536
10596
|
`Add-Type -MemberDefinition '[DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow();' -Name WinFocus -Namespace Bitfab; [Bitfab.WinFocus]::GetForegroundWindow().ToInt64()`
|