fix(cli): preserve installs when service state is unknown

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-07-27 15:32:13 +00:00
1 parent 06e8d2f387
commit e64d383b6f
2 files changed
+49 -2

No files matched your search

+27
View File
@@ -107,6 +107,33 @@ describe("managed install commands", () => {
expect(fs.readFileSync(userData, "utf8")).toBe("keep");
});
it("preserves the managed install when an existing systemd unit cannot be checked", async () => {
const paths = resolveInstallStorePaths();
fs.mkdirSync(path.dirname(paths.shimPath), { recursive: true });
fs.writeFileSync(paths.shimPath, "managed shim");
const unitPath = path.join(
process.env.HOME!,
".config",
"systemd",
"user",
"paperclipai.service",
);
fs.mkdirSync(path.dirname(unitPath), { recursive: true });
fs.writeFileSync(unitPath, "unit");
await expect(uninstallCommand({
detectServiceManager: vi.fn(async () => ({
supported: false as const,
reason: "No usable systemd user manager was detected",
})),
platform: "linux",
userHomeDir: process.env.HOME!,
})).rejects.toThrow("Cannot verify or remove the background service");
expect(fs.existsSync(paths.shimPath)).toBe(true);
expect(fs.existsSync(unitPath)).toBe(true);
});
it("rejects a symlinked installs root before npm writes outside the store", async () => {
const paths = resolveInstallStorePaths();
const outside = path.join(root, "outside");
+22 -2
View File
@@ -1,4 +1,5 @@
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import pc from "picocolors";
import {
@@ -9,17 +10,36 @@ import {
withInstallStoreLock,
} from "../install-store.js";
import { resolvePaperclipInstanceId } from "../config/home.js";
import { detectServiceManager } from "../services/service-manager.js";
import { detectServiceManager, systemdServiceName } from "../services/service-manager.js";
type UninstallDependencies = {
detectServiceManager: typeof detectServiceManager;
platform: NodeJS.Platform;
userHomeDir: string;
};
export async function uninstallCommand(
dependencies: Partial<UninstallDependencies> = {},
): Promise<void> {
const instanceId = resolvePaperclipInstanceId();
const detect = dependencies.detectServiceManager ?? detectServiceManager;
const detection = await detect({ instanceId: resolvePaperclipInstanceId() });
const platform = dependencies.platform ?? process.platform;
const userHomeDir = dependencies.userHomeDir ?? os.homedir();
const detection = await detect({ instanceId, platform });
if (!detection.supported && platform === "linux") {
const definitionPath = path.join(
userHomeDir,
".config",
"systemd",
"user",
systemdServiceName(instanceId),
);
if (fs.existsSync(definitionPath)) {
throw new Error(
`Cannot verify or remove the background service: ${detection.reason}. Retry when the service manager is available.`,
);
}
}
if (detection.supported) {
const status = await detection.manager.status();
if (status.installed || status.active) await detection.manager.uninstall();