Properly normalize very old chat session data (#227030)

Fix microsoft/vscode-copilot#7729
pull/227048/head
Rob Lourens 2024-08-28 19:15:04 -07:00 committed by GitHub
parent 8cd1d86cb7
commit 4ab6e5d7c3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 76 additions and 1 deletions

View File

@ -616,6 +616,8 @@ export type ISerializableChatDataIn = ISerializableChatData1 | ISerializableChat
* TODO- ChatModel#_deserialize and reviveSerializedAgent also still do some normalization and maybe that should be done in here too.
*/
export function normalizeSerializableChatData(raw: ISerializableChatDataIn): ISerializableChatData {
normalizeOldFields(raw);
if (!('version' in raw)) {
return {
version: 3,
@ -636,6 +638,30 @@ export function normalizeSerializableChatData(raw: ISerializableChatDataIn): ISe
return raw;
}
function normalizeOldFields(raw: ISerializableChatDataIn): void {
// Fill in fields that very old chat data may be missing
if (!raw.sessionId) {
raw.sessionId = generateUuid();
}
if (!raw.creationDate) {
raw.creationDate = getLastYearDate();
}
if ('version' in raw && (raw.version === 2 || raw.version === 3)) {
if (!raw.lastMessageDate) {
// A bug led to not porting creationDate properly, and that was copied to lastMessageDate, so fix that up if missing.
raw.lastMessageDate = getLastYearDate();
}
}
}
function getLastYearDate(): number {
const lastYearDate = new Date();
lastYearDate.setFullYear(lastYearDate.getFullYear() - 1);
return lastYearDate.getTime();
}
export function isExportableSessionData(obj: unknown): obj is IExportableChatData {
const data = obj as IExportableChatData;
return typeof data === 'object' &&

View File

@ -17,7 +17,7 @@ import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKe
import { ILogService, NullLogService } from 'vs/platform/log/common/log';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ChatAgentLocation, ChatAgentService, IChatAgentService } from 'vs/workbench/contrib/chat/common/chatAgents';
import { ChatModel, ISerializableChatData1, ISerializableChatData2, normalizeSerializableChatData, Response } from 'vs/workbench/contrib/chat/common/chatModel';
import { ChatModel, ISerializableChatData1, ISerializableChatData2, ISerializableChatData3, normalizeSerializableChatData, Response } from 'vs/workbench/contrib/chat/common/chatModel';
import { ChatRequestTextPart } from 'vs/workbench/contrib/chat/common/chatParserTypes';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { TestExtensionService, TestStorageService } from 'vs/workbench/test/common/workbenchTestServices';
@ -230,4 +230,53 @@ suite('normalizeSerializableChatData', () => {
assert.strictEqual(newData.lastMessageDate, v2Data.lastMessageDate);
assert.strictEqual(newData.customTitle, v2Data.computedTitle);
});
test('old bad data', () => {
const v1Data: ISerializableChatData1 = {
// Testing the scenario where these are missing
sessionId: undefined!,
creationDate: undefined!,
initialLocation: undefined,
isImported: false,
requesterAvatarIconUri: undefined,
requesterUsername: 'me',
requests: [],
responderAvatarIconUri: undefined,
responderUsername: 'bot',
welcomeMessage: []
};
const newData = normalizeSerializableChatData(v1Data);
assert.strictEqual(newData.version, 3);
assert.ok(newData.creationDate > 0);
assert.ok(newData.lastMessageDate > 0);
assert.ok(newData.sessionId);
});
test('v3 with bug', () => {
const v3Data: ISerializableChatData3 = {
// Test case where old data was wrongly normalized and these fields were missing
creationDate: undefined!,
lastMessageDate: undefined!,
version: 3,
initialLocation: undefined,
isImported: false,
requesterAvatarIconUri: undefined,
requesterUsername: 'me',
requests: [],
responderAvatarIconUri: undefined,
responderUsername: 'bot',
sessionId: 'session1',
welcomeMessage: [],
customTitle: 'computed title'
};
const newData = normalizeSerializableChatData(v3Data);
assert.strictEqual(newData.version, 3);
assert.ok(newData.creationDate > 0);
assert.ok(newData.lastMessageDate > 0);
assert.ok(newData.sessionId);
});
});