Skip to content

Commit 86d46a1

Browse files
committed
fix(web): preserve provider update notices during reconnects
1 parent 0ec48a5 commit 86d46a1

3 files changed

Lines changed: 22 additions & 21 deletions

File tree

‎apps/web/src/components/ProviderUpdateEnvironmentRows.tsx‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ function EnvironmentUpdateRow({
111111
readonly onUpdate: () => void;
112112
}) {
113113
const canManageProviders = useEnvironmentScope(group.environmentId, AuthProvidersManageScope);
114+
const canUpdateProviders = canManageProviders && group.isReady;
114115
let trailing: ReactNode;
115116
switch (status.kind) {
116117
case "loading":
@@ -122,14 +123,14 @@ function EnvironmentUpdateRow({
122123
case "failed":
123124
case "unchanged":
124125
trailing = (
125-
<Button size="xs" variant="outline" disabled={!canManageProviders} onClick={onUpdate}>
126+
<Button size="xs" variant="outline" disabled={!canUpdateProviders} onClick={onUpdate}>
126127
Retry
127128
</Button>
128129
);
129130
break;
130131
default:
131132
trailing = (
132-
<Button size="xs" variant="outline" disabled={!canManageProviders} onClick={onUpdate}>
133+
<Button size="xs" variant="outline" disabled={!canUpdateProviders} onClick={onUpdate}>
133134
Update
134135
</Button>
135136
);
@@ -203,7 +204,7 @@ export function ProviderUpdateEnvironmentRows({
203204
const handleUpdate = async (environmentId: EnvironmentId) => {
204205
if (!readEnvironmentScope(environmentId, AuthProvidersManageScope)) return;
205206
const group = groupByEnvironment.get(environmentId);
206-
if (!group || group.candidates.length === 0) {
207+
if (!group?.isReady || group.candidates.length === 0) {
207208
return;
208209
}
209210
if (inFlightEnvironmentsRef.current.has(environmentId)) {

‎apps/web/src/components/ProviderUpdateLaunchNotification.logic.test.ts‎

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -447,25 +447,25 @@ describe("provider update launch notification logic", () => {
447447
).toBe(true);
448448
});
449449

450-
it("waits for a connection before offering cached provider updates", () => {
450+
it("keeps the notification key stable while connection readiness changes", () => {
451451
const cachedProvider = provider({ driver: driver("codex") });
452452
const primary = environment({
453453
environmentId: "env-cached",
454454
isPrimary: true,
455455
connectionState: "connecting",
456456
providers: [cachedProvider],
457457
});
458-
const waiting = buildLocalEnvironmentUpdateGroups([primary]);
459-
expect(waiting.groups[0]?.candidates).toEqual([]);
460-
expect(localEnvironmentUpdateNotificationKey(waiting.groups)).toBeNull();
461-
462-
const connected = buildLocalEnvironmentUpdateGroups([
463-
{ ...primary, connectionState: "ready" },
464-
]);
465-
expect(connected.groups[0]?.candidates).toEqual([cachedProvider]);
466-
expect(localEnvironmentUpdateNotificationKey(connected.groups)).toBe(
467-
"env-cached=codex:1.1.0",
468-
);
458+
for (const connectionState of [
459+
"connecting",
460+
"ready",
461+
"disconnected",
462+
"error",
463+
"ready",
464+
] as const) {
465+
const { groups } = buildLocalEnvironmentUpdateGroups([{ ...primary, connectionState }]);
466+
expect(groups[0]?.isReady).toBe(connectionState === "ready");
467+
expect(localEnvironmentUpdateNotificationKey(groups)).toBe("env-cached=codex:1.1.0");
468+
}
469469
});
470470
});
471471

@@ -475,6 +475,7 @@ describe("provider update launch notification logic", () => {
475475
label: "WSL",
476476
isPrimary: false,
477477
isSettling: false,
478+
isReady: true,
478479
candidates: [updateCandidate({ driver: driver("codex"), latestVersion: "1.1.0" })],
479480
providers: [],
480481
};

‎apps/web/src/components/ProviderUpdateLaunchNotification.logic.ts‎

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,7 @@ export interface LocalEnvironmentUpdateGroup {
737737
readonly label: string;
738738
readonly isPrimary: boolean;
739739
readonly isSettling: boolean;
740+
readonly isReady: boolean;
740741
readonly candidates: ProviderUpdateCandidate[];
741742
readonly providers: ReadonlyArray<ServerProvider>;
742743
}
@@ -749,12 +750,10 @@ export function buildLocalEnvironmentUpdateGroups(
749750
label: environment.label,
750751
isPrimary: environment.isPrimary,
751752
isSettling: environment.connectionState === "connecting",
752-
candidates:
753-
environment.connectionState === "ready"
754-
? collectProviderUpdateCandidates(environment.providers).filter((candidate) =>
755-
canOneClickUpdateProviderCandidate(candidate, environment.providers),
756-
)
757-
: [],
753+
isReady: environment.connectionState === "ready",
754+
candidates: collectProviderUpdateCandidates(environment.providers).filter((candidate) =>
755+
canOneClickUpdateProviderCandidate(candidate, environment.providers),
756+
),
758757
providers: environment.providers,
759758
}));
760759
const isAnySettling = environments.some(

0 commit comments

Comments
 (0)