fix(server): profile options convert against the provider graph a write commits

A write that edited a provider and a profile together folded the profile against a shallow merge that dropped the provider's extends, so its legacy Fast was not converted. The fold now sees the same deep-merged providers the write commits.
This commit is contained in:
Mohamed Boudra
2026-11-01 21:09:10 +01:00
parent fbd7890f78
commit e4a49b414f
2 changed files with 28 additions and 6 deletions
@@ -468,6 +468,21 @@ describe("DaemonConfigStore", () => {
expect(store.get().agentProfiles).toEqual([{ id, name: id, provider: id, options: {} }]);
});
test("a provider edit in the same write does not hide which adapter a profile runs on", async () => {
const store = storeWithLegacyProfiles();
await store.patch({
providers: { "my-codex": { label: "Renamed" } },
agentProfiles: [
{ id: "p", name: "P", provider: "my-codex", featureValues: { fast_mode: false } },
],
});
expect(store.get().agentProfiles).toEqual([
{ id: "p", name: "P", provider: "my-codex", options: { service_tier: "default" } },
]);
});
test("a malformed value rejects the write and leaves config reads working", async () => {
const store = storeWithLegacyProfiles();
@@ -465,6 +465,18 @@ export class DaemonConfigStore {
return this.enqueue(() => this.applySupportedPatch({ skills: { selection } }));
}
private foldPatchProfiles<
T extends { agentProfiles?: AgentProfile[]; providers?: Record<string, ProviderOverride> },
>(submittedPatch: T): T {
return foldConfigProfiles({
config: submittedPatch,
// The provider graph this request will commit, so `extends` survives a partial edit.
providers: deepMerge(this.current.providers ?? {}, submittedPatch.providers ?? {}),
source: "client write",
held: this.current.agentProfiles,
});
}
private async applySupportedPatch(
parsedPatch: SupportedMutableConfigPatch,
): Promise<MutableDaemonConfig> {
@@ -474,12 +486,7 @@ export class DaemonConfigStore {
);
}
const { removeProviders = [], ...submittedPatch } = parsedPatch;
const patch = foldConfigProfiles({
config: submittedPatch,
providers: { ...this.current.providers, ...submittedPatch.providers },
source: "client write",
held: this.current.agentProfiles,
});
const patch = this.foldPatchProfiles(submittedPatch);
const { features: speechPatch, ...configPatch } = patch;
const removedProviders = Array.from(new Set(removeProviders));
const merged = deepMerge(this.current, configPatch);