Files
clawdbot/src/commands/doctor-update.ts
2026-01-20 07:43:00 +00:00

83 lines
2.8 KiB
TypeScript

import { runGatewayUpdate } from "../infra/update-runner.js";
import { isTruthyEnvValue } from "../infra/env.js";
import { runCommandWithTimeout } from "../process/exec.js";
import type { RuntimeEnv } from "../runtime.js";
import { note } from "../terminal/note.js";
import { formatCliCommand } from "../cli/command-format.js";
import type { DoctorOptions } from "./doctor-prompter.js";
async function detectClawdbotGitCheckout(root: string): Promise<"git" | "not-git" | "unknown"> {
const res = await runCommandWithTimeout(["git", "-C", root, "rev-parse", "--show-toplevel"], {
timeoutMs: 5000,
}).catch(() => null);
if (!res) return "unknown";
if (res.code !== 0) {
// Avoid noisy "Update via package manager" notes when git is missing/broken,
// but do show it when this is clearly not a git checkout.
if (res.stderr.toLowerCase().includes("not a git repository")) {
return "not-git";
}
return "unknown";
}
return res.stdout.trim() === root ? "git" : "not-git";
}
export async function maybeOfferUpdateBeforeDoctor(params: {
runtime: RuntimeEnv;
options: DoctorOptions;
root: string | null;
confirm: (p: { message: string; initialValue: boolean }) => Promise<boolean>;
outro: (message: string) => void;
}) {
const updateInProgress = isTruthyEnvValue(process.env.CLAWDBOT_UPDATE_IN_PROGRESS);
const canOfferUpdate =
!updateInProgress &&
params.options.nonInteractive !== true &&
params.options.yes !== true &&
params.options.repair !== true &&
Boolean(process.stdin.isTTY);
if (!canOfferUpdate || !params.root) return { updated: false };
const git = await detectClawdbotGitCheckout(params.root);
if (git === "git") {
const shouldUpdate = await params.confirm({
message: "Update Clawdbot from git before running doctor?",
initialValue: true,
});
if (!shouldUpdate) return { updated: false };
note("Running update (fetch/rebase/build/ui:build/doctor)…", "Update");
const result = await runGatewayUpdate({
cwd: params.root,
argv1: process.argv[1],
});
note(
[
`Status: ${result.status}`,
`Mode: ${result.mode}`,
result.root ? `Root: ${result.root}` : null,
result.reason ? `Reason: ${result.reason}` : null,
]
.filter(Boolean)
.join("\n"),
"Update result",
);
if (result.status === "ok") {
params.outro("Update completed (doctor already ran as part of the update).");
return { updated: true, handled: true };
}
return { updated: true, handled: false };
}
if (git === "not-git") {
note(
[
"This install is not a git checkout.",
`Run \`${formatCliCommand("clawdbot update")}\` to update via your package manager (npm/pnpm), then rerun doctor.`,
].join("\n"),
"Update",
);
}
return { updated: false };
}