in server/aws-lsp-codewhisperer/src/language-server/chat/chatController.ts [107:225]
async onChatPrompt(params: ChatParams, token: CancellationToken): Promise<ChatResult | ResponseError<ChatResult>> {
const maybeDefaultResponse = getDefaultChatResponse(params.prompt.prompt)
if (maybeDefaultResponse) {
return maybeDefaultResponse
}
const sessionResult = this.#chatSessionManagementService.getSession(params.tabId)
const { data: session, success } = sessionResult
if (!success) {
return new ResponseError<ChatResult>(ErrorCodes.InternalError, sessionResult.error)
}
const metric = new Metric<CombinedConversationEvent>({
cwsprChatConversationType: 'Chat',
})
const triggerContext = await this.#getTriggerContext(params, metric)
const isNewConversation = !session.conversationId
token.onCancellationRequested(() => {
this.#log('cancellation requested')
session.abortRequest()
})
let response: SendMessageCommandOutput
let requestInput: SendMessageCommandInput
const conversationIdentifier = session?.conversationId ?? 'New conversation'
try {
this.#log('Request for conversation id:', conversationIdentifier)
requestInput = this.#triggerContext.getChatParamsFromTrigger(
params,
triggerContext,
ChatTriggerType.MANUAL,
this.#customizationArn
)
metric.recordStart()
response = await session.sendMessage(requestInput)
this.#log('Response for conversation id:', conversationIdentifier, JSON.stringify(response.$metadata))
} catch (err) {
if (isAwsError(err) || (isObject(err) && 'statusCode' in err && typeof err.statusCode === 'number')) {
metric.setDimension('cwsprChatRepsonseCode', err.statusCode ?? 400)
this.#telemetryController.emitMessageResponseError(params.tabId, metric.metric)
}
const authFollowType = getAuthFollowUpType(err)
if (authFollowType) {
this.#log(`Q auth error: ${getErrorMessage(err)}`)
return createAuthFollowUpResult(authFollowType)
}
this.#log(`Q api request error ${err instanceof Error ? err.message : 'unknown'}`)
return new ResponseError<ChatResult>(
LSPErrorCodes.RequestFailed,
err instanceof Error ? err.message : 'Unknown request error'
)
}
try {
const result = await this.#processSendMessageResponse(
response,
metric.mergeWith({
cwsprChatResponseCode: response.$metadata.httpStatusCode,
cwsprChatMessageId: response.$metadata.requestId,
}),
params.partialResultToken
)
session.conversationId = result.data?.conversationId
this.#log('Session conversation id:', session.conversationId || '')
if (session.conversationId) {
this.#telemetryController.setConversationId(params.tabId, session.conversationId)
if (isNewConversation) {
this.#telemetryController.updateTriggerInfo(params.tabId, {
startTrigger: {
hasUserSnippet: metric.metric.cwsprChatHasCodeSnippet ?? false,
triggerType: triggerContext.triggerType,
},
})
this.#telemetryController.emitStartConversationMetric(params.tabId, metric.metric)
}
}
metric.setDimension('codewhispererCustomizationArn', requestInput.conversationState?.customizationArn)
await this.#telemetryController.emitAddMessageMetric(params.tabId, metric.metric)
this.#telemetryController.updateTriggerInfo(params.tabId, {
lastMessageTrigger: {
...triggerContext,
messageId: response.$metadata.requestId,
followUpActions: new Set(
result.data?.chatResult.followUp?.options
?.map(option => option.prompt ?? '')
.filter(prompt => prompt.length > 0)
),
},
})
return result.success
? result.data.chatResult
: new ResponseError<ChatResult>(LSPErrorCodes.RequestFailed, result.error)
} catch (err) {
this.#log('Error encountered during response streaming:', err instanceof Error ? err.message : 'unknown')
return new ResponseError<ChatResult>(
LSPErrorCodes.RequestFailed,
err instanceof Error ? err.message : 'Unknown error occured during response stream'
)
}
}