authorgravatar for yordis.prieto@gmail.comYordis Prieto <yordis.prieto@gmail.com> 2026-10-10 23:06:03-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-10-10 20:06:03-07:00
log4baba3b50359743998502f804801c2473b4123fe
tree0532fc661eb81a5a8706742d54382a3d89c0875c
parent0eef5d0c76f1765b7a44fa82e965bf5142d64169
signature Signed by PGP key B5690EEEBB952194

fix(server): disabled providers stop checking for CLI updates (#16772)

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com> Co-authored-by: Julius Marminge <julius0216@outlook.com>

5 files changed, 48 insertions(+), 23 deletions(-)

apps/server/src/provider/AntigravityProvider.test.ts+7-15
...@@ -257,31 +257,23 @@ it.layer(layerTest)("Antigravity provider snapshots", (it) => {...@@ -257,31 +257,23 @@ it.layer(layerTest)("Antigravity provider snapshots", (it) => {
257 ),257 ),
258 );258 );
259259
260 it.effect("records explicit sign-in while disabled without starting a health probe", () =>260 it.effect("ignores account updates while disabled", () =>
261 Effect.scoped(261 Effect.scoped(
262 Effect.gen(function* () {262 Effect.gen(function* () {
263 const harness = yield* makeHarness({ enabled: false });263 const harness = yield* makeHarness({ enabled: false });
264 const signedIn = yield* Stream.toPull(
265 harness.provider.snapshot.streamChanges.pipe(
266 Stream.filter(
267 (snapshot) =>
268 snapshot.auth.status === "authenticated" && snapshot.slashCommands.length > 0,
269 ),
270 ),
271 );
272 yield* harness.provider.onSessionStarted(started);264 yield* harness.provider.onSessionStarted(started);
273 yield* harness.provider.onAvailableCommands(commands);265 yield* harness.provider.onAvailableCommands(commands);
274 const [snapshot] = yield* signedIn;266 yield* harness.provider.onSignedOut;
267 const snapshot = yield* harness.provider.snapshot.refresh;
275 expect(snapshot).toMatchObject({268 expect(snapshot).toMatchObject({
276 enabled: false,269 enabled: false,
277 installed: true,270 installed: false,
278 status: "disabled",271 status: "disabled",
279 auth: { status: "authenticated", type: "oauth-personal" },272 auth: { status: "unknown" },
273 models: [],
274 slashCommands: [],
280 workspaceSnapshots: [],275 workspaceSnapshots: [],
281 });276 });
282 expect(snapshot.models).toEqual(buildAntigravityModelsFromSession(sessionSetupResult));
283 expect(snapshot.slashCommands).toEqual(expectedCommands);
284 expect((yield* harness.provider.snapshot.refresh).models).toEqual(snapshot.models);
285 expect(yield* Ref.get(harness.probeCalls)).toBe(0);277 expect(yield* Ref.get(harness.probeCalls)).toBe(0);
286 }),278 }),
287 ),279 ),
apps/server/src/provider/AntigravityProvider.ts+9-3
...@@ -132,7 +132,10 @@ interface AntigravityProviderOptions {...@@ -132,7 +132,10 @@ interface AntigravityProviderOptions {
132 readonly auth?: { readonly type: string; readonly label: string };132 readonly auth?: { readonly type: string; readonly label: string };
133}133}
134134
135/** Health uses initialize only. Session callbacks supply account-specific metadata. */135/**
136 * Health uses initialize only. Session callbacks supply account-specific
137 * metadata, which a disabled instance never shows.
138 */
136export const makeAntigravityProvider = Effect.fn("makeAntigravityProvider")(function* (139export const makeAntigravityProvider = Effect.fn("makeAntigravityProvider")(function* (
137 settings: AntigravitySettings,140 settings: AntigravitySettings,
138 options: AntigravityProviderOptions,141 options: AntigravityProviderOptions,
...@@ -271,6 +274,7 @@ export const makeAntigravityProvider = Effect.fn("makeAntigravityProvider")(func...@@ -271,6 +274,7 @@ export const makeAntigravityProvider = Effect.fn("makeAntigravityProvider")(func
271 started: AcpSessionRuntime.AcpSessionRuntimeStartResult,274 started: AcpSessionRuntime.AcpSessionRuntimeStartResult,
272 cwd?: string,275 cwd?: string,
273 ) {276 ) {
277 if (!settings.enabled) return;
274 const before = yield* SubscriptionRef.get(metadata);278 const before = yield* SubscriptionRef.get(metadata);
275 const supportsTextGeneration = yield* options.supportsTextGeneration;279 const supportsTextGeneration = yield* options.supportsTextGeneration;
276 const usageLimits =280 const usageLimits =
...@@ -293,7 +297,7 @@ export const makeAntigravityProvider = Effect.fn("makeAntigravityProvider")(func...@@ -293,7 +297,7 @@ export const makeAntigravityProvider = Effect.fn("makeAntigravityProvider")(func
293 draft: {297 draft: {
294 ...draft,298 ...draft,
295 installed: true,299 installed: true,
296 status: settings.enabled ? "ready" : "disabled",300 status: "ready",
297 version: started.initializeResult.agentInfo?.version || draft.version,301 version: started.initializeResult.agentInfo?.version || draft.version,
298 auth: {302 auth: {
299 status: "authenticated",303 status: "authenticated",
...@@ -339,6 +343,7 @@ export const makeAntigravityProvider = Effect.fn("makeAntigravityProvider")(func...@@ -339,6 +343,7 @@ export const makeAntigravityProvider = Effect.fn("makeAntigravityProvider")(func
339 commands: ReadonlyArray<EffectAcpSchema.AvailableCommand>,343 commands: ReadonlyArray<EffectAcpSchema.AvailableCommand>,
340 cwd?: string,344 cwd?: string,
341 ) {345 ) {
346 if (!settings.enabled) return;
342 const slashCommands = nativeCommands(commands);347 const slashCommands = nativeCommands(commands);
343 const updatedAt = DateTime.formatIso(yield* DateTime.now);348 const updatedAt = DateTime.formatIso(yield* DateTime.now);
344 yield* SubscriptionRef.update(metadata, (state) => {349 yield* SubscriptionRef.update(metadata, (state) => {
...@@ -371,6 +376,7 @@ export const makeAntigravityProvider = Effect.fn("makeAntigravityProvider")(func...@@ -371,6 +376,7 @@ export const makeAntigravityProvider = Effect.fn("makeAntigravityProvider")(func
371376
372 const clearAccountMetadata = Effect.fn("AntigravityProvider.clearAccountMetadata")(function* () {377 const clearAccountMetadata = Effect.fn("AntigravityProvider.clearAccountMetadata")(function* () {
373 if (options.clearUsage) yield* options.clearUsage;378 if (options.clearUsage) yield* options.clearUsage;
379 if (!settings.enabled) return;
374 const updatedAt = DateTime.formatIso(yield* DateTime.now);380 const updatedAt = DateTime.formatIso(yield* DateTime.now);
375 yield* SubscriptionRef.update(381 yield* SubscriptionRef.update(
376 metadata,382 metadata,
...@@ -380,7 +386,7 @@ export const makeAntigravityProvider = Effect.fn("makeAntigravityProvider")(func...@@ -380,7 +386,7 @@ export const makeAntigravityProvider = Effect.fn("makeAntigravityProvider")(func
380 draft: {386 draft: {
381 ...state.draft,387 ...state.draft,
382 auth: { status: "unauthenticated" },388 auth: { status: "unauthenticated" },
383 status: settings.enabled ? "warning" : "disabled",389 status: "warning",
384 message: SIGN_IN_MESSAGE,390 message: SIGN_IN_MESSAGE,
385 checkedAt: updatedAt,391 checkedAt: updatedAt,
386 models: [],392 models: [],
apps/server/src/provider/Drivers/AntigravityDriver.test.ts+4-4
...@@ -187,7 +187,7 @@ const makeHarness = Effect.fn("makeAntigravityDriverHarness")(function* (...@@ -187,7 +187,7 @@ const makeHarness = Effect.fn("makeAntigravityDriverHarness")(function* (
187 const instance = yield* AntigravityDriver.create({187 const instance = yield* AntigravityDriver.create({
188 instanceId,188 instanceId,
189 displayName: "Google test account",189 displayName: "Google test account",
190 enabled: options.enabled ?? false,190 enabled: options.enabled ?? true,
191 config: { ...AntigravityDriver.defaultConfig(), ...options.config },191 config: { ...AntigravityDriver.defaultConfig(), ...options.config },
192 environment: [192 environment: [
193 { name: "PATH", value: instancePath },193 { name: "PATH", value: instancePath },
...@@ -292,7 +292,7 @@ it.layer(layerTest)("AntigravityDriver", (it) => {...@@ -292,7 +292,7 @@ it.layer(layerTest)("AntigravityDriver", (it) => {
292292
293 it.effect.skipIf(windowsHost)("does not launch a process for a disabled instance", () =>293 it.effect.skipIf(windowsHost)("does not launch a process for a disabled instance", () =>
294 Effect.gen(function* () {294 Effect.gen(function* () {
295 const h = yield* makeHarness();295 const h = yield* makeHarness({ enabled: false });
296 const snapshot = yield* h.instance.snapshot.refresh;296 const snapshot = yield* h.instance.snapshot.refresh;
297 expect(snapshot.status).toBe("disabled");297 expect(snapshot.status).toBe("disabled");
298 expect(h.acquisitions).toEqual([]);298 expect(h.acquisitions).toEqual([]);
...@@ -322,13 +322,13 @@ it.layer(layerTest)("AntigravityDriver", (it) => {...@@ -322,13 +322,13 @@ it.layer(layerTest)("AntigravityDriver", (it) => {
322 );322 );
323323
324 it.effect.skipIf(windowsHost)(324 it.effect.skipIf(windowsHost)(
325 "refreshes a disabled instance through the selected executable and personal Google ACP",325 "refreshes through the selected executable and personal Google ACP",
326 () =>326 () =>
327 Effect.gen(function* () {327 Effect.gen(function* () {
328 const h = yield* makeHarness();328 const h = yield* makeHarness();
329 yield* h.refresh();329 yield* h.refresh();
330 const snapshot = yield* h.instance.snapshot.getSnapshot;330 const snapshot = yield* h.instance.snapshot.getSnapshot;
331 expect(snapshot.status).toBe("disabled");331 expect(snapshot.status).toBe("ready");
332 expect(snapshot.auth.status).toBe("authenticated");332 expect(snapshot.auth.status).toBe("authenticated");
333 expect(snapshot.models.map((model) => model.slug)).toEqual([333 expect(snapshot.models.map((model) => model.slug)).toEqual([
334 "gemini-test-low",334 "gemini-test-low",
packages/provider-core/src/server/managedProvider.test.ts+25
...@@ -183,6 +183,31 @@ describe("makeManagedServerProvider", () => {...@@ -183,6 +183,31 @@ describe("makeManagedServerProvider", () => {
183 ).pipe(Effect.provide(layerAlwaysRunTest)),183 ).pipe(Effect.provide(layerAlwaysRunTest)),
184 );184 );
185185
186 it.effect("does not enrich a disabled provider's snapshot", () =>
187 Effect.scoped(
188 Effect.gen(function* () {
189 let enrichmentCalls = 0;
190 const provider = yield* makeManagedServerProvider<TestSettings>({
191 resolveMaintenance: () => Effect.succeed(maintenanceCapabilities),
192 getSettings: Effect.succeed({ enabled: false }),
193 streamSettings: Stream.empty,
194 haveSettingsChanged: (previous, next) => previous.enabled !== next.enabled,
195 refreshOnInterval: false,
196 initialSnapshot: () => Effect.succeed({ ...initialSnapshot, enabled: false }),
197 checkProvider: Effect.succeed({ ...refreshedSnapshot, enabled: false }),
198 enrichSnapshot: () => {
199 enrichmentCalls += 1;
200 return Effect.void;
201 },
202 });
203
204 yield* provider.refresh;
205
206 assert.strictEqual(enrichmentCalls, 0);
207 }),
208 ).pipe(Effect.provide(layerAlwaysRunTest)),
209 );
210
186 it.effect("skips periodic provider refreshes without foreground provider-status demand", () =>211 it.effect("skips periodic provider refreshes without foreground provider-status demand", () =>
187 Effect.scoped(212 Effect.scoped(
188 Effect.gen(function* () {213 Effect.gen(function* () {
packages/provider-core/src/server/managedProvider.ts+3-1
...@@ -106,7 +106,9 @@ export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")(...@@ -106,7 +106,9 @@ export const makeManagedServerProvider = Effect.fn("makeManagedServerProvider")(
106 yield* Fiber.interrupt(previousFiber).pipe(Effect.ignore);106 yield* Fiber.interrupt(previousFiber).pipe(Effect.ignore);
107 }107 }
108108
109 if (!input.enrichSnapshot) {109 // Enrichment resolves binaries and package-manager state, which a disabled
110 // provider has no use for.
111 if (!input.enrichSnapshot || !snapshot.enabled) {
110 return;112 return;
111 }113 }
112114