bitfab-cli 0.2.31 → 0.2.32
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 +91 -99
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7347,49 +7347,35 @@ function isProcessAlive(pid) {
|
|
|
7347
7347
|
return err.code === "EPERM";
|
|
7348
7348
|
}
|
|
7349
7349
|
}
|
|
7350
|
-
function
|
|
7351
|
-
try {
|
|
7352
|
-
const current = readActiveStudioSessionRaw();
|
|
7353
|
-
if (!current || current.sessionId !== sessionId || current[field]) {
|
|
7354
|
-
return;
|
|
7355
|
-
}
|
|
7356
|
-
if (current.pid !== process.pid && isProcessAlive(current.pid)) {
|
|
7357
|
-
return;
|
|
7358
|
-
}
|
|
7359
|
-
writeRecord({ ...current, [field]: (/* @__PURE__ */ new Date()).toISOString() });
|
|
7360
|
-
} catch {
|
|
7361
|
-
}
|
|
7362
|
-
}
|
|
7363
|
-
function markActiveStudioSessionClosed(sessionId) {
|
|
7364
|
-
stampActiveStudioSession(sessionId, "closedAt");
|
|
7365
|
-
}
|
|
7366
|
-
function markActiveStudioSessionEnded(sessionId) {
|
|
7367
|
-
stampActiveStudioSession(sessionId, "endedAt");
|
|
7368
|
-
}
|
|
7369
|
-
function reactivateActiveStudioSession(sessionId) {
|
|
7350
|
+
function clearActiveStudioSession(sessionId, opts = {}) {
|
|
7370
7351
|
try {
|
|
7371
7352
|
const current = readActiveStudioSessionRaw();
|
|
7372
7353
|
if (!current || current.sessionId !== sessionId) {
|
|
7373
|
-
return;
|
|
7354
|
+
return false;
|
|
7374
7355
|
}
|
|
7375
|
-
if (!current.
|
|
7376
|
-
return;
|
|
7356
|
+
if (!opts.force && current.pid !== process.pid && isProcessAlive(current.pid)) {
|
|
7357
|
+
return false;
|
|
7377
7358
|
}
|
|
7378
|
-
|
|
7379
|
-
|
|
7380
|
-
serviceUrl: current.serviceUrl,
|
|
7381
|
-
pid: current.pid,
|
|
7382
|
-
startedAt: current.startedAt
|
|
7383
|
-
});
|
|
7359
|
+
fs6.unlinkSync(filePath());
|
|
7360
|
+
return true;
|
|
7384
7361
|
} catch {
|
|
7362
|
+
return false;
|
|
7385
7363
|
}
|
|
7386
7364
|
}
|
|
7387
7365
|
function readActiveStudioSessionRaw() {
|
|
7388
7366
|
try {
|
|
7389
7367
|
const raw = fs6.readFileSync(filePath(), "utf-8");
|
|
7390
7368
|
const parsed = JSON.parse(raw);
|
|
7391
|
-
if (
|
|
7392
|
-
return
|
|
7369
|
+
if (parsed.closedAt != null || parsed.endedAt != null) {
|
|
7370
|
+
return null;
|
|
7371
|
+
}
|
|
7372
|
+
if (typeof parsed.sessionId === "string" && typeof parsed.serviceUrl === "string" && typeof parsed.pid === "number" && typeof parsed.startedAt === "string") {
|
|
7373
|
+
return {
|
|
7374
|
+
sessionId: parsed.sessionId,
|
|
7375
|
+
serviceUrl: parsed.serviceUrl,
|
|
7376
|
+
pid: parsed.pid,
|
|
7377
|
+
startedAt: parsed.startedAt
|
|
7378
|
+
};
|
|
7393
7379
|
}
|
|
7394
7380
|
return null;
|
|
7395
7381
|
} catch {
|
|
@@ -7915,26 +7901,29 @@ var StudioNavigationError = class extends Error {
|
|
|
7915
7901
|
this.name = "StudioNavigationError";
|
|
7916
7902
|
}
|
|
7917
7903
|
};
|
|
7918
|
-
async function openStudioTo(path15, opts) {
|
|
7919
|
-
const
|
|
7904
|
+
async function openStudioTo(path15, opts = {}) {
|
|
7905
|
+
const config2 = getConfig();
|
|
7906
|
+
const serviceUrl = config2.serviceUrl;
|
|
7907
|
+
const apiKey = hasCredentials() ? config2.apiKey : null;
|
|
7920
7908
|
const noop = () => {
|
|
7921
7909
|
};
|
|
7922
7910
|
const restoreFocus = recordFocus();
|
|
7923
|
-
if (!
|
|
7911
|
+
if (!apiKey) {
|
|
7912
|
+
const sessionId2 = crypto4.randomUUID();
|
|
7924
7913
|
const separator = path15.includes("?") ? "&" : "?";
|
|
7925
|
-
const redirectPath = `${path15}${separator}session=${encodeURIComponent(
|
|
7914
|
+
const redirectPath = `${path15}${separator}session=${encodeURIComponent(sessionId2)}&pluginLogin=true`;
|
|
7926
7915
|
const signInPath = `/studio/sign-in?redirect_url=${encodeURIComponent(redirectPath)}`;
|
|
7927
|
-
const signInUrl = `${
|
|
7916
|
+
const signInUrl = `${serviceUrl}${signInPath}&session=${encodeURIComponent(sessionId2)}`;
|
|
7928
7917
|
openChromelessWindow(signInUrl);
|
|
7929
|
-
opts.onLoginRequired?.(
|
|
7918
|
+
opts.onLoginRequired?.(sessionId2, signInUrl);
|
|
7930
7919
|
const abortController = new AbortController();
|
|
7931
7920
|
const timer = setTimeout(() => abortController.abort(), LOGIN_TIMEOUT_MS);
|
|
7932
7921
|
const keepalive = setInterval(() => process.stderr.write(""), 3e4);
|
|
7933
|
-
let
|
|
7922
|
+
let loginApiKey;
|
|
7934
7923
|
try {
|
|
7935
|
-
|
|
7936
|
-
serviceUrl
|
|
7937
|
-
sessionId,
|
|
7924
|
+
loginApiKey = await pollLoginEvents({
|
|
7925
|
+
serviceUrl,
|
|
7926
|
+
sessionId: sessionId2,
|
|
7938
7927
|
abortSignal: abortController.signal
|
|
7939
7928
|
});
|
|
7940
7929
|
} catch (err) {
|
|
@@ -7944,82 +7933,90 @@ async function openStudioTo(path15, opts) {
|
|
|
7944
7933
|
}
|
|
7945
7934
|
clearTimeout(timer);
|
|
7946
7935
|
clearInterval(keepalive);
|
|
7947
|
-
saveCredentials(
|
|
7948
|
-
opts.onAuthenticated?.(
|
|
7936
|
+
saveCredentials(loginApiKey);
|
|
7937
|
+
opts.onAuthenticated?.(sessionId2);
|
|
7949
7938
|
if (opts.onEvent) {
|
|
7950
7939
|
await waitForSessionReady({
|
|
7951
|
-
serviceUrl
|
|
7952
|
-
apiKey,
|
|
7953
|
-
sessionId
|
|
7940
|
+
serviceUrl,
|
|
7941
|
+
apiKey: loginApiKey,
|
|
7942
|
+
sessionId: sessionId2
|
|
7954
7943
|
});
|
|
7955
|
-
writeActiveStudioSession({ sessionId, serviceUrl
|
|
7956
|
-
const poller2 = startEventPoller(
|
|
7944
|
+
writeActiveStudioSession({ sessionId: sessionId2, serviceUrl });
|
|
7945
|
+
const poller2 = startEventPoller(serviceUrl, loginApiKey, sessionId2, opts.onEvent, restoreFocus);
|
|
7957
7946
|
return {
|
|
7958
|
-
sessionId,
|
|
7959
|
-
serviceUrl
|
|
7960
|
-
apiKey,
|
|
7947
|
+
sessionId: sessionId2,
|
|
7948
|
+
serviceUrl,
|
|
7949
|
+
apiKey: loginApiKey,
|
|
7961
7950
|
opened: true,
|
|
7962
7951
|
...poller2
|
|
7963
7952
|
};
|
|
7964
7953
|
}
|
|
7965
7954
|
restoreFocus();
|
|
7966
7955
|
return {
|
|
7967
|
-
sessionId,
|
|
7968
|
-
serviceUrl
|
|
7969
|
-
apiKey,
|
|
7956
|
+
sessionId: sessionId2,
|
|
7957
|
+
serviceUrl,
|
|
7958
|
+
apiKey: loginApiKey,
|
|
7970
7959
|
opened: true,
|
|
7971
7960
|
abort: noop,
|
|
7972
7961
|
done: Promise.resolve()
|
|
7973
7962
|
};
|
|
7974
7963
|
}
|
|
7975
|
-
const
|
|
7976
|
-
const reachable = active && !active.closedAt ? active : null;
|
|
7977
|
-
const existing = opts.sessionId != null && (reachable?.sessionId !== opts.sessionId || reachable?.serviceUrl !== opts.serviceUrl) ? null : reachable;
|
|
7964
|
+
const existing = readActiveStudioSession();
|
|
7978
7965
|
if (existing) {
|
|
7979
7966
|
const client = {
|
|
7980
7967
|
serviceUrl: existing.serviceUrl,
|
|
7981
|
-
apiKey
|
|
7968
|
+
apiKey,
|
|
7982
7969
|
sessionId: existing.sessionId
|
|
7983
7970
|
};
|
|
7984
7971
|
const ack = await navigateStudioAndAwaitAck(client, path15);
|
|
7985
|
-
if (ack.acked) {
|
|
7986
|
-
if (existing.endedAt != null || existing.closedAt != null) {
|
|
7987
|
-
reactivateActiveStudioSession(existing.sessionId);
|
|
7988
|
-
}
|
|
7989
|
-
const poller2 = opts.onEvent ? startEventPoller(existing.serviceUrl, opts.apiKey, existing.sessionId, opts.onEvent, restoreFocus) : { abort: noop, done: Promise.resolve() };
|
|
7990
|
-
return {
|
|
7991
|
-
sessionId: existing.sessionId,
|
|
7992
|
-
serviceUrl: existing.serviceUrl,
|
|
7993
|
-
apiKey: opts.apiKey,
|
|
7994
|
-
opened: false,
|
|
7995
|
-
...poller2
|
|
7996
|
-
};
|
|
7997
|
-
}
|
|
7998
|
-
const tabGone = ack.reason === "session-ended" || ack.reason === "push-failed" || ack.reason === "timeout";
|
|
7999
|
-
const canReopenSilently = tabGone && (existing.endedAt != null || opts.sessionId != null);
|
|
8000
|
-
if (!canReopenSilently) {
|
|
7972
|
+
if (!ack.acked) {
|
|
8001
7973
|
throw new StudioNavigationError(ack.reason ?? "unknown", ack.blockedReason, existing.sessionId);
|
|
8002
7974
|
}
|
|
7975
|
+
const poller2 = opts.onEvent ? startEventPoller(existing.serviceUrl, apiKey, existing.sessionId, opts.onEvent, restoreFocus) : { abort: noop, done: Promise.resolve() };
|
|
7976
|
+
return {
|
|
7977
|
+
sessionId: existing.sessionId,
|
|
7978
|
+
serviceUrl: existing.serviceUrl,
|
|
7979
|
+
apiKey,
|
|
7980
|
+
opened: false,
|
|
7981
|
+
...poller2
|
|
7982
|
+
};
|
|
8003
7983
|
}
|
|
7984
|
+
const sessionId = crypto4.randomUUID();
|
|
8004
7985
|
const session = await createStudioSession({
|
|
8005
|
-
serviceUrl
|
|
8006
|
-
apiKey
|
|
7986
|
+
serviceUrl,
|
|
7987
|
+
apiKey,
|
|
8007
7988
|
sessionId,
|
|
8008
7989
|
initialPath: path15,
|
|
8009
7990
|
clientHeaders: opts.clientHeaders
|
|
8010
7991
|
});
|
|
8011
|
-
const poller = opts.onEvent ? startEventPoller(session.serviceUrl,
|
|
7992
|
+
const poller = opts.onEvent ? startEventPoller(session.serviceUrl, apiKey, session.sessionId, opts.onEvent, restoreFocus) : { abort: noop, done: Promise.resolve() };
|
|
8012
7993
|
return {
|
|
8013
7994
|
sessionId: session.sessionId,
|
|
8014
7995
|
serviceUrl: session.serviceUrl,
|
|
8015
|
-
apiKey
|
|
7996
|
+
apiKey,
|
|
8016
7997
|
opened: true,
|
|
8017
7998
|
...poller
|
|
8018
7999
|
};
|
|
8019
8000
|
}
|
|
8020
8001
|
function startEventPoller(serviceUrl, apiKey, sessionId, onEvent, restoreFocus) {
|
|
8021
8002
|
const abortController = new AbortController();
|
|
8022
|
-
let
|
|
8003
|
+
let graceTimer = null;
|
|
8004
|
+
let sawSessionEnded = false;
|
|
8005
|
+
const clearGraceTimer = () => {
|
|
8006
|
+
if (graceTimer) {
|
|
8007
|
+
clearTimeout(graceTimer);
|
|
8008
|
+
graceTimer = null;
|
|
8009
|
+
}
|
|
8010
|
+
};
|
|
8011
|
+
const terminate = (clear, baseEvent) => {
|
|
8012
|
+
graceTimer = null;
|
|
8013
|
+
if (clear) {
|
|
8014
|
+
clearActiveStudioSession(sessionId);
|
|
8015
|
+
}
|
|
8016
|
+
restoreFocus();
|
|
8017
|
+
onEvent({ ...baseEvent, type: "studio:session-ended" });
|
|
8018
|
+
abortController.abort();
|
|
8019
|
+
};
|
|
8023
8020
|
const done = pollAgentSessionEvents({
|
|
8024
8021
|
serviceUrl,
|
|
8025
8022
|
apiKey,
|
|
@@ -8027,35 +8024,31 @@ function startEventPoller(serviceUrl, apiKey, sessionId, onEvent, restoreFocus)
|
|
|
8027
8024
|
abortSignal: abortController.signal,
|
|
8028
8025
|
onEvent: (event) => {
|
|
8029
8026
|
if (event.type === "studio:session-closed") {
|
|
8030
|
-
|
|
8031
|
-
|
|
8027
|
+
clearGraceTimer();
|
|
8028
|
+
if (sawSessionEnded) {
|
|
8029
|
+
terminate(true, event);
|
|
8030
|
+
} else {
|
|
8031
|
+
graceTimer = setTimeout(() => {
|
|
8032
|
+
terminate(true, event);
|
|
8033
|
+
}, SESSION_CLOSE_GRACE_PERIOD_MS);
|
|
8032
8034
|
}
|
|
8033
|
-
sessionEndGraceTimer = setTimeout(() => {
|
|
8034
|
-
sessionEndGraceTimer = null;
|
|
8035
|
-
markActiveStudioSessionClosed(sessionId);
|
|
8036
|
-
restoreFocus();
|
|
8037
|
-
onEvent({ ...event, type: "studio:session-ended" });
|
|
8038
|
-
abortController.abort();
|
|
8039
|
-
}, SESSION_CLOSE_GRACE_PERIOD_MS);
|
|
8040
8035
|
return;
|
|
8041
8036
|
}
|
|
8042
8037
|
if (event.type === "studio:session-started") {
|
|
8043
|
-
if (
|
|
8044
|
-
|
|
8045
|
-
sessionEndGraceTimer = null;
|
|
8038
|
+
if (graceTimer) {
|
|
8039
|
+
clearGraceTimer();
|
|
8046
8040
|
console.error("Studio reconnected after page refresh");
|
|
8047
8041
|
}
|
|
8042
|
+
sawSessionEnded = false;
|
|
8048
8043
|
return;
|
|
8049
8044
|
}
|
|
8050
8045
|
if (event.type === "studio:session-ended") {
|
|
8051
|
-
|
|
8052
|
-
|
|
8053
|
-
|
|
8046
|
+
sawSessionEnded = true;
|
|
8047
|
+
if (!graceTimer) {
|
|
8048
|
+
graceTimer = setTimeout(() => {
|
|
8049
|
+
terminate(false, event);
|
|
8050
|
+
}, SESSION_CLOSE_GRACE_PERIOD_MS);
|
|
8054
8051
|
}
|
|
8055
|
-
markActiveStudioSessionEnded(sessionId);
|
|
8056
|
-
restoreFocus();
|
|
8057
|
-
onEvent(event);
|
|
8058
|
-
abortController.abort();
|
|
8059
8052
|
return;
|
|
8060
8053
|
}
|
|
8061
8054
|
if (event.type === "studio:not-member") {
|
|
@@ -8101,7 +8094,6 @@ async function runLogin(platform2, pluginVersion, options) {
|
|
|
8101
8094
|
const closePath = `/studio/close?autoClose=true&message=${encodeURIComponent("Login complete")}`;
|
|
8102
8095
|
try {
|
|
8103
8096
|
const result = await openStudioTo(closePath, {
|
|
8104
|
-
serviceUrl: config2.serviceUrl,
|
|
8105
8097
|
onLoginRequired: (_sessionId, signInUrl) => {
|
|
8106
8098
|
console.log(`
|
|
8107
8099
|
If the browser didn't open, visit this URL manually:
|