106
return false;
107
}
109
>
110
>
const urisEqual = (a: UriComponents, b: UriComponents): boolean => {
111
return _urisEqual(URI.from(a), URI.from(b));
112
};
114
>
const messageSchema = Adapt.object<IParsedChatRequest, IParsedChatRequest>({
115
>
text: Adapt.v(m => m.text),
116
>
parts: Adapt.v(m => m.parts, (a, b) => a.length === b.length && a.every((part, i) => part.text === b[i].text)),
117
>
});
118
>
119
>
const agentEditedFileEventSchema = Adapt.object<IChatAgentEditedFileEvent, IChatAgentEditedFileEvent>({
120
>
uri: Adapt.v(e => e.uri, urisEqual),
121
>
eventKind: Adapt.v(e => e.eventKind),
122
>
});
123
>
124
>
const chatVariableSchema = Adapt.object<IChatRequestVariableData, IChatRequestVariableData>({
125
>
variables: Adapt.t(v => v.variables.map(IChatRequestVariableEntry.toExport), Adapt.array(Adapt.value((a, b) => a.name === b.name))),
126
>
});
127
>
128
>
const requestSchema = Adapt.object<IChatRequestModel, ISerializableChatRequestData>({
129
>
// request parts
130
>
requestId: Adapt.t(m => m.id, Adapt.key()),
131
>
timestamp: Adapt.v(m => m.requestTimestamp),
132
>
confirmation: Adapt.v(m => m.confirmation),
133
>
message: Adapt.t(m => m.message, messageSchema),
134
>
shouldBeRemovedOnSend: Adapt.v(m => m.shouldBeRemovedOnSend, objectsEqual),
135
>
agent: Adapt.v(m => m.response?.agent, (a, b) => a?.id === b?.id),
136
>
modelId: Adapt.v(m => m.modelId),
137
>
editedFileEvents: Adapt.t(m => m.editedFileEvents, Adapt.array(agentEditedFileEventSchema)),
138
>
variableData: Adapt.t(m => m.variableData, chatVariableSchema),
139
>
isHidden: Adapt.v(() => undefined), // deprecated, always undefined for new data
140
>
isCanceled: Adapt.v(() => undefined), // deprecated, modelState is used instead
141
>
142
>
response: Adapt.t(m => m.response?.entireResponse.value.filter((p): p is Exclude<IChatProgressResponseContent, IChatMcpAuthenticationRequired | IChatMcpServersStartingSlow> => p.kind !== 'mcpAuthenticationRequired' && p.kind !== 'mcpServersStartingSlow'), Adapt.array(responsePartSchema)),
143
>
responseId: Adapt.v(m => m.response?.id),
144
>
responseTimestamp: Adapt.v(m => m.response?.timestamp),
145
>
result: Adapt.v(m => m.response?.result, objectsEqual),
146
>
responseMarkdownInfo: Adapt.v(
147
>
m => m.response?.codeBlockInfos?.map(info => ({ suggestionId: info.suggestionId })),
148
>
objectsEqual,
149
>
),
150
>
followups: Adapt.v(m => m.response?.followups, objectsEqual),
151
>
modelState: Adapt.v(m => m.response?.stateT, objectsEqual),
152
>
vote: Adapt.v(m => m.response?.vote),
153
>
slashCommand: Adapt.t(m => m.response?.slashCommand, Adapt.value((a, b) => a?.name === b?.name)),
154
>
usedContext: Adapt.v(m => m.response?.usedContext, objectsEqual),
155
>
contentReferences: Adapt.v(m => m.response?.contentReferences, objectsEqual),
156
>
codeCitations: Adapt.v(m => m.response?.codeCitations, objectsEqual),
157
>
timeSpentWaiting: Adapt.v(m => m.response?.timestamp), // based on response timestamp
158
>
completionTokens: Adapt.v(m => m.response?.completionTokenCount),
159
>
promptTokens: Adapt.v(m => m.response?.usage?.promptTokens),
160
>
outputBuffer: Adapt.v(m => m.response?.usage?.outputBuffer),
161
>
promptTokenDetails: Adapt.v(m => m.response?.usage?.promptTokenDetails, objectsEqual),
162
>
copilotCredits: Adapt.v(m => m.response?.usage?.copilotCredits),
163
>
elapsedMs: Adapt.v(m => m.response?.elapsedMs ?? (m.response?.completedAt ? Math.max(0, m.response.completedAt - m.response.confirmationAdjustedTimestamp.get()) : undefined)),
164
>
modeInfo: Adapt.v(m => m.modeInfo, objectsEqual),
165
>
isSystemInitiated: Adapt.v(m => m.isSystemInitiated),
166
>
systemInitiatedLabel: Adapt.v(m => m.systemInitiatedLabel),
167
>
terminalExecutionId: Adapt.v(m => m.terminalExecutionId),
168
>
}, {
169
>
sealed: (o) => o.modelState?.value === ResponseModelState.Cancelled || o.modelState?.value === ResponseModelState.Failed || o.modelState?.value === ResponseModelState.Complete,
170
>
});
171
>
172
>
const inputStateSchema = Adapt.object<ISerializableChatModelInputState, ISerializableChatModelInputState>({
173
>
attachments: Adapt.v(i => i.attachments.map(IChatRequestVariableEntry.toExport), objectsEqual),
174
>
mode: Adapt.v(i => i.mode, (a, b) => a.id === b.id),
175
>
selectedModel: Adapt.v(i => i.selectedModel, (a, b) => a?.identifier === b?.identifier && objectsEqual(a?.modelConfiguration, b?.modelConfiguration)),
176
>
inputText: Adapt.v(i => i.inputText),
177
>
selections: Adapt.v(i => i.selections, objectsEqual),
178
>
permissionLevel: Adapt.v(i => i.permissionLevel),
179
>
contrib: Adapt.v(i => i.contrib, objectsEqual),
180
>
});
181
>
182
>
const pendingRequestSchema = Adapt.object<IChatPendingRequest, ISerializablePendingRequestData>({
183
>
id: Adapt.t(p => p.request.id, Adapt.key()),
184
>
request: Adapt.t(p => p.request, requestSchema),
185
>
kind: Adapt.v(p => p.kind),
186
>
sendOptions: Adapt.v(p => serializeSendOptions(p.sendOptions), objectsEqual),
187
>
});
188
>
189
>
export const storageSchema = Adapt.object<IChatModel, ISerializableChatData>({
190
>
version: Adapt.v(() => 3),
191
>
creationDate: Adapt.v(m => m.timestamp),
192
>
customTitle: Adapt.v(m => m.hasCustomTitle ? m.title : undefined),
193
>
initialLocation: Adapt.v(m => m.initialLocation),
194
>
inputState: Adapt.t(m => m.inputModel.toJSON(), inputStateSchema),
195
>
responderUsername: Adapt.v(m => m.responderUsername),
196
>
sessionId: Adapt.v(m => m.sessionId),
197
>
requests: Adapt.t(m => m.getRequests(), Adapt.array(requestSchema)),
198
>
hasPendingEdits: Adapt.v(m => m.editingSession?.entries.get().some(e => e.state.get() === ModifiedFileEntryState.Modified)),
199
>
repoData: Adapt.v(m => m.repoData, objectsEqual),
200
>
pendingRequests: Adapt.t(m => m.getPendingRequests(), Adapt.array(pendingRequestSchema)),
201
>
workingDirectory: Adapt.v(m => m.workingDirectory?.toString()),
202
>
});
203
>
204
>
export class ChatSessionOperationLog extends Adapt.ObjectMutationLog<IChatModel, ISerializableChatData> implements IChatDataSerializerLog {
205
>
constructor() {
206
super(storageSchema, 1024);
207
}