feat(cli): hint gateway reachability for local/remote
This commit is contained in:
@@ -37,6 +37,7 @@ import {
|
|||||||
guardCancel,
|
guardCancel,
|
||||||
openUrl,
|
openUrl,
|
||||||
printWizardHeader,
|
printWizardHeader,
|
||||||
|
probeGatewayReachable,
|
||||||
randomToken,
|
randomToken,
|
||||||
summarizeExistingConfig,
|
summarizeExistingConfig,
|
||||||
} from "./onboard-helpers.js";
|
} from "./onboard-helpers.js";
|
||||||
@@ -384,12 +385,42 @@ export async function runConfigureWizard(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const localUrl = "ws://127.0.0.1:18789";
|
||||||
|
const localProbe = await probeGatewayReachable({
|
||||||
|
url: localUrl,
|
||||||
|
token: process.env.CLAWDIS_GATEWAY_TOKEN,
|
||||||
|
password:
|
||||||
|
baseConfig.gateway?.auth?.password ??
|
||||||
|
process.env.CLAWDIS_GATEWAY_PASSWORD,
|
||||||
|
});
|
||||||
|
const remoteUrl = baseConfig.gateway?.remote?.url?.trim() ?? "";
|
||||||
|
const remoteProbe = remoteUrl
|
||||||
|
? await probeGatewayReachable({
|
||||||
|
url: remoteUrl,
|
||||||
|
token: baseConfig.gateway?.remote?.token,
|
||||||
|
})
|
||||||
|
: null;
|
||||||
|
|
||||||
const mode = guardCancel(
|
const mode = guardCancel(
|
||||||
await select({
|
await select({
|
||||||
message: "Where will the Gateway run?",
|
message: "Where will the Gateway run?",
|
||||||
options: [
|
options: [
|
||||||
{ value: "local", label: "Local (this machine)" },
|
{
|
||||||
{ value: "remote", label: "Remote (info-only)" },
|
value: "local",
|
||||||
|
label: "Local (this machine)",
|
||||||
|
hint: localProbe.ok
|
||||||
|
? `Gateway reachable (${localUrl})`
|
||||||
|
: `No gateway detected (${localUrl})`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "remote",
|
||||||
|
label: "Remote (info-only)",
|
||||||
|
hint: !remoteUrl
|
||||||
|
? "No remote URL configured yet"
|
||||||
|
: remoteProbe?.ok
|
||||||
|
? `Gateway reachable (${remoteUrl})`
|
||||||
|
: `Configured but unreachable (${remoteUrl})`,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
runtime,
|
runtime,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
import type { ClawdisConfig } from "../config/config.js";
|
import type { ClawdisConfig } from "../config/config.js";
|
||||||
import { CONFIG_PATH_CLAWDIS } from "../config/config.js";
|
import { CONFIG_PATH_CLAWDIS } from "../config/config.js";
|
||||||
import { resolveSessionTranscriptsDir } from "../config/sessions.js";
|
import { resolveSessionTranscriptsDir } from "../config/sessions.js";
|
||||||
|
import { callGateway } from "../gateway/call.js";
|
||||||
import { runCommandWithTimeout } from "../process/exec.js";
|
import { runCommandWithTimeout } from "../process/exec.js";
|
||||||
import type { RuntimeEnv } from "../runtime.js";
|
import type { RuntimeEnv } from "../runtime.js";
|
||||||
import { CONFIG_DIR, resolveUserPath } from "../utils.js";
|
import { CONFIG_DIR, resolveUserPath } from "../utils.js";
|
||||||
@@ -171,4 +172,36 @@ export async function detectBinary(name: string): Promise<boolean> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function probeGatewayReachable(params: {
|
||||||
|
url: string;
|
||||||
|
token?: string;
|
||||||
|
password?: string;
|
||||||
|
timeoutMs?: number;
|
||||||
|
}): Promise<{ ok: boolean; detail?: string }> {
|
||||||
|
const url = params.url.trim();
|
||||||
|
const timeoutMs = params.timeoutMs ?? 1500;
|
||||||
|
try {
|
||||||
|
await callGateway({
|
||||||
|
url,
|
||||||
|
token: params.token,
|
||||||
|
password: params.password,
|
||||||
|
method: "health",
|
||||||
|
timeoutMs,
|
||||||
|
});
|
||||||
|
return { ok: true };
|
||||||
|
} catch (err) {
|
||||||
|
return { ok: false, detail: summarizeError(err) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function summarizeError(err: unknown): string {
|
||||||
|
const raw = String(err ?? "unknown error");
|
||||||
|
const line =
|
||||||
|
raw
|
||||||
|
.split("\n")
|
||||||
|
.map((s) => s.trim())
|
||||||
|
.find(Boolean) ?? raw;
|
||||||
|
return line.length > 120 ? `${line.slice(0, 119)}…` : line;
|
||||||
|
}
|
||||||
|
|
||||||
export const DEFAULT_WORKSPACE = DEFAULT_AGENT_WORKSPACE_DIR;
|
export const DEFAULT_WORKSPACE = DEFAULT_AGENT_WORKSPACE_DIR;
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import {
|
|||||||
handleReset,
|
handleReset,
|
||||||
openUrl,
|
openUrl,
|
||||||
printWizardHeader,
|
printWizardHeader,
|
||||||
|
probeGatewayReachable,
|
||||||
randomToken,
|
randomToken,
|
||||||
summarizeExistingConfig,
|
summarizeExistingConfig,
|
||||||
} from "./onboard-helpers.js";
|
} from "./onboard-helpers.js";
|
||||||
@@ -113,14 +114,44 @@ export async function runInteractiveOnboarding(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const localUrl = "ws://127.0.0.1:18789";
|
||||||
|
const localProbe = await probeGatewayReachable({
|
||||||
|
url: localUrl,
|
||||||
|
token: process.env.CLAWDIS_GATEWAY_TOKEN,
|
||||||
|
password:
|
||||||
|
baseConfig.gateway?.auth?.password ??
|
||||||
|
process.env.CLAWDIS_GATEWAY_PASSWORD,
|
||||||
|
});
|
||||||
|
const remoteUrl = baseConfig.gateway?.remote?.url?.trim() ?? "";
|
||||||
|
const remoteProbe = remoteUrl
|
||||||
|
? await probeGatewayReachable({
|
||||||
|
url: remoteUrl,
|
||||||
|
token: baseConfig.gateway?.remote?.token,
|
||||||
|
})
|
||||||
|
: null;
|
||||||
|
|
||||||
const mode =
|
const mode =
|
||||||
opts.mode ??
|
opts.mode ??
|
||||||
(guardCancel(
|
(guardCancel(
|
||||||
await select({
|
await select({
|
||||||
message: "Where will the Gateway run?",
|
message: "Where will the Gateway run?",
|
||||||
options: [
|
options: [
|
||||||
{ value: "local", label: "Local (this machine)" },
|
{
|
||||||
{ value: "remote", label: "Remote (info-only)" },
|
value: "local",
|
||||||
|
label: "Local (this machine)",
|
||||||
|
hint: localProbe.ok
|
||||||
|
? `Gateway reachable (${localUrl})`
|
||||||
|
: `No gateway detected (${localUrl})`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "remote",
|
||||||
|
label: "Remote (info-only)",
|
||||||
|
hint: !remoteUrl
|
||||||
|
? "No remote URL configured yet"
|
||||||
|
: remoteProbe?.ok
|
||||||
|
? `Gateway reachable (${remoteUrl})`
|
||||||
|
: `Configured but unreachable (${remoteUrl})`,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
runtime,
|
runtime,
|
||||||
|
|||||||
Reference in New Issue
Block a user