Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions packages/shared/src/serverSettings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
normalizePersistedServerSettingString,
parsePersistedServerObservabilitySettings,
resolveSourceControlWriterModelSelection,
textGenerationSelectionForTarget,
} from "./serverSettings.ts";

describe("serverSettings helpers", () => {
Expand Down Expand Up @@ -515,3 +516,89 @@ describe("serverSettings helpers", () => {
expect(resolved.pauseWhenOnBattery).toBe(false);
});
});

describe("textGenerationSelectionForTarget", () => {
const claudeSelection = createModelSelection(
ProviderInstanceId.make("claudeAgent"),
"claude-opus-4-6",
);
const sourceSettings = {
...DEFAULT_SERVER_SETTINGS,
providerInstances: {
claudeAgent: {
driver: ProviderDriverKind.make("claudeAgent"),
enabled: true,
config: {},
},
},
};

it("keeps a matching enabled instance on the target", () => {
expect(
textGenerationSelectionForTarget(claudeSelection, sourceSettings, sourceSettings),
).toEqual(claudeSelection);
});

it("maps onto another enabled instance of the same driver", () => {
const targetSettings = {
...DEFAULT_SERVER_SETTINGS,
providerInstances: {
claude_work: {
driver: ProviderDriverKind.make("claudeAgent"),
enabled: true,
config: {},
},
},
};
expect(
textGenerationSelectionForTarget(claudeSelection, sourceSettings, targetSettings),
).toEqual(createModelSelection(ProviderInstanceId.make("claude_work"), "claude-opus-4-6"));
});

it("uses the canonical instance id for an enabled legacy target", () => {
const targetSettings = {
...DEFAULT_SERVER_SETTINGS,
providerInstances: {},
};
expect(
textGenerationSelectionForTarget(claudeSelection, sourceSettings, targetSettings),
).toEqual(claudeSelection);
});

it("does not fall back to legacy settings when a migrated instance is disabled", () => {
const targetSettings = {
...DEFAULT_SERVER_SETTINGS,
providerInstances: {
claude_work: {
driver: ProviderDriverKind.make("claudeAgent"),
enabled: false,
config: {},
},
},
};
expect(
textGenerationSelectionForTarget(claudeSelection, sourceSettings, targetSettings),
).toBeUndefined();
});

it.each(["disabled", "different-driver"] as const)(
"does not copy an instance id onto a %s target provider",
(availability) => {
const targetSettings = {
...DEFAULT_SERVER_SETTINGS,
providerInstances: {
claudeAgent: {
driver: ProviderDriverKind.make(
availability === "different-driver" ? "codex" : "claudeAgent",
),
enabled: availability !== "disabled",
config: {},
},
},
};
expect(
textGenerationSelectionForTarget(claudeSelection, sourceSettings, targetSettings),
).toBeUndefined();
},
);
});
57 changes: 57 additions & 0 deletions packages/shared/src/serverSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
resolveProviderInstanceEnabled,
type ModelSelection,
type ProviderDriverKind,
ProviderInstanceId,
type ServerProvider,
ServerSettings,
type ServerSettingsPatch,
Expand Down Expand Up @@ -46,6 +47,62 @@ export function isModelSelectionProviderEnabled(
);
}

function providerDriverForSelection(
settings: ServerSettings,
selection: ModelSelection,
): ProviderDriverKind | undefined {
const instance = settings.providerInstances[selection.instanceId];
if (instance !== undefined) return instance.driver;
return isProviderDriverKind(selection.instanceId) ? selection.instanceId : undefined;
}

/**
* Map a text-generation model onto another environment by enabled provider
* identity (driver), not by copying instance IDs blindly.
*/
export function textGenerationSelectionForTarget(
selection: ModelSelection,
sourceSettings: ServerSettings,
targetSettings: ServerSettings,
): ModelSelection | undefined {
const sourceDriver = providerDriverForSelection(sourceSettings, selection);
if (sourceDriver === undefined) return undefined;

const sameId = targetSettings.providerInstances[selection.instanceId];
if (
sameId !== undefined &&
sameId.driver === sourceDriver &&
resolveProviderInstanceEnabled(sameId)
) {
return createModelSelection(selection.instanceId, selection.model, selection.options);
}

const targetInstances = Object.entries(targetSettings.providerInstances);
const matched = targetInstances.find(
([, instance]) => instance.driver === sourceDriver && resolveProviderInstanceEnabled(instance),
);
if (matched !== undefined) {
return createModelSelection(
ProviderInstanceId.make(matched[0]),
selection.model,
selection.options,
);
}

if (targetInstances.some(([, instance]) => instance.driver === sourceDriver)) {
return undefined;
}

const legacyInstanceId = ProviderInstanceId.make(sourceDriver);
if (
targetSettings.providerInstances[legacyInstanceId] === undefined &&
getLegacyProviderSettings(targetSettings, sourceDriver)?.enabled === true
Comment thread
greptile-apps[bot] marked this conversation as resolved.
) {
return createModelSelection(legacyInstanceId, selection.model, selection.options);
}
return undefined;
}

export function resolveSourceControlWriterModelSelection(
settings: ServerSettings,
providers?: ReadonlyArray<ServerProvider>,
Expand Down
Loading