mirror of
https://github.com/morluto/rea
synced 2026-10-25 22:08:11 -04:00
fix(setup): preserve owned Gemini user settings
This commit is contained in:
@@ -110,10 +110,13 @@ const workspaceTrusted = async (
|
||||
return ok(trusted);
|
||||
};
|
||||
|
||||
/** Check effective Gemini scopes while preserving their authority and source identity. */
|
||||
/**
|
||||
* Check Gemini scopes using the caller's user-file observation (undefined means absent).
|
||||
* Other settings sources are read here; transaction owners supply fresh user facts.
|
||||
*/
|
||||
export const readClientPolicyBlock = async (
|
||||
client: SetupClient,
|
||||
userDocument?: ClientConfigurationDocument,
|
||||
userDocument: ClientConfigurationDocument | undefined,
|
||||
desiredRegistration?: unknown,
|
||||
resources?: ArtifactResourceScope,
|
||||
): Promise<Result<string | undefined, ClientConfigurationFileError>> => {
|
||||
@@ -128,7 +131,7 @@ export const readClientPolicyBlock = async (
|
||||
settings.systemPath,
|
||||
]) {
|
||||
const parsed =
|
||||
path === client.configPath && userDocument !== undefined
|
||||
path === client.configPath
|
||||
? ok(userDocument)
|
||||
: await readConfigurationFile(path, "json", resources);
|
||||
if (!parsed.ok) return parsed;
|
||||
|
||||
@@ -138,7 +138,7 @@ const configureClientDocument = async (
|
||||
return { status: "failed", reason: "readback" };
|
||||
const policy = await readClientPolicyBlock(
|
||||
client,
|
||||
undefined,
|
||||
existing,
|
||||
await clientConfigurationDesired(
|
||||
client,
|
||||
environment,
|
||||
@@ -498,7 +498,7 @@ const inspectClientDocument = async (
|
||||
};
|
||||
const policy = await readClientPolicyBlock(
|
||||
client,
|
||||
undefined,
|
||||
existing,
|
||||
await clientConfigurationDesired(
|
||||
client,
|
||||
providerEnvironment,
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
import { mkdir, rm, writeFile } from "node:fs/promises";
|
||||
import { dirname, join } from "node:path";
|
||||
import { expect, it } from "vitest";
|
||||
|
||||
import { readConfigurationFile } from "../../../src/application/ClientConfigurationFiles.js";
|
||||
import { readClientPolicyBlock } from "../../../src/application/GeminiClientSettings.js";
|
||||
import type { SetupClient } from "../../../src/application/SupportedClients.js";
|
||||
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
||||
|
||||
const fixture = async () => {
|
||||
const home = await createTestTempDirectory("rea-gemini-policy-sources-");
|
||||
const configPath = join(home, ".gemini", "settings.json");
|
||||
await mkdir(dirname(configPath), { recursive: true });
|
||||
const client: SetupClient = {
|
||||
name: "gemini_cli",
|
||||
configPath,
|
||||
format: "json",
|
||||
geminiSettings: {
|
||||
defaultsPath: join(home, "defaults.json"),
|
||||
systemPath: join(home, "system.json"),
|
||||
workspaceDirectory: home,
|
||||
trustedFoldersPath: join(home, "trust.json"),
|
||||
platform: process.platform,
|
||||
},
|
||||
};
|
||||
return { client, configPath, systemPath: join(home, "system.json") };
|
||||
};
|
||||
|
||||
it("keeps observed user absence until the caller reads a new configuration", async () => {
|
||||
const { client, configPath } = await fixture();
|
||||
const absent = await readConfigurationFile(configPath, "json");
|
||||
expect(absent).toEqual({ ok: true, value: undefined });
|
||||
if (!absent.ok) throw absent.error;
|
||||
|
||||
await writeFile(configPath, JSON.stringify({ mcp: { excluded: ["rea"] } }));
|
||||
expect(await readClientPolicyBlock(client, absent.value)).toEqual({
|
||||
ok: true,
|
||||
value: undefined,
|
||||
});
|
||||
|
||||
const current = await readConfigurationFile(configPath, "json");
|
||||
if (!current.ok) throw current.error;
|
||||
expect(await readClientPolicyBlock(client, current.value)).toMatchObject({
|
||||
ok: true,
|
||||
value: expect.stringContaining("mcp.excluded"),
|
||||
});
|
||||
});
|
||||
|
||||
it("preserves the parsed user policy when its source disappears", async () => {
|
||||
const { client, configPath } = await fixture();
|
||||
await writeFile(configPath, JSON.stringify({ mcp: { excluded: ["rea"] } }));
|
||||
const observed = await readConfigurationFile(configPath, "json");
|
||||
if (!observed.ok) throw observed.error;
|
||||
await rm(configPath);
|
||||
|
||||
expect(await readClientPolicyBlock(client, observed.value)).toMatchObject({
|
||||
ok: true,
|
||||
value: expect.stringContaining(configPath),
|
||||
});
|
||||
});
|
||||
|
||||
it("still reads independent system policy when the user file was absent", async () => {
|
||||
const { client, configPath, systemPath } = await fixture();
|
||||
const absent = await readConfigurationFile(configPath, "json");
|
||||
if (!absent.ok) throw absent.error;
|
||||
await writeFile(systemPath, JSON.stringify({ mcp: { excluded: ["rea"] } }));
|
||||
|
||||
expect(await readClientPolicyBlock(client, absent.value)).toMatchObject({
|
||||
ok: true,
|
||||
value: expect.stringContaining(systemPath),
|
||||
});
|
||||
await writeFile(systemPath, "{ invalid settings");
|
||||
expect(await readClientPolicyBlock(client, absent.value)).toMatchObject({
|
||||
ok: false,
|
||||
error: { kind: "malformed", path: systemPath },
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user