Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
269 commits
Select commit Hold shift + click to select a range
caaf9fd
Merge remote-tracking branch 'origin/sandy081/agents/chat-view-sessio…
sandy081 Nov 14, 2026
319fd9f
Merge branch 'sandy081/agents/editor-window-worktree-locations' (#348…
sandy081 Nov 14, 2026
66034e7
Merge remote-tracking branch 'origin/sandy081/agents/editor-window-wo…
sandy081 Nov 14, 2026
82c6c4c
Sessions: the workspace picker's folder sections come from the shared…
sandy081 Nov 14, 2026
6ad6b5f
Chat view: report 'restore' only for the chat that the view restores,…
sandy081 Nov 14, 2026
3a1cd39
Merge branch 'sandy081/agents/editor-window-worktree-locations' (#348…
sandy081 Nov 14, 2026
fd14c5c
Editor window: worktree support follows only the user's latest choice…
sandy081 Nov 14, 2026
174131c
Sessions: the chat part of editor windows, for any feature to enable
sandy081 Nov 14, 2026
900d637
Merge branch 'sandy081/agents/editor-window-worktree-locations' (#348…
sandy081 Nov 14, 2026
edceb5b
Merge #348304 into #348302; report the shown chat of the host that sh…
sandy081 Nov 14, 2026
a8d3bbb
Merge branch 'sandy081/agents/editor-window-worktree-locations' of ht…
sandy081 Nov 14, 2026
e80755f
Merge remote-tracking branch 'origin/sandy081/agents/editor-window-wo…
sandy081 Nov 14, 2026
ad3aede
Chat part: report 'restore' only for the tabs that its restore shows
sandy081 Nov 14, 2026
bb450bc
Chat part: report a composer's first send as opened, also in a restor…
sandy081 Nov 14, 2026
43ef657
Chat part: name its availability AgentsViewAvailable, for the session…
sandy081 Nov 14, 2026
f975be4
Chat part: show the chats of every type the window's sessions provide…
sandy081 Nov 14, 2026
ecd54bd
Worktree infra: wait for the sessions list before reading working dir…
sandy081 Nov 14, 2026
0c1fa66
chat: track the Chat view's shown chat only while a host replaces it
sandy081 Nov 14, 2026
36e1d8a
Merge branch 'sandy081/agents/editor-window-worktree-locations' (#348…
sandy081 Nov 14, 2026
41e831c
Merge remote-tracking branch 'origin/sandy081/agents/chat-view-sessio…
sandy081 Nov 14, 2026
f750f6b
Merge branch 'sandy081/agents/editor-window-worktree-locations' (#348…
sandy081 Nov 14, 2026
de3f079
Sessions: the workspace picker's current folder says it is current to…
sandy081 Nov 14, 2026
1a6ddcf
Workbench: the chat part follows its anchor view as the view deregist…
sandy081 Nov 14, 2026
82469f8
chat: New Chat of the Chat view starts a provided composer over
sandy081 Nov 14, 2026
0045946
Merge branch 'main' into sandy081/agents/chat-part-anchor
sandy081 Nov 14, 2026
c891b9b
Editor window: hide the worktree folder chip with AI features off
sandy081 Nov 14, 2026
753dba5
Editor window sessions: review fixes (workspace trust, legacy resourc…
sandy081 Nov 14, 2026
2bd34c0
Merge remote-tracking branch 'origin/sandy081/agents/editor-window-wo…
sandy081 Nov 14, 2026
c21ff92
Merge branch 'sandy081/agents/editor-window-sessions-runtime' into sa…
sandy081 Nov 14, 2026
4716dc8
Merge branch 'sandy081/agents/editor-window-worktree-locations' of ht…
sandy081 Nov 14, 2026
26ff303
Worktree infra: describe worktrees by branch, compare real paths, and…
sandy081 Nov 14, 2026
de4283d
Merge branch 'sandy081/agents/editor-window-worktree-locations' into …
sandy081 Nov 14, 2026
6569af4
Worktree support: supersede pending moves, follow into enclosing work…
sandy081 Nov 14, 2026
7e256b0
Editor window sessions: one registration per call, and a test of New …
sandy081 Nov 14, 2026
e5f464a
Chat part: report an explicit open as opened, hold composers apart fr…
sandy081 Nov 14, 2026
38e3f7e
Merge branch 'sandy081/agents/editor-window-sessions-runtime' into sa…
sandy081 Nov 14, 2026
029b83e
Merge remote-tracking branch 'origin/sandy081/agents/chat-view-sessio…
sandy081 Nov 14, 2026
1272926
Worktree infra: describe worktrees by branch, compare real paths, and…
sandy081 Nov 14, 2026
340767a
Merge remote-tracking branch 'origin/sandy081/agents/editor-window-wo…
sandy081 Nov 14, 2026
42565a8
Merge branch 'sandy081/agents/editor-window-worktree-locations' into …
sandy081 Nov 14, 2026
5f56e14
Worktree support: list the worktree the folder is at in the folder ch…
sandy081 Nov 14, 2026
380ee57
Merge branch 'sandy081/agents/editor-window-worktree-locations' of ht…
sandy081 Nov 14, 2026
039d452
Worktree infra: an open to restore the chat that a host shows already…
sandy081 Nov 14, 2026
4d4e374
Merge branch 'sandy081/agents/editor-window-worktree-locations' into …
sandy081 Nov 14, 2026
e9ddbc2
Merge remote-tracking branch 'origin/sandy081/agents/editor-window-wo…
sandy081 Nov 14, 2026
766c360
chat: reveal, toggle and New Chat claim the shown chat; keep it on un…
sandy081 Nov 14, 2026
8b26ed9
Merge branch 'sandy081/agents/editor-window-worktree-locations' of ht…
sandy081 Nov 14, 2026
faa486d
Worktree support: address code review
sandy081 Nov 14, 2026
6680d51
Worktree infra: report each explicit open of the chat a view shows, a…
sandy081 Nov 14, 2026
b29c10c
Chat part: review fixes (registrations, superseded starts, restore pr…
sandy081 Nov 14, 2026
9482af2
Editor window sessions: let a feature override the chat the window's …
sandy081 Nov 14, 2026
41c8625
Merge branch 'sandy081/agents/editor-window-sessions-runtime' into sa…
sandy081 Nov 14, 2026
eb1c519
Worktree infra: wait for the local agent host sessions to resolve, al…
sandy081 Nov 14, 2026
5a24a7e
Merge branch 'sandy081/agents/editor-window-worktree-locations' into …
sandy081 Nov 14, 2026
75ccadb
Worktree support: dispose the location provider with the contribution
sandy081 Nov 14, 2026
fc593e5
Merge branch 'sandy081/agents/editor-window-worktree-locations' of ht…
sandy081 Nov 14, 2026
766d7c4
Merge remote-tracking branch 'origin/sandy081/agents/editor-window-wo…
sandy081 Nov 14, 2026
59577f9
Merge remote-tracking branch 'origin/sandy081/agents/chat-view-sessio…
sandy081 Nov 14, 2026
914a7f3
Chat part anchor: ignore an unregistered view's saved location, resto…
sandy081 Nov 14, 2026
b1a8f44
Merge remote-tracking branch 'origin/sandy081/agents/editor-window-ch…
sandy081 Nov 14, 2026
3f1b481
Merge branch 'sandy081/agents/worktree-picker-groups' of https://gith…
sandy081 Nov 14, 2026
86e8786
Merge remote-tracking branch 'origin/sandy081/agents/editor-window-wo…
sandy081 Nov 14, 2026
dd36a4e
Chat part: composers follow their host to another folder, and each ex…
sandy081 Nov 14, 2026
fa88097
Chat part: actions only while chats open in it, New Chat ownership, a…
sandy081 Nov 14, 2026
6e0d90b
chat: New Chat of a composer shown during a slow load supersedes the …
sandy081 Nov 14, 2026
05ed22f
Merge commit 'fa880971e20' into sandy081/agents/f4-composer-folders-prep
sandy081 Nov 14, 2026
27bd82f
Merge remote-tracking branch 'origin/sandy081/agents/worktree-picker-…
sandy081 Nov 14, 2026
92c4607
Worktree support: the chat part's new-session composers offer the fol…
sandy081 Nov 14, 2026
ecbf8fc
Editor window sessions: the folders of new-session composers in a ser…
sandy081 Nov 14, 2026
190001f
Merge remote-tracking branch 'origin/sandy081/agents/chat-view-sessio…
sandy081 Nov 14, 2026
259eb73
Worktree infra: report a first send's session as committed, also thro…
sandy081 Nov 14, 2026
f64fec5
Merge branch 'sandy081/agents/editor-window-worktree-locations' into …
sandy081 Nov 14, 2026
fdeaddd
Worktree support: recall the shown chat as restored without reloading…
sandy081 Nov 14, 2026
df54a17
Editor window sessions: retarget every composer of the window through…
sandy081 Nov 14, 2026
8de8394
Merge commit 'df54a17a0fc' into sandy081/agents/editor-window-worktre…
sandy081 Nov 14, 2026
bb62ee6
Worktree support: register the composer folders and retarget through …
sandy081 Nov 14, 2026
ee64ec2
Worktree infra: test mocks of the Chat view report shown chats throug…
sandy081 Nov 14, 2026
d485605
Merge branch 'sandy081/agents/editor-window-worktree-locations' into …
sandy081 Nov 14, 2026
92417e3
Merge branch 'sandy081/agents/editor-window-worktree-locations' of ht…
sandy081 Nov 14, 2026
7ca8e3f
Dispose session settings schemas outside the provider's listing scope
sandy081 Nov 14, 2026
3daf793
Offer Show Working Set from the Changes pill and show it once empty
sandy081 Nov 14, 2026
7fba78b
Keep folder-location sessions listed across workbench state changes
sandy081 Nov 14, 2026
371df34
Merge remote-tracking branch 'origin/main' into sandy081/agents/agent…
sandy081 Nov 14, 2026
700832b
Merge remote-tracking branch 'origin/main' into sandy081/agents/edito…
sandy081 Nov 14, 2026
7a68189
Merge commit 'ee64ec290ce' into sandy081/agents/editor-window-chat-part
sandy081 Nov 14, 2026
261fb0b
Worktree support: test that a folder move retargets every composer re…
sandy081 Nov 14, 2026
07cb7a6
chat: no claim from removed hosts; the composer takes focus as New Ch…
sandy081 Nov 14, 2026
fad96b9
Merge branch 'sandy081/agents/editor-window-worktree-locations' of ht…
sandy081 Nov 14, 2026
6c92a81
Worktree support: keeping the folder in place for a later chat supers…
sandy081 Nov 14, 2026
62e5d2c
Chat part: mark a chat tab read through the sessions list, and show c…
sandy081 Nov 14, 2026
4cadf3a
Merge remote-tracking branch 'origin/sandy081/agents/session-working-…
sandy081 Nov 14, 2026
b3e0a3f
Merge remote-tracking branch 'origin/sandy081/agents/editor-window-ch…
sandy081 Nov 14, 2026
24afef7
Merge branch 'sandy081/agents/editor-window-sessions-runtime' into sa…
sandy081 Nov 14, 2026
ba3c213
Chat view host: New Chat completes once the new chat shows, aimed at …
sandy081 Nov 14, 2026
401dc3b
chat: New Chat of the Chat view resolves once the new chat shows, aim…
sandy081 Nov 14, 2026
9e67715
Chat part actions test: check that disposing restores the read-state …
sandy081 Nov 14, 2026
1ee85e8
Chat part: scoped New Chat of the Chat view, restore intent before ac…
sandy081 Nov 14, 2026
8459c20
chat: a Chat view that shows only the sessions focuses its sessions
sandy081 Nov 14, 2026
c4f23c3
Merge branch 'sandy081/agents/chat-view-sessions-control' of https://…
sandy081 Nov 14, 2026
5399af6
Merge commit '8459c200528' into sandy081/agents/editor-window-chat-part
sandy081 Nov 14, 2026
5d67350
Chat window composer: a composer that follows its host to another fol…
sandy081 Nov 14, 2026
49b6db7
Sessions runtime: wait for a session's chats among every session, wha…
sandy081 Nov 14, 2026
6112b7a
Merge branch 'sandy081/agents/editor-window-sessions-runtime' into sa…
sandy081 Nov 14, 2026
57c4581
Chat part host: the wait for a session takes no resource
sandy081 Nov 14, 2026
9ce6adc
Chat view host service: keep the claim guard of #348302 for removed h…
sandy081 Nov 14, 2026
20aa95f
Worktree infra: a worktree's admin back-link must name the checkout i…
sandy081 Nov 14, 2026
1fbcf1a
Worktree infra: tests reach the trust consumer through a refused move…
sandy081 Nov 14, 2026
c12151c
Merge branch 'sandy081/agents/editor-window-worktree-locations' into …
sandy081 Nov 14, 2026
5201f74
Worktree support: dispose the Chat view host service in the shown-ses…
sandy081 Nov 14, 2026
6a624ae
Merge branch 'sandy081/agents/editor-window-worktree-locations' of ht…
sandy081 Nov 14, 2026
cf8b72c
Merge branch 'sandy081/agents/editor-window-worktree-locations' of ht…
sandy081 Nov 14, 2026
2282263
Merge commit '1fbcf1a37ef' into sandy081/agents/editor-window-chat-part
sandy081 Nov 14, 2026
2c60b3d
chat: dispose the Chat view host service of the shown-chat test
sandy081 Nov 14, 2026
8ef0cbc
Chat view pane test: dispose the Chat view host service that the test…
sandy081 Nov 14, 2026
8c6f879
chat: New Chat of the Chat view with options: own the chat, preserve …
sandy081 Nov 14, 2026
241a857
Merge commit '8ef0cbc142c' into sandy081/agents/editor-window-worktre…
sandy081 Nov 14, 2026
e5ccc60
chat: the composer takes focus only from the chat it replaces
sandy081 Nov 14, 2026
3932f25
Worktree support: load the editor window's worktree contribution from…
sandy081 Nov 14, 2026
a5ecaab
Editor cloud sandbox test: its workspace stub has a workbench state e…
sandy081 Nov 14, 2026
be9f2e6
Merge commit '914a7f30cea' into sandy081/agents/editor-window-chat-part
sandy081 Nov 14, 2026
787f246
Worktree infra: a Chat view load reports its chat itself, once, unles…
sandy081 Nov 14, 2026
c532b0f
Merge branch 'sandy081/agents/editor-window-worktree-locations' into …
sandy081 Nov 14, 2026
5ca890b
Chat part: a recovery composer aims at the provider's session type; N…
sandy081 Nov 14, 2026
f49a710
Worktree support: dispose the Chat view host service in the restore-t…
sandy081 Nov 14, 2026
6382f9d
Merge branch 'sandy081/agents/editor-window-worktree-locations' of ht…
sandy081 Nov 14, 2026
9fc294d
Merge commit '5ca890b1ae3' into sandy081/agents/editor-window-worktre…
sandy081 Nov 14, 2026
0b1a597
Merge branch 'sandy081/agents/editor-window-worktree-locations' of ht…
sandy081 Nov 14, 2026
7739d41
chat: dispose the Chat view host service of the restore-supersede test
sandy081 Nov 14, 2026
b84f234
Sessions: hide the phone Mode and Model picker with AI features off; …
sandy081 Nov 14, 2026
7156747
Session working set: the Changes pill follows what the working set shows
sandy081 Nov 14, 2026
685b00d
Editor window sessions: a later open supersedes one that still resolves
sandy081 Nov 14, 2026
be7c5c2
Chat part: a retargeted composer offers its folder; read state for se…
sandy081 Nov 14, 2026
38e75c3
Worktree infra: sources of where local agent host sessions work, besi…
sandy081 Nov 14, 2026
6c646c5
Merge branch 'sandy081/agents/editor-window-worktree-locations' into …
sandy081 Nov 14, 2026
68224e9
chat: a New Chat of the Chat view's own is a transition that a later …
sandy081 Nov 14, 2026
6d4c3e8
Worktree support: follow and offer the worktrees of the editor window…
sandy081 Nov 14, 2026
287d8b1
Merge branch 'sandy081/agents/editor-window-worktree-locations' of ht…
sandy081 Nov 14, 2026
776c223
Merge branch 'sandy081/agents/editor-window-worktree-locations' of ht…
sandy081 Nov 14, 2026
a4a5bfc
Editor window sessions: wait for a session to load only while it loads
sandy081 Nov 14, 2026
b30c018
chat: the two-New-Chat race test releases the rig's unused chat
sandy081 Nov 14, 2026
16821a6
Worktree support: a working directory that changes back to where the …
sandy081 Nov 14, 2026
88a4415
Merge commit 'b30c018a9fb' into sandy081/agents/editor-window-chat-part
sandy081 Nov 14, 2026
6a53df9
Chat part anchor: make room for the chat part beside a wide bar inste…
sandy081 Nov 14, 2026
dd8a606
Worktree infra: the session that a started chat moves to after its fi…
sandy081 Nov 14, 2026
981a7d0
Merge branch 'sandy081/agents/editor-window-worktree-locations' into …
sandy081 Nov 14, 2026
5aba8c4
Worktree support: dispose the Chat view host service in the moved-com…
sandy081 Nov 14, 2026
5937e47
Merge branch 'sandy081/agents/editor-window-worktree-locations' of ht…
sandy081 Nov 14, 2026
c36a683
Merge commit 'b84f234a7fd' into sandy081/agents/editor-window-session…
sandy081 Nov 14, 2026
c45ae52
Merge branch 'sandy081/agents/editor-window-sessions-runtime' into sa…
sandy081 Nov 14, 2026
76dc9ef
Merge commit '6a53df9244a' into sandy081/agents/editor-window-chat-part
sandy081 Nov 14, 2026
2620273
Merge commit 'dd8a60671d8' into sandy081/agents/editor-window-chat-part
sandy081 Nov 14, 2026
ded9a0a
Chat part host: the session a started chat's first request made shows…
sandy081 Nov 14, 2026
dc846cd
Merge branch 'sandy081/agents/editor-window-worktree-locations' of ht…
sandy081 Nov 14, 2026
f6f0295
Editor window composers: folder options follow the provider set later
sandy081 Nov 14, 2026
9af3004
Chat part anchor: make room against the width the grid gives the edit…
sandy081 Nov 14, 2026
16759fb
chat: dispose the Chat view host service of the moved-session test
sandy081 Nov 14, 2026
7071def
Merge commit 'f6f02953891' into sandy081/agents/editor-window-worktre…
sandy081 Nov 14, 2026
8482c9a
Chat window composer: a retarget aims the picker before its observers…
sandy081 Nov 14, 2026
95a1257
Merge commit '7156747395f' into sandy081/agents/editor-window-chat-part
sandy081 Nov 14, 2026
286038a
Merge commit '9af30045f19' into sandy081/agents/editor-window-chat-part
sandy081 Nov 14, 2026
6ed0b73
chat: a New Chat that an open supersedes does not claim its host
sandy081 Nov 14, 2026
4852a12
Merge commit '6ed0b73b404' into sandy081/agents/editor-window-chat-part
sandy081 Nov 14, 2026
6d5fd1b
Chat part test: an open to restore the chat it shows already reports …
sandy081 Nov 14, 2026
5dc6d4d
Worktree support: the session layer's source follows every session th…
sandy081 Nov 14, 2026
757c9cb
Merge commit '6d5fd1be47f' into sandy081/agents/editor-window-worktre…
sandy081 Nov 14, 2026
9b07a59
chat: the latest New Chat claims its host; a removed host's claim sup…
sandy081 Nov 14, 2026
fd658d5
Chat part anchor: budget the chat part against its branch's width les…
sandy081 Nov 14, 2026
90eb147
Chat window composer: no retarget while a submit runs its checks
sandy081 Nov 14, 2026
e8f9dbc
Chat window composer: a restored composer keeps whether its host or t…
sandy081 Nov 14, 2026
8d2d7ed
Merge #348292 fd658d5c488 (chat part anchor budget) into sandy081/age…
sandy081 Nov 14, 2026
795e690
Merge #348302 9b07a590d37 into sandy081/agents/editor-window-chat-part
sandy081 Nov 14, 2026
6105297
Worktree support: trace why a shown chat does not move the folder, an…
sandy081 Nov 14, 2026
b014b26
Worktree support: the composers' folder choices read the worktrees ag…
sandy081 Nov 14, 2026
d42b465
Merge commit '795e69019c0' into sandy081/agents/editor-window-worktre…
sandy081 Nov 14, 2026
9237cfe
Worktree support: tell as a session comes to work elsewhere in any of…
sandy081 Nov 14, 2026
7522545
Agents chat part: its host reports the chat of the active tab, readin…
sandy081 Nov 14, 2026
61d451e
Merge commit '75225454575' into sandy081/agents/editor-window-worktre…
sandy081 Nov 14, 2026
5f20e3a
Sessions: a composer's picker of a window's folder and its worktrees …
sandy081 Nov 14, 2026
44dc0b5
Sessions: a composer's picker at the location a window's folder moved…
sandy081 Nov 14, 2026
99ac12e
Worktree support: the Chat view's folder chip shows the folder or wor…
sandy081 Nov 14, 2026
6ee9348
Worktree support: test that an existing chat's folder chip shows the …
sandy081 Nov 14, 2026
ef6b4b2
Worktree support: the folder chip shows a folder it does not list as …
sandy081 Nov 14, 2026
d3efaf4
Sessions: a composer's picker selects the location a window's folder …
sandy081 Nov 14, 2026
3690943
Worktree support: the folder chip reads again whether a folder it doe…
sandy081 Nov 14, 2026
9240953
Worktree support: the Chat view's sessions list also lists the sessio…
sandy081 Nov 14, 2026
0fc969e
Worktree support: the Chat view's sessions list lists the sessions wh…
sandy081 Nov 14, 2026
43020e2
Worktree support: match the sessions list by project apart from how i…
sandy081 Nov 14, 2026
7d6f515
Worktree support: the sessions list matches by project only sessions …
sandy081 Nov 14, 2026
4169870
Worktree support: test that a session of another workspace file whose…
sandy081 Nov 14, 2026
10a4cb2
Worktree support: the project-root test's workspace also reports work…
sandy081 Nov 14, 2026
660e14e
Worktree support: the sessions list keeps the sessions of the folder'…
sandy081 Nov 14, 2026
9fea8f8
Sessions: a composer's chip of a window's folder and its worktrees al…
sandy081 Nov 14, 2026
8d7f9f2
Sessions: a composer's chip shows New Worktree by that name
sandy081 Nov 14, 2026
2c1fec3
Worktree support: the folder chip shows New Worktree by that name
sandy081 Nov 14, 2026
f9ca40a
Worktree support: the folder chip leads the chat input's pickers, as …
sandy081 Nov 14, 2026
5886b54
Worktree support: the folder chip shows a worktree that VS Code creat…
sandy081 Nov 14, 2026
95aac71
Worktree support: a folder named like a worktree of the window's fold…
sandy081 Nov 14, 2026
6b6eecf
Worktree support: the Chat view's folder chip offers No Workspace whi…
sandy081 Nov 14, 2026
8f1dd92
Worktree support: the Chat view's folder chip always shows the folder…
sandy081 Nov 14, 2026
8dba43d
Sessions: an editor window's composer offers No Workspace beside its …
sandy081 Nov 14, 2026
8d58ac9
Worktree support: the Chat view's folder chip shows only for a new ch…
sandy081 Nov 14, 2026
a9ca279
Revert "Worktree support: the Chat view's folder chip shows only for …
sandy081 Nov 14, 2026
d7287d3
Revert "Worktree support: the folder chip leads the chat input's pick…
sandy081 Nov 14, 2026
66d0ee3
Worktree support: test that the folder chip sits where the multi-root…
sandy081 Nov 14, 2026
7fd1f0a
Worktree support: No Workspace applies at once, so a send right after…
sandy081 Nov 14, 2026
a33b660
Worktree support: the Chat view's folder chip ellipsizes a long name …
sandy081 Nov 14, 2026
ef00f28
Worktree support: the Chat view's folder chip needs the width of the …
sandy081 Nov 14, 2026
a9191a0
Worktree support: test that the folder chip's width follows its name …
sandy081 Nov 14, 2026
48f7740
Worktree support: the Chat view's folder chip measures what it needs …
sandy081 Nov 14, 2026
cf97880
Worktree support: the Chat view's folder chip shows No Workspace for …
sandy081 Nov 14, 2026
5261ebb
Worktree support: the Chat view's folder picker offers No Workspace a…
sandy081 Nov 14, 2026
a439bfb
Sessions: an editor window's composer offers No Workspace and its fol…
sandy081 Nov 14, 2026
acf5dd8
Worktree infra: what a folder picker's folder and New Worktree do, to…
sandy081 Nov 14, 2026
ac649e0
Merge branch 'sandy081/agents/editor-window-worktree-locations' into …
sandy081 Nov 14, 2026
d71a688
Worktree support: the Chat view's folder picker shows what No Workspa…
sandy081 Nov 14, 2026
9301a35
Merge branch 'sandy081/agents/editor-window-worktree-locations' into …
sandy081 Nov 14, 2026
41350a8
Sessions: an editor window's composer shows what No Workspace, its fo…
sandy081 Nov 14, 2026
6aa8ba0
Action list: a row with a description and a detail keeps its detail i…
sandy081 Nov 14, 2026
009c1f2
Merge branch 'sandy081/agents/editor-window-worktree-locations' into …
sandy081 Nov 14, 2026
b4fc202
Merge branch 'sandy081/agents/editor-window-worktree-locations' into …
sandy081 Nov 14, 2026
a82a018
Action list: a row with a detail is laid out alike with descriptions …
sandy081 Nov 14, 2026
9d4e455
Merge branch 'sandy081/agents/editor-window-worktree-locations' into …
sandy081 Nov 14, 2026
90306c9
Merge branch 'sandy081/agents/editor-window-worktree-locations' into …
sandy081 Nov 14, 2026
6659885
Sessions: an editor window's composer lays out its choices with detai…
sandy081 Nov 14, 2026
84b9a4d
Revert the action list's detail row fixes, which the folder pickers a…
sandy081 Nov 14, 2026
42542d7
Merge branch 'sandy081/agents/editor-window-worktree-locations' into …
sandy081 Nov 14, 2026
787b2a8
Merge branch 'sandy081/agents/editor-window-worktree-locations' into …
sandy081 Nov 14, 2026
088fbea
Sessions: an editor window's composer lays out its choices with a det…
sandy081 Nov 14, 2026
10573cd
Worktree support: the Chat view's folder picker keeps the detail of a…
sandy081 Nov 14, 2026
375b387
Merge main into sandy081/agents/agent-host-list-folder-location
sandy081 Nov 14, 2026
6540229
Worktree support: the chat input component fixtures stub whether a ne…
sandy081 Nov 14, 2026
ca9b1ea
Merge remote-tracking branch 'origin/main' into sandy081/agents/edito…
sandy081 Nov 14, 2026
b132856
Merge branch 'sandy081/agents/editor-window-worktree-locations' into …
sandy081 Nov 14, 2026
ceba42b
Merge branch 'sandy081/agents/editor-window-worktree-locations' into …
sandy081 Nov 14, 2026
46793f6
Agent host: offer the worktree folder chip only for local agent host …
sandy081 Nov 15, 2026
023023b
Sessions: name New Worktree from a worktree by the worktree when seve…
sandy081 Nov 15, 2026
36d7018
Merge remote-tracking branch 'origin/sandy081/agents/agent-host-list-…
sandy081 Nov 15, 2026
25ab514
Merge remote-tracking branch 'origin/main' into sandy081/agents/edito…
sandy081 Nov 15, 2026
1cf86c1
Merge branch 'sandy081/agents/editor-window-worktree-locations' into …
sandy081 Nov 15, 2026
cf34efb
Merge commit '776b518e720' into sandy081/agents/agent-host-list-folde…
sandy081 Nov 15, 2026
c0265aa
Merge remote-tracking branch 'origin/main' into sandy081/agents/edito…
sandy081 Nov 15, 2026
2fe9218
Merge remote-tracking branch 'origin/sandy081/agents/worktree-picker-…
sandy081 Nov 15, 2026
9ab4ecf
Merge remote-tracking branch 'origin/sandy081/agents/agent-host-list-…
sandy081 Nov 15, 2026
0e6ee63
Agent host: offer a worktree that sessions reach by several paths onc…
sandy081 Nov 15, 2026
03029ea
Merge branch 'sandy081/agents/editor-window-worktree-locations' into …
sandy081 Nov 15, 2026
c85967f
Sessions: count an allowed folder without a kind as a folder when nam…
sandy081 Nov 15, 2026
59fa32a
Merge remote-tracking branch 'origin/sandy081/agents/worktree-picker-…
sandy081 Nov 15, 2026
1b8da23
Worktree support: stop re-reading every session as busy sessions upda…
sandy081 Nov 15, 2026
453649c
Worktree support: follow a session that its provider replaces by a ne…
sandy081 Nov 15, 2026
71a9b86
Worktree support: test that the session layer's source follows archiv…
sandy081 Nov 15, 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
4 changes: 0 additions & 4 deletions build/lib/i18n.resources.json
Original file line number Diff line number Diff line change
Expand Up @@ -748,10 +748,6 @@
"name": "vs/sessions/contrib/chat",
"project": "vscode-sessions"
},
{
"name": "vs/sessions/contrib/chatEditor",
"project": "vscode-sessions"
},
{
"name": "vs/sessions/contrib/chatWindow",
"project": "vscode-sessions"
Expand Down
280 changes: 280 additions & 0 deletions build/lib/test/editorWindowSessionsServices.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import assert from 'assert';
import fs from 'fs';
import path from 'path';
import { suite, test } from 'node:test';
import ts from 'typescript';
import { collectSourceDependencies, repositoryRoot, resolveSourceImport } from './sourceDependencies.ts';

const editorWindowEntry = 'src/vs/workbench/workbench.desktop.main.ts';

/** The files that set up the main service collection of an editor window, before any registered singleton. */
const mainServiceCollectionFiles = ['src/vs/workbench/electron-browser/desktop.main.ts', 'src/vs/workbench/browser/workbench.ts'];

/** The sessions code shared with the Agents window, which can depend on services that only the Agents window registers. */
const sessionsRoots = ['src/vs/workbench/contrib/sessions/', 'src/vs/workbench/services/sessions/'];

/**
* The services that an instantiation service scoped to a part of the sessions UI provides, rather than the window: their
* consumers are created through that scope only.
*/
const scopedServices = new Set<string>([
// The model and picker state of a chat input composer, for its toolbar's pickers (see SharedChatInputComposer)
'newChatModelPickerService', 'sessionModelSelection', 'sessionInputPickerVisibility',
]);

const registrationFunctions = new Set(['registerSingleton', 'registerMainProcessRemoteService', 'registerSharedProcessRemoteService']);

const sourceFiles = new Map<string, ts.SourceFile>();

function parse(file: string): ts.SourceFile {
let source = sourceFiles.get(file);
if (!source) {
source = ts.createSourceFile(file, fs.readFileSync(path.join(repositoryRoot, file), 'utf8'), ts.ScriptTarget.Latest, true);
sourceFiles.set(file, source);
}
return source;
}

function forEachDescendant(node: ts.Node, callback: (node: ts.Node) => void): void {
node.forEachChild(child => {
callback(child);
forEachDescendant(child, callback);
});
}

interface IDeclaration {
readonly file: string;
readonly node: ts.ClassDeclaration | ts.VariableDeclaration;
}

const declarations = new Map<string, IDeclaration | undefined>();

/** The class or variable that `name` refers to in `file`: declared there, or imported, also through re-exports. */
function findDeclaration(file: string, name: string): IDeclaration | undefined {
const key = `${file}#${name}`;
if (declarations.has(key)) {
return declarations.get(key);
}
declarations.set(key, undefined);
let result: IDeclaration | undefined;
const source = parse(file);
for (const statement of source.statements) {
if (ts.isClassDeclaration(statement) && statement.name?.text === name) {
result = { file, node: statement };
} else if (ts.isVariableStatement(statement)) {
const declaration = statement.declarationList.declarations.find(candidate => ts.isIdentifier(candidate.name) && candidate.name.text === name);
if (declaration) {
result = { file, node: declaration };
}
}
if (result) {
break;
}
}
for (const statement of source.statements) {
if (result) {
break;
}
if (!(ts.isImportDeclaration(statement) || ts.isExportDeclaration(statement)) || !statement.moduleSpecifier || !ts.isStringLiteral(statement.moduleSpecifier) || !statement.moduleSpecifier.text.startsWith('.')) {
continue;
}
const bindings = ts.isImportDeclaration(statement) ? statement.importClause?.namedBindings : statement.exportClause;
const target = resolveSourceImport(file, statement.moduleSpecifier.text);
if (bindings && (ts.isNamedImports(bindings) || ts.isNamedExports(bindings))) {
const element = bindings.elements.find(candidate => candidate.name.text === name);
if (element) {
result = findDeclaration(target, (element.propertyName ?? element.name).text);
}
} else if (ts.isExportDeclaration(statement) && !bindings) {
result = findDeclaration(target, name);
}
}
declarations.set(key, result);
return result;
}

/** The ID of the service decorator `name` in `file`, which a refined decorator shares with the decorator it refines. */
function serviceIdOf(file: string, name: string): string | undefined {
const declaration = findDeclaration(file, name);
if (!declaration || !ts.isVariableDeclaration(declaration.node)) {
return undefined;
}
const initializer = declaration.node.initializer;
if (!initializer || !ts.isCallExpression(initializer) || !ts.isIdentifier(initializer.expression)) {
return undefined;
}
const [argument] = initializer.arguments;
if (initializer.expression.text === 'createDecorator' && argument && ts.isStringLiteral(argument)) {
return argument.text;
}
if (initializer.expression.text === 'refineServiceDecorator' && argument && ts.isIdentifier(argument)) {
return serviceIdOf(declaration.file, argument.text);
}
return undefined;
}

/** Whether `node` is within a class, rather than at the top level of its module, such as in a function there. */
function isInClass(node: ts.Node): boolean {
for (let parent = node.parent; parent; parent = parent.parent) {
if (ts.isClassLike(parent)) {
return true;
}
}
return false;
}

/** The classes that the `createInstance` calls within `node` create. */
function createdClassesOf(node: ts.Node): string[] {
const created: string[] = [];
forEachDescendant(node, descendant => {
if (ts.isCallExpression(descendant) && ts.isPropertyAccessExpression(descendant.expression) && descendant.expression.name.text === 'createInstance') {
const name = classNameOf(descendant.arguments[0]);
if (name) {
created.push(name);
}
}
});
return created;
}

/** The class that `expression`, such as the first argument of `createInstance`, names. */
function classNameOf(expression: ts.Expression | undefined): string | undefined {
if (expression && ts.isExpressionWithTypeArguments(expression)) {
expression = expression.expression;
}
return expression && ts.isIdentifier(expression) ? expression.text : undefined;
}

interface IClassReference {
readonly file: string;
readonly name: string;
}

interface IEditorWindowServices {
/** The IDs of the services that an editor window provides. */
readonly provided: Set<string>;
/** The implementations that an editor window registers, by service ID. */
readonly implementations: Map<string, IClassReference[]>;
/** The classes that the sessions code of an editor window registers, or creates outside of classes. */
readonly roots: IClassReference[];
}

function collectEditorWindowServices(): IEditorWindowServices {
const provided = new Set<string>(['instantiationService']);
const implementations = new Map<string, IClassReference[]>();
const roots: IClassReference[] = [];
for (const file of mainServiceCollectionFiles) {
forEachDescendant(parse(file), node => {
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && node.expression.name.text === 'set' && node.arguments[0] && ts.isIdentifier(node.arguments[0])) {
const id = serviceIdOf(file, node.arguments[0].text);
if (id) {
provided.add(id);
}
}
});
}
for (const file of collectSourceDependencies(editorWindowEntry)) {
if (!file.startsWith('src/') || !file.endsWith('.ts') || file.endsWith('.d.ts')) {
continue;
}
const isSessions = sessionsRoots.some(root => file.startsWith(root));
const text = fs.readFileSync(path.join(repositoryRoot, file), 'utf8');
if (!/register(Singleton|MainProcessRemoteService|SharedProcessRemoteService)\(/.test(text) && !isSessions) {
continue;
}
forEachDescendant(parse(file), node => {
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && registrationFunctions.has(node.expression.text) && node.arguments[0] && ts.isIdentifier(node.arguments[0])) {
const id = serviceIdOf(file, node.arguments[0].text);
if (!id) {
return;
}
provided.add(id);
const implementation = classNameOf(node.arguments[1]);
if (implementation) {
const references = implementations.get(id) ?? [];
references.push({ file, name: implementation });
implementations.set(id, references);
}
}
if (!isSessions) {
return;
}
// What the sessions code registers or creates outside of classes: services, contributions, views and editors. A
// class creates what it creates once it is created itself.
let root: string | undefined;
if (ts.isCallExpression(node)) {
const callee = ts.isPropertyAccessExpression(node.expression) ? node.expression.name.text : ts.isIdentifier(node.expression) ? node.expression.text : undefined;
if (callee === 'createInstance' && !isInClass(node)) {
root = classNameOf(node.arguments[0]);
} else if (callee === 'registerSingleton' || callee === 'registerWorkbenchContribution2') {
root = classNameOf(node.arguments[1]);
}
} else if (ts.isNewExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === 'SyncDescriptor') {
root = classNameOf(node.arguments?.[0]);
}
if (root) {
roots.push({ file, name: root });
}
});
}
return { provided, implementations, roots };
}

/**
* The services that the classes of `roots` inject, through their constructors and those of their base classes, and of
* the classes they create and the editor window's implementations of the services they inject, within the sessions code:
* each with the class that injects it.
*/
function collectInjectedServices(roots: readonly IClassReference[], implementations: Map<string, IClassReference[]>): Map<string, string> {
const injected = new Map<string, string>();
const visited = new Set<ts.ClassDeclaration>();
const pending = [...roots];
while (pending.length > 0) {
const reference = pending.pop()!;
const declaration = findDeclaration(reference.file, reference.name);
if (!declaration || !ts.isClassDeclaration(declaration.node) || visited.has(declaration.node) || !sessionsRoots.some(root => declaration.file.startsWith(root))) {
continue;
}
visited.add(declaration.node);
const className = `${declaration.node.name?.text} (${declaration.file})`;
const constructor = declaration.node.members.find(ts.isConstructorDeclaration);
for (const parameter of constructor?.parameters ?? []) {
for (const decorator of ts.getDecorators(parameter) ?? []) {
const id = ts.isIdentifier(decorator.expression) ? serviceIdOf(declaration.file, decorator.expression.text) : undefined;
if (!id) {
continue;
}
if (!injected.has(id)) {
injected.set(id, className);
}
pending.push(...implementations.get(id) ?? []);
}
}
pending.push(...createdClassesOf(declaration.node).map(name => ({ file: declaration.file, name })));
for (const clause of declaration.node.heritageClauses ?? []) {
if (clause.token === ts.SyntaxKind.ExtendsKeyword) {
const base = classNameOf(clause.types[0]);
if (base) {
pending.push({ file: declaration.file, name: base });
}
}
}
}
return injected;
}

suite('Editor window sessions services', () => {

test('an editor window provides every service that the sessions code it loads injects, also those that only the Agents window registers', () => {
const { provided, implementations, roots } = collectEditorWindowServices();
const injected = collectInjectedServices(roots, implementations);

const missing = [...injected].filter(([id]) => !provided.has(id) && !scopedServices.has(id)).map(([id, consumer]) => `${id}, injected by ${consumer}`).sort();
assert.deepStrictEqual(missing, []);
});
});
38 changes: 2 additions & 36 deletions build/lib/test/sessionsPresentationDependencies.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import path from 'path';
import { suite, test } from 'node:test';
import ts from 'typescript';
import { getResourcePaths } from '../../next/resources.ts';
import { collectSourceDependencies, repositoryRoot } from './sourceDependencies.ts';

const repositoryRoot = path.resolve(import.meta.dirname, '../../..');
const hostPickerRoot = 'src/vs/sessions/contrib/providers/remoteAgentHost/browser/';
const sharedHostPickerRoot = 'src/vs/workbench/contrib/sessions/providers/remoteAgentHost/browser/';
const originalPicker = [
Expand All @@ -28,7 +28,6 @@ const experimentalPicker = [
'media/hostPlaceChip.css',
'media/mobileHostPickerSheet.css',
].map(file => hostPickerRoot + file);
const dependenciesByFile = new Map<string, readonly string[]>();
const composerRoot = 'src/vs/sessions/contrib/providers/agentHost/browser/mobile/';
const originalConfigurationPresenter = 'src/vs/workbench/contrib/sessions/providers/agentHost/browser/mobile/mobileChatPhoneInputPresenter.ts';
const mobileConfigurationPresenter = composerRoot + 'mobileChatPhoneInputPresenter.ts';
Expand Down Expand Up @@ -149,7 +148,7 @@ suite('Sessions presentation entry isolation', () => {
}, {
canvas: ['IWindowCanvasService', 'WindowCanvasService'],
pinnedCanvas: mobile ? undefined : ['IPinnedCanvasService', 'PinnedCanvasService'],
chatWindow: ['IChatWindowService', mobile ? 'MobileNullChatWindowService' : 'ChatWindowService'],
chatWindow: ['IChatWindowService', mobile ? 'NullChatWindowService' : 'ChatWindowService'],
presentation: mobile ? [] : desktopPresentation,
});
});
Expand Down Expand Up @@ -329,36 +328,3 @@ function isMobileEntryFile(file: string): boolean {
hostPickerRoot + 'mobileTunnelConnection.ts',
].includes(file);
}

/** Includes type imports conservatively: neither source graph may depend on the other presentation. */
function collectSourceDependencies(entry: string): Set<string> {
const visited = new Set<string>();
const pending = [entry];
while (pending.length > 0) {
const file = pending.pop()!;
if (visited.has(file)) {
continue;
}
visited.add(file);
if (!file.endsWith('.ts') && !file.endsWith('.js')) {
continue;
}
let dependencies = dependenciesByFile.get(file);
if (!dependencies) {
const source = fs.readFileSync(path.join(repositoryRoot, file), 'utf8');
dependencies = ts.preProcessFile(source, true).importedFiles
.map(reference => reference.fileName)
.filter(specifier => specifier.startsWith('.'))
.map(specifier => {
const resolved = path.resolve(repositoryRoot, path.dirname(file), specifier);
const candidates = [resolved.replace(/\.js$/, '.ts'), resolved.replace(/\.js$/, '.tsx'), resolved.replace(/\.js$/, '.d.ts'), resolved];
const dependency = candidates.find(candidate => fs.existsSync(candidate) && fs.statSync(candidate).isFile());
assert.ok(dependency, `Cannot resolve ${specifier} from ${file}`);
return path.relative(repositoryRoot, dependency).replaceAll('\\', '/');
});
dependenciesByFile.set(file, dependencies);
}
pending.push(...dependencies);
}
return visited;
}
Loading
Loading