mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-08 01:14:52 +00:00
fix(app): select available host model by default
This commit is contained in:
@@ -47,6 +47,9 @@ The component renders state and dispatches intent. That is all it does.
|
||||
4. **Resolution is explicit model state, per host** (`idle | pending |
|
||||
complete`), keyed off the opened snapshot's serverId. Waiting for data is a
|
||||
state you can render, not an effect race.
|
||||
Create-agent model preferences are shared across hosts, so resolve remembered
|
||||
models against the selected host's ready catalog before applying them. Keep
|
||||
explicit initial values and user selections intact.
|
||||
5. **Displays are owned state.** The selected option's label is captured at
|
||||
selection/seed time (`setProject(value, display)`), never re-derived from a
|
||||
live options list — list churn must not flicker or blank a selection.
|
||||
|
||||
@@ -131,6 +131,34 @@ describe("resolveDefaultModel", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("remembered model availability", () => {
|
||||
it("uses the selected host's default when the remembered model belongs to another host", () => {
|
||||
const preferences = {
|
||||
provider: "codex" as const,
|
||||
providerPreferences: { codex: { model: "remote/model" } },
|
||||
};
|
||||
const models: AgentModelDefinition[] = [
|
||||
{ provider: "codex", id: "local/first", label: "First" },
|
||||
{ provider: "codex", id: "local/default", label: "Default", isDefault: true },
|
||||
];
|
||||
const resolve = (availableModels: AgentModelDefinition[] | null) =>
|
||||
resolveFormState(
|
||||
undefined,
|
||||
preferences,
|
||||
availableModels,
|
||||
INITIAL_USER_MODIFIED,
|
||||
makeState().form,
|
||||
codexProviderMap,
|
||||
).model;
|
||||
|
||||
expect(resolve(null)).toBe("remote/model");
|
||||
expect(resolve(models)).toBe("local/default");
|
||||
expect(resolve([{ provider: "codex", id: "remote/model", label: "Remote" }])).toBe(
|
||||
"remote/model",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("model aliases", () => {
|
||||
it("canonicalizes a retired preferred model and restores thinking from its alias key", () => {
|
||||
const resolved = resolveFormState(
|
||||
@@ -791,17 +819,16 @@ describe("resolveFormState", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps the explicit model when a refreshed catalogue no longer lists it", () => {
|
||||
it("keeps a user-selected model when a refreshed catalog no longer lists it", () => {
|
||||
const resolved = resolveFormState(
|
||||
undefined,
|
||||
{ provider: "codex", providerPreferences: { codex: { model: "gpt-6-astra" } } },
|
||||
{ provider: "codex" },
|
||||
CODEX_MODELS,
|
||||
INITIAL_USER_MODIFIED,
|
||||
makeState().form,
|
||||
{ ...INITIAL_USER_MODIFIED, model: true },
|
||||
makeState({ provider: "codex", model: "gpt-6-astra" }).form,
|
||||
codexProviderMap,
|
||||
);
|
||||
expect(resolved.model).toBe("gpt-6-astra");
|
||||
// Label/persistence lookup must not reinterpret the submitted ID as another model.
|
||||
expect(resolveEffectiveModel(CODEX_MODELS, resolved.model)).toBeNull();
|
||||
});
|
||||
|
||||
|
||||
@@ -317,9 +317,10 @@ function resolveModelField(input: {
|
||||
: resolveCanonicalModelId(availableModels, initialModel) || initialModel;
|
||||
}
|
||||
if (preferredModel) {
|
||||
return !availableModels
|
||||
return !availableModels?.length
|
||||
? preferredModel
|
||||
: resolveCanonicalModelId(availableModels, preferredModel) || preferredModel;
|
||||
: resolveCanonicalModelId(availableModels, preferredModel) ||
|
||||
resolveDefaultModelId(availableModels);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user