Skip to content

Add Discard changes button to the Agent Changes view#356

Draft
anderson-joyle wants to merge 6 commits into
mainfrom
andersonf/discard-changes-2
Draft

Add Discard changes button to the Agent Changes view#356
anderson-joyle wants to merge 6 commits into
mainfrom
andersonf/discard-changes-2

Conversation

@anderson-joyle

Copy link
Copy Markdown
Contributor

Summary

Adds a Discard changes button to the Agent Changes view and restores selected local changes to their last-synced baseline through a local-only, projection-aware Sync/LSP operation.

This replacement branch is based on the latest main and supersedes #349.

Resolves #343.

Behavior

  • Enables discard only when local changes exist and no sync operation is running.
  • Recomputes local changes from disk before discard instead of trusting stale tree state.
  • Keeps workspace tracking active when the initial local-diff request fails, allowing later file events to retry.
  • Deletes locally created files and restores updated or deleted text resources from the cached cloud baseline.
  • Preserves directory-based component-collection references through a durable hidden baseline maintained across clone, pull, push, sync, and retarget flows.
  • Removes invalid replacement reference entries when restoring the authoritative manifest.
  • Deletes created knowledge attachment metadata and payload atomically, rolling metadata back if payload deletion fails.
  • Reports partial outcomes whenever skipped or residual local changes remain; success is shown only when the workspace is clean.
  • Returns remaining local changes from the LSP request and refreshes the Agent Changes tree directly.

Design

  • WorkspaceSynchronizer.DiscardLocalChanges owns cache restoration and projection-aware file handling in the shared Sync layer.
  • powerplatformls/discardLocalChanges combines fresh disk projection with compiled component-collection state before applying discard.
  • Local change calculation remains credential-free and does not require Dataverse access.
  • The TypeScript command handles orchestration, confirmation, progress, telemetry-safe reporting, and tree replacement.

Testing

  • CopilotStudio.Sync unit tests: 525 passed / 0 failed
  • Extension host tests: 159 passed / 0 failed
  • TypeScript type-check and ESLint: passed
  • Discard LSP endpoint regression: passed

anderson-joyle and others added 6 commits July 23, 2026 17:52
Adds a "Discard changes" title-bar button (arrow-back icon) to the Agent
Changes view that reverts all of the selected agent's local changes back
to their last-synced baseline, entirely offline. Resolves #343.

Behavior:
- Enabled only when local changes exist and no sync is running
  (mcs.agentChangesView.hasLocalChanges && !mcs.isSyncing).
- Prompts for the agent when more than one workspace is connected, then
  shows a modal confirmation with the local-change count.
- Per change: locally added files are deleted; locally updated/deleted
  files are rewritten from the cached (getCachedFile) baseline.
- Binary changes the text-only cache cannot restore (the agent icon and
  knowledge file attachments) are skipped and reported so the user can
  restore them with Get.

The revert logic lives in a pure, dependency-injected module
(sync/discardChanges.ts) with host tests; the command module wires the
real language-server cache read and workspace filesystem, holds the sync
busy state for the operation, and refreshes the Agent Changes tree.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 29babeb3-e4ad-4c53-a6e8-60b0a5dbbe38
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Move discard restoration into the Sync/LSP layer so shared manifests,
workflow pairs, CLI connection references, and missing directories are
handled from the cached projection without authenticated refresh work.
Preserve unresolved changes on refresh failures and redact agent names in
telemetry.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 35147f40-12f6-448f-81cf-915987e9414c
Run the discard integration test against a temporary workspace copy so it
cannot mutate shared test output or race workspace compiler tests. Assert the
restored topic outcome without depending on unrelated baseline projection
change counts.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 35147f40-12f6-448f-81cf-915987e9414c
Show picker cancellation and missing-workspace failures in the VS Code UI,
matching existing sync command behavior. Preserve useful text when a command
rejects with a non-Error value while keeping telemetry PII redaction.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 35147f40-12f6-448f-81cf-915987e9414c
Keep workspace tracking active after bootstrap failures, restore directory references from a durable baseline, and make knowledge attachment discard atomic and accurately reported.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8f9c2dec-ba43-4b17-b031-8f143c5cf2a8
Copilot AI review requested due to automatic review settings July 23, 2026 22:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an end-to-end Discard changes capability to the VS Code extension’s Agent Changes view by introducing a new local-only LSP endpoint backed by projection-aware logic in CopilotStudio.Sync, enabling offline restoration of last-synced baselines.

Changes:

  • Adds a Discard changes UI command (title bar + command palette) and orchestration in the extension.
  • Introduces powerplatformls/discardLocalChanges and Sync-layer discard APIs/results to revert local changes from the cached baseline.
  • Makes local-diff calculation credential-free and adds unit/host test coverage for the new flows.

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/vscode-extensions/microsoft-powerplatformlang-extension/package.json Contributes the new Discard command to the Agent Changes view and command list.
src/vscode-extensions/microsoft-powerplatformlang-extension/client/src/types.ts Adds Discard result contracts and simplifies DiffRequest for credential-free local diff.
src/vscode-extensions/microsoft-powerplatformlang-extension/client/src/tests/host/workspaceScm.test.ts Adds host-test coverage for initial local diff failure handling.
src/vscode-extensions/microsoft-powerplatformlang-extension/client/src/tests/host/discardChanges.test.ts Adds host-test coverage for discard telemetry formatting and completeness logic.
src/vscode-extensions/microsoft-powerplatformlang-extension/client/src/sync/workspaceScm.ts Adds local-change replacement support and adjusts local diff fetching/initial error handling.
src/vscode-extensions/microsoft-powerplatformlang-extension/client/src/extension.ts Registers the new Discard Changes command at activation.
src/vscode-extensions/microsoft-powerplatformlang-extension/client/src/constants.ts Adds the new LSP method name constant for discard.
src/vscode-extensions/microsoft-powerplatformlang-extension/client/src/commands/discardChanges.ts Implements the Discard Changes command UX + LSP invocation + reporting.
src/LanguageServers/PowerPlatformLS/UnitTests/PowerPlatformLS.UnitTests/Impl.PullAgent/Methods/ReattachAgentHandlerTests.cs Updates test doubles for new synchronizer API surface.
src/LanguageServers/PowerPlatformLS/UnitTests/PowerPlatformLS.UnitTests/Impl.PullAgent/Methods/DiscardLocalChangesHandlerTests.cs Adds unit tests for the new discard handler behavior.
src/LanguageServers/PowerPlatformLS/UnitTests/PowerPlatformLS.UnitTests/Impl.PullAgent/AgentWriterTests.cs Updates local-change tests to use the new credential-free local diff API.
src/LanguageServers/PowerPlatformLS/UnitTests/PowerPlatformLS.UnitTests/Impl.Core/ChangeMethodTests.cs Adds regression coverage for discarding local changes without remote credentials.
src/LanguageServers/PowerPlatformLS/Impl.PullAgent/GetLocalChangeHandler.cs Removes Dataverse/token dependencies from local diff handling.
src/LanguageServers/PowerPlatformLS/Impl.PullAgent/DiscardLocalChangesHandler.cs Adds the new local-only discard endpoint and response shaping.
src/LanguageServers/PowerPlatformLS/Impl.PullAgent/DiffLocalRequest.cs Simplifies the local diff request contract to workspace-only.
src/LanguageServers/PowerPlatformLS/Impl.PullAgent/DependencyInjection/PullAgentLspModule.cs Registers the new discard handler in DI.
src/LanguageServers/PowerPlatformLS/Contracts.Internal/Constants.cs Adds the JSON-RPC method constant for discard and confirms camelCase serialization.
src/CopilotStudio.Sync/WorkspaceSynchronizer.cs Implements projection-aware discard logic and adds a durable references baseline cache.
src/CopilotStudio.Sync/Models.cs Adds DiscardResult and DiscardSkippedChange models for the new API.
src/CopilotStudio.Sync/IWorkspaceSynchronizer.cs Adds discard APIs and a new local-diff overload without remote-service dependencies.
src/CopilotStudio.Sync.UnitTests/DiscardLocalChangesTests.cs Adds extensive Sync-layer unit tests for discard scenarios and partial-failure behavior.
Comments suppressed due to low confidence (1)

src/vscode-extensions/microsoft-powerplatformlang-extension/client/src/sync/workspaceScm.ts:345

  • onLocalChange logs the failure and then rethrows. Because onWorkspaceChange already has its own .catch(...) logging, this change causes duplicate telemetry/log entries for the same local-diff failure and makes initial SCM setup rely on the separate refreshInitialLocalChanges swallow wrapper to avoid aborting setup. Consider logging once and not rethrowing from onLocalChange so tracking stays alive without double-reporting.
      } catch (e) {
        logger.logError(TelemetryEventsKeys.SyncWorkspaceError, undefined, {
          message: `onLocalChangeError: ${e instanceof Error ? e.message : String(e)}`
        });
        throw e;

Comment on lines +69 to +75
const localChanges = getWorkspaceChanges(selectedWorkspace.workspaceUri)?.localChanges ?? [];
if (localChanges.length === 0) {
void window.showInformationMessage(`No local changes to discard for "${selectedWorkspace.displayName}".`);
return;
}

const count = localChanges.length;
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.

Discard changes option

2 participants