refactor(FN-1616): convert blocking fs operations to async on HTTP request paths

- Convert skills-adapter.ts readFileSync/writeFileSync to async readFile/writeFile
- Cache GitHub webhook private key in memory to avoid repeated fs reads
- Convert usage.ts readFileSync to async readFile
- Update usage.test.ts to work with async file operations
- All HTTP request handlers now use non-blocking async fs operations
This commit is contained in:
Fusion
2026-04-15 01:39:34 -07:00
committed by gsxdsm
parent fd70323a5f
commit f93e343648
4 changed files with 145 additions and 128 deletions

View File

@@ -22,10 +22,11 @@ vi.mock("node:https", () => ({
request: (...args: any[]) => mockRequest(...args),
}));
// Mock fs
const mockReadFileSync = vi.fn();
vi.mock("node:fs", () => ({
readFileSync: (...args: any[]) => mockReadFileSync(...args),
// Mock fs/promises
const mockReadFile = vi.fn();
vi.mock("node:fs/promises", () => ({
readFile: (...args: any[]) => mockReadFile(...args),
default: { readFile: (...args: any[]) => mockReadFile(...args) },
}));
// Mock child_process
@@ -53,7 +54,7 @@ describe("usage", () => {
clearUsageCache();
_clearRefreshedToken();
mockRequest.mockClear();
mockReadFileSync.mockClear();
mockReadFile.mockClear();
mockExecFileSync.mockClear();
vi.stubEnv("HOME", "/home/testuser");
});
@@ -65,8 +66,8 @@ describe("usage", () => {
describe("fetchAllProviderUsage", () => {
it("returns providers array even when all are not authenticated", async () => {
// All credential files don't exist
mockReadFileSync.mockImplementation(() => {
throw new Error("File not found");
mockReadFile.mockImplementation(async () => {
return Promise.reject(new Error("File not found"));
});
const providers = await fetchAllProviderUsage();
@@ -87,8 +88,8 @@ describe("usage", () => {
});
it("returns cached data within TTL", async () => {
mockReadFileSync.mockImplementation(() => {
throw new Error("File not found");
mockReadFile.mockImplementation(async () => {
return Promise.reject(new Error("File not found"));
});
const first = await fetchAllProviderUsage();
@@ -99,8 +100,8 @@ describe("usage", () => {
});
it("fetches fresh data after cache expires", async () => {
mockReadFileSync.mockImplementation(() => {
throw new Error("File not found");
mockReadFile.mockImplementation(async () => {
return Promise.reject(new Error("File not found"));
});
const first = await fetchAllProviderUsage();
@@ -129,11 +130,11 @@ describe("usage", () => {
}) {
const { credFileContent = null, keychainContent = null } = options;
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes("claude") && credFileContent !== null) {
return JSON.stringify(credFileContent);
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation((cmd: string, _args: string[]) => {
@@ -177,8 +178,8 @@ describe("usage", () => {
}
it("detects no auth when credentials file doesn't exist and keychain fails", async () => {
mockReadFileSync.mockImplementation(() => {
throw new Error("File not found");
mockReadFile.mockImplementation(async () => {
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -255,14 +256,14 @@ describe("usage", () => {
});
it("detects missing scope error", async () => {
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes("claude")) {
return JSON.stringify({
accessToken: "test-token",
scopes: ["other:scope"], // missing user:profile
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -450,14 +451,14 @@ describe("usage", () => {
five_hour: { utilization: 10.0 },
};
mockReadFileSync.mockImplementation((path: string) => {
mockReadFile.mockImplementation((path: string) => {
if (path.includes("claude")) {
return JSON.stringify({
accessToken: "test-token",
scopes: ["user:profile"],
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -505,14 +506,14 @@ describe("usage", () => {
},
};
mockReadFileSync.mockImplementation((path: string) => {
mockReadFile.mockImplementation((path: string) => {
if (path.includes("claude")) {
return JSON.stringify({
accessToken: "test-token",
scopes: ["user:profile"],
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -593,14 +594,14 @@ describe("usage", () => {
const noopSleep = vi.fn().mockResolvedValue(undefined);
_setSleepFn(noopSleep);
mockReadFileSync.mockImplementation((path: string) => {
mockReadFile.mockImplementation((path: string) => {
if (path.includes("claude")) {
return JSON.stringify({
accessToken: "test-token",
scopes: ["user:profile"],
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -647,14 +648,14 @@ describe("usage", () => {
const noopSleep = vi.fn().mockResolvedValue(undefined);
_setSleepFn(noopSleep);
mockReadFileSync.mockImplementation((path: string) => {
mockReadFile.mockImplementation((path: string) => {
if (path.includes("claude")) {
return JSON.stringify({
accessToken: "test-token",
scopes: ["user:profile"],
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -698,14 +699,14 @@ describe("usage", () => {
const noopSleep = vi.fn().mockResolvedValue(undefined);
_setSleepFn(noopSleep);
mockReadFileSync.mockImplementation((path: string) => {
mockReadFile.mockImplementation((path: string) => {
if (path.includes("claude")) {
return JSON.stringify({
accessToken: "test-token",
scopes: ["user:profile"],
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -970,14 +971,14 @@ describe("usage", () => {
const noopSleep = vi.fn().mockResolvedValue(undefined);
_setSleepFn(noopSleep);
mockReadFileSync.mockImplementation((path: string) => {
mockReadFile.mockImplementation((path: string) => {
if (path.includes("claude")) {
return JSON.stringify({
accessToken: "expired-token",
scopes: ["user:profile"],
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -1040,14 +1041,14 @@ describe("usage", () => {
const noopSleep = vi.fn().mockResolvedValue(undefined);
_setSleepFn(noopSleep);
mockReadFileSync.mockImplementation((path: string) => {
mockReadFile.mockImplementation((path: string) => {
if (path.includes("claude")) {
return JSON.stringify({
accessToken: "forbidden-token",
scopes: ["user:profile"],
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -1534,8 +1535,8 @@ describe("usage", () => {
describe("Codex provider", () => {
it("detects no auth when auth.json doesn't exist", async () => {
mockReadFileSync.mockImplementation(() => {
throw new Error("File not found");
mockReadFile.mockImplementation(async () => {
return Promise.reject(new Error("File not found"));
});
const providers = await fetchAllProviderUsage();
@@ -1564,7 +1565,7 @@ describe("usage", () => {
},
};
mockReadFileSync.mockImplementation((path: string) => {
mockReadFile.mockImplementation((path: string) => {
if (path.includes("codex")) {
return JSON.stringify({
tokens: {
@@ -1573,7 +1574,7 @@ describe("usage", () => {
},
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
const mockReq = {
@@ -1625,7 +1626,7 @@ describe("usage", () => {
},
};
mockReadFileSync.mockImplementation((path: string) => {
mockReadFile.mockImplementation((path: string) => {
if (path.includes("codex")) {
return JSON.stringify({
tokens: {
@@ -1633,7 +1634,7 @@ describe("usage", () => {
},
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
const mockReq = { on: vi.fn(), write: vi.fn(), end: vi.fn() };
@@ -1669,7 +1670,7 @@ describe("usage", () => {
},
};
mockReadFileSync.mockImplementation((path: string) => {
mockReadFile.mockImplementation((path: string) => {
if (path.includes("codex")) {
return JSON.stringify({
tokens: {
@@ -1677,7 +1678,7 @@ describe("usage", () => {
},
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
const mockReq = { on: vi.fn(), write: vi.fn(), end: vi.fn() };
@@ -1709,8 +1710,8 @@ describe("usage", () => {
describe("Gemini provider", () => {
it("detects no auth when oauth_creds.json doesn't exist", async () => {
mockReadFileSync.mockImplementation(() => {
throw new Error("File not found");
mockReadFile.mockImplementation(async () => {
return Promise.reject(new Error("File not found"));
});
const providers = await fetchAllProviderUsage();
@@ -1737,7 +1738,7 @@ describe("usage", () => {
],
};
mockReadFileSync.mockImplementation((path: string) => {
mockReadFile.mockImplementation((path: string) => {
if (path.includes("gemini")) {
if (path.includes("oauth_creds")) {
return JSON.stringify({
@@ -1746,9 +1747,9 @@ describe("usage", () => {
});
}
// settings.json doesn't exist (oauth-personal is default)
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
const mockReq = {
@@ -1799,7 +1800,7 @@ describe("usage", () => {
],
};
mockReadFileSync.mockImplementation((path: string) => {
mockReadFile.mockImplementation((path: string) => {
if (path.includes("gemini")) {
if (path.includes("oauth_creds")) {
return JSON.stringify({
@@ -1807,9 +1808,9 @@ describe("usage", () => {
id_token: "header.eyJlbWFpbCI6InRlc3RAZXhhbXBsZS5jb20ifQ.signature",
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
const mockReq = { on: vi.fn(), write: vi.fn(), end: vi.fn() };
@@ -1835,7 +1836,7 @@ describe("usage", () => {
});
it("handles unsupported auth type (api-key)", async () => {
mockReadFileSync.mockImplementation((path: string) => {
mockReadFile.mockImplementation((path: string) => {
if (path.includes("gemini")) {
if (path.includes("oauth_creds")) {
return JSON.stringify({
@@ -1852,7 +1853,7 @@ describe("usage", () => {
});
}
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
const providers = await fetchAllProviderUsage();
@@ -1865,8 +1866,8 @@ describe("usage", () => {
describe("Minimax provider", () => {
it("detects no auth when pi auth.json doesn't exist", async () => {
mockReadFileSync.mockImplementation(() => {
throw new Error("File not found");
mockReadFile.mockImplementation(async () => {
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -1881,13 +1882,13 @@ describe("usage", () => {
});
it("detects no auth when minimax entry has no key", async () => {
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes(".pi/agent/auth.json")) {
return JSON.stringify({
minimax: { type: "api_key" /* missing key */ },
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -1901,11 +1902,11 @@ describe("usage", () => {
});
it("detects no auth when minimax entry is missing entirely", async () => {
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes(".pi/agent/auth.json")) {
return JSON.stringify({ /* no minimax key */ });
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -1942,13 +1943,13 @@ describe("usage", () => {
],
};
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes(".pi/agent/auth.json")) {
return JSON.stringify({
minimax: { type: "api_key", key: "test-api-key" },
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -2014,13 +2015,13 @@ describe("usage", () => {
],
};
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes(".pi/agent/auth.json")) {
return JSON.stringify({
minimax: { type: "api_key", key: "test-api-key" },
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -2063,8 +2064,8 @@ describe("usage", () => {
],
};
mockReadFileSync.mockImplementation(() => {
throw new Error("File not found");
mockReadFile.mockImplementation(async () => {
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -2099,13 +2100,13 @@ describe("usage", () => {
});
it("handles 401 auth error", async () => {
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes(".pi/agent/auth.json")) {
return JSON.stringify({
minimax: { type: "api_key", key: "expired-key" },
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -2133,13 +2134,13 @@ describe("usage", () => {
});
it("handles 403 auth error", async () => {
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes(".pi/agent/auth.json")) {
return JSON.stringify({
minimax: { type: "api_key", key: "forbidden-key" },
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -2181,11 +2182,11 @@ describe("usage", () => {
],
};
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes(".pi/agent/auth.json")) {
return JSON.stringify({ minimax: { type: "api_key", key: "test-key" } });
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -2220,8 +2221,8 @@ describe("usage", () => {
describe("Zai provider", () => {
it("detects no auth when pi auth.json doesn't exist", async () => {
mockReadFileSync.mockImplementation(() => {
throw new Error("File not found");
mockReadFile.mockImplementation(async () => {
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -2236,13 +2237,13 @@ describe("usage", () => {
});
it("detects no auth when zai entry has no key", async () => {
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes(".pi/agent/auth.json")) {
return JSON.stringify({
zai: { type: "api_key" /* missing key */ },
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -2284,13 +2285,13 @@ describe("usage", () => {
success: true,
};
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes(".pi/agent/auth.json")) {
return JSON.stringify({
zai: { type: "api_key", key: "test-api-key" },
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -2346,8 +2347,8 @@ describe("usage", () => {
success: true,
};
mockReadFileSync.mockImplementation(() => {
throw new Error("File not found");
mockReadFile.mockImplementation(async () => {
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -2397,13 +2398,13 @@ describe("usage", () => {
success: true,
};
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes(".fusion/agent/auth.json")) {
return JSON.stringify({
zai: { type: "api_key", key: "fusion-zai-key" },
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -2446,13 +2447,13 @@ describe("usage", () => {
success: true,
};
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes(".pi/agent/auth.json")) {
return JSON.stringify({
zai: { type: "api_key", key: "test-api-key" },
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -2488,13 +2489,13 @@ describe("usage", () => {
success: false,
};
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes(".pi/agent/auth.json")) {
return JSON.stringify({
zai: { type: "api_key", key: "test-api-key" },
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -2522,13 +2523,13 @@ describe("usage", () => {
});
it("handles 401 auth error", async () => {
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes(".pi/agent/auth.json")) {
return JSON.stringify({
zai: { type: "api_key", key: "expired-key" },
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -2556,13 +2557,13 @@ describe("usage", () => {
});
it("handles 403 auth error", async () => {
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes(".pi/agent/auth.json")) {
return JSON.stringify({
zai: { type: "api_key", key: "forbidden-key" },
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -2607,11 +2608,11 @@ describe("usage", () => {
success: true,
};
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes(".pi/agent/auth.json")) {
return JSON.stringify({ zai: { type: "api_key", key: "test-api-key" } });
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -2665,11 +2666,11 @@ describe("usage", () => {
success: true,
};
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes(".pi/agent/auth.json")) {
return JSON.stringify({ zai: { type: "api_key", key: "test-api-key" } });
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -2762,14 +2763,14 @@ describe("usage", () => {
describe("error handling", () => {
it("handles Claude API errors gracefully", async () => {
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes("claude")) {
return JSON.stringify({
accessToken: "test-token",
scopes: ["user:profile"],
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -2797,14 +2798,14 @@ describe("usage", () => {
});
it("handles Claude network error", async () => {
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes("claude")) {
return JSON.stringify({
accessToken: "test-token",
scopes: ["user:profile"],
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -2834,7 +2835,7 @@ describe("usage", () => {
describe("formatDuration helper", () => {
it("formats duration correctly via resetText", async () => {
mockReadFileSync.mockImplementation((path: string) => {
mockReadFile.mockImplementation((path: string) => {
if (path.includes("codex")) {
return JSON.stringify({
tokens: {
@@ -2842,7 +2843,7 @@ describe("usage", () => {
},
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
const mockResponse = {
@@ -2902,11 +2903,11 @@ describe("usage", () => {
],
};
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes(".pi/agent/auth.json")) {
return JSON.stringify({ minimax: { type: "api_key", key: "test-key" } });
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -2953,11 +2954,11 @@ describe("usage", () => {
],
};
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes(".pi/agent/auth.json")) {
return JSON.stringify({ minimax: { type: "api_key", key: "test-key" } });
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -3245,14 +3246,14 @@ describe("usage", () => {
describe("Claude API error diagnostics", () => {
it("includes response body snippet in HTTP 500 error", async () => {
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes("claude")) {
return JSON.stringify({
accessToken: "test-token",
scopes: ["user:profile"],
});
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation(() => {
throw new Error("Keychain item not found");
@@ -3357,11 +3358,11 @@ describe("usage", () => {
}) {
const { credFileContent = null, keychainContent = null } = options;
mockReadFileSync.mockImplementation((filePath: string) => {
mockReadFile.mockImplementation((filePath: string) => {
if (filePath.includes("claude") && credFileContent !== null) {
return JSON.stringify(credFileContent);
}
throw new Error("File not found");
return Promise.reject(new Error("File not found"));
});
mockExecFileSync.mockImplementation((cmd: string, _args: string[]) => {