mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
fix(providers): prevent stale models during refresh
Provider settings sheets can remain mounted while hidden, so the old display cache could survive into a different provider. Scope the cache to the active provider identity and remount the sheet when that identity changes.
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { AgentModelDefinition } from "@getpaseo/protocol/agent-types";
|
||||
import {
|
||||
resolveProviderDiscoveredModels,
|
||||
type ProviderDiscoveredModelsCache,
|
||||
} from "./provider-diagnostic-models";
|
||||
|
||||
const piModel: AgentModelDefinition = {
|
||||
provider: "pi",
|
||||
id: "pi/model",
|
||||
label: "Pi Model",
|
||||
};
|
||||
|
||||
const grokModel: AgentModelDefinition = {
|
||||
provider: "grok",
|
||||
id: "grok-build",
|
||||
label: "Grok Build",
|
||||
};
|
||||
|
||||
function resolveModels(input: {
|
||||
serverId?: string;
|
||||
provider: string;
|
||||
currentModels?: AgentModelDefinition[];
|
||||
loading?: boolean;
|
||||
cache?: ProviderDiscoveredModelsCache | null;
|
||||
}) {
|
||||
return resolveProviderDiscoveredModels({
|
||||
serverId: input.serverId ?? "local",
|
||||
provider: input.provider,
|
||||
currentModels: input.currentModels,
|
||||
providerSnapshotRefreshing: input.loading === true,
|
||||
previousCache: input.cache ?? null,
|
||||
});
|
||||
}
|
||||
|
||||
describe("resolveProviderDiscoveredModels", () => {
|
||||
it("keeps a provider's cached discovered models visible while that provider refreshes", () => {
|
||||
const ready = resolveModels({ provider: "grok", currentModels: [grokModel] });
|
||||
|
||||
const refreshing = resolveModels({ provider: "grok", loading: true, cache: ready.cache });
|
||||
|
||||
expect(refreshing.models).toEqual([grokModel]);
|
||||
});
|
||||
|
||||
it("does not show one provider's cached models while another provider loads", () => {
|
||||
const ready = resolveModels({ provider: "pi", currentModels: [piModel] });
|
||||
|
||||
const refreshing = resolveModels({ provider: "grok", loading: true, cache: ready.cache });
|
||||
|
||||
expect(refreshing.models).toEqual([]);
|
||||
});
|
||||
|
||||
it("does not show another server's cached models while the same provider loads", () => {
|
||||
const ready = resolveModels({
|
||||
serverId: "server-a",
|
||||
provider: "grok",
|
||||
currentModels: [grokModel],
|
||||
});
|
||||
|
||||
const refreshing = resolveModels({
|
||||
serverId: "server-b",
|
||||
provider: "grok",
|
||||
loading: true,
|
||||
cache: ready.cache,
|
||||
});
|
||||
|
||||
expect(refreshing.models).toEqual([]);
|
||||
});
|
||||
});
|
||||
43
packages/app/src/components/provider-diagnostic-models.ts
Normal file
43
packages/app/src/components/provider-diagnostic-models.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import type { AgentModelDefinition } from "@getpaseo/protocol/agent-types";
|
||||
|
||||
export interface ProviderDiscoveredModelsCache {
|
||||
serverId: string;
|
||||
provider: string;
|
||||
models: AgentModelDefinition[];
|
||||
}
|
||||
|
||||
export interface ResolveProviderDiscoveredModelsInput {
|
||||
serverId: string;
|
||||
provider: string;
|
||||
currentModels: AgentModelDefinition[] | undefined;
|
||||
providerSnapshotRefreshing: boolean;
|
||||
previousCache: ProviderDiscoveredModelsCache | null;
|
||||
}
|
||||
|
||||
export interface ResolveProviderDiscoveredModelsResult {
|
||||
models: AgentModelDefinition[];
|
||||
cache: ProviderDiscoveredModelsCache | null;
|
||||
}
|
||||
|
||||
export function resolveProviderDiscoveredModels({
|
||||
serverId,
|
||||
provider,
|
||||
currentModels,
|
||||
providerSnapshotRefreshing,
|
||||
previousCache,
|
||||
}: ResolveProviderDiscoveredModelsInput): ResolveProviderDiscoveredModelsResult {
|
||||
if (currentModels && currentModels.length > 0) {
|
||||
const cache = { serverId, provider, models: currentModels };
|
||||
return { models: currentModels, cache };
|
||||
}
|
||||
|
||||
if (
|
||||
providerSnapshotRefreshing &&
|
||||
previousCache?.serverId === serverId &&
|
||||
previousCache.provider === provider
|
||||
) {
|
||||
return { models: previousCache.models, cache: previousCache };
|
||||
}
|
||||
|
||||
return { models: [], cache: previousCache };
|
||||
}
|
||||
@@ -32,6 +32,10 @@ import { formatTimeAgo } from "@/utils/time";
|
||||
import { compareMatchScores, scoreTextFields } from "@/utils/score-match";
|
||||
import type { AgentModelDefinition, AgentProvider } from "@getpaseo/protocol/agent-types";
|
||||
import type { ProviderProfileModel } from "@getpaseo/protocol/provider-config";
|
||||
import {
|
||||
resolveProviderDiscoveredModels,
|
||||
type ProviderDiscoveredModelsCache,
|
||||
} from "./provider-diagnostic-models";
|
||||
|
||||
interface ProviderDiagnosticSheetProps {
|
||||
provider: string;
|
||||
@@ -599,21 +603,16 @@ export function ProviderDiagnosticSheet({
|
||||
: null;
|
||||
const modelsRefreshing = isRefreshing || providerSnapshotRefreshing;
|
||||
|
||||
const stableDiscoveredRef = useRef<AgentModelDefinition[]>([]);
|
||||
const stableDiscoveredRef = useRef<ProviderDiscoveredModelsCache | null>(null);
|
||||
const currentModels = providerEntry?.models;
|
||||
if (currentModels && currentModels.length > 0) {
|
||||
stableDiscoveredRef.current = currentModels;
|
||||
}
|
||||
|
||||
const discoveredModels = useMemo(() => {
|
||||
if (currentModels && currentModels.length > 0) {
|
||||
return currentModels;
|
||||
}
|
||||
if (providerSnapshotRefreshing) {
|
||||
return stableDiscoveredRef.current;
|
||||
}
|
||||
return [];
|
||||
}, [currentModels, providerSnapshotRefreshing]);
|
||||
const { models: discoveredModels, cache: nextDiscoveredCache } = resolveProviderDiscoveredModels({
|
||||
serverId,
|
||||
provider,
|
||||
currentModels,
|
||||
providerSnapshotRefreshing,
|
||||
previousCache: stableDiscoveredRef.current,
|
||||
});
|
||||
stableDiscoveredRef.current = nextDiscoveredCache;
|
||||
|
||||
const [clockTick, setClockTick] = useState(0);
|
||||
useEffect(() => {
|
||||
|
||||
@@ -18,6 +18,7 @@ export function ProviderSettingsHost() {
|
||||
|
||||
return (
|
||||
<ProviderDiagnosticSheet
|
||||
key={`${serverId}:${provider}`}
|
||||
provider={provider}
|
||||
serverId={serverId}
|
||||
visible={visible}
|
||||
|
||||
Reference in New Issue
Block a user