fix(cli): report web readiness probe failures (#169)

Co-authored-by: Yaowei Zheng <hiyouga@buaa.edu.cn>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Laodouuu
2026-08-04 12:34:27 +08:00
committed by GitHub
parent 4d5d55d15a
commit e05dea536b
3 changed files with 244 additions and 15 deletions
+33 -4
View File
@@ -9,6 +9,10 @@
/** UI language. */
export type Language = "en" | "zh";
/** Readiness probe failure classes; selects which hint `webProbeFailed` appends. */
export type WebProbeFailureKind =
"timeout" | "refused" | "reset" | "permission" | "dns" | "unknown";
/** Resolve the language from the env var; `zh` matches exactly, everything else falls back to English (see comment #2). */
export function resolveLanguage(): Language {
const v = (process.env.PENGUIN_LANG ?? "").trim().toLowerCase();
@@ -219,8 +223,8 @@ export interface Messages {
vaultListEmpty(): string;
/** URL prompt once the `penguin web` service is ready. */
webReady(url: string): string;
/** Manual-open prompt after the `penguin web` ready-poll times out (15s). */
webTimeout(url: string): string;
/** Diagnostic shown after the `penguin web` ready-poll times out (15s). */
webProbeFailed(url: string, detail: string, kind: WebProbeFailureKind, port: number): string;
}
function headerEn(
@@ -451,7 +455,22 @@ const en: Messages = {
vaultListTitle: () => "Vault environment variables (values masked):",
vaultListEmpty: () => "The vault is empty. Add one with `penguin config vault set`.",
webReady: (url) => `Web UI ready: ${url}`,
webTimeout: (url) => `Server is not responding yet; open ${url} manually once it is ready.`,
webProbeFailed: (url, detail, kind, port) => {
const hint = {
timeout:
`The connection timed out. Check whether a firewall or security application is blocking it. ` +
`Allow PenguinHarness to communicate on local port ${port}.`,
refused:
"Nothing accepted the connection. Check whether the server exited or HOST/PORT points somewhere else.",
reset:
"The connection closed before an HTTP response. Check local security software and retry.",
permission:
"The operating system denied the connection. Check firewall or security policy permissions.",
dns: "The host name could not be resolved. Check --host or HOST.",
unknown: `Open ${url} manually after the server is ready.`,
}[kind];
return `Server readiness check failed for ${url}.\nLast probe error: ${detail}\n${hint}`;
},
};
const zh: Messages = {
@@ -645,7 +664,17 @@ const zh: Messages = {
vaultListTitle: () => "vault 环境变量(值已掩码):",
vaultListEmpty: () => "vault 为空。用 `penguin config vault set` 添加。",
webReady: (url) => `Web 界面已就绪:${url}`,
webTimeout: (url) => `服务尚未就绪,请稍后手动打开 ${url}。`,
webProbeFailed: (url, detail, kind, port) => {
const hint = {
timeout: `连接超时。请检查防火墙或安全软件是否拦截。请允许 PenguinHarness 在本机端口 ${port} 上通信。`,
refused: "没有进程接受连接。请检查服务是否已经退出,或 HOST/PORT 是否指向了其他地址。",
reset: "连接在收到 HTTP 响应前已关闭。请检查本机安全软件后重试。",
permission: "操作系统拒绝了连接。请检查防火墙或安全策略权限。",
dns: "无法解析主机名。请检查 --host 或 HOST。",
unknown: `请在服务就绪后手动打开 ${url}。`,
}[kind];
return `服务探活失败:${url}\n最后一次探测错误:${detail}\n${hint}`;
},
};
/** Get the message set for a language. */