Skip to content

Merge main into feature/beta - #2870

Open
aws-toolkit-automation wants to merge 211 commits into
feature/betafrom
autoMerge/feature/beta
Open

Merge main into feature/beta#2870
aws-toolkit-automation wants to merge 211 commits into
feature/betafrom
autoMerge/feature/beta

Conversation

@aws-toolkit-automation

Copy link
Copy Markdown
Collaborator

Automatic merge failed

  • Resolve conflicts and push to this PR branch.
  • Do not squash-merge this PR. Use the "Create a merge commit" option to do a regular merge.

Command line hint

To perform the merge from the command line, you could do something like the following (where "origin" is the name of the remote in your local git repo):

git stash
git fetch --all
git checkout origin/feature/beta
git merge origin/main
git commit
git push origin HEAD:refs/heads/autoMerge/feature/beta

bywang56 and others added 30 commits November 10, 2025 13:29
#2475)

* feat: differenciate implicit and explicit reject for inline completion

* fix: add UT for inline reject metric type
* fix: McpManager not initialized error

* fix: adding more try catch to avoid crashes due to mcpmanager initialization error

* fix: adding error to debug logs
* Revert "chore: patch 940da04 PR #2478 (#2482)"

This reverts commit bfd2780.

* Revert "chore: update indexing bundle to 4f4fd25d (#2478)"

This reverts commit 940da04.

* chore: update q project context assets 4f4fd25d
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Will Lo <[email protected]>
Co-authored-by: aws-toolkit-automation <>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: aws-toolkit-automation <>
* Revert "fix(amazonq): send full finding details to plugin, partial to agent (#2356)"

This reverts commit 961e6ca.

* feat(amazonq): if there are more than 30 findings, do not send to agent, only to code issues panel

* fix(amazonq): do not stop calling listFindings if there are more than 30 findings

* fix(amazonq): do not stop calling listFindings if there are more than 30 findings

---------

Co-authored-by: Blake Lazarine <[email protected]>
Error handling in `setPaidTierMode` is broken as it attempts to JSON stringify a circular type which results in the Flare process crashing. This codepath is not new but is now being hit due to a service side change.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…ead of empty object (#2492)

* fix(amazonq): prevent base64 encoding error by passing undefined instead of empty object

Fixes #8253, #7896, #8076, #8184

When userInputMessageContext was undefined, it was being replaced with an
empty object {}. The AWS SDK's base64 encoder attempted to encode this
empty object and threw: "toBase64 encoder function only accepts string |
Uint8Array".

Changed messageToStreamingMessage() and chatMessageToMessage() to pass
undefined instead of {} when userInputMessageContext is not provided.

* fix(amazonq): prevent base64 encoding error by passing undefined instead of empty object (#2459)

Fixes #8253, #7896, #8076, #8184

When userInputMessageContext was undefined, it was being replaced with an
empty object {}. The AWS SDK's base64 encoder attempted to encode this
empty object and threw: "toBase64 encoder function only accepts string |
Uint8Array".

Changed messageToStreamingMessage() and chatMessageToMessage() to pass
undefined instead of {} when userInputMessageContext is not provided.

---------

Co-authored-by: aws-toolkit-automation <[email protected]>
* feat: add MCP registry service and validator for governance (#2433)

* feat: add MCP registry service and validator for governance

* fix: fix for unit tests

* fix: fix for using httpUtils with proxy agent

* feat: add MCP registry validation and server config conversion (#2440)

* feat: add MCP registry validation and server config conversion

* fix: fix for mcpManager failures

* feat: implement MCP registry service with validation, error handling, and synchronization (#2443)

* feat(amazonq): add MCP registry sync, enterprise validation. (#2450)

* feat(amazonq): add MCP registry sync, enterprise validation, ACG support, version caching

* fix: fix for test failures

* fix: removed Agentcore check

* feat: add OCI registry support, improve MCP initialization flow (#2465)

* feat: add OCI registry support, improve MCP initialization flow, and enhance registry validation

* fix: fix for failing tests

* fix: fix to make registryActive non-optional

* fix(amazonq): separate server discovery from init (#2480)

* fix(amazonq): separate server discovery from init and improve error handling

* fix: update package-lock.json

* fix: fix for delete, save and cancel buttons for registry mcps

* fix: fix to add addiotnal header and variables to registry mcps

* fix: fix for failing registryUrl tests

* fix: move OCI environment variables to config.env and correct mcpRegistryUrl property name (#2486)

* fix: fix for arguments for local docker mcp servers (#2489)

* fix: fix for env variables for local docker mcp servers

* fix: imporve readability for oci check

* feat: add Docker env var support and enable timeout config for MCP (#2494)

* feat: add Docker env var support and enable timeout config for MCP registry servers

* fix: fix for unit tests

* fix: fix for compilation failure

* fix(amazonq): fix for server refresh

* fix: fix for server refresh

* fix: fix for server init

* fix: fix to add the mcp command in logs (#2499)

* fix: fix to add the mcp command in logs

* fix: fix to add stderr logs

* fix: fix to provide error messages for removed errors from registry (#2511)

* fix: fix upgarde the lsp version to 1.47.0

* fix: fix to provide server error messages for removed errors

* revert: revert package-lock.json changes

* Revert "fix: fix upgarde the lsp version to 1.47.0"

This reverts commit 4086962.

* revert: revert for check interval

* fix: fix for failing unit tests

---------

Co-authored-by: aws-toolkit-automation <[email protected]>
Co-authored-by: Richard Li <[email protected]>
* chore(release): release packages from branch main

* fix: fix for dependency failures

* fix: fix for install failures

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Ashish Reddy Podduturi <[email protected]>
Co-authored-by: aws-toolkit-automation <>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: aws-toolkit-automation <>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: aws-toolkit-automation <>
* Atx riv final (#2520)

* feat: add atx fes integration for transform profiles

* feat: implement Transform profile discovery via ATX FES with cache clearing

* fix: remove unsupported eu-central-1 region from ATX FES endpoints

* feat: add separate flow for RTS and ATX listavailableprofile api

* fix: remove profile handling from atxnettransformserver

* feat: separating qdev and aws transform

* fix: fixing unit tests

* fix: adding tests

* fix: updating as per langugae server runtime updates

* feat: add starttranform and workspace

* feat: added getTransformInfo and its support methods

* fix: with new runtimes

* feat: add stopjob support

* merged stopjob and added upload plan

* chore: force use of new runtimes

* fix: completed getting plan, worklogs, and final artifact

* chore: deleting unused RPC messages

* feat: added list worklogs before planning

* fix: remove unused methods

---------

Co-authored-by: Pranav Firake <[email protected]>
Co-authored-by: pranav firake <[email protected]>
Co-authored-by: Jordan Miao <[email protected]>

* fix: adding atxcredentials details

* fix: updating plan for completed status

* fix: separating aws atx and q credentials storage

* fix: changed customer_output to customer_input

* fix: added new atx-fes-client models to allow CUSTOMER_INPUT types

* fix: multiple accounts token auth

* fix: auto-sync transform profiles using TransformConfigurationServer and prevent us-east-1 defaults

* fix: set default fallback transform request from net 8 to net 10

* fix: changed back q flow to net 8, added target framework to create job requests

* fix: updates aws-server-runtimes to 0.3.8 and added Syd endpoint to constants

* fix: maintaining backwards compatibility

* fix: fixing failing test

* fix: fixing tests

* fix: get endpoints by stage

* fix: regex for appUrl not handling gamma stage and return default region

* fix: fix for initInstance and moved init of atx servers to be after base server is initialized

* fix: fixing tests

* fix: fixing tests

* fix: fixing tests

* chore: bumping lsp version to 0.3.8

* chore: revert naming from Q back to codewhisperer

* chore: deleting stale function

* chore: updating folder

* fix: changed transformserver to log caught errors instead of throwing

* chore: reverting changes and adding todo

* fix: tests with changes

* fix: tests with changes

* chore: removing debug logs

---------

Co-authored-by: Pranav Firake <[email protected]>
Co-authored-by: pranav firake <[email protected]>
Co-authored-by: Jordan Miao <[email protected]>
Co-authored-by: Sherry Lu <[email protected]>
Co-authored-by: Chris Long <[email protected]>
araarush and others added 30 commits July 9, 2026 13:49
…ironments (#2778)

* test(chat-client): cover postMessage origin handling for all host environments

Extend the Eclipse origin regression tests from #2740 to every supported IDE
host environment, so a future change to the handleInboundMessage origin check
cannot silently break a single host.

Adds a table-driven suite (HOST_ORIGIN_CASES) that mirrors the host-environment
matrix in chat-client/README.md and asserts the accept/reject outcome for each
host's origin format:
  - accepts: VS Code (vscode-webview://), JetBrains and Visual Studio and
    SageMaker (same-origin), Eclipse on macOS/Linux (WebKit same-origin),
    Eclipse on Windows (Edge WebView2 empty "" / "null" origin), and file://
  - rejects: cross-origin HTTPS, cross-origin plain-http, and same-host
    different-subdomain pages (the origin !== window.location.origin branch)

Because the origin check compares event.origin against window.location.origin,
each case runs in its own JSDOM served from the host's real page origin; the
shared about:blank harness reports origin "null", under which the same-origin
HTTP hosts would never exercise that comparison.

Test-only change; no runtime behavior is modified. Guards against regressions
of the Eclipse-on-Windows outage (Amazon-Q-Developer/amazon-q-eclipse#555, fixed in #2740).

* test(chat-client): strengthen origin coverage — opaque host reject + delivery assert

Address two gaps in the host-environment origin suite:

1. Add a reject case where the host page origin is opaque ("null") — i.e. Eclipse
   on Windows, the host the origin fix was written for. The other reject cases use
   an http(s) page, so a refactor that only enforced the check on http(s) pages
   would silently disable it on the opaque-origin host and leave every reject case
   green; this case fails on that regression. Drop the redundant plain-http reject
   case (it takes the same startsWith('http') branch as the https one).

2. Assert the accepted path positively: the message clears the origin gate and
   reaches the command router (unknown-command telemetry fires exactly once),
   rather than only asserting the absence of an untrustedOrigin rejection. A
   regression that silently swallowed inbound messages would now fail.

Test-only; no runtime behavior changes.

* test(chat-client): close per-case JSDOM to avoid mynah-ui state leak

The host-environment origin suite creates a fresh JSDOM (and a createChat /
mynah-ui instance) per case but never tore them down, so timers/observers
accumulated on the shared global window across cases. This is the same
state-leak class that made an unrelated mynah-ui test flaky under CI load
(see #2741 / #2746) and can push it past its timeout.

Track each case's JSDOM and call window.close() in afterEach so state does
not carry over. Test-only.
Co-authored-by: aws-toolkit-automation <>
…undary check (#2787)

* fix: canonicalize symlinks (including dangling links) in workspace boundary check

The workspace-boundary acceptance check (requiresPathAcceptance) canonicalized
paths with fs.realpath and, for paths that do not exist yet, fell back to
realpath(parent) + basename. That fallback returned the in-workspace link name
for a symlink whose target does not exist yet (a "dangling" symlink), so such a
path was treated as in-workspace and a create through it (e.g. fsWrite create)
could land outside the workspace without prompting for approval.

Add resolveSymlinkAwarePath, which follows a symlink at the leaf even when its
target does not exist, resolves symlinked ancestor directories and symlink
chains (with a cycle guard), and re-appends not-yet-created segments so the
result reflects where a read/write would actually land. Also canonicalize
workspace folders before the containment comparison so a workspace located
under a symlinked directory (e.g. macOS /tmp -> /private/tmp) does not produce
false prompts.

Add OS-agnostic real-filesystem tests covering dangling leaf symlinks,
symlinked ancestors, symlink chains, the existing-target regression, and the
symlinked-workspace-root case.

Also add hardening TODOs to grepSearch and lspApplyWorkspaceEdit (both
currently not enabled) to route their boundary checks through the same
symlink-aware helper before they are enabled.

* test: make symlink path assertions robust to Windows 8.3 short paths

The Windows CI runner's os.tmpdir() returns an 8.3 short path (e.g.
C:\Users\RUNNER~1\...), while fs.realpath inside resolveSymlinkAwarePath
expands it to the long form (C:\Users\runneradmin\...). The expected values
were built with path.join (string-only), so they kept the short name and
mismatched the realpath-resolved actual values.

Re-read the workspace and outside directories through fs.realpathSync after
creating them so both sides of the assertions are canonical on all platforms.

* test: normalize both sides of symlink path assertions via fs.promises.realpath

The previous attempt canonicalized the test's expected paths with
fs.realpathSync, but on Windows fs.realpathSync does not expand 8.3 short
names (e.g. RUNNER~1) while fs.promises.realpath (used by the production
resolveSymlinkAwarePath) does (runneradmin), so the assertions still
mismatched by short-vs-long form.

Add a `canon` helper that normalizes a path through fs.promises.realpath (the
same call the production guard uses), resolving the deepest existing ancestor
for not-yet-created paths, and apply it to BOTH the actual and expected values
in every path-equality assertion. This makes the assertions independent of
which 8.3/long form the platform surfaces. The production code is unchanged.

* test: de-brittle isInWorkspace call-arg assertions for cross-platform

Two existing requiresPathAcceptance tests asserted that isInWorkspace was
called with the raw workspace-folder strings and path.resolve(filePath). The
symlink-aware canonicalization now passes filesystem-canonicalized folders and
a symlink-resolved path, which on Windows differ from the raw POSIX-style test
fixtures (path.resolve adds a drive letter), so the exact-arg match failed on
the Windows runner while passing on Linux.

Replace the exact calledWith(...) checks with platform-agnostic assertions:
isInWorkspace was consulted, and with an absolute resolved path. The exact
canonical form is covered by the real-filesystem tests in symlinkBoundary.test.ts.
The behavioral assertions (requiresAcceptance true/false) are unchanged.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: aws-toolkit-automation <>
…IDC role (#2789)

* chore(amazonq): use DEXP-owned canary SSO token via OIDC for agentic-chat E2E tests

Short-term Flare fix: re-point the q-agentic-chat-server integration tests at the
DEXP-owned SSOTokenSecret in the gamma-IAD canary account, replacing the removed
Blueshift QnetTransformTokenRefresher.

- Configure AWS Credentials now assumes the least-privilege OIDC read role
  arn:aws:iam::550160095699:role/LanguageServersGitHubActionsReadRole (us-east-1).
- Remove the 'Refresh Token' lambda-invoke step; the canary SSORefreshTokenLambda
  refreshes SSOTokenSecret every ~5 min.
- Replace 'Get SSO Token' with a raw GetSecretValue + jq extraction of the
  canaryGammaIAD accessToken into TEST_SSO_TOKEN, masked via ::add-mask::.
- Tag traffic with AWS_SDK_UA_APP_ID=lsp-integ-ci for dashboard/BI segmentation.

DO NOT MERGE yet: depends on the OIDC role deploying (canary CR-290695975),
AppSec sign-off, and repo secrets TEST_SSO_START_URL + TEST_PROFILE_ARN.

* chore(amazonq): source integ-test SSO secrets from INTEG_-prefixed names

Point TEST_SSO_START_URL / TEST_PROFILE_ARN at new repo secrets
INTEG_TEST_SSO_START_URL / INTEG_TEST_PROFILE_ARN instead of the existing
TEST_SSO_START_URL / TEST_PROFILE_ARN (the env var names the test reads are
unchanged; only the secret source moves).

The old secrets still feed the current QnetTransform-based workflow, so
overwriting them would risk breaking the currently-passing tests and they are
unrecoverable once QnetTransform is torn down. New names keep old and new
isolated and preserve a clean rollback: reverting this PR restores the old
workflow + old secrets, which still work while QnetTransform is alive.
…o the client (#2794)

RTS gates Q Developer plugin traffic in QDevPluginAccessGateHandler: requests whose
user-agent carries the shared AWS-Language-Servers-AWS-CodeWhisperer language-server
token are checked, and Builder ID identities created on or after 2026-07-25 are denied
with AccessDeniedException reason=FEATURE_NOT_SUPPORTED. IdC identities are exempt.

Because the gate runs before the activity, a blocked identity fails every operation.
Today that surfaces as unexplained failures -- the first one being the A/B config fetch
moments after credentials arrive -- and the customer is left with a silently
non-functional plugin and no indication why.

Detect it centrally and surface the service's own message.

isQDevPluginAccessBlockedError classifies the rejection. The match is deliberately
narrow: reason must be exactly FEATURE_NOT_SUPPORTED, so the other modeled reasons do
not match. TEMPORARILY_SUSPENDED especially, since it is transient and recoverable, and
treating it as permanent would strand a user whose access is returning. Matching is by
exception name rather than instanceof, because the same modeled exception is generated
separately into the runtime and streaming clients and callers rethrow it wrapped; the
cause chain is walked for the same reason, with a visited set so a cyclic chain
terminates.

Detection is a passthrough middleware on the token client, registered on the outermost
initialize step so the error is observed once per operation after retries are exhausted
rather than once per attempt. It always rethrows the original error unchanged, and the
observer runs inside its own try/catch, so no existing operation's error handling or
retry behaviour changes and a faulty observer cannot mask a service error. When no
observer is supplied the middleware is not registered at all, leaving AtxTokenServiceManager
and toolServer -- which construct services without one -- behaviourally identical.

The observer is a late-bound property on CodeWhispererServiceToken rather than a
constructor parameter, mirroring the existing shareCodeWhispererContentWithAWS closure in
the same constructor, so no call site signature changes.

The reaction goes out over the existing showNotification channel. This matters for
rollout: the language server ships ahead of the plugins, and every plugin version already
in the market will pick up this server. The runtime already gates showNotification on the
client-advertised awsClientCapabilities.window.notifications capability, so plugins that
know nothing about this receive nothing and are unaffected, while plugins that do
advertise it get the real reason instead of a silent failure. No new protocol message and
no client change are required for that to hold.

The service message is shown verbatim rather than substituting our own copy:
FEATURE_NOT_SUPPORTED is reused across several RTS gates, so the reason tells us that
access is blocked while only the message says why and what to do about it. The notifier
fires at most once per instance, since otherwise a blocked identity would produce one
notification per API call, and the dedupe is scoped to the instance rather than the
process so that switching accounts notifies again instead of being suppressed.

notification is added to QServiceManagerFeatures as optional so that every existing
construction site, including partial test fixtures, keeps compiling and stays inert
without it.

Signing out and showing a blocking screen remain the plugin's responsibility and are not
attempted here.

Verified: tsc, prettier and eslint clean; 14 new unit tests pass; the suites covering
every touched module were baselined against a worktree at HEAD and show identical
results, with the same pre-existing failures on both sides.
…d beam discovery/download (#2798)

* feat: scope local build verification to the loaded beamed repo and add beam discovery/download

* fix: only attach StepId to local-build-verification HITL when present

The beam LBV early-return always included a StepId field, so a HITL
with no stepId returned { HitlTag, TaskId, StepId: undefined }. The
existing unit test asserts the return deep-equals { HitlTag, TaskId },
which the extra key broke. Attach StepId only when defined so the
non-beam return shape is unchanged; beam jobs still carry the stepId.

* fix: address PR review — escape jobId, validate beam-map, guard zip-slip, tests

Addresses inline review comments on PR #2798:

- Regex injection/ReDoS: escape parentJobId before interpolating into
  new RegExp() in listBeamedRepos.
- Unvalidated beam-map JSON: shape-validate downloadJsonArtifact result
  (only objects yielding a non-empty repo name survive; malformed/null
  entries rejected + logged) before it drives artifact selection.
- Zip-slip: extractAllEntriesTo now resolves each entry against the
  extraction root and skips (logs) entries that escape via ../ or
  absolute paths. downloadBeamArtifact adds defensive destDir validation
  (rejects non-absolute, ..-containing, or empty paths).
- Backoff jitter: throttle retries use base * (0.5 + Math.random()).
- Typed contract: new BeamMapRepo / BeamedRepoInfo interfaces; listBeamedRepos
  returns Promise<BeamedRepoInfo[]>. Removes `any` from the beam discovery
  path.
- Bounded candidate scan: cap at BEAM_MAP_SCAN_MAX_CANDIDATES = 25 and
  BEAM_MAP_SCAN_BUDGET_MS = 15000 to keep listBeamedRepos responsive on
  artifact-heavy jobs.
- Shared scoped-HITL helper: selectScopedLbvHitl centralizes the
  scoped-LBV selection previously duplicated between getHitlAgentArtifact
  and the EXECUTING path.
- Central getStepId helper: single source of truth for the
  stepId ?? planStepId ?? parentStepId coalescing across all call sites.

Test coverage:
- New Beam to IDE unit suite for getStepId, normalizeBeamRepo, and
  listBeamedRepos (empty / beam-map / beam-status fallback / hash-suffix /
  regex-edge / send-failure), plus downloadBeamArtifact destDir rejection
  and a zip-slip regression test in utils.test.ts.

Deferred as tracked follow-ups (reviewer flagged non-blocking):
- Silent error swallowing → {repos, hadErrors}: return-shape change needs
  coordinated IDE-client update.
- Extract BeamRepoService: ~700-line refactor; hold for a dedicated PR to
  avoid pre-release regression risk on the shared handler.
… client (#2800)

* fix(amazonq): pass notification feature to the Q service manager (#2796)

The access-blocked notification added in #2794 never reached the client.
AmazonQServiceServerFactory destructures the features it forwards to the service
manager, and notification was not among them, so features.notification was always
undefined, the guard in serviceFactory never passed, onAccessBlocked was never
assigned, and the notifier could not run.

notification is optional on QServiceManagerFeatures so that existing constructions
and test fixtures keep compiling. That is also why omitting it here did not fail the
build -- it silently disabled client-facing reporting instead. Noted at the call site
so the next person adding a feature there does not repeat it.

Also set a stable id on the notification. Clients need to recognise it without
inspecting its text: the message is the service's own copy and is expected to change,
and FEATURE_NOT_SUPPORTED is reused across several RTS gates so the reason alone does
not identify this one. Both IDE clients already prefer the id when present and fall
back to matching the title only because the released server does not send one yet.

Verified: tsc clean, prettier clean, 6/6 notifier tests pass, and a server bundle
built from this branch contains the wiring where a bundle from the previous head did
not.

* fix(amazonq): declare serverInfo so notifications reach the client (#2797)

* fix(amazonq): declare serverInfo so notifications reach the client

The access-blocked notification still never reached the client after #2796. The
runtime only constructs a notification router for servers that declare serverInfo:

    if (initializeResult?.serverInfo) {
        this.notificationRouter = new RouterByServerName(initializeResult.serverInfo.name, ...)
    }

AmazonQServiceServer returned only capabilities and awsServerCapabilities, so the
router was never built and notification.showNotification() logged "Notifications are
not supported: serverInfo is not defined" and dropped the notification. Observed in
VS Code: the block was detected and logged, then silently discarded.

This is the last piece. With #2794 (detect), #2796 (wire) and this change (deliver),
a blocked identity produces a notification the client can act on.

Added a regression test, because the failure mode is silent: nothing throws and only
a debug line marks the loss. The test asserts the exact name, which is deliberate --
the name is encoded into the id of every notification the client echoes back, so
renaming it strands followups for notifications already on screen.

Note: amazonQServer.test.ts has one pre-existing failure on this branch,
"hooks onUpdateConfiguration handler to LSP server", present before this change
(6 passing/1 failing before, 7 passing/1 failing after). Left alone as unrelated.

* fix(amazonq): observe access-blocked on the streaming client too

The observer added in #2794 was only on the token client. Chat runs through the
streaming client, so the one surface where a blocked identity actually shows up to the
user was the one place nothing was watching. Detection happened to work anyway because
the gate denies every operation and the A/B config fetch goes through the token client
moments after credentials arrive -- but that is incidental, not a guarantee.

Mirrors the token client exactly: middleware on the outermost initialize step so it
fires once per operation after retries are exhausted, the observer is called inside its
own try/catch, and the error is always rethrown so callers behave as before.

The notifier is now created once per service generation and shared by both clients
rather than created per client. The notifier dedupes per instance, so sharing is what
keeps a blocked identity to a single notification no matter which client sees it first.
It is cleared by resetCodewhispererService, so signing out and back in with another
blocked identity notifies again instead of being suppressed.

Scoped to StreamingClientServiceToken. The IAM variant serves a different surface and
the gate only denies Builder ID, which is bearer-token only.

Pre-existing failures on this branch, unchanged by this commit: utils.test.ts 11
failing (89 passing) and amazonQServer.test.ts 1 failing, both identical before and
after.

* fix(amazonq): give the IAM and token servers distinct serverInfo names (#2799)

The serverInfo added in #2797 used one hardcoded name, but
AmazonQServiceServerFactory is instantiated twice -- AmazonQServiceServerIAM and
AmazonQServiceServerToken -- and runtimes including agent-standalone register both. Two
servers reporting the same name makes lspRouter reject initialize outright:

    Duplicate servers defined: AWS Language Server for Amazon Q Developer

That fails the whole language server, not just the duplicate. Observed in VS Code as:

    Failed to start downloaded LSP, falling back to bundled LSP:
    Duplicate servers defined: AWS Language Server for Amazon Q Developer

The client then silently ran its bundled server instead, so Q appeared to work while
none of the access-blocked reporting existed, with only a client-side warning to show
for it.

serverName is now a required parameter rather than a shared constant, since a default
is precisely what let two instantiations collide. The two names are exported so the
uniqueness is assertable, and they must stay stable: the name is encoded into the id of
every notification the client echoes back.

Added a regression test on the distinctness. Verified it bites -- reintroducing the
collision gives 7 passing/2 failing, the fix gives 8 passing/1 failing. No existing
test registers two servers from one runtime, which is why this reached a release.

Pre-existing failure on this branch, unchanged: amazonQServer.test.ts
"hooks onUpdateConfiguration handler to LSP server".

* test(amazonq): address review findings on the access-blocked observer (#2801)

Three review follow-ups, no behaviour change for users.

Name the streaming client's middleware, matching the token client. Without a name a
second registration stacks another observer rather than replacing the first, which would
report the same block twice, and the middleware is anonymous in SDK stack introspection.

Assert the server-name uniqueness against the real exported servers rather than the two
constants. Comparing constants cannot catch the same name being passed to both factory
calls, which is the mistake that actually shipped. Verified the test bites: making the
names identical fails it (7 passing/2 failing vs 8/1).

Add two tests for the streaming observer. They assert the wiring rather than the callback
because the existing harness stubs CodeWhispererStreaming.prototype.sendMessage, which
bypasses the middleware stack entirely -- a behavioural test there would pass even if the
middleware did not exist.

shared group: 337 passing / 45 failing, against 334 / 45 before, so the 3 new tests and
no new failures.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: aws-toolkit-automation <>
…2838)

The repo moved from aws/language-servers to
Amazon-Q-Developer/language-servers (P490405625).

CODEOWNERS still referenced @aws/flare. Team grants do not follow a repo
across orgs, so GitHub cannot resolve that team and reviewer assignment
is broken while main still requires code owner review. Point it at
@Amazon-Q-Developer/sync-team-dae-production-eng-team, which has push
access on the repo.

The repository.url fields in all nine workspace package.json files also
still referenced the old org. Publishing uses OIDC trusted publishing,
which validates repository.url against the OIDC claims of the building
repository and generates provenance from them, so stale URLs fail the
publish step.
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 #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.
…em silently (#2841)

When a tool-use content block is streamed but the response ends before its terminating
`stop` event (e.g. the output-token limit is reached mid tool-input), the tool-use input
is never JSON-parsed and no error is recorded, so the parser reports success. The agentic
loop keeps only stopped tool uses as pending, so the unterminated one is filtered out, the
turn is reported as Succeeded, and the loop breaks -- the tool never runs and the user sees
no error or retry.

Add AgenticChatEventParser.finalize(), called once the response stream is fully consumed:
any tool use still lacking a stop is marked stopped and given an incomplete-input error
(reusing the malformed-JSON prefix) so it survives the pending-tool-use filter and is routed
into the existing recovery path, which re-prompts the model to split the work into smaller
tool uses. User cancellation is unaffected (aborts throw before finalize runs).
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* fix: scope and forward stepId for the planning-branch lbv hitl

The AWAITING_HUMAN_INPUT path already scopes the local-build-verification
HITL to the loaded beamed repo and forwards its plan-step id, but the
PLANNING branch did neither: it picked the first LBV HITL in the list and
returned it without StepInformation. On a multi-repo beam where the job
sits in PLANNING at build time, that surfaces a sibling's (or untagged)
HITL, so the IDE scope guard cannot confirm ownership and defers the build
indefinitely.

Bring the PLANNING branch to parity with AWAITING_HUMAN_INPUT:
- prefer the in-scope LBV via selectScopedLbvHitl (no-op when scope is
  empty, so non-beam behavior is unchanged)
- forward StepInformation.StepId when present

Verified live on a 3-repo beam: each loaded repo now builds and siblings
are correctly deferred.

* fix: suppress out-of-scope sibling LBVs in the planning branch

Brings the PLANNING branch of getTransformInfo to full parity with the
EXECUTING / getHitlAgentArtifact paths for multi-repo beam. It already
preferred the loaded repo's in-scope LBV and forwarded its stepId, but it
did not suppress out-of-scope sibling LBVs: when scope was set with no
in-scope LBV it could still surface a sibling's LBV HITL to the IDE.

Mirror the sibling branches:
- when scope is set and every pending HITL is a sibling's LBV, return
  plan-only (surface nothing)
- otherwise drop out-of-scope LBVs from the fallback pool so a sibling's
  LBV can't be picked in a mixed pending set

Not a live false-green (the IDE scope guard already rejects a HITL whose
stepId is out of the loaded subtree) — this restores the LSP-side layer so
all three branches behave identically. Non-beam is byte-identical: the new
logic is gated on a non-empty beam scope.

* fix: harden beam LSP stepId coalescing and tidy beam docs

- getStepId uses || so an empty-string id falls through to the next spelling
  (was ?? which let an empty id defeat coalescing and scope matching)
- move the normalizeBeamRepo JSDoc onto normalizeBeamRepo
  (was stranded above getStepId)

* test: cover beam LBV planning-scope and getStepId coalescing

- PLANNING branch: a sibling repo's out-of-scope LBV is not surfaced
- getStepId: empty stepId falls through to planStepId/parentStepId (|| not ??)
…es in telemetry (#2847)

* fix(amazonq): only retry tool-use streams that were genuinely truncated

Treating every response stream that ends without a terminating tool-use `stop`
event as a truncated tool input is too broad. A stream also ends without `stop`
when the request is aborted (response-processing timeout or cancellation), and
when the model announced a tool use but streamed no input at all. Reporting those
as failures and re-prompting the model produces failed intermediate stream events
for turns that were not broken, and can re-run the agent loop without making
progress.

- finalize() now only reports an incomplete tool input when partial input was
  actually received and the request was not aborted; other unterminated tool uses
  are left unstopped and filtered out downstream, as before.
- The abort state is passed into finalize() from the response processor.
- Consecutive incomplete tool-use retries are now bounded
  (MAX_INCOMPLETE_TOOL_USE_RETRIES). On exceeding the limit the agent loop stops
  and surfaces an actionable error instead of retrying indefinitely.

Genuine truncation (partial input present, request not aborted) still routes into
the existing recovery path and is retried.

* fix(amazonq): allow 3 incomplete tool-use retries before giving up

* feat(amazonq): classify incomplete tool-use retries in invokeLLM telemetry

A response stream whose tool-use input is cut off is retried inside the agent
loop and usually recovers within the same user turn. Every one of those
iterations emits amazonq_invokeLLM with result='Failed', so a per-call success
rate built on that metric drops even though the user was unaffected.

Report a `reason` alongside the existing result so the two cases can be told
apart downstream:

  INCOMPLETE_TOOL_USE_RETRYING   retry budget remains; transient, recovers
  INCOMPLETE_TOOL_USE_EXHAUSTED  retries used up; the user sees an error

The classification is computed before the emit. Because the retry budget is
bounded, whether this iteration will be retried is already known at that point,
so no post-hoc correlation is needed.

result stays 'Failed' in both cases, so raw failure counts are unchanged and
remain available for diagnostics. Consumers can now exclude the transient class
from success-rate calculations while still counting the terminal give-up.

The reason values are consumed by ToolkitTelemetryLambda to emit a separate EMF
counter; renaming them requires updating that transform first.

Retry behaviour is unchanged: incrementing the counter before the emit and
testing `count <= MAX_INCOMPLETE_TOOL_USE_RETRIES` preserves the existing
off-by-one, so 3 retries still follow the initial failure.

* chore(amazonq): describe the telemetry reason consumer generically

The do-not-rename note on the reason constants pointed at a specific internal
consumer by name. Describe it as a downstream metrics pipeline instead: the
warning is what matters to anyone editing these values, and the constants are
part of a contract rather than a link to one particular implementation.

No functional change.
Co-authored-by: aws-toolkit-automation <>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Laxman Reddy <[email protected]>
Co-authored-by: aws-toolkit-automation <>
…bvPending (#2849)

- listBeamedRepos: derive repo name from both subdir (<repo>_<hash>/file.zip) and flat
(<repo>_<hash>[_suffix].zip) transformed-source shapes, so a flat-named repo is no
longer dropped from the beamed list.
- Add optional Lightweight param: the IDE poll-refresh sets it to skip the beam-map
download scan (throttle-safe); the IDE preserves stepId across lightweight ticks.
- Add IsLbvPending (beamed but LBV HITL not created yet) via isRepoLbvHitlPending, so
the IDE gates Load (IsLbvOpen && !IsLbvPending) until the HITL exists.
getTransformInfo already resolves the interactive mode from the job
objective (cachedInteractiveMode) but never returned it. Add the
InteractiveMode field to AtxGetTransformInfoResponse and populate it at the
getTransformInfo wrapper so the IDE can restore the correct mode after a
restart instead of trusting its local settings store.

Paired with the IDE change in aws-toolkit-visual-studio-staging.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: aws-toolkit-automation <>
The prerelease workflow interpolated github.event values directly into
inline `run:` script bodies. Because GitHub substitutes those expressions
textually before the shell parses the script, a crafted branch name or
workflow input could terminate the surrounding quoting and run arbitrary
commands on the runner.

Move each untrusted value (inputs.tag_name, workflow_run.head_branch,
workflow_run.head_sha) into a step-level `env:` block and reference it as
a shell variable, so the value is always treated as data. This matches
the pattern the create-release job in this workflow already uses.

No behavior change: tag and prerelease names are unchanged for main,
feature/*, and release/agentic/* branches, and unsupported branches still
fail the same way.
…eps (#2857)

* feat(amazonq): render unit-test-generation substeps as status-only

Mark the direct substeps of the "Generate Unit Tests" step (plan / generate /
merge / coverage) as status-only so the IDE renders them as progress-only rows,
without a checkpoint toggle, "View Results" button, or checkpoint checkbox.

The step data returned by the service has no machine-readable step label, so the
flag is assigned structurally during plan-tree assembly based on the parent
step's name rather than a label prefix. The parent step keeps its normal
checkpoint affordance.

* feat: forward generate_unit_tests choice into ATX job objective (#2855)

Include GenerateUnitTests in the CreateJob objective only when it is a real boolean,

so clients that omit it keep legacy behavior and an explicit false stays a decline.

Matches shipped backend contract CR-298620129. Adds 4 unit tests.

---------

Co-authored-by: Meha Sharma <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: aws-toolkit-automation <>
Bind the customVersion and versionIncrement workflow_dispatch inputs to
step-level environment variables instead of interpolating them into the
inline shell script, so the values are passed as data rather than
expanded into the script source.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.