mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-18 12:41:12 +00:00
fix: clarify dirty dev update error
This commit is contained in:
@@ -120,6 +120,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Discord/image generation: include the real generated `MEDIA:` paths in tool output and avoid duplicate plain-output media requeueing so Discord image replies stop pointing at missing local files.
|
||||
- Slack: route live DM replies back to the concrete inbound DM channel while keeping persisted routing metadata user-scoped, so normal assistant replies stop disappearing when pairing and system messages still arrive. (#59030) Thanks @afurm.
|
||||
- Discord/reply tags: strip leaked `[[reply_to_current]]` control tags from preview text and honor explicit reply-tag threading during final delivery, so Discord replies stay attached to the triggering message instead of printing reply metadata into chat.
|
||||
- CLI/update: block `openclaw update --channel dev` with a clearer explainer when the git checkout has edited local files, instead of failing later once commit-switching work starts.
|
||||
- Telegram: fix current-model checks in the model picker, HTML-format non-default `/model` confirmations, explicit topic replies, persisted reaction ownership across restarts, caption-media placeholder and `file_id` preservation on download failure, and upgraded-install inbound image reads. (#60384, #60042, #59634, #59207, #59948, #59971) Thanks @sfuminya, @GitZhangChi, @dashhuang, @samzong, @v1p0r, and @neeravmakwana.
|
||||
- Telegram: restore DM voice-note preflight transcription so direct-message audio stops arriving as raw `<media:audio>` placeholders. (#61008) Thanks @manueltarouca.
|
||||
- Telegram/reasoning: only create a Telegram reasoning preview lane when the session is explicitly `reasoning:stream`, so hidden `<think>` traces from streamed replies stop surfacing as chat previews on normal sessions. Thanks @vincentkoc.
|
||||
|
||||
@@ -127,13 +127,17 @@ vi.mock("../process/exec.js", () => ({
|
||||
runCommandWithTimeout: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../utils.js", () => ({
|
||||
displayString: (input: string) => input,
|
||||
isRecord: (value: unknown) =>
|
||||
typeof value === "object" && value !== null && !Array.isArray(value),
|
||||
pathExists: (...args: unknown[]) => pathExists(...args),
|
||||
resolveConfigDir: () => "/tmp/openclaw-config",
|
||||
}));
|
||||
vi.mock("../utils.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../utils.js")>();
|
||||
return {
|
||||
...actual,
|
||||
displayString: (input: string) => input,
|
||||
isRecord: (value: unknown) =>
|
||||
typeof value === "object" && value !== null && !Array.isArray(value),
|
||||
pathExists: (...args: unknown[]) => pathExists(...args),
|
||||
resolveConfigDir: () => "/tmp/openclaw-config",
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../plugins/update.js", () => ({
|
||||
syncPluginsForUpdateChannel: (...args: unknown[]) => syncPluginsForUpdateChannel(...args),
|
||||
@@ -1034,7 +1038,31 @@ describe("update-cli", () => {
|
||||
"Skipped plugin update sync in the pre-update CLI process after switching to a git install.",
|
||||
);
|
||||
});
|
||||
it("explains why git updates cannot run with edited files", async () => {
|
||||
vi.mocked(defaultRuntime.log).mockClear();
|
||||
vi.mocked(defaultRuntime.error).mockClear();
|
||||
vi.mocked(defaultRuntime.exit).mockClear();
|
||||
vi.mocked(runGatewayUpdate).mockResolvedValue({
|
||||
status: "skipped",
|
||||
mode: "git",
|
||||
reason: "dirty",
|
||||
steps: [],
|
||||
durationMs: 100,
|
||||
} satisfies UpdateRunResult);
|
||||
|
||||
await updateCommand({ channel: "dev" });
|
||||
|
||||
const errors = vi.mocked(defaultRuntime.error).mock.calls.map((call) => String(call[0]));
|
||||
const logs = vi.mocked(defaultRuntime.log).mock.calls.map((call) => String(call[0]));
|
||||
expect(errors.join("\n")).toContain("Update blocked: local files are edited in this checkout.");
|
||||
expect(logs.join("\n")).toContain(
|
||||
"Git-based updates need a clean working tree before they can switch commits, fetch, or rebase.",
|
||||
);
|
||||
expect(logs.join("\n")).toContain(
|
||||
"Commit, stash, or discard the local changes, then rerun `openclaw update`.",
|
||||
);
|
||||
expect(defaultRuntime.exit).toHaveBeenCalledWith(0);
|
||||
});
|
||||
it.each([
|
||||
{
|
||||
name: "refreshes service env when already installed",
|
||||
|
||||
@@ -1012,11 +1012,15 @@ export async function updateCommand(opts: UpdateCommandOptions): Promise<void> {
|
||||
|
||||
if (result.status === "skipped") {
|
||||
if (result.reason === "dirty") {
|
||||
defaultRuntime.error(theme.error("Update blocked: local files are edited in this checkout."));
|
||||
defaultRuntime.log(
|
||||
theme.warn(
|
||||
"Skipped: working directory has uncommitted changes. Commit or stash them first.",
|
||||
"Git-based updates need a clean working tree before they can switch commits, fetch, or rebase.",
|
||||
),
|
||||
);
|
||||
defaultRuntime.log(
|
||||
theme.muted("Commit, stash, or discard the local changes, then rerun `openclaw update`."),
|
||||
);
|
||||
}
|
||||
if (result.reason === "not-git-install") {
|
||||
defaultRuntime.log(
|
||||
|
||||
Reference in New Issue
Block a user