chatServiceImpl.ts ×10

Frontier kind: Code frontier

unlabeled · c_219d2b2f1e27

64 tests · 70793 LOC · 309 files · introduces 0 tests · 82 LOC · 4 files

Introduces — evidence that enters the hierarchy at this concept

Code
21 ranges82 lines · 4 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
5833 ranges70793 lines · 309 files · Browse complete extent
All tests (intent)
64 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

4 files ranked by introduced lines: 82 introduced LOC across 21 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/workbench/contrib/chat/common/chatService/chatServiceImpl.ts 43 introduced LOC · 10 ranges

Open complete file

265 createModel: (props: IStartSessionProps) => this._startSession(props),
266 willDisposeModel: async (model: ChatModel) => {
267 > const localSessionId = LocalChatSessionUri.parseLocalSessionId(model.sessionResource); chatServiceImpl.ts
268 > if (localSessionId && this.shouldStoreSession(model)) {
269 // Always preserve sessions that have custom titles, even if empty
270 if (model.getRequests().length === 0 && !model.customTitle) {
275 await this._chatSessionStore.storeSessions([model]);
276 }
277 > } else if (!localSessionId && (model.getRequests().length > 0 || hasDraftInput(model))) { chatServiceImpl.ts
278 logChangesToStateModel(model.inputModel, `disposing external session ${model.sessionResource} with requests or draft input, storing metadata to storage`, undefined, undefined, this.logService);
279 // External sessions: persist metadata when there are requests, OR when the
281 await this._chatSessionStore.storeSessionsMetadataOnly([model]);
282 }
284 }));
285 this._register(this._sessionModels.onDidDisposeModel(model => {
403
404 private trace(method: string, message?: string): void {
405 > if (message) { chatServiceImpl.ts
406 > this.logService.trace(`ChatService#${method}: ${message}`);
407 > } else {
408 this.logService.trace(`ChatService#${method}`);
409 }
411
412 private info(method: string, message?: string): void {
543
544 private _startSession(props: IStartSessionProps): ChatModel {
545 > const { initialData, location, sessionResource, canUseTools, transferEditingSession, disableBackgroundKeepAlive, inputState, isReadOnly } = props; chatServiceImpl.ts
546 > const model = this.instantiationService.createInstance(ChatModel, initialData, { initialLocation: location, canUseTools, resource: sessionResource, disableBackgroundKeepAlive, inputState, isReadOnly });
547 > if (location === ChatAgentLocation.Chat) {
548 > model.startEditingSession(true, transferEditingSession);
549 > }
550 >
551 > this.initializeSession(model);
552 > return model;
553 > }
554
555 private initializeSession(model: ChatModel): void {
556 > this.trace('initializeSession', `Initialize session ${model.sessionResource}`); chatServiceImpl.ts
557 >
558 > // Activate the default extension provided agent but do not wait
559 > // for it to be ready so that the session can be used immediately
560 > // without having to wait for the agent to be ready.
561 > this.activateDefaultAgent(model.initialLocation).catch(e => this.logService.error(e));
562 > }
563
564 async activateDefaultAgent(location: ChatAgentLocation): Promise<void> {
565 > await this.extensionService.whenInstalledExtensionsRegistered(); chatServiceImpl.ts
566 >
567 > const defaultAgentData = this.chatAgentService.getContributedDefaultAgent(location) ?? this.chatAgentService.getContributedDefaultAgent(ChatAgentLocation.Chat);
568 > if (!defaultAgentData) {
569 throw new ErrorNoTelemetry('No default agent contributed');
570 }
572 > // Await activation of the extension provided agent
573 > // Using `activateById` as workaround for the issue
574 > // https://github.com/microsoft/vscode/issues/250590
575 > if (!defaultAgentData.isCore) {
576 > await this.extensionService.activateById(defaultAgentData.extensionId, {
577 > activationEvent: `onChatParticipant:${defaultAgentData.id}`,
578 > extensionId: defaultAgentData.extensionId,
579 > startup: false
580 > });
581 > }
582 >
583 > const defaultAgent = this.chatAgentService.getActivatedAgents().find(agent => agent.id === defaultAgentData.id);
584 > if (!defaultAgent) {
585 throw new ErrorNoTelemetry('No default agent registered');
586 }
588
589 getSession(sessionResource: URI): IChatModel | undefined {
src/vs/workbench/contrib/chat/common/model/chatModel.ts 29 introduced LOC · 8 ranges

Open complete file

2560 // Set the session resource and id
2561 if (initialModelProps.resource) {
2562 > // prefer using the provided resource if provided chatModel.ts
2563 > this._sessionId = chatSessionResourceToId(initialModelProps.resource);
2564 > this._sessionResource = initialModelProps.resource;
2565 } else if (isValidFullData) {
2566 // Otherwise use the serialized id. This is only valid for local chat sessions
2667
2668 startEditingSession(isGlobalEditingSession?: boolean, transferFromSession?: IChatEditingSession): void {
2669 > const session = this._editingSession ??= this._register( chatModel.ts
2670 > transferFromSession
2671 ? this.chatEditingService.transferEditingSession(this, transferFromSession)
2672 > : isGlobalEditingSession chatModel.ts
2673 > ? this.chatEditingService.startOrContinueGlobalEditingSession(this)
2674 : this.chatEditingService.createEditingSession(this)
2675 > ); chatModel.ts
2676 >
2677 > if (!this._disableBackgroundKeepAlive) {
2678 > // todo@connor4312: hold onto a reference so background sessions don't
2679 > // trigger early disposal. This will be cleaned up with the globalization of edits.
2680 > const selfRef = this._register(new MutableDisposable<IChatModelReference>());
2681 > this._register(autorun(r => {
2682 > const hasModified = session.entries.read(r).some(e => e.state.read(r) === ModifiedFileEntryState.Modified);
2683 > if (hasModified && !selfRef.value) {
2684 selfRef.value = this.chatService.acquireExistingSession(this._sessionResource, 'ChatModel#modifiedEditsKeepAlive');
2685 > } else if (!hasModified && selfRef.value) { chatModel.ts
2686 selfRef.clear();
2687 }
2688 > })); chatModel.ts
2689 > }
2690 >
2691 > this._register(autorun(reader => {
2692 > this._setDisabledRequests(session.requestDisablement.read(reader));
2693 > }));
2694 > }
2695
2696 private currentEditedFileEvents = new ResourceMap<IChatAgentEditedFileEvent>();
2917
2918 private _setDisabledRequests(requestIds: IChatRequestDisablement[]) {
2919 > this._requests.forEach((request) => { chatModel.ts
2920 const shouldBeRemovedOnSend = requestIds.find(r => r.requestId === request.id);
2921 request.shouldBeRemovedOnSend = shouldBeRemovedOnSend;
2923 request.response.shouldBeRemovedOnSend = shouldBeRemovedOnSend;
2924 }
2925 > }); chatModel.ts
2926 >
2927 > this._onDidChange.fire({ kind: 'setHidden' });
2928 > }
2929
2930 addRequest(
src/vs/base/common/arraysFind.ts 8 introduced LOC · 2 ranges

Open complete file

13 return undefined;
14 }
15 > return array[idx]; arraysFind.ts
16 > }
17
18 export function findLastIdx<T>(array: readonly T[], predicate: (item: T, index: number) => unknown, fromIndex = array.length - 1): number {
19 for (let i = fromIndex; i >= 0; i--) {
20 > const element = array[i]; arraysFind.ts
21 >
22 > if (predicate(element, i)) {
23 > return i;
24 > }
25 > }
26
27 return -1;
src/vs/workbench/contrib/chat/common/participants/chatAgents.ts 2 introduced LOC · 1 range

Open complete file

462
463 getContributedDefaultAgent(location: ChatAgentLocation): IChatAgentData | undefined {
464 > return this._preferExtensionAgent(this.getAgents().filter(a => !!a.isDefault && a.locations.includes(location))); chatAgents.ts
465 > }
466
467 private _preferExtensionAgent<T extends IChatAgentData>(agents: T[]): T | undefined {