feat(amazonq): initialize Q services when credentials arrive - #2840
Merged
ashishrp-aws merged 1 commit intoAug 17, 2026
Merged
Conversation
The token service issues its first service call from its constructor, and the service is built lazily by whichever consumer asks first. That consumer is the chat webview finishing boot, measured at ~0.66s after the credentials landed. Nothing contacts the service in that window, so a rejected identity cannot be discovered and the user sits in front of a chat view that is never going to work. Uses onCredentialsUpdated, added in language-server-runtimes 0.3.21, to build the services as soon as bearer credentials arrive. The dead code this replaces -- an `in` check plus an `any` cast, added in Amazon-Q-Developer#2521 -- was reaching for this event before the runtime had it, so it never fired. Reuses handleSsoConnectionChange rather than constructing anything, so this changes only when initialization happens, not how: - Idempotent. createCodewhispererServiceInstances records the connection type, so the consumer's later call short-circuits instead of resetting live services. This matters beyond tidiness: the event fires on every token refresh, and rebuilding would drop in-flight requests and replace the service that observers are attached to. - IdC with developer profiles still stops at PENDING_Q_PROFILE and builds nothing, so no request is made before a profile is chosen. - IAM updates are ignored. - Failures are logged, not thrown: this runs inside the client's credentials request, and the lazy path still runs for whoever asks first, so a failure costs the head start only. Checked for regressions rather than assumed: the opt-out header defaults to the conservative value and configuration is read at onInitialized, long before sign-in, so an earlier request cannot leak content for a user who opted out. getConnectionType is accurate because the runtime awaits connection metadata before storing credentials. One behaviour change worth noting: ProfileStatusMonitor.emitAuthSuccess, and therefore MCP registry sync, now fires ~0.66s earlier. Tests: AmazonQTokenServiceManager 40 passing/3 failing against 35/3 on main; shared group 342/45 against 337/45. The 3 and 45 are pre-existing and unchanged.
chungjac
approved these changes
Aug 17, 2026
laileni-aws
approved these changes
Aug 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Depends on
@aws/language-server-runtimes0.3.21 (Amazon-Q-Developer/language-server-runtimes#779), which is published. Dependency floor bumped from^0.3.19.Problem
The token service issues its first service call from its constructor, and the service is built lazily by whichever consumer asks first. In practice that consumer is the chat webview finishing boot. From a real session:
~0.66s in which nothing has contacted the service. For an identity the service rejects, that is 0.66s of a user sitting in front of a chat view that is never going to work, before we can tell them why.
The dead code this replaces was reaching for exactly this event:
Added in #2521, guarded by an
incheck and ananycast, and never fired because the runtime had no such member.Change
handleOnCredentialsUpdatednow callshandleSsoConnectionChange()— the same function the lazy path calls. This changes when initialization happens, not how. It also removes theanycast and the capability check in favour of optional chaining, so a build running on an older runtime simply never receives the event.Regression analysis
I checked these rather than assuming them:
createCodewhispererServiceInstancesrecords the connection type, so later calls short-circuit on "Connection type did not change". Without this, every refresh would reset services, dropping in-flight requests and replacing the instance observers are attached to. Test asserts the same instance survives three eventsPENDING_Q_PROFILEand builds nothing, so no request is made until a profile arrives. Test asserts thisshareCodeWhispererContentWithAWSdefaults tofalse, and configuration is read atonInitialized, long before sign-in. An earlier request cannot leak content for a user who opted outhandleBearerCredentialsMetadatabeforesetCredentials, which is where the event fires, sogetConnectionType()is already correctBehaviour changes: Builder ID and IdC-without-profiles build services ~0.66s earlier;
ProfileStatusMonitor.emitAuthSuccess— and therefore MCP registry sync — fires ~0.66s earlier.Testing
PENDING_Q_PROFILE, no throw without credentialsAmazonQTokenServiceManager: 40 passing / 3 failing vs 35 / 3 onmainsharedgroup: 342 / 45 vs 337 / 45 onmaintscand prettier clean, against the published 0.3.21 rather than a locally patched copyBranched from current
main(43e44dc5a).Known limitation
This removes the ~0.66s wait, not the service round trip, so a rejected identity is discovered in roughly 0.9s rather than 1.5s. Fully eliminating the window means holding the chat reveal until the first call resolves, which would stall every healthy sign-in — a separate product decision.
One thing worth a real-IDE check before merge: the block notification can now arrive while the JetBrains chat webview is still booting rather than after it, so the panel swap may overlap chat panel construction. VS Code is unaffected, since its login view is driven by context keys.