mirror of
https://github.com/microsoft/vscode.git
synced 2026-08-21 00:42:58 +01:00
* agentHost: multi-root turn changeset diffs (foundation) Compute per-turn and static (branch/session/uncommitted) changesets across all working directories of a multi-root agent host session: partition git repositories vs non-git folders, dedupe repositories shared by multiple folders, cap per-turn fan-out, and fall back to tracked edits when a git diff is unavailable. Single-folder sessions keep their existing behavior. Telemetry: - New `agentHost.changesetComputed` event (branch/session/uncommitted/turn kinds) reporting compute duration, outcome, and the resolved multi-root git topology; static and per-turn reporters funnel into the one event. - Add `isMultiRoot`/`folderCount` (and browser-projected git topology) to `agentHost.turnCompleted`, `agents/requestSent`, and `agents/sessionSummary`. - Bound the `resolveSessionRepositories` git rev-parse fan-out with a concurrency limiter. Also includes documentation clarifications and tracked-edit helper renames. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: Implement robust worktree removal with retry logic for transient errors * agentHost: replace 20-repo changeset cap with bounded-concurrency fan-out Per-turn and branch-summary changeset diffs previously capped to the first 20 git repositories (slice(0, 20) + unbounded Promise.all), silently dropping repositories 21+ and warning about "capping". Diff every resolved repository through a per-call Limiter(5) fan-out instead, mirroring the built-in git extension, so no repository is dropped while at most 5 git processes run concurrently. - Rename MAX_TURN_DIFF_REPOSITORIES (20) to MAX_TURN_DIFF_REPOSITORY_CONCURRENCY (5) - Lower REPOSITORY_ROOT_RESOLUTION_CONCURRENCY from 8 to 5 - Remove the now-dead capHit / diffedGitFolderCount telemetry - Rewrite the cap test as a bounded-concurrency + no-truncation regression Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
85 lines
3.0 KiB
TypeScript
85 lines
3.0 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
import { URI } from '../../../base/common/uri.js';
|
|
|
|
const GIT_BLOB_SCHEME = 'git-blob';
|
|
|
|
interface IGitBlobUriQuery {
|
|
readonly sessionUri: string;
|
|
readonly sha: string;
|
|
readonly repoRelativePath: string;
|
|
}
|
|
|
|
/**
|
|
* Builds a `git-blob:` URI that references a file blob at a specific git
|
|
* commit, scoped to a given session. Resolved by reading the session's
|
|
* working directory and shelling out to `git show <sha>:<path>`.
|
|
*
|
|
* The URI path is the absolute working-tree path so resource labels show a
|
|
* recognizable file path and so the "before" side lines up with the
|
|
* working-tree "after" side in diff editors. The session URI, SHA, and
|
|
* repository-relative path needed to fetch the blob are carried in the
|
|
* query.
|
|
*
|
|
* @param sessionUri Session the blob belongs to; used to find the working
|
|
* directory.
|
|
* @param sha Git commit/ref the blob is read from.
|
|
* @param repoRelativePath Repository-relative path passed to `git show`.
|
|
* @param absolutePath Absolute working-tree path used as the display path.
|
|
*/
|
|
export function buildGitBlobUri(sessionUri: string, sha: string, repoRelativePath: string, absolutePath: string): string {
|
|
return URI.from({
|
|
scheme: GIT_BLOB_SCHEME,
|
|
path: absolutePath,
|
|
query: JSON.stringify({ sessionUri, sha, repoRelativePath } satisfies IGitBlobUriQuery),
|
|
}).toString();
|
|
}
|
|
|
|
/** Parsed fields from a `git-blob:` content URI. */
|
|
export interface IGitBlobUriFields {
|
|
readonly sessionUri: string;
|
|
readonly sha: string;
|
|
readonly repoRelativePath: string;
|
|
/**
|
|
* Absolute working-tree path of the blob, taken from the URI `path` set by
|
|
* {@link buildGitBlobUri}. Used SERVER-SIDE only to select which of the
|
|
* session's own repository roots to run `git show` in — never as a working
|
|
* directory itself. Empty for legacy URIs that encoded no path, which
|
|
* callers treat as "fall back to the primary directory".
|
|
*/
|
|
readonly absolutePath: string;
|
|
}
|
|
|
|
/**
|
|
* Parses a `git-blob:` URI produced by {@link buildGitBlobUri}.
|
|
* Returns `undefined` if the URI is not a valid `git-blob:` URI.
|
|
*/
|
|
export function parseGitBlobUri(raw: string): IGitBlobUriFields | undefined {
|
|
let parsed: URI;
|
|
try {
|
|
parsed = URI.parse(raw);
|
|
} catch {
|
|
return undefined;
|
|
}
|
|
if (parsed.scheme !== GIT_BLOB_SCHEME || !parsed.query) {
|
|
return undefined;
|
|
}
|
|
try {
|
|
const query = JSON.parse(parsed.query) as Partial<IGitBlobUriQuery>;
|
|
if (typeof query.sessionUri === 'string' && typeof query.sha === 'string' && typeof query.repoRelativePath === 'string') {
|
|
return {
|
|
sessionUri: query.sessionUri,
|
|
sha: query.sha,
|
|
repoRelativePath: query.repoRelativePath,
|
|
absolutePath: parsed.path,
|
|
};
|
|
}
|
|
} catch {
|
|
return undefined;
|
|
}
|
|
return undefined;
|
|
}
|