Change:
In one of my workspaces I see no more chat. The console shows the stacktraces below, the debugger stops like this <img width="1302" alt="Screenshot 2023-09-28 at 10 26 44" src=""
omg, 1-indexed vs 0-indexed ranges... That is the fix, thanks for saving me from candidate shame
This would happen when a request body is empty. But probably the only way you would get in that state is if you had a session that was broken due to the issue that my original commit was fixing, which was broken chat session serialization. So I think the only way to verify it really is to check the window where you noticed the original issue. Or we can call it verified by code review.
verified by code review

Discussion:
} }); <del> // Code Actions on Save registerEditorSettingMigration('codeActionsOnSave', (value, read, write) => { if (value && typeof value === 'object') { const newValue = {} as any; for (const entry of Object.entries(value)) { if (typeof entry[1] === 'boolean') { newValue[entry[0]] = entry[1] ? 'explicit' : 'never'; } else { newValue[entry[0]] = entry[1]; } } write(`codeActionsOnSave`, newValue); } }); </del> <ins> // // Code Actions on Save // registerEditorSettingMigration('codeActionsOnSave', (value, read, write) => { // 	if (value && typeof value === 'object') { // 		const newValue = {} as any; // 		for (const entry of Object.entries(value)) { // 			if (typeof entry[1] === 'boolean') { // 				newValue[entry[0]] = entry[1] ? 'explicit' : 'never'; // 			} else { // 				newValue[entry[0]] = entry[1]; // 			} // 		} // 		write(`codeActionsOnSave`, newValue); // 	} // }); </ins>

this._welcomeMessage = new ChatWelcomeMessageModel(this, content); } <del> return requests.map((raw: ISerializableChatRequestData) => { const parsedRequest = typeof raw.message === 'string' ? this.getParsedRequestFromString(raw.message) : reviveParsedChatRequest(raw.message); const request = new ChatRequestModel(this, parsedRequest, raw.providerRequestId); if (raw.response || raw.responseErrorDetails) { const agent = raw.agent && this.chatAgentService.getAgents().find(a => a.id === raw.agent!.id); // TODO do something reasonable if this agent has disappeared since the last session request.response = new ChatResponseModel(raw.response ?? [new MarkdownString(raw.response)], this, agent, true, raw.isCanceled, raw.vote, raw.providerRequestId, raw.responseErrorDetails, raw.followups); } return request; }); </del> <ins> try { return requests.map((raw: ISerializableChatRequestData) => { const parsedRequest = typeof raw.message === 'string' ? this.getParsedRequestFromString(raw.message) : reviveParsedChatRequest(raw.message); const request = new ChatRequestModel(this, parsedRequest, raw.providerRequestId); if (raw.response || raw.responseErrorDetails) { const agent = raw.agent && this.chatAgentService.getAgents().find(a => a.id === raw.agent!.id); // TODO do something reasonable if this agent has disappeared since the last session request.response = new ChatResponseModel(raw.response ?? [new MarkdownString(raw.response)], this, agent, true, raw.isCanceled, raw.vote, raw.providerRequestId, raw.responseErrorDetails, raw.followups); } return request; }); } catch (error) { this.logService.error('Failed to parse chat data', error); return []; } </ins> } private getParsedRequestFromString(message: string): IParsedChatRequest { // TODO These offsets won't be used, but chat replies need to go through the parser as well <del> const parts = [new ChatRequestTextPart(new OffsetRange(1, message.length), { startColumn: 1, startLineNumber: 1, endColumn: 1, endLineNumber: 1 }, message)]; </del> <ins> const parts = [new ChatRequestTextPart(new OffsetRange(0, message.length), { startColumn: 1, startLineNumber: 1, endColumn: 1, endLineNumber: 1 }, message)]; </ins> return { text: message, parts