fix(FN-1952): merge pi package settings
This commit is contained in:
45
packages/cli/src/commands/auth-paths.test.ts
Normal file
45
packages/cli/src/commands/auth-paths.test.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { getFusionAgentDir, getLegacyAgentDir, getPackageManagerAgentDir } from "./auth-paths.js";
|
||||
|
||||
function writeJson(path: string, value: Record<string, unknown>): void {
|
||||
writeFileSync(path, JSON.stringify(value, null, 2));
|
||||
}
|
||||
|
||||
describe("getPackageManagerAgentDir", () => {
|
||||
it("falls back to legacy Pi settings when Fusion settings only contain Fusion metadata", () => {
|
||||
const home = mkdtempSync(join(tmpdir(), "fusion-agent-dir-"));
|
||||
const fusionAgentDir = getFusionAgentDir(home);
|
||||
const legacyAgentDir = getLegacyAgentDir(home);
|
||||
|
||||
mkdirSync(fusionAgentDir, { recursive: true });
|
||||
mkdirSync(legacyAgentDir, { recursive: true });
|
||||
writeJson(join(fusionAgentDir, "settings.json"), {
|
||||
fusionDisabledExtensions: ["/Users/example/.pi/agent/extensions/browse.ts"],
|
||||
});
|
||||
writeJson(join(legacyAgentDir, "settings.json"), {
|
||||
packages: ["npm:pi-claude-cli"],
|
||||
});
|
||||
|
||||
expect(getPackageManagerAgentDir(home)).toBe(legacyAgentDir);
|
||||
});
|
||||
|
||||
it("prefers Fusion settings when they contain package-manager settings", () => {
|
||||
const home = mkdtempSync(join(tmpdir(), "fusion-agent-dir-"));
|
||||
const fusionAgentDir = getFusionAgentDir(home);
|
||||
const legacyAgentDir = getLegacyAgentDir(home);
|
||||
|
||||
mkdirSync(fusionAgentDir, { recursive: true });
|
||||
mkdirSync(legacyAgentDir, { recursive: true });
|
||||
writeJson(join(fusionAgentDir, "settings.json"), {
|
||||
packages: ["npm:pi-claude-cli"],
|
||||
});
|
||||
writeJson(join(legacyAgentDir, "settings.json"), {
|
||||
packages: ["npm:legacy-only"],
|
||||
});
|
||||
|
||||
expect(getPackageManagerAgentDir(home)).toBe(fusionAgentDir);
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
import { homedir } from "node:os";
|
||||
import { existsSync } from "node:fs";
|
||||
import { existsSync, readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
export function getFusionAgentDir(home = process.env.HOME || process.env.USERPROFILE || homedir()): string {
|
||||
@@ -41,15 +41,34 @@ export function getModelRegistryModelsPath(home = process.env.HOME || process.en
|
||||
return getLegacyModelsPaths(home).find((modelsPath) => existsSync(modelsPath)) ?? fusionModelsPath;
|
||||
}
|
||||
|
||||
export function getPackageManagerAgentDir(home = process.env.HOME || process.env.USERPROFILE || homedir()): string {
|
||||
const fusionAgentDir = getFusionAgentDir(home);
|
||||
if (
|
||||
existsSync(join(fusionAgentDir, "settings.json")) ||
|
||||
existsSync(join(fusionAgentDir, "extensions"))
|
||||
) {
|
||||
return fusionAgentDir;
|
||||
function readJsonObject(path: string): Record<string, unknown> {
|
||||
if (!existsSync(path)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const legacyAgentDir = getLegacyAgentDir(home);
|
||||
return existsSync(legacyAgentDir) ? legacyAgentDir : fusionAgentDir;
|
||||
try {
|
||||
const parsed = JSON.parse(readFileSync(path, "utf-8"));
|
||||
return parsed && typeof parsed === "object" ? parsed as Record<string, unknown> : {};
|
||||
} catch {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
function hasPackageManagerSettings(settings: Record<string, unknown>): boolean {
|
||||
return Array.isArray(settings.packages) || Array.isArray(settings.npmCommand);
|
||||
}
|
||||
|
||||
export function getPackageManagerAgentDir(home = process.env.HOME || process.env.USERPROFILE || homedir()): string {
|
||||
const fusionAgentDir = getFusionAgentDir(home);
|
||||
const legacyAgentDir = getLegacyAgentDir(home);
|
||||
const fusionSettings = readJsonObject(join(fusionAgentDir, "settings.json"));
|
||||
const legacySettings = readJsonObject(join(legacyAgentDir, "settings.json"));
|
||||
|
||||
if (hasPackageManagerSettings(fusionSettings) || !existsSync(legacyAgentDir)) {
|
||||
return fusionAgentDir;
|
||||
}
|
||||
if (hasPackageManagerSettings(legacySettings)) {
|
||||
return legacyAgentDir;
|
||||
}
|
||||
return existsSync(fusionAgentDir) ? fusionAgentDir : legacyAgentDir;
|
||||
}
|
||||
|
||||
@@ -55,6 +55,38 @@ describe("createReadOnlyProviderSettingsView", () => {
|
||||
expect(view.getProjectSettings()).toEqual({});
|
||||
expect(view.getNpmCommand()).toEqual(["pnpm"]);
|
||||
});
|
||||
|
||||
it("merges legacy Pi and Fusion agent settings with Fusion taking precedence", () => {
|
||||
const home = mkdtempSync(join(tmpdir(), "fusion-provider-settings-"));
|
||||
const cwd = join(home, "project");
|
||||
const fusionAgentDir = join(home, ".fusion", "agent");
|
||||
const legacyAgentDir = join(home, ".pi", "agent");
|
||||
|
||||
mkdirSync(join(cwd, ".fusion"), { recursive: true });
|
||||
mkdirSync(fusionAgentDir, { recursive: true });
|
||||
mkdirSync(legacyAgentDir, { recursive: true });
|
||||
|
||||
writeJson(join(legacyAgentDir, "settings.json"), {
|
||||
packages: ["npm:pi-claude-cli"],
|
||||
npmCommand: ["npm"],
|
||||
shared: "legacy",
|
||||
});
|
||||
writeJson(join(fusionAgentDir, "settings.json"), {
|
||||
fusionDisabledExtensions: ["/tmp/disabled.ts"],
|
||||
npmCommand: ["pnpm"],
|
||||
shared: "fusion",
|
||||
});
|
||||
|
||||
const view = createReadOnlyProviderSettingsView(cwd, fusionAgentDir);
|
||||
|
||||
expect(view.getGlobalSettings()).toMatchObject({
|
||||
packages: ["npm:pi-claude-cli"],
|
||||
fusionDisabledExtensions: ["/tmp/disabled.ts"],
|
||||
npmCommand: ["pnpm"],
|
||||
shared: "fusion",
|
||||
});
|
||||
expect(view.getNpmCommand()).toEqual(["pnpm"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("createProjectSettingsPersistence", () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
||||
import { join, dirname } from "node:path";
|
||||
import { join, dirname, basename } from "node:path";
|
||||
|
||||
export interface PackageManagerSettingsView {
|
||||
getGlobalSettings(): Record<string, any>;
|
||||
@@ -7,6 +7,13 @@ export interface PackageManagerSettingsView {
|
||||
getNpmCommand(): string[] | undefined;
|
||||
}
|
||||
|
||||
function siblingAgentDir(agentDir: string, siblingRoot: ".fusion" | ".pi"): string | undefined {
|
||||
if (basename(agentDir) !== "agent") {
|
||||
return undefined;
|
||||
}
|
||||
return join(dirname(dirname(agentDir)), siblingRoot, "agent");
|
||||
}
|
||||
|
||||
function readJsonObject(path: string): Record<string, any> {
|
||||
if (!existsSync(path)) {
|
||||
return {};
|
||||
@@ -21,7 +28,16 @@ function readJsonObject(path: string): Record<string, any> {
|
||||
}
|
||||
|
||||
export function createReadOnlyProviderSettingsView(cwd: string, agentDir: string): PackageManagerSettingsView {
|
||||
const globalSettings = readJsonObject(join(agentDir, "settings.json"));
|
||||
const fusionAgentDir = agentDir.includes(`${join(".fusion", "agent")}`)
|
||||
? agentDir
|
||||
: siblingAgentDir(agentDir, ".fusion");
|
||||
const legacyAgentDir = agentDir.includes(`${join(".pi", "agent")}`)
|
||||
? agentDir
|
||||
: siblingAgentDir(agentDir, ".pi");
|
||||
const legacyGlobalSettings = legacyAgentDir ? readJsonObject(join(legacyAgentDir, "settings.json")) : {};
|
||||
const fusionGlobalSettings = fusionAgentDir ? readJsonObject(join(fusionAgentDir, "settings.json")) : {};
|
||||
const directGlobalSettings = readJsonObject(join(agentDir, "settings.json"));
|
||||
const globalSettings = { ...legacyGlobalSettings, ...directGlobalSettings, ...fusionGlobalSettings };
|
||||
const fusionProjectSettings = readJsonObject(join(cwd, ".fusion", "settings.json"));
|
||||
const mergedSettings = { ...globalSettings, ...fusionProjectSettings };
|
||||
|
||||
|
||||
Reference in New Issue
Block a user