@vibelet/cli 1.2.158 → 1.2.160
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.cjs +1 -1
- package/dist/runtime-version.cjs +1 -1
- package/dist/vibelet.mjs +765 -158
- package/package.json +1 -1
package/dist/vibelet.mjs
CHANGED
|
@@ -11252,12 +11252,12 @@ module.exports = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("zlib");
|
|
|
11252
11252
|
// EXPORTS
|
|
11253
11253
|
__nccwpck_require__.d(__webpack_exports__, {
|
|
11254
11254
|
vD: () => (/* reexport */ clearTunnelState),
|
|
11255
|
-
|
|
11255
|
+
M: () => (/* reexport */ getAliveManagedQuickTunnel),
|
|
11256
11256
|
DH: () => (/* reexport */ startTunnel),
|
|
11257
|
-
|
|
11257
|
+
HW: () => (/* reexport */ stopManagedQuickTunnel)
|
|
11258
11258
|
});
|
|
11259
11259
|
|
|
11260
|
-
// UNUSED EXPORTS: isProcessAlive, loadTunnelState, readCloudflaredLog, saveTunnelState
|
|
11260
|
+
// UNUSED EXPORTS: getAliveTunnel, isProcessAlive, isQuickTunnelProcessCommand, loadTunnelState, readCloudflaredLog, saveTunnelState, stopTunnel
|
|
11261
11261
|
|
|
11262
11262
|
// EXTERNAL MODULE: external "node:child_process"
|
|
11263
11263
|
var external_node_child_process_ = __nccwpck_require__(1421);
|
|
@@ -11479,6 +11479,139 @@ function extractQuickTunnelUrl(logContent) {
|
|
|
11479
11479
|
return match?.[0] ?? null;
|
|
11480
11480
|
}
|
|
11481
11481
|
|
|
11482
|
+
function isQuickTunnelUrl(url) {
|
|
11483
|
+
if (typeof url !== 'string' || !url.trim()) return false;
|
|
11484
|
+
try {
|
|
11485
|
+
return new URL(url).hostname.toLowerCase().endsWith('.trycloudflare.com');
|
|
11486
|
+
} catch {
|
|
11487
|
+
return false;
|
|
11488
|
+
}
|
|
11489
|
+
}
|
|
11490
|
+
|
|
11491
|
+
function normalizeOriginUrl(url) {
|
|
11492
|
+
if (typeof url !== 'string' || !url.trim()) return null;
|
|
11493
|
+
try {
|
|
11494
|
+
const parsed = new URL(url);
|
|
11495
|
+
const hostname = parsed.hostname.toLowerCase();
|
|
11496
|
+
if (
|
|
11497
|
+
parsed.protocol !== 'http:' ||
|
|
11498
|
+
!['localhost', '127.0.0.1', '[::1]'].includes(hostname) ||
|
|
11499
|
+
!parsed.port ||
|
|
11500
|
+
parsed.pathname !== '/' ||
|
|
11501
|
+
parsed.username ||
|
|
11502
|
+
parsed.password ||
|
|
11503
|
+
parsed.search ||
|
|
11504
|
+
parsed.hash
|
|
11505
|
+
) {
|
|
11506
|
+
return null;
|
|
11507
|
+
}
|
|
11508
|
+
return parsed.href;
|
|
11509
|
+
} catch {
|
|
11510
|
+
return null;
|
|
11511
|
+
}
|
|
11512
|
+
}
|
|
11513
|
+
|
|
11514
|
+
function extractUrlArgs(commandLine) {
|
|
11515
|
+
const matches = String(commandLine).matchAll(/(?:^|\s)--url(?:=|\s+)(?:"([^"]+)"|'([^']+)'|([^\s"']+))/giu);
|
|
11516
|
+
return [...matches].map((match) => match[1] || match[2] || match[3]).filter(Boolean);
|
|
11517
|
+
}
|
|
11518
|
+
|
|
11519
|
+
function isQuickTunnelProcessCommand(commandLine, { originUrl = '' } = {}) {
|
|
11520
|
+
if (typeof commandLine !== 'string' || !commandLine.trim()) return false;
|
|
11521
|
+
|
|
11522
|
+
const referencesCloudflared =
|
|
11523
|
+
/(?:^|[\\/\s"'=])cloudflared(?:\.exe)?(?=$|[\s"'])/iu.test(commandLine) ||
|
|
11524
|
+
/[\\/]cloudflared[\\/]lib[\\/]cloudflared\.js(?=$|[\s"'])/iu.test(commandLine) ||
|
|
11525
|
+
/(?:^|\s)--package(?:=|\s+)cloudflared(?=$|\s)/iu.test(commandLine);
|
|
11526
|
+
if (!referencesCloudflared) return false;
|
|
11527
|
+
if (!/(?:^|\s)tunnel(?=$|\s)/iu.test(commandLine)) return false;
|
|
11528
|
+
// Named Tunnels use `cloudflared tunnel ... run`; never treat one as a
|
|
11529
|
+
// Vibelet-managed Quick Tunnel even if an unrelated --url flag is present.
|
|
11530
|
+
if (/(?:^|\s)run(?=$|\s)/iu.test(commandLine)) return false;
|
|
11531
|
+
|
|
11532
|
+
const expectedOriginUrl = originUrl ? normalizeOriginUrl(originUrl) : null;
|
|
11533
|
+
if (originUrl && !expectedOriginUrl) return false;
|
|
11534
|
+
return extractUrlArgs(commandLine).some((candidate) => {
|
|
11535
|
+
const normalizedCandidate = normalizeOriginUrl(candidate);
|
|
11536
|
+
if (!normalizedCandidate) return false;
|
|
11537
|
+
return !expectedOriginUrl || normalizedCandidate === expectedOriginUrl;
|
|
11538
|
+
});
|
|
11539
|
+
}
|
|
11540
|
+
|
|
11541
|
+
function readProcessCommandLine(pid, { platform = process.platform, spawnSyncImpl = external_node_child_process_.spawnSync } = {}) {
|
|
11542
|
+
if (!Number.isInteger(pid) || pid <= 0) return '';
|
|
11543
|
+
|
|
11544
|
+
if (platform === 'win32') {
|
|
11545
|
+
const result = spawnSyncImpl(
|
|
11546
|
+
'powershell.exe',
|
|
11547
|
+
[
|
|
11548
|
+
'-NoProfile',
|
|
11549
|
+
'-NonInteractive',
|
|
11550
|
+
'-Command',
|
|
11551
|
+
`(Get-CimInstance Win32_Process -Filter "ProcessId = ${pid}").CommandLine`,
|
|
11552
|
+
],
|
|
11553
|
+
{ encoding: 'utf8', timeout: 1_500, windowsHide: true },
|
|
11554
|
+
);
|
|
11555
|
+
return result.status === 0 ? String(result.stdout || '').trim() : '';
|
|
11556
|
+
}
|
|
11557
|
+
|
|
11558
|
+
const result = spawnSyncImpl('ps', ['-ww', '-p', String(pid), '-o', 'command='], {
|
|
11559
|
+
encoding: 'utf8',
|
|
11560
|
+
timeout: 1_500,
|
|
11561
|
+
windowsHide: true,
|
|
11562
|
+
});
|
|
11563
|
+
return result.status === 0 ? String(result.stdout || '').trim() : '';
|
|
11564
|
+
}
|
|
11565
|
+
|
|
11566
|
+
function extractCloudflaredMetricsBaseUrl(logContent) {
|
|
11567
|
+
if (typeof logContent !== 'string' || logContent.length === 0) {
|
|
11568
|
+
return null;
|
|
11569
|
+
}
|
|
11570
|
+
const match = logContent.match(
|
|
11571
|
+
/Starting metrics server on (?:https?:\/\/)?(127\.0\.0\.1|localhost|\[::1\]):(\d+)\/metrics\b/iu,
|
|
11572
|
+
);
|
|
11573
|
+
if (!match) return null;
|
|
11574
|
+
return `http://${match[1]}:${match[2]}`;
|
|
11575
|
+
}
|
|
11576
|
+
|
|
11577
|
+
async function probeCloudflaredReadiness(logContent, { fetchFn = globalThis.fetch, timeoutMs = 1000 } = {}) {
|
|
11578
|
+
const metricsBaseUrl = extractCloudflaredMetricsBaseUrl(logContent);
|
|
11579
|
+
if (!metricsBaseUrl || typeof fetchFn !== 'function') return false;
|
|
11580
|
+
|
|
11581
|
+
const controller = new AbortController();
|
|
11582
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
11583
|
+
try {
|
|
11584
|
+
const response = await fetchFn(`${metricsBaseUrl}/ready`, { signal: controller.signal });
|
|
11585
|
+
return response.ok;
|
|
11586
|
+
} catch {
|
|
11587
|
+
return false;
|
|
11588
|
+
} finally {
|
|
11589
|
+
clearTimeout(timeout);
|
|
11590
|
+
}
|
|
11591
|
+
}
|
|
11592
|
+
|
|
11593
|
+
async function probeQuickTunnelPublicHealth(state, { fetchFn = globalThis.fetch, timeoutMs = 1_500 } = {}) {
|
|
11594
|
+
if (!isQuickTunnelUrl(state?.url) || typeof fetchFn !== 'function') return false;
|
|
11595
|
+
|
|
11596
|
+
const controller = new AbortController();
|
|
11597
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
11598
|
+
try {
|
|
11599
|
+
const healthUrl = new URL('/health', state.url);
|
|
11600
|
+
healthUrl.searchParams.set('_vibelet_reuse_probe', String(Date.now()));
|
|
11601
|
+
const response = await fetchFn(healthUrl, {
|
|
11602
|
+
headers: { 'cache-control': 'no-cache' },
|
|
11603
|
+
signal: controller.signal,
|
|
11604
|
+
});
|
|
11605
|
+
if (!response.ok) return false;
|
|
11606
|
+
const payload = await response.json().catch(() => null);
|
|
11607
|
+
return payload?.status === 'ok';
|
|
11608
|
+
} catch {
|
|
11609
|
+
return false;
|
|
11610
|
+
} finally {
|
|
11611
|
+
clearTimeout(timeout);
|
|
11612
|
+
}
|
|
11613
|
+
}
|
|
11614
|
+
|
|
11482
11615
|
function getNpmFallbackCommand(platform = process.platform) {
|
|
11483
11616
|
return platform === 'win32' ? 'npx.cmd' : 'npx';
|
|
11484
11617
|
}
|
|
@@ -11683,18 +11816,22 @@ function formatCloudflaredFailureMessage({ launchSpec, logContent = '', logPath,
|
|
|
11683
11816
|
|
|
11684
11817
|
if (phase === 'timeout') {
|
|
11685
11818
|
const summary = summarizeCloudflaredLog(logContent);
|
|
11819
|
+
const waitTarget = extractQuickTunnelUrl(logContent) ? 'tunnel readiness' : 'tunnel URL';
|
|
11686
11820
|
if (summary) {
|
|
11687
|
-
return `Timed out waiting for
|
|
11821
|
+
return `Timed out waiting for ${waitTarget} (${Math.round((launchSpec?.urlTimeoutMs ?? 30_000) / 1000)}s)${launchSuffix}.\nRecent stderr:\n${summary}`;
|
|
11688
11822
|
}
|
|
11689
|
-
return `Timed out waiting for
|
|
11823
|
+
return `Timed out waiting for ${waitTarget} (${Math.round((launchSpec?.urlTimeoutMs ?? 30_000) / 1000)}s)${launchSuffix}. Check network/proxy settings and ${logPath}.`;
|
|
11690
11824
|
}
|
|
11691
11825
|
|
|
11692
11826
|
const summary = summarizeCloudflaredLog(logContent);
|
|
11827
|
+
const exitTarget = extractQuickTunnelUrl(logContent)
|
|
11828
|
+
? 'before the tunnel became ready'
|
|
11829
|
+
: 'before producing a tunnel URL';
|
|
11693
11830
|
if (summary) {
|
|
11694
|
-
return `cloudflared exited
|
|
11831
|
+
return `cloudflared exited ${exitTarget}${launchSuffix}.\nRecent stderr:\n${summary}`;
|
|
11695
11832
|
}
|
|
11696
11833
|
|
|
11697
|
-
return `cloudflared exited
|
|
11834
|
+
return `cloudflared exited ${exitTarget}${launchSuffix}. Check ${logPath}.`;
|
|
11698
11835
|
}
|
|
11699
11836
|
|
|
11700
11837
|
function isProcessAlive(pid) {
|
|
@@ -11714,9 +11851,15 @@ function loadTunnelState({ tunnelStatePath }) {
|
|
|
11714
11851
|
}
|
|
11715
11852
|
}
|
|
11716
11853
|
|
|
11717
|
-
function saveTunnelState({ tunnelStatePath, pid, url }) {
|
|
11854
|
+
function saveTunnelState({ tunnelStatePath, pid, url, managerId, originUrl }) {
|
|
11718
11855
|
(0,external_node_fs_.mkdirSync)((0,external_node_path_.dirname)(tunnelStatePath), { recursive: true });
|
|
11719
|
-
|
|
11856
|
+
const state = {
|
|
11857
|
+
pid,
|
|
11858
|
+
url,
|
|
11859
|
+
...(managerId ? { managerId } : {}),
|
|
11860
|
+
...(originUrl ? { originUrl } : {}),
|
|
11861
|
+
};
|
|
11862
|
+
(0,external_node_fs_.writeFileSync)(tunnelStatePath, `${JSON.stringify(state, null, 2)}\n`, 'utf8');
|
|
11720
11863
|
}
|
|
11721
11864
|
|
|
11722
11865
|
function clearTunnelState({ tunnelStatePath }) {
|
|
@@ -11735,6 +11878,147 @@ function stopTunnel({ tunnelStatePath, isAlive = isProcessAlive, killProcess = p
|
|
|
11735
11878
|
clearTunnelState({ tunnelStatePath });
|
|
11736
11879
|
}
|
|
11737
11880
|
|
|
11881
|
+
function waitForProcessExit(pid, { isAlive = isProcessAlive, timeoutMs = 5_000, pollIntervalMs = 50 } = {}) {
|
|
11882
|
+
const deadline = Date.now() + timeoutMs;
|
|
11883
|
+
const waitBuffer = new Int32Array(new SharedArrayBuffer(4));
|
|
11884
|
+
while (Date.now() < deadline) {
|
|
11885
|
+
if (!isAlive(pid)) return true;
|
|
11886
|
+
Atomics.wait(waitBuffer, 0, 0, Math.min(pollIntervalMs, Math.max(1, deadline - Date.now())));
|
|
11887
|
+
}
|
|
11888
|
+
return !isAlive(pid);
|
|
11889
|
+
}
|
|
11890
|
+
|
|
11891
|
+
function tunnelStateIdentityMatches(left, right) {
|
|
11892
|
+
if (!left || !right) return false;
|
|
11893
|
+
return (
|
|
11894
|
+
left.pid === right.pid &&
|
|
11895
|
+
left.url === right.url &&
|
|
11896
|
+
left.managerId === right.managerId &&
|
|
11897
|
+
normalizeOriginUrl(left.originUrl) === normalizeOriginUrl(right.originUrl)
|
|
11898
|
+
);
|
|
11899
|
+
}
|
|
11900
|
+
|
|
11901
|
+
/**
|
|
11902
|
+
* Stop a tracked Quick Tunnel only after both its persisted state and live
|
|
11903
|
+
* command line identify it as the same Vibelet-managed process. An unverifiable
|
|
11904
|
+
* live PID is deliberately left untouched so a Named Tunnel (or a reused PID)
|
|
11905
|
+
* can never be terminated from stale tunnel state.
|
|
11906
|
+
*/
|
|
11907
|
+
function stopManagedQuickTunnel({
|
|
11908
|
+
tunnelStatePath,
|
|
11909
|
+
managerId,
|
|
11910
|
+
isAlive = isProcessAlive,
|
|
11911
|
+
getProcessCommandLine = readProcessCommandLine,
|
|
11912
|
+
killProcess = process.kill,
|
|
11913
|
+
waitForExit = waitForProcessExit,
|
|
11914
|
+
}) {
|
|
11915
|
+
const state = loadTunnelState({ tunnelStatePath });
|
|
11916
|
+
if (!state) return { status: 'absent', state: null };
|
|
11917
|
+
if (
|
|
11918
|
+
!Number.isInteger(state.pid) ||
|
|
11919
|
+
state.pid <= 0 ||
|
|
11920
|
+
!isQuickTunnelUrl(state.url) ||
|
|
11921
|
+
(state.managerId && state.managerId !== managerId)
|
|
11922
|
+
) {
|
|
11923
|
+
return { status: 'not-managed-quick', state };
|
|
11924
|
+
}
|
|
11925
|
+
|
|
11926
|
+
if (!isAlive(state.pid)) {
|
|
11927
|
+
clearTunnelState({ tunnelStatePath });
|
|
11928
|
+
return { status: 'stale-state-cleared', state };
|
|
11929
|
+
}
|
|
11930
|
+
|
|
11931
|
+
// Legacy state did not record an owner or the exact origin. Even when its
|
|
11932
|
+
// PID currently belongs to a Quick Tunnel, that is not enough to prove it
|
|
11933
|
+
// is the same process (the PID may have been reused). Leave live legacy
|
|
11934
|
+
// state untouched and require a newly written, fully identified state file
|
|
11935
|
+
// before allowing any signal.
|
|
11936
|
+
if (!state.managerId || !normalizeOriginUrl(state.originUrl)) {
|
|
11937
|
+
return { status: 'identity-unverified', state };
|
|
11938
|
+
}
|
|
11939
|
+
|
|
11940
|
+
let commandLine = '';
|
|
11941
|
+
try {
|
|
11942
|
+
commandLine = getProcessCommandLine(state.pid);
|
|
11943
|
+
} catch {
|
|
11944
|
+
// Process inspection is best-effort. Never kill when identity cannot be
|
|
11945
|
+
// proven.
|
|
11946
|
+
}
|
|
11947
|
+
if (!isQuickTunnelProcessCommand(commandLine, { originUrl: state.originUrl || '' })) {
|
|
11948
|
+
return { status: 'identity-unverified', state };
|
|
11949
|
+
}
|
|
11950
|
+
|
|
11951
|
+
try {
|
|
11952
|
+
killProcess(state.pid, 'SIGTERM');
|
|
11953
|
+
} catch {
|
|
11954
|
+
if (isAlive(state.pid)) {
|
|
11955
|
+
return { status: 'stop-failed', state };
|
|
11956
|
+
}
|
|
11957
|
+
}
|
|
11958
|
+
|
|
11959
|
+
let exited = false;
|
|
11960
|
+
try {
|
|
11961
|
+
exited = waitForExit(state.pid, { isAlive });
|
|
11962
|
+
} catch {
|
|
11963
|
+
// A failed exit check can never justify clearing process state.
|
|
11964
|
+
}
|
|
11965
|
+
if (!exited) {
|
|
11966
|
+
return { status: 'stop-failed', state };
|
|
11967
|
+
}
|
|
11968
|
+
|
|
11969
|
+
const latestState = loadTunnelState({ tunnelStatePath });
|
|
11970
|
+
if (latestState && !tunnelStateIdentityMatches(latestState, state)) {
|
|
11971
|
+
// Another manager invocation replaced the state while the old process was
|
|
11972
|
+
// draining. Never erase the new process identity.
|
|
11973
|
+
return { status: 'stop-failed', state };
|
|
11974
|
+
}
|
|
11975
|
+
clearTunnelState({ tunnelStatePath });
|
|
11976
|
+
return { status: 'stopped', state };
|
|
11977
|
+
}
|
|
11978
|
+
|
|
11979
|
+
/**
|
|
11980
|
+
* Return a reusable Quick Tunnel only when its persisted owner/origin, live
|
|
11981
|
+
* command line, and public health endpoint all identify the same working
|
|
11982
|
+
* process. PID liveness alone is never sufficient because PIDs can be reused
|
|
11983
|
+
* by a Named Tunnel or an unrelated process.
|
|
11984
|
+
*/
|
|
11985
|
+
async function getAliveManagedQuickTunnel({
|
|
11986
|
+
tunnelStatePath,
|
|
11987
|
+
managerId,
|
|
11988
|
+
isAlive = isProcessAlive,
|
|
11989
|
+
getProcessCommandLine = readProcessCommandLine,
|
|
11990
|
+
readinessProbe = probeQuickTunnelPublicHealth,
|
|
11991
|
+
}) {
|
|
11992
|
+
const state = loadTunnelState({ tunnelStatePath });
|
|
11993
|
+
if (
|
|
11994
|
+
!state ||
|
|
11995
|
+
!Number.isInteger(state.pid) ||
|
|
11996
|
+
state.pid <= 0 ||
|
|
11997
|
+
!isQuickTunnelUrl(state.url) ||
|
|
11998
|
+
state.managerId !== managerId ||
|
|
11999
|
+
!normalizeOriginUrl(state.originUrl) ||
|
|
12000
|
+
!isAlive(state.pid)
|
|
12001
|
+
) {
|
|
12002
|
+
return null;
|
|
12003
|
+
}
|
|
12004
|
+
|
|
12005
|
+
let commandLine = '';
|
|
12006
|
+
try {
|
|
12007
|
+
commandLine = getProcessCommandLine(state.pid);
|
|
12008
|
+
} catch {
|
|
12009
|
+
return null;
|
|
12010
|
+
}
|
|
12011
|
+
if (!isQuickTunnelProcessCommand(commandLine, { originUrl: state.originUrl })) {
|
|
12012
|
+
return null;
|
|
12013
|
+
}
|
|
12014
|
+
|
|
12015
|
+
try {
|
|
12016
|
+
return (await readinessProbe(state)) ? state : null;
|
|
12017
|
+
} catch {
|
|
12018
|
+
return null;
|
|
12019
|
+
}
|
|
12020
|
+
}
|
|
12021
|
+
|
|
11738
12022
|
function getAliveTunnel({ tunnelStatePath, isAlive = isProcessAlive }) {
|
|
11739
12023
|
const state = loadTunnelState({ tunnelStatePath });
|
|
11740
12024
|
if (state?.pid && state?.url && isAlive(state.pid)) {
|
|
@@ -11759,6 +12043,8 @@ async function startTunnel({
|
|
|
11759
12043
|
updateStatePath,
|
|
11760
12044
|
resolveLaunchSpec = resolvePreferredCloudflaredLaunchSpec,
|
|
11761
12045
|
resolveFallbackLaunchSpec = resolveCloudflaredLaunchSpec,
|
|
12046
|
+
readinessProbe = probeCloudflaredReadiness,
|
|
12047
|
+
managerId,
|
|
11762
12048
|
}) {
|
|
11763
12049
|
if (!['auto', 'quic', 'http2'].includes(protocol)) {
|
|
11764
12050
|
throw new Error(`Unsupported cloudflared protocol: ${protocol}`);
|
|
@@ -11800,10 +12086,11 @@ async function startTunnel({
|
|
|
11800
12086
|
const stdoutLogFd = (0,external_node_fs_.openSync)(logPath, 'a');
|
|
11801
12087
|
const stderrLogFd = (0,external_node_fs_.openSync)(logPath, 'a');
|
|
11802
12088
|
let child;
|
|
12089
|
+
const originUrl = `http://localhost:${port}`;
|
|
11803
12090
|
try {
|
|
11804
12091
|
child = (0,external_node_child_process_.spawn)(
|
|
11805
12092
|
launchSpec.command,
|
|
11806
|
-
[...launchSpec.args, 'tunnel', '--protocol', effectiveProtocol, '--url',
|
|
12093
|
+
[...launchSpec.args, 'tunnel', '--no-autoupdate', '--protocol', effectiveProtocol, '--url', originUrl],
|
|
11807
12094
|
{
|
|
11808
12095
|
detached: true,
|
|
11809
12096
|
stdio: ['ignore', stdoutLogFd, stderrLogFd],
|
|
@@ -11851,6 +12138,7 @@ async function startTunnel({
|
|
|
11851
12138
|
let url = null;
|
|
11852
12139
|
let settled = false;
|
|
11853
12140
|
let childExited = false;
|
|
12141
|
+
let readinessProbeInFlight = false;
|
|
11854
12142
|
let poll;
|
|
11855
12143
|
let timeout;
|
|
11856
12144
|
|
|
@@ -11865,35 +12153,43 @@ async function startTunnel({
|
|
|
11865
12153
|
}
|
|
11866
12154
|
|
|
11867
12155
|
timeout = setTimeout(() => {
|
|
11868
|
-
|
|
11869
|
-
|
|
11870
|
-
|
|
11871
|
-
|
|
11872
|
-
// ignore
|
|
11873
|
-
}
|
|
11874
|
-
settle(
|
|
11875
|
-
rejectStart,
|
|
11876
|
-
new Error(
|
|
11877
|
-
formatCloudflaredFailureMessage({
|
|
11878
|
-
launchSpec,
|
|
11879
|
-
logContent: readCloudflaredLog(logPath),
|
|
11880
|
-
logPath,
|
|
11881
|
-
phase: 'timeout',
|
|
11882
|
-
}),
|
|
11883
|
-
),
|
|
11884
|
-
);
|
|
12156
|
+
try {
|
|
12157
|
+
process.kill(pid, 'SIGTERM');
|
|
12158
|
+
} catch {
|
|
12159
|
+
// ignore
|
|
11885
12160
|
}
|
|
12161
|
+
settle(
|
|
12162
|
+
rejectStart,
|
|
12163
|
+
new Error(
|
|
12164
|
+
formatCloudflaredFailureMessage({
|
|
12165
|
+
launchSpec,
|
|
12166
|
+
logContent: readCloudflaredLog(logPath),
|
|
12167
|
+
logPath,
|
|
12168
|
+
phase: 'timeout',
|
|
12169
|
+
}),
|
|
12170
|
+
),
|
|
12171
|
+
);
|
|
11886
12172
|
}, launchSpec.urlTimeoutMs);
|
|
11887
12173
|
|
|
11888
|
-
poll = setInterval(() => {
|
|
12174
|
+
poll = setInterval(async () => {
|
|
12175
|
+
if (readinessProbeInFlight || settled) return;
|
|
11889
12176
|
try {
|
|
11890
12177
|
const content = (0,external_node_fs_.readFileSync)(logPath, 'utf8');
|
|
11891
12178
|
const tunnelUrl = extractQuickTunnelUrl(content);
|
|
11892
12179
|
if (tunnelUrl) {
|
|
11893
12180
|
url = tunnelUrl;
|
|
11894
|
-
|
|
11895
|
-
|
|
11896
|
-
|
|
12181
|
+
readinessProbeInFlight = true;
|
|
12182
|
+
let ready = false;
|
|
12183
|
+
try {
|
|
12184
|
+
ready = await readinessProbe(content);
|
|
12185
|
+
} finally {
|
|
12186
|
+
readinessProbeInFlight = false;
|
|
12187
|
+
}
|
|
12188
|
+
if (ready && !settled) {
|
|
12189
|
+
saveTunnelState({ tunnelStatePath, pid, url, managerId, originUrl: managerId ? originUrl : undefined });
|
|
12190
|
+
settle(resolveStart, { pid, url });
|
|
12191
|
+
return;
|
|
12192
|
+
}
|
|
11897
12193
|
}
|
|
11898
12194
|
if (childExited) {
|
|
11899
12195
|
settle(
|
|
@@ -11915,15 +12211,8 @@ async function startTunnel({
|
|
|
11915
12211
|
|
|
11916
12212
|
child.once('exit', () => {
|
|
11917
12213
|
childExited = true;
|
|
11918
|
-
if (!
|
|
12214
|
+
if (!settled) {
|
|
11919
12215
|
const content = readCloudflaredLog(logPath);
|
|
11920
|
-
const tunnelUrl = extractQuickTunnelUrl(content);
|
|
11921
|
-
if (tunnelUrl) {
|
|
11922
|
-
url = tunnelUrl;
|
|
11923
|
-
saveTunnelState({ tunnelStatePath, pid, url });
|
|
11924
|
-
settle(resolveStart, { pid, url });
|
|
11925
|
-
return;
|
|
11926
|
-
}
|
|
11927
12216
|
settle(
|
|
11928
12217
|
rejectStart,
|
|
11929
12218
|
new Error(
|
|
@@ -13535,6 +13824,174 @@ function parseAccessTargetArg(argv, fail, env = process.env) {
|
|
|
13535
13824
|
}
|
|
13536
13825
|
|
|
13537
13826
|
|
|
13827
|
+
/***/ }),
|
|
13828
|
+
|
|
13829
|
+
/***/ 3869:
|
|
13830
|
+
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nccwpck_require__) => {
|
|
13831
|
+
|
|
13832
|
+
/* harmony export */ __nccwpck_require__.d(__webpack_exports__, {
|
|
13833
|
+
/* harmony export */ BT: () => (/* binding */ tryUpdateRunningDaemonRelay),
|
|
13834
|
+
/* harmony export */ T7: () => (/* binding */ createRelayConfigStore),
|
|
13835
|
+
/* harmony export */ kS: () => (/* binding */ prepareManagedQuickTunnel),
|
|
13836
|
+
/* harmony export */ zj: () => (/* binding */ retireTrackedQuickTunnel)
|
|
13837
|
+
/* harmony export */ });
|
|
13838
|
+
/* harmony import */ var node_fs__WEBPACK_IMPORTED_MODULE_0__ = __nccwpck_require__(3024);
|
|
13839
|
+
/* harmony import */ var node_path__WEBPACK_IMPORTED_MODULE_1__ = __nccwpck_require__(6760);
|
|
13840
|
+
/* harmony import */ var _cloudflared_tunnel_manager_mjs__WEBPACK_IMPORTED_MODULE_2__ = __nccwpck_require__(2755);
|
|
13841
|
+
|
|
13842
|
+
|
|
13843
|
+
|
|
13844
|
+
|
|
13845
|
+
const TUNNEL_MANAGER_ID = 'vibelet-cli';
|
|
13846
|
+
|
|
13847
|
+
function createRelayConfigStore(relayConfigPath) {
|
|
13848
|
+
return {
|
|
13849
|
+
load() {
|
|
13850
|
+
try {
|
|
13851
|
+
const data = JSON.parse((0,node_fs__WEBPACK_IMPORTED_MODULE_0__.readFileSync)(relayConfigPath, 'utf8'));
|
|
13852
|
+
return data.relayUrl || '';
|
|
13853
|
+
} catch {
|
|
13854
|
+
return '';
|
|
13855
|
+
}
|
|
13856
|
+
},
|
|
13857
|
+
save(relayUrl) {
|
|
13858
|
+
(0,node_fs__WEBPACK_IMPORTED_MODULE_0__.mkdirSync)((0,node_path__WEBPACK_IMPORTED_MODULE_1__.dirname)(relayConfigPath), { recursive: true });
|
|
13859
|
+
(0,node_fs__WEBPACK_IMPORTED_MODULE_0__.writeFileSync)(relayConfigPath, `${JSON.stringify({ relayUrl }, null, 2)}\n`, 'utf8');
|
|
13860
|
+
},
|
|
13861
|
+
clear() {
|
|
13862
|
+
(0,node_fs__WEBPACK_IMPORTED_MODULE_0__.rmSync)(relayConfigPath, { force: true });
|
|
13863
|
+
},
|
|
13864
|
+
};
|
|
13865
|
+
}
|
|
13866
|
+
|
|
13867
|
+
function retireTrackedQuickTunnel({
|
|
13868
|
+
tunnelStatePath,
|
|
13869
|
+
isAlive,
|
|
13870
|
+
required = false,
|
|
13871
|
+
fail,
|
|
13872
|
+
writeStdout = (message) => process.stdout.write(message),
|
|
13873
|
+
writeStderr = (message) => process.stderr.write(message),
|
|
13874
|
+
}) {
|
|
13875
|
+
const retirement = (0,_cloudflared_tunnel_manager_mjs__WEBPACK_IMPORTED_MODULE_2__/* .stopManagedQuickTunnel */ .HW)({
|
|
13876
|
+
tunnelStatePath,
|
|
13877
|
+
isAlive,
|
|
13878
|
+
managerId: TUNNEL_MANAGER_ID,
|
|
13879
|
+
});
|
|
13880
|
+
if (retirement.status === 'stopped') {
|
|
13881
|
+
writeStdout(`Stopped obsolete managed Quick Tunnel: ${retirement.state.url} (pid ${retirement.state.pid}).\n`);
|
|
13882
|
+
} else if (retirement.status === 'stale-state-cleared') {
|
|
13883
|
+
writeStdout('Cleared stale managed Quick Tunnel state.\n');
|
|
13884
|
+
} else if (
|
|
13885
|
+
retirement.status === 'identity-unverified' ||
|
|
13886
|
+
retirement.status === 'stop-failed' ||
|
|
13887
|
+
retirement.status === 'not-managed-quick'
|
|
13888
|
+
) {
|
|
13889
|
+
const stateSummary = retirement.state
|
|
13890
|
+
? `${retirement.state.url || 'unknown URL'} (pid ${retirement.state.pid || 'unknown'})`
|
|
13891
|
+
: 'unknown tracked process';
|
|
13892
|
+
const message =
|
|
13893
|
+
retirement.status === 'stop-failed'
|
|
13894
|
+
? `Tracked Quick Tunnel ${stateSummary} did not exit after a verified stop request; its state was preserved.`
|
|
13895
|
+
: `Tracked tunnel ${stateSummary} was left running because its Vibelet Quick Tunnel identity could not be safely verified.`;
|
|
13896
|
+
if (required) {
|
|
13897
|
+
fail(
|
|
13898
|
+
'Refusing to replace an unverified tracked tunnel.',
|
|
13899
|
+
`${message}\nInspect the tracked process and tunnel.json before retrying --force.`,
|
|
13900
|
+
);
|
|
13901
|
+
} else {
|
|
13902
|
+
writeStderr(`${message}\n`);
|
|
13903
|
+
}
|
|
13904
|
+
}
|
|
13905
|
+
return retirement;
|
|
13906
|
+
}
|
|
13907
|
+
|
|
13908
|
+
async function prepareManagedQuickTunnel({
|
|
13909
|
+
force,
|
|
13910
|
+
port,
|
|
13911
|
+
logDir,
|
|
13912
|
+
tunnelStatePath,
|
|
13913
|
+
protocol,
|
|
13914
|
+
updateStatePath,
|
|
13915
|
+
isAlive,
|
|
13916
|
+
fail,
|
|
13917
|
+
writeStdout = (message) => process.stdout.write(message),
|
|
13918
|
+
writeStderr = (message) => process.stderr.write(message),
|
|
13919
|
+
}) {
|
|
13920
|
+
const existing = force
|
|
13921
|
+
? null
|
|
13922
|
+
: await (0,_cloudflared_tunnel_manager_mjs__WEBPACK_IMPORTED_MODULE_2__/* .getAliveManagedQuickTunnel */ .M)({
|
|
13923
|
+
tunnelStatePath,
|
|
13924
|
+
isAlive,
|
|
13925
|
+
managerId: TUNNEL_MANAGER_ID,
|
|
13926
|
+
});
|
|
13927
|
+
if (existing) {
|
|
13928
|
+
writeStdout(`Reusing tunnel: ${existing.url} (pid ${existing.pid})\n`);
|
|
13929
|
+
return { failed: false, relayUrl: existing.url };
|
|
13930
|
+
}
|
|
13931
|
+
|
|
13932
|
+
// A non-ready tracked Quick Tunnel must be retired with the same strict
|
|
13933
|
+
// identity proof as --force before its state can be replaced.
|
|
13934
|
+
retireTrackedQuickTunnel({
|
|
13935
|
+
tunnelStatePath,
|
|
13936
|
+
isAlive,
|
|
13937
|
+
required: true,
|
|
13938
|
+
fail,
|
|
13939
|
+
writeStdout,
|
|
13940
|
+
writeStderr,
|
|
13941
|
+
});
|
|
13942
|
+
writeStdout('Starting Cloudflare Tunnel...\n');
|
|
13943
|
+
try {
|
|
13944
|
+
const tunnel = await (0,_cloudflared_tunnel_manager_mjs__WEBPACK_IMPORTED_MODULE_2__/* .startTunnel */ .DH)({
|
|
13945
|
+
port,
|
|
13946
|
+
logDir,
|
|
13947
|
+
tunnelStatePath,
|
|
13948
|
+
protocol,
|
|
13949
|
+
updateStatePath,
|
|
13950
|
+
managerId: TUNNEL_MANAGER_ID,
|
|
13951
|
+
});
|
|
13952
|
+
writeStdout(`Tunnel ready: ${tunnel.url}\n`);
|
|
13953
|
+
return { failed: false, relayUrl: tunnel.url };
|
|
13954
|
+
} catch (error) {
|
|
13955
|
+
(0,_cloudflared_tunnel_manager_mjs__WEBPACK_IMPORTED_MODULE_2__/* .clearTunnelState */ .vD)({ tunnelStatePath });
|
|
13956
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
13957
|
+
writeStderr(`${message}\n`);
|
|
13958
|
+
writeStderr(
|
|
13959
|
+
'Continuing with LAN/local pairing. Use `npx vibelet --access=remote --force` after fixing Cloudflare Tunnel, or pass `--access=https://<url>` for a custom tunnel.\n',
|
|
13960
|
+
);
|
|
13961
|
+
return { failed: true, relayUrl: '' };
|
|
13962
|
+
}
|
|
13963
|
+
}
|
|
13964
|
+
|
|
13965
|
+
async function tryUpdateRunningDaemonRelay({
|
|
13966
|
+
port,
|
|
13967
|
+
relayUrl,
|
|
13968
|
+
probeHealth,
|
|
13969
|
+
fetchFn = globalThis.fetch,
|
|
13970
|
+
writeStderr = (message) => process.stderr.write(message),
|
|
13971
|
+
}) {
|
|
13972
|
+
try {
|
|
13973
|
+
const response = await fetchFn(`http://127.0.0.1:${port}/connection/relay`, {
|
|
13974
|
+
method: 'POST',
|
|
13975
|
+
headers: { 'Content-Type': 'application/json' },
|
|
13976
|
+
body: JSON.stringify({ relayUrl }),
|
|
13977
|
+
signal: AbortSignal.timeout(2_000),
|
|
13978
|
+
});
|
|
13979
|
+
if (!response.ok) {
|
|
13980
|
+
if (response.status !== 404) {
|
|
13981
|
+
const payload = await response.text().catch(() => '');
|
|
13982
|
+
writeStderr(
|
|
13983
|
+
`Running daemon declined live relay refresh (${response.status})${payload ? `: ${payload.trim()}` : ''}.\n`,
|
|
13984
|
+
);
|
|
13985
|
+
}
|
|
13986
|
+
return null;
|
|
13987
|
+
}
|
|
13988
|
+
return await probeHealth(1_500);
|
|
13989
|
+
} catch {
|
|
13990
|
+
return null;
|
|
13991
|
+
}
|
|
13992
|
+
}
|
|
13993
|
+
|
|
13994
|
+
|
|
13538
13995
|
/***/ }),
|
|
13539
13996
|
|
|
13540
13997
|
/***/ 1010:
|
|
@@ -13612,6 +14069,7 @@ function describeLaunchctlResult(result) {
|
|
|
13612
14069
|
/* harmony export */ SF: () => (/* binding */ selectWebUiConnectionTarget),
|
|
13613
14070
|
/* harmony export */ YP: () => (/* binding */ createCompactPairingPayload),
|
|
13614
14071
|
/* harmony export */ dE: () => (/* binding */ findUnsafeCleartextHosts),
|
|
14072
|
+
/* harmony export */ mp: () => (/* binding */ applyRelayUrlToPairingPayload),
|
|
13615
14073
|
/* harmony export */ uR: () => (/* binding */ formatConnectionSummary)
|
|
13616
14074
|
/* harmony export */ });
|
|
13617
14075
|
/* unused harmony exports normalizeHostValue, isIpv4Host, isTailscaleHost, isSharedIpv4Host, isLocalNetworkHost, isLoopbackHost, isPlainLocalHostname, isTrustedCleartextHost, parseCommaSeparatedHosts, isQuickTunnelHost, buildLegacyConnection, formatConnectionSourceLabel, buildConnectionHttpUrl, isPreferredWebUiHost, encodePairingPayloadForUrlFragment */
|
|
@@ -13779,6 +14237,65 @@ function normalizePairingConnections(pairingPayload) {
|
|
|
13779
14237
|
]);
|
|
13780
14238
|
}
|
|
13781
14239
|
|
|
14240
|
+
/**
|
|
14241
|
+
* Overlay a freshly selected relay on a pairing payload without requiring the
|
|
14242
|
+
* daemon process that issued the nonce to restart. This keeps active sessions
|
|
14243
|
+
* alive while still propagating a rotated Quick Tunnel URL through the QR/code.
|
|
14244
|
+
* Stable direct paths are retained as fallbacks; obsolete relay paths are
|
|
14245
|
+
* removed.
|
|
14246
|
+
*/
|
|
14247
|
+
function applyRelayUrlToPairingPayload(pairingPayload, relayUrl) {
|
|
14248
|
+
const connections = normalizePairingConnections(pairingPayload);
|
|
14249
|
+
const directConnections = connections.filter((target) => target.kind !== 'relay');
|
|
14250
|
+
const normalizedRelayUrl = typeof relayUrl === 'string' ? relayUrl.trim() : '';
|
|
14251
|
+
|
|
14252
|
+
if (!normalizedRelayUrl) {
|
|
14253
|
+
const [preferredDirect, ...fallbackDirect] = directConnections;
|
|
14254
|
+
if (!preferredDirect) {
|
|
14255
|
+
return { ...pairingPayload, connections: [] };
|
|
14256
|
+
}
|
|
14257
|
+
return {
|
|
14258
|
+
...pairingPayload,
|
|
14259
|
+
canonicalHost: preferredDirect.host,
|
|
14260
|
+
port: preferredDirect.port,
|
|
14261
|
+
fallbackHosts: fallbackDirect
|
|
14262
|
+
.filter((target) => target.port === preferredDirect.port)
|
|
14263
|
+
.map((target) => target.host),
|
|
14264
|
+
connections: directConnections,
|
|
14265
|
+
};
|
|
14266
|
+
}
|
|
14267
|
+
|
|
14268
|
+
let parsed;
|
|
14269
|
+
try {
|
|
14270
|
+
parsed = new URL(normalizedRelayUrl);
|
|
14271
|
+
} catch {
|
|
14272
|
+
return pairingPayload;
|
|
14273
|
+
}
|
|
14274
|
+
const secure = parsed.protocol === 'https:';
|
|
14275
|
+
const relayPort = parsed.port ? Number(parsed.port) : secure ? 443 : 80;
|
|
14276
|
+
if (!parsed.hostname || !Number.isInteger(relayPort) || relayPort <= 0 || relayPort > 65_535) {
|
|
14277
|
+
return pairingPayload;
|
|
14278
|
+
}
|
|
14279
|
+
const relayHost = normalizeHostValue(parsed.hostname);
|
|
14280
|
+
const quickTunnel = isQuickTunnelHost(relayHost);
|
|
14281
|
+
const relayConnection = {
|
|
14282
|
+
kind: 'relay',
|
|
14283
|
+
host: relayHost,
|
|
14284
|
+
port: relayPort,
|
|
14285
|
+
...(secure ? { secure: true } : {}),
|
|
14286
|
+
source: quickTunnel ? 'quick_tunnel' : 'configured_relay',
|
|
14287
|
+
stability: quickTunnel ? 'ephemeral' : 'stable',
|
|
14288
|
+
};
|
|
14289
|
+
|
|
14290
|
+
return {
|
|
14291
|
+
...pairingPayload,
|
|
14292
|
+
canonicalHost: relayHost,
|
|
14293
|
+
port: relayPort,
|
|
14294
|
+
fallbackHosts: undefined,
|
|
14295
|
+
connections: [relayConnection, ...directConnections],
|
|
14296
|
+
};
|
|
14297
|
+
}
|
|
14298
|
+
|
|
13782
14299
|
function createCompactPairingPayload(pairingPayload) {
|
|
13783
14300
|
const connections = normalizePairingConnections(pairingPayload);
|
|
13784
14301
|
const compactPayload = {
|
|
@@ -13880,10 +14397,13 @@ function buildWebUiUrl(target, pairingPayload) {
|
|
|
13880
14397
|
|
|
13881
14398
|
/* harmony export */ __nccwpck_require__.d(__webpack_exports__, {
|
|
13882
14399
|
/* harmony export */ Ne: () => (/* binding */ shouldRefuseRuntimeDowngrade),
|
|
14400
|
+
/* harmony export */ Pg: () => (/* binding */ shouldRetireManagedQuickTunnel),
|
|
13883
14401
|
/* harmony export */ ZN: () => (/* binding */ shouldReuseHealthyDaemon),
|
|
14402
|
+
/* harmony export */ gm: () => (/* binding */ shouldManageQuickTunnel),
|
|
13884
14403
|
/* harmony export */ iX: () => (/* binding */ doesHealthSupportTerminalControl),
|
|
13885
14404
|
/* harmony export */ nW: () => (/* binding */ doesHealthMatchRequestedConnectionConfig)
|
|
13886
14405
|
/* harmony export */ });
|
|
14406
|
+
/* unused harmony export isQuickTunnelRelayUrl */
|
|
13887
14407
|
function compareSemverTriple(a, b) {
|
|
13888
14408
|
const pa = String(a)
|
|
13889
14409
|
.split('.')
|
|
@@ -13913,10 +14433,15 @@ function shouldRefuseRuntimeDowngrade({ cliVersion, runtimeVersion, runtimeEntry
|
|
|
13913
14433
|
return compareSemverTriple(cliVersion, runtimeVersion) < 0;
|
|
13914
14434
|
}
|
|
13915
14435
|
|
|
13916
|
-
function shouldReuseHealthyDaemon({
|
|
14436
|
+
function shouldReuseHealthyDaemon({
|
|
14437
|
+
command,
|
|
14438
|
+
daemonHealthy,
|
|
14439
|
+
hasExplicitConfigOverrides,
|
|
14440
|
+
canApplyConnectionConfigWithoutRestart = false,
|
|
14441
|
+
}) {
|
|
13917
14442
|
if (!daemonHealthy) return false;
|
|
13918
14443
|
if (command !== 'default' && command !== 'start') return false;
|
|
13919
|
-
return !hasExplicitConfigOverrides;
|
|
14444
|
+
return !hasExplicitConfigOverrides || canApplyConnectionConfigWithoutRestart;
|
|
13920
14445
|
}
|
|
13921
14446
|
|
|
13922
14447
|
function doesHealthSupportTerminalControl(health) {
|
|
@@ -13947,6 +14472,41 @@ function isQuickTunnelHost(host) {
|
|
|
13947
14472
|
return normalizeHostValue(host.replace(/^https?:\/\//, '').replace(/\/.*$/, '')).endsWith('.trycloudflare.com');
|
|
13948
14473
|
}
|
|
13949
14474
|
|
|
14475
|
+
function isQuickTunnelRelayUrl(relayUrl) {
|
|
14476
|
+
if (typeof relayUrl !== 'string' || !relayUrl.trim()) return false;
|
|
14477
|
+
try {
|
|
14478
|
+
return normalizeHostValue(new URL(relayUrl).hostname).endsWith('.trycloudflare.com');
|
|
14479
|
+
} catch {
|
|
14480
|
+
return isQuickTunnelHost(relayUrl);
|
|
14481
|
+
}
|
|
14482
|
+
}
|
|
14483
|
+
|
|
14484
|
+
/**
|
|
14485
|
+
* A saved stable relay is an explicit connection choice and must survive an
|
|
14486
|
+
* ordinary start/restart. Quick Tunnel URLs remain managed because their
|
|
14487
|
+
* process and hostname are ephemeral, while --force explicitly requests a new
|
|
14488
|
+
* managed tunnel.
|
|
14489
|
+
*/
|
|
14490
|
+
function shouldManageQuickTunnel({
|
|
14491
|
+
startCommand,
|
|
14492
|
+
localMode = false,
|
|
14493
|
+
relayArg = null,
|
|
14494
|
+
hostArg = null,
|
|
14495
|
+
fallbackHostsArg = null,
|
|
14496
|
+
savedRelayUrl = '',
|
|
14497
|
+
force = false,
|
|
14498
|
+
}) {
|
|
14499
|
+
if (!startCommand || localMode || relayArg !== null || hostArg || fallbackHostsArg) {
|
|
14500
|
+
return false;
|
|
14501
|
+
}
|
|
14502
|
+
if (force) return true;
|
|
14503
|
+
return !savedRelayUrl || isQuickTunnelRelayUrl(savedRelayUrl);
|
|
14504
|
+
}
|
|
14505
|
+
|
|
14506
|
+
function shouldRetireManagedQuickTunnel({ startCommand, manageQuickTunnel }) {
|
|
14507
|
+
return Boolean(startCommand && !manageQuickTunnel);
|
|
14508
|
+
}
|
|
14509
|
+
|
|
13950
14510
|
function hasRemoteAdvertisementInLocalMode(health) {
|
|
13951
14511
|
const hosts = [
|
|
13952
14512
|
typeof health.canonicalHost === 'string' ? health.canonicalHost : '',
|
|
@@ -14058,14 +14618,16 @@ __nccwpck_require__.a(__webpack_module__, async (__webpack_handle_async_dependen
|
|
|
14058
14618
|
/* harmony import */ var node_path__WEBPACK_IMPORTED_MODULE_4__ = __nccwpck_require__(6760);
|
|
14059
14619
|
/* harmony import */ var node_url__WEBPACK_IMPORTED_MODULE_5__ = __nccwpck_require__(3136);
|
|
14060
14620
|
/* harmony import */ var qrcode__WEBPACK_IMPORTED_MODULE_6__ = __nccwpck_require__(7514);
|
|
14061
|
-
/* harmony import */ var
|
|
14621
|
+
/* harmony import */ var _vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_15__ = __nccwpck_require__(6927);
|
|
14062
14622
|
/* harmony import */ var _cloudflared_tunnel_manager_mjs__WEBPACK_IMPORTED_MODULE_7__ = __nccwpck_require__(2755);
|
|
14063
|
-
/* harmony import */ var
|
|
14064
|
-
/* harmony import */ var
|
|
14065
|
-
/* harmony import */ var
|
|
14066
|
-
/* harmony import */ var
|
|
14067
|
-
/* harmony import */ var
|
|
14068
|
-
/* harmony import */ var
|
|
14623
|
+
/* harmony import */ var _vibelet_cloudflare_runtime_mjs__WEBPACK_IMPORTED_MODULE_8__ = __nccwpck_require__(3869);
|
|
14624
|
+
/* harmony import */ var _vibelet_launchd_mjs__WEBPACK_IMPORTED_MODULE_12__ = __nccwpck_require__(1010);
|
|
14625
|
+
/* harmony import */ var _linux_systemd_mjs__WEBPACK_IMPORTED_MODULE_9__ = __nccwpck_require__(4217);
|
|
14626
|
+
/* harmony import */ var _vibelet_stop_logic_mjs__WEBPACK_IMPORTED_MODULE_13__ = __nccwpck_require__(6274);
|
|
14627
|
+
/* harmony import */ var _vibelet_runtime_policy_mjs__WEBPACK_IMPORTED_MODULE_11__ = __nccwpck_require__(4);
|
|
14628
|
+
/* harmony import */ var _terminal_wrapper_mjs__WEBPACK_IMPORTED_MODULE_10__ = __nccwpck_require__(1427);
|
|
14629
|
+
/* harmony import */ var _vibelet_pairing_connections_mjs__WEBPACK_IMPORTED_MODULE_14__ = __nccwpck_require__(7721);
|
|
14630
|
+
|
|
14069
14631
|
|
|
14070
14632
|
|
|
14071
14633
|
|
|
@@ -14097,11 +14659,11 @@ const runtimeDir = (0,node_path__WEBPACK_IMPORTED_MODULE_4__.join)(vibeletDir, '
|
|
|
14097
14659
|
const runtimeCurrentDir = (0,node_path__WEBPACK_IMPORTED_MODULE_4__.join)(runtimeDir, 'current');
|
|
14098
14660
|
const runtimeMetadataPath = (0,node_path__WEBPACK_IMPORTED_MODULE_4__.join)(runtimeCurrentDir, 'runtime.json');
|
|
14099
14661
|
const runtimeDaemonEntryPath = (0,node_path__WEBPACK_IMPORTED_MODULE_4__.join)(runtimeCurrentDir, 'dist', 'index.cjs');
|
|
14100
|
-
const runtimeTerminalControlTokenPath =
|
|
14662
|
+
const runtimeTerminalControlTokenPath = _terminal_wrapper_mjs__WEBPACK_IMPORTED_MODULE_10__/* .terminalControlTokenPath */ .gJ;
|
|
14101
14663
|
const stdoutLogPath = (0,node_path__WEBPACK_IMPORTED_MODULE_4__.join)(logDir, 'daemon.stdout.log');
|
|
14102
14664
|
const stderrLogPath = (0,node_path__WEBPACK_IMPORTED_MODULE_4__.join)(logDir, 'daemon.stderr.log');
|
|
14103
14665
|
const pidFilePath = (0,node_path__WEBPACK_IMPORTED_MODULE_4__.join)(vibeletDir, 'daemon.pid');
|
|
14104
|
-
const
|
|
14666
|
+
const relayConfig = (0,_vibelet_cloudflare_runtime_mjs__WEBPACK_IMPORTED_MODULE_8__/* .createRelayConfigStore */ .T7)((0,node_path__WEBPACK_IMPORTED_MODULE_4__.join)(vibeletDir, 'relay.json'));
|
|
14105
14667
|
const tunnelStatePath = (0,node_path__WEBPACK_IMPORTED_MODULE_4__.join)(vibeletDir, 'tunnel.json');
|
|
14106
14668
|
const cloudflaredUpdateStatePath = (0,node_path__WEBPACK_IMPORTED_MODULE_4__.join)(vibeletDir, 'cloudflared-update.json');
|
|
14107
14669
|
const updateCheckPath = (0,node_path__WEBPACK_IMPORTED_MODULE_4__.join)(vibeletDir, 'update-check.json');
|
|
@@ -14254,7 +14816,7 @@ function ensureRuntimeInstalled() {
|
|
|
14254
14816
|
const runtimeMetadata = readRuntimeMetadata();
|
|
14255
14817
|
|
|
14256
14818
|
if (
|
|
14257
|
-
(0,
|
|
14819
|
+
(0,_vibelet_runtime_policy_mjs__WEBPACK_IMPORTED_MODULE_11__/* .shouldRefuseRuntimeDowngrade */ .Ne)({
|
|
14258
14820
|
cliVersion: packageJson.version,
|
|
14259
14821
|
runtimeVersion: runtimeMetadata?.version,
|
|
14260
14822
|
runtimeEntryExists: (0,node_fs__WEBPACK_IMPORTED_MODULE_1__.existsSync)(runtimeDaemonEntryPath),
|
|
@@ -14458,7 +15020,7 @@ function createDarwinBackend() {
|
|
|
14458
15020
|
}
|
|
14459
15021
|
|
|
14460
15022
|
function bootoutService() {
|
|
14461
|
-
return (0,
|
|
15023
|
+
return (0,_vibelet_launchd_mjs__WEBPACK_IMPORTED_MODULE_12__/* .bootoutLaunchdService */ .B)({
|
|
14462
15024
|
launchctl,
|
|
14463
15025
|
launchDomain,
|
|
14464
15026
|
label,
|
|
@@ -14547,7 +15109,7 @@ ${envSection}
|
|
|
14547
15109
|
if (result.status !== 0) {
|
|
14548
15110
|
fail(
|
|
14549
15111
|
'Failed to bootstrap vibelet launch agent.',
|
|
14550
|
-
[(0,
|
|
15112
|
+
[(0,_vibelet_launchd_mjs__WEBPACK_IMPORTED_MODULE_12__/* .describeLaunchctlResult */ .N)(bootoutResult.result), (0,_vibelet_launchd_mjs__WEBPACK_IMPORTED_MODULE_12__/* .describeLaunchctlResult */ .N)(result)].filter(Boolean).join('\n'),
|
|
14551
15113
|
);
|
|
14552
15114
|
}
|
|
14553
15115
|
}
|
|
@@ -14563,7 +15125,7 @@ ${envSection}
|
|
|
14563
15125
|
stop() {
|
|
14564
15126
|
const bootoutResult = bootoutService();
|
|
14565
15127
|
if (!bootoutResult.ok) {
|
|
14566
|
-
fail('Failed to unload vibelet launch agent.', (0,
|
|
15128
|
+
fail('Failed to unload vibelet launch agent.', (0,_vibelet_launchd_mjs__WEBPACK_IMPORTED_MODULE_12__/* .describeLaunchctlResult */ .N)(bootoutResult.result));
|
|
14567
15129
|
}
|
|
14568
15130
|
// bootout returns before launchd actually finishes unloading. Poll
|
|
14569
15131
|
// until the service is gone so a follow-up install() doesn't see a
|
|
@@ -14594,10 +15156,10 @@ function createLinuxBackend() {
|
|
|
14594
15156
|
return [result?.stderr, result?.stdout].filter(Boolean).join('\n').trim();
|
|
14595
15157
|
}
|
|
14596
15158
|
|
|
14597
|
-
let useSystemd = (0,
|
|
15159
|
+
let useSystemd = (0,_linux_systemd_mjs__WEBPACK_IMPORTED_MODULE_9__/* .canUseSystemdUserManager */ .X)();
|
|
14598
15160
|
|
|
14599
15161
|
function demoteToDetachedIfSystemdUnavailable(result) {
|
|
14600
|
-
if (!(0,
|
|
15162
|
+
if (!(0,_linux_systemd_mjs__WEBPACK_IMPORTED_MODULE_9__/* .isSystemdUserManagerUnavailable */ .a)(resultOutput(result))) {
|
|
14601
15163
|
return false;
|
|
14602
15164
|
}
|
|
14603
15165
|
useSystemd = false;
|
|
@@ -14896,9 +15458,18 @@ function isDaemonStartCommand(command) {
|
|
|
14896
15458
|
return command === 'default' || command === 'start' || command === 'restart' || command === 'reset';
|
|
14897
15459
|
}
|
|
14898
15460
|
|
|
15461
|
+
function retireTrackedQuickTunnel({ required = false } = {}) {
|
|
15462
|
+
return (0,_vibelet_cloudflare_runtime_mjs__WEBPACK_IMPORTED_MODULE_8__/* .retireTrackedQuickTunnel */ .zj)({
|
|
15463
|
+
tunnelStatePath,
|
|
15464
|
+
isAlive: isProcessAlive,
|
|
15465
|
+
required,
|
|
15466
|
+
fail,
|
|
15467
|
+
});
|
|
15468
|
+
}
|
|
15469
|
+
|
|
14899
15470
|
async function stopRunningDaemon(backend) {
|
|
14900
15471
|
try {
|
|
14901
|
-
await (0,
|
|
15472
|
+
await (0,_vibelet_stop_logic_mjs__WEBPACK_IMPORTED_MODULE_13__/* .stopDaemonWithHooks */ .v)({
|
|
14902
15473
|
requestShutdown,
|
|
14903
15474
|
backendStop: () => backend.stop(),
|
|
14904
15475
|
waitForDaemonExit,
|
|
@@ -14911,7 +15482,7 @@ async function stopRunningDaemon(backend) {
|
|
|
14911
15482
|
async function ensureDaemonForTerminalControl(backend) {
|
|
14912
15483
|
const healthyDaemon = await probeHealth(1_500);
|
|
14913
15484
|
const tokenReady = (0,node_fs__WEBPACK_IMPORTED_MODULE_1__.existsSync)(runtimeTerminalControlTokenPath);
|
|
14914
|
-
const terminalControlReady = healthyDaemon && tokenReady && (0,
|
|
15485
|
+
const terminalControlReady = healthyDaemon && tokenReady && (0,_vibelet_runtime_policy_mjs__WEBPACK_IMPORTED_MODULE_11__/* .doesHealthSupportTerminalControl */ .iX)(healthyDaemon);
|
|
14915
15486
|
if (terminalControlReady) {
|
|
14916
15487
|
return healthyDaemon;
|
|
14917
15488
|
}
|
|
@@ -14919,7 +15490,7 @@ async function ensureDaemonForTerminalControl(backend) {
|
|
|
14919
15490
|
if (healthyDaemon && !terminalControlReady) {
|
|
14920
15491
|
const activeSessions = typeof healthyDaemon.activeSessions === 'number' ? healthyDaemon.activeSessions : 0;
|
|
14921
15492
|
if (activeSessions > 0) {
|
|
14922
|
-
const reason = (0,
|
|
15493
|
+
const reason = (0,_vibelet_runtime_policy_mjs__WEBPACK_IMPORTED_MODULE_11__/* .doesHealthSupportTerminalControl */ .iX)(healthyDaemon)
|
|
14923
15494
|
? 'terminal-control token is missing'
|
|
14924
15495
|
: 'the running daemon does not advertise terminal-control support';
|
|
14925
15496
|
process.stderr.write(
|
|
@@ -14938,7 +15509,7 @@ async function ensureDaemonForTerminalControl(backend) {
|
|
|
14938
15509
|
}
|
|
14939
15510
|
|
|
14940
15511
|
function validateExplicitCleartextHosts({ hostArg, fallbackHostsArg }) {
|
|
14941
|
-
const unsafeHosts = (0,
|
|
15512
|
+
const unsafeHosts = (0,_vibelet_pairing_connections_mjs__WEBPACK_IMPORTED_MODULE_14__/* .findUnsafeCleartextHosts */ .dE)({ hostArg, fallbackHostsArg });
|
|
14942
15513
|
if (unsafeHosts.length === 0) {
|
|
14943
15514
|
return;
|
|
14944
15515
|
}
|
|
@@ -14948,8 +15519,8 @@ function validateExplicitCleartextHosts({ hostArg, fallbackHostsArg }) {
|
|
|
14948
15519
|
}
|
|
14949
15520
|
|
|
14950
15521
|
async function printPairingQr(pairingPayload) {
|
|
14951
|
-
const payload = JSON.stringify((0,
|
|
14952
|
-
const deepLink = (0,
|
|
15522
|
+
const payload = JSON.stringify((0,_vibelet_pairing_connections_mjs__WEBPACK_IMPORTED_MODULE_14__/* .createCompactPairingPayload */ .YP)(pairingPayload));
|
|
15523
|
+
const deepLink = (0,_vibelet_pairing_connections_mjs__WEBPACK_IMPORTED_MODULE_14__/* .buildPairingDeepLink */ .N7)(payload);
|
|
14953
15524
|
(0,node_fs__WEBPACK_IMPORTED_MODULE_1__.mkdirSync)(vibeletDir, { recursive: true });
|
|
14954
15525
|
await qrcode__WEBPACK_IMPORTED_MODULE_6__.toFile(pairingQrPngPath, payload, {
|
|
14955
15526
|
type: 'png',
|
|
@@ -14972,12 +15543,16 @@ async function printPairingQr(pairingPayload) {
|
|
|
14972
15543
|
|
|
14973
15544
|
// ─── Commands ───────────────────────────────────────────────────────────────────
|
|
14974
15545
|
|
|
14975
|
-
async function printPairingSummary(existingHealth = null) {
|
|
15546
|
+
async function printPairingSummary(existingHealth = null, { relayUrlOverride = null } = {}) {
|
|
14976
15547
|
const health = existingHealth ?? (await waitForHealth());
|
|
14977
|
-
const
|
|
14978
|
-
const
|
|
15548
|
+
const daemonPairingPayload = await postJson('/pair/open');
|
|
15549
|
+
const pairingPayload =
|
|
15550
|
+
relayUrlOverride === null
|
|
15551
|
+
? daemonPairingPayload
|
|
15552
|
+
: (0,_vibelet_pairing_connections_mjs__WEBPACK_IMPORTED_MODULE_14__/* .applyRelayUrlToPairingPayload */ .mp)(daemonPairingPayload, relayUrlOverride);
|
|
15553
|
+
const connections = (0,_vibelet_pairing_connections_mjs__WEBPACK_IMPORTED_MODULE_14__/* .normalizePairingConnections */ .No)(pairingPayload);
|
|
14979
15554
|
const [preferredConnection, ...otherConnections] = connections;
|
|
14980
|
-
const webUiConnection = (0,
|
|
15555
|
+
const webUiConnection = (0,_vibelet_pairing_connections_mjs__WEBPACK_IMPORTED_MODULE_14__/* .selectWebUiConnectionTarget */ .SF)(connections);
|
|
14981
15556
|
|
|
14982
15557
|
process.stdout.write(`Vibelet daemon is ready.\n\n`);
|
|
14983
15558
|
process.stdout.write(`Device: ${health.displayName}\n`);
|
|
@@ -14985,16 +15560,16 @@ async function printPairingSummary(existingHealth = null) {
|
|
|
14985
15560
|
process.stdout.write(`Host: ${pairingPayload.canonicalHost}\n`);
|
|
14986
15561
|
process.stdout.write(`Port: ${pairingPayload.port}\n`);
|
|
14987
15562
|
if (preferredConnection) {
|
|
14988
|
-
process.stdout.write(`Preferred path: ${(0,
|
|
15563
|
+
process.stdout.write(`Preferred path: ${(0,_vibelet_pairing_connections_mjs__WEBPACK_IMPORTED_MODULE_14__/* .formatConnectionSummary */ .uR)(preferredConnection)}\n`);
|
|
14989
15564
|
}
|
|
14990
15565
|
if (otherConnections.length > 0) {
|
|
14991
15566
|
process.stdout.write(`Other paths:\n`);
|
|
14992
15567
|
otherConnections.forEach((target) => {
|
|
14993
|
-
process.stdout.write(` - ${(0,
|
|
15568
|
+
process.stdout.write(` - ${(0,_vibelet_pairing_connections_mjs__WEBPACK_IMPORTED_MODULE_14__/* .formatConnectionSummary */ .uR)(target)}\n`);
|
|
14994
15569
|
});
|
|
14995
15570
|
}
|
|
14996
15571
|
if (webUiConnection) {
|
|
14997
|
-
process.stdout.write(`Web UI: ${(0,
|
|
15572
|
+
process.stdout.write(`Web UI: ${(0,_vibelet_pairing_connections_mjs__WEBPACK_IMPORTED_MODULE_14__/* .buildWebUiUrl */ .Gv)(webUiConnection, (0,_vibelet_pairing_connections_mjs__WEBPACK_IMPORTED_MODULE_14__/* .createCompactPairingPayload */ .YP)(pairingPayload))}\n`);
|
|
14998
15573
|
}
|
|
14999
15574
|
process.stdout.write(`Paired devices: ${health.pairedDevices}\n`);
|
|
15000
15575
|
await printPairingQr(pairingPayload);
|
|
@@ -15051,7 +15626,7 @@ function printHelp() {
|
|
|
15051
15626
|
}
|
|
15052
15627
|
|
|
15053
15628
|
function parseNamedArg(name, errorHint) {
|
|
15054
|
-
return (0,
|
|
15629
|
+
return (0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_15__/* .parseNamedArg */ .nE)(process.argv, name, errorHint, fail);
|
|
15055
15630
|
}
|
|
15056
15631
|
|
|
15057
15632
|
function parseRelayArg() {
|
|
@@ -15109,28 +15684,10 @@ function parseCommandArg(argv) {
|
|
|
15109
15684
|
return 'default';
|
|
15110
15685
|
}
|
|
15111
15686
|
|
|
15112
|
-
function loadRelayConfig() {
|
|
15113
|
-
try {
|
|
15114
|
-
const data = JSON.parse((0,node_fs__WEBPACK_IMPORTED_MODULE_1__.readFileSync)(relayConfigPath, 'utf8'));
|
|
15115
|
-
return data.relayUrl || '';
|
|
15116
|
-
} catch {
|
|
15117
|
-
return '';
|
|
15118
|
-
}
|
|
15119
|
-
}
|
|
15120
|
-
|
|
15121
|
-
function saveRelayConfig(relayUrl) {
|
|
15122
|
-
(0,node_fs__WEBPACK_IMPORTED_MODULE_1__.mkdirSync)(vibeletDir, { recursive: true });
|
|
15123
|
-
(0,node_fs__WEBPACK_IMPORTED_MODULE_1__.writeFileSync)(relayConfigPath, JSON.stringify({ relayUrl }, null, 2) + '\n', 'utf8');
|
|
15124
|
-
}
|
|
15125
|
-
|
|
15126
|
-
function clearRelayConfig() {
|
|
15127
|
-
(0,node_fs__WEBPACK_IMPORTED_MODULE_1__.rmSync)(relayConfigPath, { force: true });
|
|
15128
|
-
}
|
|
15129
|
-
|
|
15130
15687
|
// ─── Tunnel management ──────────────────────────────────────────────────────────
|
|
15131
15688
|
|
|
15132
|
-
function
|
|
15133
|
-
return {
|
|
15689
|
+
async function tryUpdateRunningDaemonRelay(relayUrl) {
|
|
15690
|
+
return await (0,_vibelet_cloudflare_runtime_mjs__WEBPACK_IMPORTED_MODULE_8__/* .tryUpdateRunningDaemonRelay */ .BT)({ port, relayUrl, probeHealth });
|
|
15134
15691
|
}
|
|
15135
15692
|
|
|
15136
15693
|
async function main() {
|
|
@@ -15164,10 +15721,10 @@ async function main() {
|
|
|
15164
15721
|
return;
|
|
15165
15722
|
}
|
|
15166
15723
|
|
|
15167
|
-
if ((0,
|
|
15724
|
+
if ((0,_terminal_wrapper_mjs__WEBPACK_IMPORTED_MODULE_10__/* .isTerminalAgentCommand */ .$c)(command)) {
|
|
15168
15725
|
const backend = resolveBackend();
|
|
15169
15726
|
await ensureDaemonForTerminalControl(backend);
|
|
15170
|
-
process.exitCode = await (0,
|
|
15727
|
+
process.exitCode = await (0,_terminal_wrapper_mjs__WEBPACK_IMPORTED_MODULE_10__/* .runManagedNativeTerminal */ .WA)({
|
|
15171
15728
|
agent: command,
|
|
15172
15729
|
args: process.argv.slice(3),
|
|
15173
15730
|
port,
|
|
@@ -15176,26 +15733,26 @@ async function main() {
|
|
|
15176
15733
|
return;
|
|
15177
15734
|
}
|
|
15178
15735
|
|
|
15179
|
-
const accessTarget = (0,
|
|
15180
|
-
if (accessTarget && (0,
|
|
15736
|
+
const accessTarget = (0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_15__/* .parseAccessTargetArg */ .tY)(process.argv, fail);
|
|
15737
|
+
if (accessTarget && (0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_15__/* .hasLegacyAccessArgs */ .NT)(process.argv, process.env)) {
|
|
15181
15738
|
fail(
|
|
15182
15739
|
'Do not combine --access with legacy access flags.',
|
|
15183
15740
|
'Use one form, for example `--access=local`, `--access=remote`, `--access=https://...`, or `--access=<host>`.',
|
|
15184
15741
|
);
|
|
15185
15742
|
}
|
|
15186
15743
|
if (!accessTarget) {
|
|
15187
|
-
(0,
|
|
15188
|
-
(0,
|
|
15189
|
-
(0,
|
|
15190
|
-
(0,
|
|
15744
|
+
(0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_15__/* .consumeFlag */ .PC)(process.argv, 'remote') ||
|
|
15745
|
+
(0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_15__/* .consumeFlag */ .PC)(process.argv, 'tunnel') ||
|
|
15746
|
+
(0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_15__/* .readNpmConfigFlag */ .AW)('remote') ||
|
|
15747
|
+
(0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_15__/* .readNpmConfigFlag */ .AW)('tunnel');
|
|
15191
15748
|
}
|
|
15192
15749
|
const localFlag =
|
|
15193
15750
|
accessTarget?.kind === 'local' ||
|
|
15194
15751
|
(!accessTarget &&
|
|
15195
|
-
((0,
|
|
15196
|
-
(0,
|
|
15752
|
+
((0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_15__/* .consumeFlag */ .PC)(process.argv, 'local') ||
|
|
15753
|
+
(0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_15__/* .readNpmConfigFlag */ .AW)('local') ||
|
|
15197
15754
|
isTruthyEnvFlag(process.env.VIBELET_LOCAL_ONLY)));
|
|
15198
|
-
const forceFlag = (0,
|
|
15755
|
+
const forceFlag = (0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_15__/* .consumeFlag */ .PC)(process.argv, 'force') || (0,_vibelet_cli_args_mjs__WEBPACK_IMPORTED_MODULE_15__/* .readNpmConfigFlag */ .AW)('force');
|
|
15199
15756
|
const relayArg =
|
|
15200
15757
|
accessTarget?.kind === 'relay'
|
|
15201
15758
|
? accessTarget.relayUrl
|
|
@@ -15219,14 +15776,32 @@ async function main() {
|
|
|
15219
15776
|
let managedTunnelFailed = false;
|
|
15220
15777
|
command = parseCommandArg(process.argv);
|
|
15221
15778
|
const startCommand = isDaemonStartCommand(command);
|
|
15779
|
+
const savedRelayUrl = relayConfig.load();
|
|
15222
15780
|
// --remote/--tunnel remain accepted for compatibility, but startup commands
|
|
15223
15781
|
// now default to managed remote access unless another connection target wins.
|
|
15224
|
-
const shouldManageTunnel =
|
|
15782
|
+
const shouldManageTunnel = (0,_vibelet_runtime_policy_mjs__WEBPACK_IMPORTED_MODULE_11__/* .shouldManageQuickTunnel */ .gm)({
|
|
15783
|
+
startCommand,
|
|
15784
|
+
localMode: localFlag,
|
|
15785
|
+
relayArg,
|
|
15786
|
+
hostArg,
|
|
15787
|
+
fallbackHostsArg,
|
|
15788
|
+
savedRelayUrl,
|
|
15789
|
+
force: forceFlag,
|
|
15790
|
+
});
|
|
15225
15791
|
const cloudflaredProtocol = process.env.VIBELET_CLOUDFLARED_PROTOCOL?.trim() || 'http2';
|
|
15226
15792
|
if (!['auto', 'quic', 'http2'].includes(cloudflaredProtocol)) {
|
|
15227
15793
|
fail(`Unsupported VIBELET_CLOUDFLARED_PROTOCOL: ${cloudflaredProtocol}. Use auto, quic, or http2.`);
|
|
15228
15794
|
}
|
|
15229
15795
|
|
|
15796
|
+
if (
|
|
15797
|
+
(0,_vibelet_runtime_policy_mjs__WEBPACK_IMPORTED_MODULE_11__/* .shouldRetireManagedQuickTunnel */ .Pg)({
|
|
15798
|
+
startCommand,
|
|
15799
|
+
manageQuickTunnel: shouldManageTunnel,
|
|
15800
|
+
})
|
|
15801
|
+
) {
|
|
15802
|
+
retireTrackedQuickTunnel();
|
|
15803
|
+
}
|
|
15804
|
+
|
|
15230
15805
|
if (localFlag) {
|
|
15231
15806
|
process.env.VIBELET_LOCAL_ONLY = '1';
|
|
15232
15807
|
} else {
|
|
@@ -15234,47 +15809,35 @@ async function main() {
|
|
|
15234
15809
|
}
|
|
15235
15810
|
|
|
15236
15811
|
if (shouldManageTunnel) {
|
|
15237
|
-
const
|
|
15238
|
-
|
|
15239
|
-
|
|
15240
|
-
|
|
15241
|
-
|
|
15242
|
-
|
|
15243
|
-
|
|
15244
|
-
|
|
15245
|
-
|
|
15246
|
-
|
|
15247
|
-
|
|
15248
|
-
|
|
15249
|
-
|
|
15250
|
-
|
|
15251
|
-
|
|
15252
|
-
process.stdout.write(`Tunnel ready: ${tunnel.url}\n`);
|
|
15253
|
-
saveRelayConfig(tunnel.url);
|
|
15254
|
-
} catch (err) {
|
|
15255
|
-
managedTunnelFailed = true;
|
|
15256
|
-
(0,_cloudflared_tunnel_manager_mjs__WEBPACK_IMPORTED_MODULE_7__/* .clearTunnelState */ .vD)({ tunnelStatePath });
|
|
15257
|
-
clearRelayConfig();
|
|
15258
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
15259
|
-
process.stderr.write(`${message}\n`);
|
|
15260
|
-
process.stderr.write(
|
|
15261
|
-
'Continuing with LAN/local pairing. Use `npx vibelet --access=remote --force` after fixing Cloudflare Tunnel, or pass `--access=https://<url>` for a custom tunnel.\n',
|
|
15262
|
-
);
|
|
15263
|
-
}
|
|
15812
|
+
const managedTunnel = await (0,_vibelet_cloudflare_runtime_mjs__WEBPACK_IMPORTED_MODULE_8__/* .prepareManagedQuickTunnel */ .kS)({
|
|
15813
|
+
force: forceFlag,
|
|
15814
|
+
port,
|
|
15815
|
+
logDir,
|
|
15816
|
+
tunnelStatePath,
|
|
15817
|
+
protocol: cloudflaredProtocol,
|
|
15818
|
+
updateStatePath: cloudflaredUpdateStatePath,
|
|
15819
|
+
isAlive: isProcessAlive,
|
|
15820
|
+
fail,
|
|
15821
|
+
});
|
|
15822
|
+
managedTunnelFailed = managedTunnel.failed;
|
|
15823
|
+
if (managedTunnel.relayUrl) {
|
|
15824
|
+
relayConfig.save(managedTunnel.relayUrl);
|
|
15825
|
+
} else if (managedTunnel.failed) {
|
|
15826
|
+
relayConfig.clear();
|
|
15264
15827
|
}
|
|
15265
15828
|
}
|
|
15266
15829
|
|
|
15267
15830
|
// --access= clears saved relay; --access=https://... saves it; omitted uses saved value.
|
|
15268
15831
|
if (relayArg !== null) {
|
|
15269
15832
|
if (relayArg) {
|
|
15270
|
-
|
|
15833
|
+
relayConfig.save(relayArg);
|
|
15271
15834
|
} else {
|
|
15272
|
-
|
|
15835
|
+
relayConfig.clear();
|
|
15273
15836
|
}
|
|
15274
15837
|
}
|
|
15275
15838
|
const shouldIgnoreSavedRelay =
|
|
15276
15839
|
relayArg === null && (localFlag || Boolean(hostArg) || Boolean(fallbackHostsArg) || managedTunnelFailed);
|
|
15277
|
-
const relayUrl = relayArg !== null ? relayArg : shouldIgnoreSavedRelay ? '' :
|
|
15840
|
+
const relayUrl = relayArg !== null ? relayArg : shouldIgnoreSavedRelay ? '' : relayConfig.load();
|
|
15278
15841
|
if (relayUrl) {
|
|
15279
15842
|
process.env.VIBELET_RELAY_URL = relayUrl;
|
|
15280
15843
|
} else {
|
|
@@ -15298,12 +15861,10 @@ async function main() {
|
|
|
15298
15861
|
// Always try graceful HTTP shutdown first — gives the daemon time to
|
|
15299
15862
|
// close sessions and flush logs before the service manager kills it.
|
|
15300
15863
|
await stopRunningDaemon(backend);
|
|
15301
|
-
//
|
|
15302
|
-
|
|
15303
|
-
|
|
15304
|
-
|
|
15305
|
-
process.stdout.write('Tunnel stopped.\n');
|
|
15306
|
-
}
|
|
15864
|
+
// Stop only a tunnel whose persisted owner, origin, and live command all
|
|
15865
|
+
// prove it is the Vibelet-managed Quick Tunnel. Named/external tunnels are
|
|
15866
|
+
// deliberately left alone.
|
|
15867
|
+
retireTrackedQuickTunnel();
|
|
15307
15868
|
process.stdout.write('Daemon stopped.\n');
|
|
15308
15869
|
return;
|
|
15309
15870
|
}
|
|
@@ -15311,11 +15872,15 @@ async function main() {
|
|
|
15311
15872
|
if (command === 'status') {
|
|
15312
15873
|
process.stdout.write(`Service (${backend.name}): ${backend.statusLabel()}\n`);
|
|
15313
15874
|
process.stdout.write(`Runtime: ${(0,node_fs__WEBPACK_IMPORTED_MODULE_1__.existsSync)(runtimeDaemonEntryPath) ? runtimeDaemonEntryPath : 'not installed'}\n`);
|
|
15314
|
-
const tunnelState = (0,_cloudflared_tunnel_manager_mjs__WEBPACK_IMPORTED_MODULE_7__/* .
|
|
15875
|
+
const tunnelState = await (0,_cloudflared_tunnel_manager_mjs__WEBPACK_IMPORTED_MODULE_7__/* .getAliveManagedQuickTunnel */ .M)({
|
|
15876
|
+
tunnelStatePath,
|
|
15877
|
+
isAlive: isProcessAlive,
|
|
15878
|
+
managerId: 'vibelet-cli',
|
|
15879
|
+
});
|
|
15315
15880
|
if (tunnelState) {
|
|
15316
15881
|
process.stdout.write(`Tunnel: ${tunnelState.url} (pid ${tunnelState.pid})\n`);
|
|
15317
15882
|
}
|
|
15318
|
-
const savedRelay =
|
|
15883
|
+
const savedRelay = relayConfig.load();
|
|
15319
15884
|
if (savedRelay) {
|
|
15320
15885
|
process.stdout.write(`Relay: ${savedRelay}\n`);
|
|
15321
15886
|
}
|
|
@@ -15364,14 +15929,14 @@ async function main() {
|
|
|
15364
15929
|
if (command === 'reset') {
|
|
15365
15930
|
const healthyDaemon = await probeHealth(1_500);
|
|
15366
15931
|
const hasExplicitConfigOverrides =
|
|
15367
|
-
!(0,
|
|
15932
|
+
!(0,_vibelet_runtime_policy_mjs__WEBPACK_IMPORTED_MODULE_11__/* .doesHealthMatchRequestedConnectionConfig */ .nW)({
|
|
15368
15933
|
health: healthyDaemon,
|
|
15369
15934
|
relayUrl,
|
|
15370
15935
|
canonicalHost: hostArg || '',
|
|
15371
15936
|
fallbackHosts: fallbackHostsArg || '',
|
|
15372
15937
|
localMode: localFlag,
|
|
15373
15938
|
}) &&
|
|
15374
|
-
(localFlag || Boolean(relayUrl) || Boolean(hostArg) || Boolean(fallbackHostsArg));
|
|
15939
|
+
(localFlag || relayArg !== null || Boolean(relayUrl) || Boolean(hostArg) || Boolean(fallbackHostsArg));
|
|
15375
15940
|
const shouldReplaceDetachedDaemon =
|
|
15376
15941
|
!healthyDaemon && !backend.handlesProcessLifecycle && backend.isServiceInstalled();
|
|
15377
15942
|
if (shouldReplaceDetachedDaemon || (healthyDaemon && hasExplicitConfigOverrides)) {
|
|
@@ -15391,20 +15956,44 @@ async function main() {
|
|
|
15391
15956
|
fail(`Unknown command: ${command}`);
|
|
15392
15957
|
}
|
|
15393
15958
|
|
|
15394
|
-
|
|
15395
|
-
|
|
15396
|
-
!(0,
|
|
15959
|
+
let healthyDaemon = await probeHealth(1_500);
|
|
15960
|
+
let hasExplicitConfigOverrides =
|
|
15961
|
+
!(0,_vibelet_runtime_policy_mjs__WEBPACK_IMPORTED_MODULE_11__/* .doesHealthMatchRequestedConnectionConfig */ .nW)({
|
|
15397
15962
|
health: healthyDaemon,
|
|
15398
15963
|
relayUrl,
|
|
15399
15964
|
canonicalHost: hostArg || '',
|
|
15400
15965
|
fallbackHosts: fallbackHostsArg || '',
|
|
15401
15966
|
localMode: localFlag,
|
|
15402
15967
|
}) &&
|
|
15403
|
-
(localFlag ||
|
|
15404
|
-
|
|
15968
|
+
(localFlag ||
|
|
15969
|
+
shouldManageTunnel ||
|
|
15970
|
+
relayArg !== null ||
|
|
15971
|
+
Boolean(relayUrl) ||
|
|
15972
|
+
Boolean(hostArg) ||
|
|
15973
|
+
Boolean(fallbackHostsArg));
|
|
15974
|
+
const relayOverrideRequested =
|
|
15975
|
+
!localFlag && !hostArg && !fallbackHostsArg && (shouldManageTunnel || relayArg !== null || Boolean(savedRelayUrl));
|
|
15976
|
+
const canApplyConnectionConfigWithoutRestart = Boolean(
|
|
15977
|
+
healthyDaemon && relayOverrideRequested && hasExplicitConfigOverrides,
|
|
15978
|
+
);
|
|
15979
|
+
if (healthyDaemon && hasExplicitConfigOverrides && canApplyConnectionConfigWithoutRestart) {
|
|
15980
|
+
const refreshedHealth = await tryUpdateRunningDaemonRelay(relayUrl);
|
|
15981
|
+
if (refreshedHealth) {
|
|
15982
|
+
healthyDaemon = refreshedHealth;
|
|
15983
|
+
hasExplicitConfigOverrides = !(0,_vibelet_runtime_policy_mjs__WEBPACK_IMPORTED_MODULE_11__/* .doesHealthMatchRequestedConnectionConfig */ .nW)({
|
|
15984
|
+
health: healthyDaemon,
|
|
15985
|
+
relayUrl,
|
|
15986
|
+
canonicalHost: '',
|
|
15987
|
+
fallbackHosts: '',
|
|
15988
|
+
localMode: false,
|
|
15989
|
+
});
|
|
15990
|
+
}
|
|
15991
|
+
}
|
|
15992
|
+
const existingHealth = (0,_vibelet_runtime_policy_mjs__WEBPACK_IMPORTED_MODULE_11__/* .shouldReuseHealthyDaemon */ .ZN)({
|
|
15405
15993
|
command,
|
|
15406
15994
|
daemonHealthy: Boolean(healthyDaemon),
|
|
15407
15995
|
hasExplicitConfigOverrides,
|
|
15996
|
+
canApplyConnectionConfigWithoutRestart,
|
|
15408
15997
|
})
|
|
15409
15998
|
? healthyDaemon
|
|
15410
15999
|
: null;
|
|
@@ -15418,7 +16007,7 @@ async function main() {
|
|
|
15418
16007
|
const runningDriver = normalizeDriver(existingHealth.claudeDriverMode);
|
|
15419
16008
|
const driverMismatch = requestedDriver !== null && runningDriver !== requestedDriver;
|
|
15420
16009
|
const needsRestart = Boolean(isOutdated) || driverMismatch;
|
|
15421
|
-
if (needsRestart && activeSessions === 0) {
|
|
16010
|
+
if (needsRestart && activeSessions === 0 && !canApplyConnectionConfigWithoutRestart) {
|
|
15422
16011
|
process.stdout.write(
|
|
15423
16012
|
isOutdated
|
|
15424
16013
|
? `Daemon is running v${runningVersion}, CLI is v${packageJson.version}. Restarting daemon to upgrade...\n`
|
|
@@ -15433,29 +16022,47 @@ async function main() {
|
|
|
15433
16022
|
return;
|
|
15434
16023
|
}
|
|
15435
16024
|
if (isOutdated) {
|
|
15436
|
-
|
|
15437
|
-
|
|
15438
|
-
|
|
15439
|
-
|
|
16025
|
+
if (canApplyConnectionConfigWithoutRestart) {
|
|
16026
|
+
process.stdout.write(
|
|
16027
|
+
`Daemon is running v${runningVersion}, CLI is v${packageJson.version}; the upgrade was deferred so this relay change cannot restart the running daemon.\n`,
|
|
16028
|
+
);
|
|
16029
|
+
process.stdout.write('Run `npx vibelet restart` later to upgrade the daemon explicitly.\n');
|
|
16030
|
+
} else {
|
|
16031
|
+
process.stdout.write(
|
|
16032
|
+
`Daemon is running v${runningVersion}, CLI is v${packageJson.version}, but ${activeSessions} active session(s) would be interrupted.\n`,
|
|
16033
|
+
);
|
|
16034
|
+
process.stdout.write('Run `npx vibelet restart` once those sessions are idle to upgrade the daemon.\n');
|
|
16035
|
+
}
|
|
15440
16036
|
} else if (driverMismatch) {
|
|
16037
|
+
if (canApplyConnectionConfigWithoutRestart) {
|
|
16038
|
+
process.stdout.write(
|
|
16039
|
+
`Daemon driver switch to "${requestedDriver}" was deferred so this relay change cannot restart the running daemon.\n`,
|
|
16040
|
+
);
|
|
16041
|
+
} else {
|
|
16042
|
+
process.stdout.write(
|
|
16043
|
+
`Daemon is using the "${runningDriver}" Claude driver; you requested "${requestedDriver}", but ${activeSessions} active session(s) would be interrupted.\n`,
|
|
16044
|
+
);
|
|
16045
|
+
}
|
|
15441
16046
|
process.stdout.write(
|
|
15442
|
-
`
|
|
15443
|
-
);
|
|
15444
|
-
process.stdout.write(
|
|
15445
|
-
`Run \`npx vibelet restart --claude-driver ${requestedDriver}\` once those sessions are idle to switch.\n`,
|
|
16047
|
+
`Run \`npx vibelet restart --claude-driver ${requestedDriver}\` later to switch explicitly.\n`,
|
|
15446
16048
|
);
|
|
15447
16049
|
} else {
|
|
15448
16050
|
process.stdout.write('Vibelet daemon is already running.\n');
|
|
15449
16051
|
process.stdout.write('Reusing the current runtime so active sessions stay alive.\n');
|
|
15450
16052
|
process.stdout.write('Run `npx vibelet restart` to force a full restart.\n\n');
|
|
15451
16053
|
}
|
|
15452
|
-
await printPairingSummary(existingHealth
|
|
16054
|
+
await printPairingSummary(existingHealth, {
|
|
16055
|
+
relayUrlOverride: relayOverrideRequested ? relayUrl : null,
|
|
16056
|
+
});
|
|
15453
16057
|
return;
|
|
15454
16058
|
}
|
|
15455
16059
|
|
|
15456
16060
|
const shouldReplaceDetachedDaemon =
|
|
15457
16061
|
!healthyDaemon && !backend.handlesProcessLifecycle && backend.isServiceInstalled();
|
|
15458
|
-
if (
|
|
16062
|
+
if (
|
|
16063
|
+
shouldReplaceDetachedDaemon ||
|
|
16064
|
+
(healthyDaemon && hasExplicitConfigOverrides && !canApplyConnectionConfigWithoutRestart)
|
|
16065
|
+
) {
|
|
15459
16066
|
await stopRunningDaemon(backend);
|
|
15460
16067
|
}
|
|
15461
16068
|
|