172
*/
173
export function setActiveSessionContextKeys(session: IActiveSession | undefined, contextKeyService: IContextKeyService, reader: IReader | undefined): void {
175
>
const keys = getBoundKeys(contextKeyService);
176
>
keys.isCreated.set(session?.isCreated.read(reader) ?? false);
177
>
keys.sticky.set(session?.sticky.read(reader) ?? false);
178
>
179
>
// Count committed (non-draft) chats: untitled in-composer drafts are excluded
180
>
// so the Conversations menu only surfaces once a session has more than one
181
>
// real chat. Counts the whole chat list (open or closed) so a committed chat
182
>
// that was closed still keeps the menu available to reopen it.
183
>
const committedChatCount = session?.chats.read(reader)
184
>
.reduce((count, chat) => chat.status.read(reader) === SessionStatus.Untitled || chat.origin?.kind === ChatOriginKind.Tool ? count : count + 1, 0) ?? 0;
185
>
keys.hasMultipleCommittedChats.set(committedChatCount > 1);
186
>
187
>
// The tab strip is shown when the session has more than one chat (counting
188
>
// closed chats) or its single remaining chat's title diverged from the
189
>
// session title; the header then hides its own New Chat button.
190
>
keys.shouldShowChatTabs.set(session?.shouldShowChatTabs.read(reader) ?? false);
191
>
192
>
// More than one open chat tab (incl. drafts): scopes chat-to-chat navigation
193
>
// so it stays a no-op when only a single open chat remains (e.g. a single
194
>
// chat with a diverged title, or one open + one closed chat).
195
>
keys.hasMultipleOpenChats.set((session?.visibleChatTabs.read(reader).length ?? 0) > 1);
196
>
197
>
// The active chat can be closed (hidden) from the tab strip when it is a
198
>
// non-main chat — including read-only subagent chats, which surface as
199
>
// closeable tabs. The main chat lives and dies with its session.
200
>
const activeChat = session?.activeChat.read(reader);
201
>
const mainResource = session?.mainChat.read(reader).resource;
202
>
const isNonMainChat = !!activeChat && !!mainResource && !isEqual(activeChat.resource, mainResource);
203
>
keys.activeChatIsClosable.set(isNonMainChat);
204
>
// It can be permanently deleted only when its effective capabilities allow
205
>
// it: the main chat and worker (subagent) chats report `canDelete: false`,
206
>
// so they are closeable but not deletable.
207
>
keys.activeChatIsDeletable.set(!!activeChat && getChatCapabilities(activeChat, session, reader).canDelete);
208
>
209
>
// The active chat has subagents when any tool-origin chat names it as its
210
>
// parent. These are listed as a separate group in the Conversations menu, so
211
>
// the menu must surface even when the active chat is the only committed chat.
212
>
const allChats = session?.chats.read(reader) ?? [];
213
>
keys.activeChatHasSubagents.set(!!activeChat && allChats.some(chat =>
214
>
chat.origin?.kind === ChatOriginKind.Tool &&
215
>
!!chat.origin.parentChat &&
216
>
isEqual(chat.origin.parentChat, activeChat.resource)));
217
>
}