src/vs/platform/agentHost/node/agentModelRefreshScheduler.ts

86 LOC · 86 covered · 0 uncovered · 5 ranges · 5 concepts · 3 introducers · 4 tests

File neighbourhood

The centred file is linked to every concept that introduces one of its ranges, every test that runs code from the file, and the gray connector concepts standing between those tests and the file's own introducer concepts. Undirected links join concepts to every file where they introduce source and concepts to the tests they introduce; arrows show specialization between the displayed concepts and bridge only concepts omitted from this view. Concept colors match the source ranges below; connector concepts have no source color and are shown in gray.

Focused file, its introducer and connector concepts, their introduced files, and tests that run code from the file

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the related-file, concept, and source links on this page.

Focused file, its introducer and connector concepts, their introduced files, and tests that run code from the filesrc/vs/base/common/async.ts · 2749 LOCcommon/async.tsagentModelRefreshScheduler.test|title=AgentModelRefreshScheduler registering another agent does not postpone the next tick|occurrence=1 · 0 introduced LOCagentModelRefreshSchedul…agentModelRefreshScheduler.ts ×1 · 4 introduced LOCagentModelRefreshSchedul…agentModelRefreshScheduler.test|title=AgentModelRefreshScheduler ticks every registered agent repeatedly and stops on dispose|occurrence=1 · 0 introduced LOCagentModelRefreshSchedul…agentModelRefreshScheduler.ts ×1 · 2 introduced LOCagentModelRefreshSchedul…agentModelRefreshScheduler.ts ×3 · 81 introduced LOCagentModelRefreshSchedul…agentModelRefreshScheduler.test|title=AgentModelRefreshScheduler a failing or unimplemented refresh does not stop the other agents or later ticks|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/platform/agentHost/test/node/agentModelRefreshScheduler.test|title=AgentModelRefreshScheduler a failing or unimplemented refresh does not stop the other agents or later ticks|occurrence=1agentModelRefreshSchedul…agentModelRefreshScheduler.test|title=AgentModelRefreshScheduler does not tick while no agents are registered, and starts once one appears|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/platform/agentHost/test/node/agentModelRefreshScheduler.test|title=AgentModelRefreshScheduler does not tick while no agents are registered, and starts once one appears|occurrence=1agentModelRefreshSchedul…agentModelRefreshScheduler.test|title=AgentModelRefreshScheduler registering another agent does not postpone the next tick|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/platform/agentHost/test/node/agentModelRefreshScheduler.test|title=AgentModelRefreshScheduler registering another agent does not postpone the next tick|occurrence=1agentModelRefreshSchedul…agentModelRefreshScheduler.test|title=AgentModelRefreshScheduler ticks every registered agent repeatedly and stops on dispose|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/platform/agentHost/test/node/agentModelRefreshScheduler.test|title=AgentModelRefreshScheduler ticks every registered agent repeatedly and stops on dispose|occurrence=1agentModelRefreshSchedul…Focused file · src/vs/platform/agentHost/node/agentModelRefreshScheduler.ts · 86 LOCnode/agentModelRefreshSc…

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the related-file, concept, and source links on this page while the interactive map is unavailable.

1 > /*--------------------------------------------------------------------------------------------- agentModelRefreshScheduler.ts ×3
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import { IntervalTimer } from '../../../base/common/async.js';
7 > import { Disposable } from '../../../base/common/lifecycle.js';
8 > import { IObservable, autorun } from '../../../base/common/observable.js';
9 > import { ILogService } from '../../log/common/log.js';
10 > import { IAgent } from '../common/agentService.js';
11 >
12 > /**
13 > * How often every provider re-enumerates its model catalog.
14 > *
15 > * Model refreshes are otherwise edge-triggered — authentication, transport
16 > * flips, client restarts — so without a periodic tick a model added on the
17 > * service side stays invisible until the GitHub token happens to rotate, which
18 > * on a long-lived window can be hours or never.
19 > */
20 > export const MODEL_REFRESH_INTERVAL_MS = 10 * 60 * 1000;
21 >
22 > /**
23 > * Ticks {@link IAgent.refreshModels} across every registered provider on a
24 > * fixed interval.
25 > *
26 > * Lives in the host rather than the client because model freshness is provider
27 > * truth: only the provider knows its backend, holds the credential, and owns
28 > * the stale-write and backoff policy. Keeping the timer here also means one
29 > * tick per provider regardless of how many windows are connected, and requires
30 > * no AHP surface — the existing `models` observable already fans a change out
31 > * through `RootAgentsChanged` to every client.
32 > *
33 > * A tick is cheap when nothing changed: providers short-circuit without a
34 > * credential, and `AgentSideEffects` compares the published `AgentInfo[]`
35 > * before dispatching, so an unchanged catalog produces no protocol traffic.
36 > */
37 > export class AgentModelRefreshScheduler extends Disposable {
38 >
39 > private readonly _timer = this._register(new IntervalTimer());
40 > private _agents: readonly IAgent[] = [];
41 > private _isTimerRunning = false;
42 >
43 > constructor(
44 > agents: IObservable<readonly IAgent[]>,
45 > /**
46 > * Tick cadence, normally {@link MODEL_REFRESH_INTERVAL_MS}. Passed in
47 > * rather than read from an overridable field because the timer is armed
48 > * from this constructor, which runs before a subclass could install its
49 > * own value.
50 > */
51 > intervalMs: number,
52 > @ILogService private readonly _logService: ILogService,
53 > ) {
54 > super();
55 >
56 > // Start ticking once there is at least one provider, and stop again if
57 > // they all go away. Provider changes update the snapshot read by each
58 > // tick without re-arming the timer: dynamically registering Codex must
59 > // not postpone the next refresh for providers that were already present.
60 > this._register(autorun(reader => {
61 > this._agents = agents.read(reader);
62 > if (this._agents.length === 0) {
63 > this._timer.cancel(); agentModelRefreshScheduler.ts ×1
64 > this._isTimerRunning = false;
65 > return;
66 > }
67 > if (!this._isTimerRunning) { agentModelRefreshScheduler.ts ×3
68 > this._timer.cancelAndSet(() => this._refreshAll(this._agents), intervalMs);
69 > this._isTimerRunning = true;
70 > }
71 > }));
72 > }
73 >
74 > private _refreshAll(agents: readonly IAgent[]): void {
75 > for (const agent of agents) {
76 > if (!agent.refreshModels) {
78 > }
79 > const provider = agent.getDescriptor().provider; agentModelRefreshScheduler.ts ×3
80 > this._logService.trace(`[AgentHost] Periodic model refresh for ${provider}`);
81 > // `refreshModels` is contractually non-rejecting, but a provider bug
82 > // must not take down the tick for the providers after it.
83 > agent.refreshModels().catch(err => this._logService.error(err, `[AgentHost] Periodic model refresh failed for ${provider}`));
84 > }
85 > }
86 > }