Merge pull request #982 from wes-davis/fix/gateway-connection-diagnostics
macOS: keep gateway connected (stop port flapping)
This commit is contained in:
@@ -87,6 +87,14 @@ final class GatewayProcessManager {
|
|||||||
self.status = .stopped
|
self.status = .stopped
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// Many surfaces can call `setActive(true)` in quick succession (startup, Canvas, health checks).
|
||||||
|
// Avoid spawning multiple concurrent "start" tasks that can thrash launchd and flap the port.
|
||||||
|
switch self.status {
|
||||||
|
case .starting, .running, .attachedExisting:
|
||||||
|
return
|
||||||
|
case .stopped, .failed:
|
||||||
|
break
|
||||||
|
}
|
||||||
self.status = .starting
|
self.status = .starting
|
||||||
self.logger.debug("gateway start requested")
|
self.logger.debug("gateway start requested")
|
||||||
|
|
||||||
|
|||||||
@@ -351,10 +351,11 @@ actor PortGuardian {
|
|||||||
if port == GatewayEnvironment.gatewayPort() { return cmd.contains("ssh") }
|
if port == GatewayEnvironment.gatewayPort() { return cmd.contains("ssh") }
|
||||||
return false
|
return false
|
||||||
case .local:
|
case .local:
|
||||||
if !cmd.contains("clawdbot") { return false }
|
// The gateway daemon may listen as `clawdbot` or as its runtime (`node`, `bun`, etc).
|
||||||
if full.contains("gateway-daemon") { return true }
|
if full.contains("gateway-daemon") { return true }
|
||||||
// If args are unavailable, treat a clawdbot listener as expected.
|
// If args are unavailable, treat a clawdbot listener as expected.
|
||||||
return full == cmd
|
if cmd.contains("clawdbot"), full == cmd { return true }
|
||||||
|
return false
|
||||||
case .unconfigured:
|
case .unconfigured:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -206,6 +206,31 @@ if [[ "$NO_SIGN" -ne 1 && -f "${LAUNCHAGENT_DISABLE_MARKER}" ]]; then
|
|||||||
run_step "clear launchagent disable marker" /bin/rm -f "${LAUNCHAGENT_DISABLE_MARKER}"
|
run_step "clear launchagent disable marker" /bin/rm -f "${LAUNCHAGENT_DISABLE_MARKER}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# When unsigned, ensure the gateway LaunchAgent targets the repo CLI (before the app launches).
|
||||||
|
# This reduces noisy "could not connect" errors during app startup.
|
||||||
|
if [ "$NO_SIGN" -eq 1 ]; then
|
||||||
|
run_step "install gateway launch agent (unsigned)" bash -lc "cd '${ROOT_DIR}' && node dist/entry.js daemon install --force --runtime node"
|
||||||
|
run_step "restart gateway daemon (unsigned)" bash -lc "cd '${ROOT_DIR}' && node dist/entry.js daemon restart"
|
||||||
|
if [[ "${GATEWAY_WAIT_SECONDS}" -gt 0 ]]; then
|
||||||
|
run_step "wait for gateway (unsigned)" sleep "${GATEWAY_WAIT_SECONDS}"
|
||||||
|
fi
|
||||||
|
GATEWAY_PORT="$(
|
||||||
|
node -e '
|
||||||
|
const fs = require("node:fs");
|
||||||
|
const path = require("node:path");
|
||||||
|
try {
|
||||||
|
const raw = fs.readFileSync(path.join(process.env.HOME, ".clawdbot", "clawdbot.json"), "utf8");
|
||||||
|
const cfg = JSON.parse(raw);
|
||||||
|
const port = cfg && cfg.gateway && typeof cfg.gateway.port === "number" ? cfg.gateway.port : 18789;
|
||||||
|
process.stdout.write(String(port));
|
||||||
|
} catch {
|
||||||
|
process.stdout.write("18789");
|
||||||
|
}
|
||||||
|
'
|
||||||
|
)"
|
||||||
|
run_step "verify gateway port ${GATEWAY_PORT} (unsigned)" bash -lc "lsof -iTCP:${GATEWAY_PORT} -sTCP:LISTEN | head -n 5 || true"
|
||||||
|
fi
|
||||||
|
|
||||||
# 4) Launch the installed app in the foreground so the menu bar extra appears.
|
# 4) Launch the installed app in the foreground so the menu bar extra appears.
|
||||||
# LaunchServices can inherit a huge environment from this shell (secrets, prompt vars, etc.).
|
# LaunchServices can inherit a huge environment from this shell (secrets, prompt vars, etc.).
|
||||||
# That can cause launchd spawn failures and is undesirable for a GUI app anyway.
|
# That can cause launchd spawn failures and is undesirable for a GUI app anyway.
|
||||||
@@ -226,13 +251,6 @@ else
|
|||||||
fail "App exited immediately. Check ${LOG_PATH} or Console.app (User Reports)."
|
fail "App exited immediately. Check ${LOG_PATH} or Console.app (User Reports)."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# When unsigned, ensure the gateway LaunchAgent targets the repo CLI (after the app launches).
|
|
||||||
if [ "$NO_SIGN" -eq 1 ]; then
|
if [ "$NO_SIGN" -eq 1 ]; then
|
||||||
run_step "install gateway launch agent (unsigned)" bash -lc "cd '${ROOT_DIR}' && node dist/entry.js daemon install --force --runtime node"
|
|
||||||
run_step "restart gateway daemon (unsigned)" bash -lc "cd '${ROOT_DIR}' && node dist/entry.js daemon restart"
|
|
||||||
if [[ "${GATEWAY_WAIT_SECONDS}" -gt 0 ]]; then
|
|
||||||
run_step "wait for gateway (unsigned)" sleep "${GATEWAY_WAIT_SECONDS}"
|
|
||||||
fi
|
|
||||||
run_step "verify gateway port 18789 (unsigned)" bash -lc "lsof -iTCP:18789 -sTCP:LISTEN | head -n 5 || true"
|
|
||||||
run_step "show gateway launch agent args (unsigned)" bash -lc "/usr/bin/plutil -p '${HOME}/Library/LaunchAgents/com.clawdbot.gateway.plist' | head -n 40 || true"
|
run_step "show gateway launch agent args (unsigned)" bash -lc "/usr/bin/plutil -p '${HOME}/Library/LaunchAgents/com.clawdbot.gateway.plist' | head -n 40 || true"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -119,10 +119,11 @@ export async function statusAllCommand(
|
|||||||
|
|
||||||
const localFallbackAuth = resolveProbeAuth("local");
|
const localFallbackAuth = resolveProbeAuth("local");
|
||||||
const remoteAuth = resolveProbeAuth("remote");
|
const remoteAuth = resolveProbeAuth("remote");
|
||||||
|
const probeAuth = isRemoteMode && !remoteUrlMissing ? remoteAuth : localFallbackAuth;
|
||||||
|
|
||||||
const gatewayProbe = await probeGateway({
|
const gatewayProbe = await probeGateway({
|
||||||
url: connection.url,
|
url: connection.url,
|
||||||
auth: remoteUrlMissing ? localFallbackAuth : remoteAuth,
|
auth: probeAuth,
|
||||||
timeoutMs: Math.min(5000, opts?.timeoutMs ?? 10_000),
|
timeoutMs: Math.min(5000, opts?.timeoutMs ?? 10_000),
|
||||||
}).catch(() => null);
|
}).catch(() => null);
|
||||||
const gatewayReachable = gatewayProbe?.ok === true;
|
const gatewayReachable = gatewayProbe?.ok === true;
|
||||||
@@ -291,7 +292,7 @@ export async function statusAllCommand(
|
|||||||
? `unreachable (${gatewayProbe.error})`
|
? `unreachable (${gatewayProbe.error})`
|
||||||
: "unreachable";
|
: "unreachable";
|
||||||
const gatewayAuth = gatewayReachable
|
const gatewayAuth = gatewayReachable
|
||||||
? ` · auth ${formatGatewayAuthUsed(remoteUrlMissing ? localFallbackAuth : remoteAuth)}`
|
? ` · auth ${formatGatewayAuthUsed(probeAuth)}`
|
||||||
: "";
|
: "";
|
||||||
const gatewaySelfLine =
|
const gatewaySelfLine =
|
||||||
gatewaySelf?.host || gatewaySelf?.ip || gatewaySelf?.version || gatewaySelf?.platform
|
gatewaySelf?.host || gatewaySelf?.ip || gatewaySelf?.version || gatewaySelf?.platform
|
||||||
|
|||||||
Reference in New Issue
Block a user