Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
6b3f6e6
Add subtle appear transitions for sidebar and auxiliary parts
mrleemurray Mar 24, 2026
90e5e74
Refactor theme and layout for sidebar, panel, and auxiliary component…
mrleemurray Mar 24, 2026
3b679fd
Add transition effects for sidebar and auxiliary components
mrleemurray Mar 24, 2026
58ddf85
Update src/vs/sessions/browser/media/style.css
mrleemurray Mar 24, 2026
34f07d4
Update src/vs/sessions/browser/media/style.css
mrleemurray Mar 24, 2026
687dc1c
Update sessions tasks
benibenj Mar 25, 2026
a042e57
remove old test
benibenj Mar 25, 2026
dced473
fix: update icon color to use var(--vscode-icon-foreground) in titleb…
mrleemurray Mar 25, 2026
ee794a4
Update src/vs/sessions/browser/parts/media/titlebarpart.css
mrleemurray Mar 25, 2026
928b737
Remove box-shadows
mrleemurray Mar 25, 2026
73aee05
Merge branch 'main' into mrleemurray/hushed-rose-python
mrleemurray Mar 25, 2026
8ce5b55
Merge pull request #304526 from microsoft/mrleemurray/effective-plum-…
mrleemurray Mar 25, 2026
cfa545c
Fixes https://github.com/microsoft/vscode/issues/303784
hediet Mar 25, 2026
1db31f8
Merge pull request #304699 from microsoft/benibenj/thoughtless-porpoise
benibenj Mar 25, 2026
4e0be70
Initial plan
Copilot Mar 25, 2026
50e62eb
fix: preserve selection context when using "Ask in Chat" from inline …
Copilot Mar 25, 2026
5096904
mergeEditor: optimize removeDiffs from O(K*N) to O(N) with single-pas…
xingsy97 Mar 24, 2026
54b102d
sessions - hide diff stats from changes view button (#304738)
bpasero Mar 25, 2026
5c69811
Fix Claude forking (#304662)
TylerLeonhardt Mar 25, 2026
c425760
Fix operator precedence in fuzzyScore2 test assertion (#304449)
ShehabSherif0 Mar 25, 2026
d82ec93
sessions - fix title for cloud sessions (#304733)
bpasero Mar 25, 2026
c92f8a4
Skip confirmation dialog when unarchiving a single session (#304718)
bpasero Mar 25, 2026
7b9578c
Include metadata in agent sessions trace logging (#304725)
bpasero Mar 25, 2026
224a1e1
Can't read archived sessions in light mode (fix #304294) (#304720)
bpasero Mar 25, 2026
2ec87ae
sessions - restore file icons in modal editor titles (#304714)
bpasero Mar 25, 2026
e852b58
sessions - separate user dir for `--sessions` runs (#304726)
bpasero Mar 25, 2026
29d5ff7
Fix copy-paste bug in performance view blocking startup count (#304452)
ShehabSherif0 Mar 25, 2026
7d7fff2
Merge pull request #304734 from microsoft/copilot/fix-inline-chat-con…
jrieken Mar 25, 2026
0502a8b
update mywork milestone (#304707)
jrieken Mar 25, 2026
ac688e9
sessions - hide worktree icon but show others (#304739)
bpasero Mar 25, 2026
f4e6a58
Merge pull request #304704 from microsoft/mrleemurray/hushed-rose-python
mrleemurray Mar 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/notebooks/my-work.github-issues
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
{
"kind": 2,
"language": "github-issues",
"value": "// list of repos we work in\n$REPOS=repo:microsoft/lsprotocol repo:microsoft/monaco-editor repo:microsoft/vscode repo:microsoft/vscode-anycode repo:microsoft/vscode-autopep8 repo:microsoft/vscode-black-formatter repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-dev repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-flake8 repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-hexeditor repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-isort repo:microsoft/vscode-js-debug repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-l10n repo:microsoft/vscode-livepreview repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-mypy repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-pylint repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-references-view repo:microsoft/vscode-remote-release repo:microsoft/vscode-remote-repositories-github repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-unpkg repo:microsoft/vscode-vsce repo:microsoft/vscode-copilot-issues repo:microsoft/vscode-extension-samples\n\n// current milestone name\n$MILESTONE=milestone:\"1.113.0\"\n"
"value": "// list of repos we work in\n$REPOS=repo:microsoft/lsprotocol repo:microsoft/monaco-editor repo:microsoft/vscode repo:microsoft/vscode-anycode repo:microsoft/vscode-autopep8 repo:microsoft/vscode-black-formatter repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-dev repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-flake8 repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-hexeditor repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-isort repo:microsoft/vscode-js-debug repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-l10n repo:microsoft/vscode-livepreview repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-mypy repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-pylint repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-references-view repo:microsoft/vscode-remote-release repo:microsoft/vscode-remote-repositories-github repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-unpkg repo:microsoft/vscode-vsce repo:microsoft/vscode-copilot-issues repo:microsoft/vscode-extension-samples\n\n// current milestone name\n$MILESTONE=milestone:\"1.114.0\"\n"
},
{
"kind": 1,
Expand Down
29 changes: 14 additions & 15 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -235,30 +235,29 @@
"command": ".\\scripts\\code.bat"
},
"args": [
"--sessions"
"--sessions",
"--user-data-dir=${userHome}/.vscode-oss-sessions-dev",
"--extensions-dir=${userHome}/.vscode-oss-sessions-dev/extensions"
],
"problemMatcher": []
},
{
"label": "Transpile Client",
"type": "npm",
"script": "transpile-client",
"problemMatcher": []
},
{
"label": "Run and Compile Sessions - OSS",
"type": "shell",
"command": "npm run transpile-client && ./scripts/code.sh",
"windows": {
"command": "npm run transpile-client && .\\scripts\\code.bat"
},
"args": [
"--sessions"
],
"dependsOn": ["Transpile Client", "Run Dev Sessions"],
"dependsOrder": "sequence",
"inSessions": true,
"problemMatcher": []
},
{
"label": "Run and Compile Code - OSS",
"type": "shell",
"command": "npm run transpile-client && ./scripts/code.sh",
"windows": {
"command": "npm run transpile-client && .\\scripts\\code.bat"
},
"dependsOn": ["Transpile Client", "Run Dev"],
"dependsOrder": "sequence",
"inSessions": true,
"problemMatcher": []
},
Expand Down Expand Up @@ -438,4 +437,4 @@
"isBackground": false
}
]
}
}
2 changes: 1 addition & 1 deletion src/vs/base/test/common/fuzzyScorer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1239,7 +1239,7 @@ suite('Fuzzy Scorer', () => {
let [multiScore, multiMatches] = _doScore2(target, 'HelLo World');

function assertScore() {
assert.ok(multiScore ?? 0 >= ((firstSingleScore ?? 0) + (secondSingleScore ?? 0)));
assert.ok((multiScore ?? 0) >= ((firstSingleScore ?? 0) + (secondSingleScore ?? 0)));
for (let i = 0; multiMatches && i < multiMatches.length; i++) {
const multiMatch = multiMatches[i];
const firstAndSecondSingleMatch = firstAndSecondSingleMatches[i];
Expand Down
95 changes: 84 additions & 11 deletions src/vs/sessions/browser/media/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -100,23 +100,12 @@
box-sizing: border-box;
}

/* ---- Session List ---- */

.agent-sessions-workbench .agent-session-title {
color: var(--vscode-list-activeSelectionForeground);
}

/* ---- Modal Editor Block ---- */

.agent-sessions-workbench .monaco-modal-editor-block {
background: rgba(0, 0, 0, 0.5);
}

/* Hide the file icon in modal editor titles */
.agent-sessions-workbench .modal-editor-title .monaco-icon-label::before,
.agent-sessions-workbench .modal-editor-title .monaco-icon-label > .monaco-icon-label-iconpath {
display: none;
}

/* ---- Customization Empty State ---- */

Expand Down Expand Up @@ -148,6 +137,90 @@
flex-shrink: 0;
}

/* ---- Part Appear Transitions ---- */

/*
* Subtle appear animation when parts transition from display:none → visible
* (via split-view-view .visible class).
*
* Animated properties: opacity, margin, border-color, background.
* Opacity transiently creates a stacking context while it animates from 0 to 1
* over 250ms — once settled at opacity: 1, no additional stacking context is
* introduced by this animation. Margin shifts are purely visual within the
* grid-allocated space.
*/

.agent-sessions-workbench .part.sidebar,
.agent-sessions-workbench .part.auxiliarybar,
.agent-sessions-workbench .part.panel,
.agent-sessions-workbench .part.chatbar {
transition:
opacity 250ms ease-out,
margin-top 250ms ease-out,
margin-right 250ms ease-out,
margin-bottom 250ms ease-out,
border-color 250ms ease-out,
background 250ms ease-out;
}

/* Sidebar & auxiliary bar also transition margin-left */
.agent-sessions-workbench .part.sidebar,
.agent-sessions-workbench .part.auxiliarybar {
transition:
opacity 250ms ease-out,
margin 250ms ease-out,
border-color 250ms ease-out,
background 250ms ease-out;
}

@starting-style {
/* Shared starting values */
.agent-sessions-workbench .part.sidebar,
.agent-sessions-workbench .part.auxiliarybar,
.agent-sessions-workbench .part.panel,
.agent-sessions-workbench .part.chatbar {
opacity: 0;
border-color: transparent;
}

/* Card parts: blend from surrounding background */
.agent-sessions-workbench .part.auxiliarybar,
.agent-sessions-workbench .part.panel,
.agent-sessions-workbench .part.chatbar {
background: color-mix(in srgb, var(--part-background) 60%, var(--vscode-sideBar-background));
}

/* Per-part margin shifts — each part settles into its resting margin */
/* Sidebar (left): slides in from 6px left → margin: 0 */
.agent-sessions-workbench .part.sidebar {
margin-left: -6px;
}

/* Panel (bottom): slides down from 6px above → margin: 0 16px 18px 16px */
.agent-sessions-workbench .part.panel {
margin: 6px 16px 18px 16px;
}

/* Auxiliary bar (right): slides in from 6px right → margin: 0 16px 2px 0 */
.agent-sessions-workbench .part.auxiliarybar {
margin: 0 16px 2px 6px;
}

/* Chat bar (center-bottom): slides up from 6px below → margin: 0 16px 2px 16px */
.agent-sessions-workbench .part.chatbar {
margin: 6px 16px 2px 16px;
}
}

@media (prefers-reduced-motion: reduce) {
.agent-sessions-workbench .part.sidebar,
.agent-sessions-workbench .part.auxiliarybar,
.agent-sessions-workbench .part.panel,
.agent-sessions-workbench .part.chatbar {
transition: none;
}
}

/* ---- Widget Customizations ---- */

/* Badge */
Expand Down
4 changes: 2 additions & 2 deletions src/vs/sessions/browser/parts/media/titlebarpart.css
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@
border-radius: var(--vscode-cornerRadius-medium);
}

.monaco-workbench .part.titlebar > .sessions-titlebar-container > .titlebar-right > .titlebar-actions-container .codicon {
color: inherit;
.monaco-workbench .part.titlebar > .sessions-titlebar-container > .titlebar-right > .titlebar-actions-container .monaco-action-bar .action-item:not(.disabled) .codicon {
color: var(--vscode-icon-foreground);
}

.monaco-workbench .part.titlebar > .sessions-titlebar-container > .titlebar-right > .titlebar-actions-container .monaco-action-bar .action-item {
Expand Down
8 changes: 1 addition & 7 deletions src/vs/sessions/contrib/changes/browser/changesView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { ICompressedTreeNode } from '../../../../base/browser/ui/tree/compressed
import { ICompressibleTreeRenderer } from '../../../../base/browser/ui/tree/objectTree.js';
import { IObjectTreeElement, ITreeNode } from '../../../../base/browser/ui/tree/tree.js';
import { Codicon } from '../../../../base/common/codicons.js';
import { MarkdownString } from '../../../../base/common/htmlContent.js';
import { Iterable } from '../../../../base/common/iterator.js';
import { Disposable, DisposableStore, MutableDisposable } from '../../../../base/common/lifecycle.js';
import { autorun, constObservable, derived, derivedOpts, IObservable, IObservableWithChange, ISettableObservable, ObservablePromise, observableSignalFromEvent, observableValue, runOnChange } from '../../../../base/common/observable.js';
Expand Down Expand Up @@ -659,7 +658,6 @@ export class ChangesViewPane extends ViewPane {
this.renderDisposables.add(scopedInstantiationService);

this.renderDisposables.add(autorun(reader => {
const { added, removed } = topLevelStats.read(reader);
const outgoingChanges = outgoingChangesObs.read(reader);
const sessionResource = this.viewModel.activeSessionResourceObs.read(reader);

Expand Down Expand Up @@ -700,11 +698,7 @@ export class ChangesViewPane extends ViewPane {
: { shouldForwardArgs: true },
buttonConfigProvider: (action) => {
if (action.id === 'chatEditing.viewChanges' || action.id === 'chatEditing.viewPreviousEdits' || action.id === 'chatEditing.viewAllSessionChanges' || action.id === 'chat.openSessionWorktreeInVSCode') {
const diffStatsLabel = new MarkdownString(
`<span class="working-set-lines-added">+${added}</span>&nbsp;<span class="working-set-lines-removed">-${removed}</span>`,
{ supportHtml: true }
);
return { showIcon: true, showLabel: true, isSecondary: true, customClass: 'working-set-diff-stats', customLabel: diffStatsLabel };
return { showIcon: true, showLabel: false, isSecondary: true };
}
if (action.id === RUN_SESSION_CODE_REVIEW_ACTION_ID) {
if (codeReviewLoading) {
Expand Down
15 changes: 0 additions & 15 deletions src/vs/sessions/contrib/changes/browser/media/changesView.css
Original file line number Diff line number Diff line change
Expand Up @@ -260,21 +260,6 @@
color: var(--vscode-chat-linesRemovedForeground);
}

/* Line counts in buttons */
.changes-view-body .chat-editing-session-actions .monaco-button.working-set-diff-stats {
flex-shrink: 0;
padding-left: 4px;
padding-right: 8px;
}

.changes-view-body .chat-editing-session-actions .monaco-button .working-set-lines-added {
color: var(--vscode-chat-linesAddedForeground);
}

.changes-view-body .chat-editing-session-actions .monaco-button .working-set-lines-removed {
color: var(--vscode-chat-linesRemovedForeground);
}

.changes-view-body .chat-editing-session-actions .monaco-button.code-review-comments,
.changes-view-body .chat-editing-session-actions .monaco-button.code-review-loading {
padding-left: 4px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import { Disposable, DisposableStore, MutableDisposable } from '../../../../base/common/lifecycle.js';
import { autorun, IObservable, observableValue, transaction } from '../../../../base/common/observable.js';
import { IObservable, observableValue, transaction } from '../../../../base/common/observable.js';
import { joinPath, dirname, isEqual } from '../../../../base/common/resources.js';
import { parse } from '../../../../base/common/jsonc.js';
import { URI } from '../../../../base/common/uri.js';
Expand Down Expand Up @@ -127,7 +127,6 @@ export class SessionsConfigurationService extends Disposable implements ISession
private static readonly _PINNED_TASK_LABELS_KEY = 'agentSessions.pinnedTaskLabels';
private readonly _sessionTasks = observableValue<readonly ISessionTaskWithTarget[]>(this, []);
private readonly _fileWatcher = this._register(new MutableDisposable());
private readonly _knownSessionWorktrees = new Map<string, string | undefined>();
private readonly _pinnedTaskLabels: Map<string, string>;
private readonly _pinnedTaskObservables = new Map<string, ReturnType<typeof observableValue<string | undefined>>>();

Expand All @@ -145,11 +144,6 @@ export class SessionsConfigurationService extends Disposable implements ISession
) {
super();
this._pinnedTaskLabels = this._loadPinnedTaskLabels();

this._register(autorun(reader => {
const activeSession = this._sessionsManagementService.activeSession.read(reader);
this._handleActiveSessionChange(activeSession);
}));
}

getSessionTasks(session: IActiveSessionItem): IObservable<readonly ISessionTaskWithTarget[]> {
Expand Down Expand Up @@ -384,65 +378,10 @@ export class SessionsConfigurationService extends Disposable implements ISession
}
}

private async _readAllTasks(session: IActiveSessionItem): Promise<readonly ITaskEntry[]> {
const result: ITaskEntry[] = [];

// Read workspace tasks
const workspaceUri = this._getTasksJsonUri(session, 'workspace');
if (workspaceUri) {
const workspaceJson = await this._readTasksJson(workspaceUri);
if (workspaceJson.tasks) {
result.push(...workspaceJson.tasks.filter(t => this._isSupportedTask(t)));
}
}

// Read user tasks
const userUri = this._getTasksJsonUri(session, 'user');
if (userUri) {
const userJson = await this._readTasksJson(userUri);
if (userJson.tasks) {
result.push(...userJson.tasks.filter(t => this._isSupportedTask(t)));
}
}

return result;
}

private _isSupportedTask(task: ITaskEntry): boolean {
return !!task.label;
}

private _handleActiveSessionChange(session: IActiveSessionItem | undefined): void {
if (!session) {
return;
}

const sessionKey = session.resource.toString();
const currentWorktree = session.worktree?.toString();
if (!this._knownSessionWorktrees.has(sessionKey)) {
this._knownSessionWorktrees.set(sessionKey, currentWorktree);
return;
}

const previousWorktree = this._knownSessionWorktrees.get(sessionKey);
this._knownSessionWorktrees.set(sessionKey, currentWorktree);
if (!currentWorktree || previousWorktree === currentWorktree) {
return;
}

void this._runWorktreeCreatedTasks(session);
}

private async _runWorktreeCreatedTasks(session: IActiveSessionItem): Promise<void> {
const tasks = await this._readAllTasks(session);
for (const task of tasks) {
if (!task.inSessions || task.runOptions?.runOn !== 'worktreeCreated') {
continue;
}
await this.runTask(task, session);
}
}

private _ensureFileWatch(folder: URI): void {
const tasksUri = joinPath(folder, '.vscode', 'tasks.json');
if (this._watchedResource && this._watchedResource.toString() === tasksUri.toString()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -615,26 +615,4 @@ suite('SessionsConfigurationService', () => {
assert.strictEqual(ranTasks.length, 1);
assert.strictEqual(ranTasks[0].label, 'build');
});

test('runs worktreeCreated session tasks when a session gains a worktree', async () => {
registerMockTask('build', worktreeUri);
const sessionResource = URI.parse('file:///session-worktree-created');
const worktreeTasksUri = URI.parse('file:///worktree/.vscode/tasks.json');
const userTasksUri = URI.from({ scheme: userSettingsUri.scheme, path: '/user/tasks.json' });
fileContents.set(worktreeTasksUri.toString(), tasksJsonContent([
{ label: 'build', type: 'shell', command: 'npm run build', inSessions: true, runOptions: { runOn: 'worktreeCreated' } },
makeTask('manual', 'npm test', true),
]));
fileContents.set(userTasksUri.toString(), tasksJsonContent([]));

activeSessionObs.set({ ...makeSession({ repository: repoUri }), resource: sessionResource }, undefined);
await new Promise(r => setTimeout(r, 10));

activeSessionObs.set({ ...makeSession({ repository: repoUri, worktree: worktreeUri }), resource: sessionResource }, undefined);
await new Promise(r => setTimeout(r, 10));

assert.strictEqual(ranTasks.length, 1);
assert.strictEqual(ranTasks[0].label, 'build');
});

});
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,22 @@ export class SessionsTitleBarWidget extends BaseActionViewItem {
return undefined;
}

return basename(uri);
const name = basename(uri);

// For local repositories (file scheme), the basename is not URI-encoded and may
// legitimately contain '%' characters. Decoding in that case can throw or
// incorrectly transform sequences like '%20' into spaces, so return it as-is.
if (uri.scheme === 'file') {
return name;
}

// For non-file schemes where the basename may be encodeURIComponent-encoded,
// attempt to decode but fall back to the raw name on any error.
try {
return decodeURIComponent(name);
} catch {
return name;
}
}

private _countUnreadSessions(): number {
Expand Down
Loading
Loading