in server/aws-lsp-codewhisperer/src/language-server/agenticChat/agenticChatEventParser.ts [87:200]
public processPartialEvent(chatEvent: ChatResponseStream): Result<ChatResultWithMetadata, string> {
const {
messageMetadataEvent,
followupPromptEvent,
supplementaryWebLinksEvent,
codeReferenceEvent,
assistantResponseEvent,
error,
invalidStateEvent,
toolUseEvent,
} = chatEvent
if (!this.#metric.metric.cwsprTimeToFirstChunk) {
this.#metric.mergeWith({
cwsprTimeToFirstChunk: this.#metric.getTimeElapsed(),
cwsprChatTimeBetweenChunks: [],
})
} else {
const chatTime = Date.now() - this.#lastChunkTime
if (chatTime !== 0) {
this.#metric.mergeWith({
cwsprChatTimeBetweenChunks: [chatTime],
})
}
}
this.#lastChunkTime = Date.now()
if (error) {
this.error = error.message
} else if (invalidStateEvent) {
this.error = invalidStateEvent.message ?? invalidStateEvent.reason ?? 'Invalid state'
} else if (assistantResponseEvent?.content) {
this.#totalEvents.assistantResponseEvent += 1
this.body = (this.body ?? '') + assistantResponseEvent.content
} else if (toolUseEvent) {
this.#totalEvents.toolUserEvent += 1
// what about no tool use id?
if (toolUseEvent.toolUseId) {
const toolUseId = toolUseEvent.toolUseId
const name = toolUseEvent.name
const input = toolUseEvent.input
this.toolUses[toolUseId] = {
...this.toolUses[toolUseId],
toolUseId,
name,
input: `${this.toolUses[toolUseId]?.input || ''}${input || ''}`,
stop: !!toolUseEvent.stop,
}
if (toolUseEvent.stop) {
const finalInput = this.toolUses[toolUseId].input
let parsedInput
try {
if (typeof finalInput === 'string') {
parsedInput = JSON.parse(finalInput === '' ? '{}' : finalInput)
} else {
parsedInput = finalInput
}
} catch (err) {
this.#logging.error(
`Error parsing tool use input: ${this.toolUses[toolUseId].input}:${loggingUtils.formatErr(err)}`
)
this.error = `ToolUse input is invalid JSON: "${this.toolUses[toolUseId].input}".`
parsedInput = {}
}
this.toolUses[toolUseId] = {
...this.toolUses[toolUseId],
input: parsedInput,
}
this.#logging.log(
`ToolUseEvent: ${toolUseId} ${name} ${loggingUtils.formatObj(this.toolUses[toolUseId].input)}`
)
}
}
} else if (followupPromptEvent?.followupPrompt) {
this.#totalEvents.followupPromptEvent += 1
const { content } = followupPromptEvent.followupPrompt
this.followUp = {
text: AgenticChatEventParser.FOLLOW_UP_TEXT,
options: [
...(this.followUp?.options ?? []),
{
pillText: content ?? '',
prompt: content ?? '',
},
],
}
} else if (
supplementaryWebLinksEvent?.supplementaryWebLinks &&
supplementaryWebLinksEvent.supplementaryWebLinks.length > 0
) {
this.#totalEvents.supplementaryWebLinksEvent += 1
const sourceLinks = supplementaryWebLinksEvent.supplementaryWebLinks.map(
AgenticChatEventParser.mapRelatedData
)
this.relatedContent = {
...this.relatedContent,
content: [...(this.relatedContent?.content ?? []), ...sourceLinks],
}
} else if (codeReferenceEvent?.references && codeReferenceEvent.references.length > 0) {
this.#totalEvents.codeReferenceEvent += 1
const references = codeReferenceEvent.references.map(AgenticChatEventParser.mapReferenceData)
this.codeReference = [...(this.codeReference ?? []), ...references]
} else if (messageMetadataEvent?.conversationId) {
this.conversationId = messageMetadataEvent?.conversationId
}
return this.getResult()
}