fix(coding-agent): repair self-update detection
Fixes #3942 Fixes #3980 Fixes #3922
This commit is contained in:
@@ -12,7 +12,9 @@ describe("package commands", () => {
|
||||
let packageDir: string;
|
||||
let originalCwd: string;
|
||||
let originalAgentDir: string | undefined;
|
||||
let originalPiPackageDir: string | undefined;
|
||||
let originalExitCode: typeof process.exitCode;
|
||||
let originalExecPath: string;
|
||||
|
||||
beforeEach(() => {
|
||||
tempDir = join(tmpdir(), `pi-package-commands-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
||||
@@ -25,7 +27,9 @@ describe("package commands", () => {
|
||||
|
||||
originalCwd = process.cwd();
|
||||
originalAgentDir = process.env[ENV_AGENT_DIR];
|
||||
originalPiPackageDir = process.env.PI_PACKAGE_DIR;
|
||||
originalExitCode = process.exitCode;
|
||||
originalExecPath = process.execPath;
|
||||
process.exitCode = undefined;
|
||||
process.env[ENV_AGENT_DIR] = agentDir;
|
||||
process.chdir(projectDir);
|
||||
@@ -39,6 +43,12 @@ describe("package commands", () => {
|
||||
} else {
|
||||
process.env[ENV_AGENT_DIR] = originalAgentDir;
|
||||
}
|
||||
if (originalPiPackageDir === undefined) {
|
||||
delete process.env.PI_PACKAGE_DIR;
|
||||
} else {
|
||||
process.env.PI_PACKAGE_DIR = originalPiPackageDir;
|
||||
}
|
||||
Object.defineProperty(process, "execPath", { value: originalExecPath, configurable: true });
|
||||
rmSync(tempDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
@@ -118,6 +128,52 @@ describe("package commands", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("uses global npmCommand for self updates", async () => {
|
||||
const globalPrefix = join(tempDir, "global-prefix");
|
||||
const projectPrefix = join(tempDir, "project-prefix");
|
||||
const selfPackageDir = join(globalPrefix, "lib", "node_modules", "@mariozechner", "pi-coding-agent");
|
||||
const fakeNpmPath = join(tempDir, "fake-npm.cjs");
|
||||
const recordPath = join(tempDir, "self-update.json");
|
||||
mkdirSync(selfPackageDir, { recursive: true });
|
||||
mkdirSync(join(projectDir, ".pi"), { recursive: true });
|
||||
writeFileSync(
|
||||
fakeNpmPath,
|
||||
`const fs=require("node:fs"),path=require("node:path"),args=process.argv.slice(2),prefix=args[args.indexOf("--prefix")+1];
|
||||
if(args.includes("root")) console.log(path.join(prefix,"lib","node_modules"));
|
||||
else fs.writeFileSync(${JSON.stringify(recordPath)},JSON.stringify(args));
|
||||
`,
|
||||
);
|
||||
writeFileSync(
|
||||
join(agentDir, "settings.json"),
|
||||
JSON.stringify({ npmCommand: [originalExecPath, fakeNpmPath, "--prefix", globalPrefix] }, null, 2),
|
||||
);
|
||||
writeFileSync(
|
||||
join(projectDir, ".pi", "settings.json"),
|
||||
JSON.stringify({ npmCommand: [originalExecPath, fakeNpmPath, "--prefix", projectPrefix] }, null, 2),
|
||||
);
|
||||
process.env.PI_PACKAGE_DIR = selfPackageDir;
|
||||
Object.defineProperty(process, "execPath", {
|
||||
value: join(selfPackageDir, "dist", "cli.js"),
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
const logSpy = vi.spyOn(console, "log").mockImplementation(() => {});
|
||||
const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
|
||||
|
||||
try {
|
||||
await expect(main(["update", "--self", "--force"])).resolves.toBeUndefined();
|
||||
|
||||
expect(process.exitCode).toBeUndefined();
|
||||
expect(errorSpy).not.toHaveBeenCalled();
|
||||
const recordedArgs = JSON.parse(readFileSync(recordPath, "utf-8")) as string[];
|
||||
expect(recordedArgs).toContain(globalPrefix);
|
||||
expect(recordedArgs).not.toContain(projectPrefix);
|
||||
} finally {
|
||||
logSpy.mockRestore();
|
||||
errorSpy.mockRestore();
|
||||
}
|
||||
});
|
||||
|
||||
it("suggests the configured source when update input omits the npm prefix", async () => {
|
||||
const settingsPath = join(agentDir, "settings.json");
|
||||
writeFileSync(settingsPath, JSON.stringify({ packages: ["npm:pi-formatter"] }, null, 2));
|
||||
|
||||
Reference in New Issue
Block a user