Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(amazonq): Add additonal fields for agentic chat in chat history #6942

Merged
merged 6 commits into from
Apr 7, 2025
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,11 @@
* SPDX-License-Identifier: Apache-2.0
*/

import {
ConversationState,
CursorState,
DocumentSymbol,
SymbolType,
TextDocument,
ChatMessage,
} from '@amzn/codewhisperer-streaming'
import { ConversationState, CursorState, DocumentSymbol, SymbolType, TextDocument } from '@amzn/codewhisperer-streaming'
import { AdditionalContentEntryAddition, ChatTriggerType, RelevantTextDocumentAddition, TriggerPayload } from '../model'
import { undefinedIfEmpty } from '../../../../shared/utilities/textUtilities'
import { ChatItemType } from '../../../../amazonq/commons/model'
import { getLogger } from '../../../../shared/logger/logger'
import { messageToChatMessage } from '../../../../shared/db/chatDb/util'

const fqnNameSizeDownLimit = 1
const fqnNameSizeUpLimit = 256
Expand Down Expand Up @@ -158,19 +151,7 @@ export function triggerPayloadToChatRequest(triggerPayload: TriggerPayload): { c
const history =
triggerPayload.history &&
triggerPayload.history.length > 0 &&
(triggerPayload.history.map((chat) =>
chat.type === ('answer' as ChatItemType)
? {
assistantResponseMessage: {
content: chat.body,
},
}
: {
userInputMessage: {
content: chat.body,
},
}
) as ChatMessage[])
triggerPayload.history.map((chat) => messageToChatMessage(chat))

return {
conversationState: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import { Selection } from 'vscode'
import { TabOpenType } from '../../../amazonq/webview/ui/storages/tabsStorage'
import { CodeReference } from '../../view/connector/connector'
import { Customization } from '../../../codewhisperer/client/codewhispereruserclient'
import { ChatItem, QuickActionCommand } from '@aws/mynah-ui'
import { QuickActionCommand } from '@aws/mynah-ui'
import { Message } from '../../../shared/db/chatDb/util'

export interface TriggerTabIDReceived {
tabID: string
Expand Down Expand Up @@ -206,7 +207,7 @@ export interface TriggerPayload {
traceId?: string
contextLengths: ContextLengths
workspaceRulesCount?: number
history?: ChatItem[]
history?: Message[]
}

export type ContextLengths = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import * as vscode from 'vscode'
import { Messenger } from './messenger/messenger'
import { Database } from '../../../shared/db/chatDb/chatDb'
import { TabBarButtonClick, SaveChatMessage } from './model'
import { Conversation, Tab } from '../../../shared/db/chatDb/util'
import { Conversation, messageToChatItem, Tab } from '../../../shared/db/chatDb/util'
import { DetailedListItemGroup, MynahIconsType } from '@aws/mynah-ui'

export class TabBarController {
Expand Down Expand Up @@ -87,7 +87,9 @@ export class TabBarController {
this.messenger.sendRestoreTabMessage(
selectedTab.historyId,
selectedTab.tabType,
selectedTab.conversations.flatMap((conv: Conversation) => conv.messages),
selectedTab.conversations.flatMap((conv: Conversation) =>
conv.messages.map((message) => messageToChatItem(message))
),
exportTab
)
}
Expand Down
13 changes: 7 additions & 6 deletions packages/core/src/shared/db/chatDb/chatDb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
import Loki from 'lokijs'
import * as vscode from 'vscode'
import { TabType } from '../../../amazonq/webview/ui/storages/tabsStorage'
import { ChatItem, ChatItemType, DetailedListItemGroup } from '@aws/mynah-ui'
import { ChatItemType, DetailedListItemGroup } from '@aws/mynah-ui'
import {
ClientType,
Conversation,
FileSystemAdapter,
groupTabsByDate,
Message,
Tab,
TabCollection,
updateOrCreateConversation,
Expand Down Expand Up @@ -171,7 +172,7 @@ export class Database {
const tabs = tabCollection.find()
const filteredTabs = tabs.filter((tab: Tab) => {
return tab.conversations.some((conversation: Conversation) => {
return conversation.messages.some((message: ChatItem) => {
return conversation.messages.some((message: Message) => {
return message.body?.toLowerCase().includes(searchTermLower)
})
})
Expand Down Expand Up @@ -225,7 +226,7 @@ export class Database {
}
}

addMessage(tabId: string, tabType: TabType, conversationId: string, chatItem: ChatItem) {
addMessage(tabId: string, tabType: TabType, conversationId: string, message: Message) {
if (this.initialized) {
const tabCollection = this.db.getCollection<Tab>(TabCollection)

Expand All @@ -238,9 +239,9 @@ export class Database {

const tabData = historyId ? tabCollection.findOne({ historyId }) : undefined
const tabTitle =
(chatItem.type === ('prompt' as ChatItemType) ? chatItem.body : tabData?.title) || 'Amazon Q Chat'
(message.type === ('prompt' as ChatItemType) ? message.body : tabData?.title) || 'Amazon Q Chat'
if (tabData) {
tabData.conversations = updateOrCreateConversation(tabData.conversations, conversationId, chatItem)
tabData.conversations = updateOrCreateConversation(tabData.conversations, conversationId, message)
tabData.updatedAt = new Date()
tabData.title = tabTitle
tabCollection.update(tabData)
Expand All @@ -251,7 +252,7 @@ export class Database {
isOpen: true,
tabType: tabType,
title: tabTitle,
conversations: [{ conversationId, clientType: ClientType.VSCode, messages: [chatItem] }],
conversations: [{ conversationId, clientType: ClientType.VSCode, messages: [message] }],
})
}
}
Expand Down
66 changes: 63 additions & 3 deletions packages/core/src/shared/db/chatDb/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,17 @@ import fs from '../../fs/fs'
import path from 'path'

import { TabType } from '../../../amazonq/webview/ui/storages/tabsStorage'
import { ChatItem, ChatItemButton, DetailedListItem, DetailedListItemGroup, MynahIconsType } from '@aws/mynah-ui'
import {
ChatItem,
ChatItemButton,
ChatItemType,
DetailedListItem,
DetailedListItemGroup,
MynahIconsType,
ReferenceTrackerInformation,
SourceLink,
} from '@aws/mynah-ui'
import { ChatMessage, Origin, ToolUse, UserInputMessageContext, UserIntent } from '@amzn/codewhisperer-streaming'

export const TabCollection = 'tabs'

Expand All @@ -24,7 +34,7 @@ export type Tab = {
export type Conversation = {
conversationId: string
clientType: ClientType
messages: ChatItem[]
messages: Message[]
}

export enum ClientType {
Expand All @@ -33,6 +43,56 @@ export enum ClientType {
CLI = 'CLI',
}

export type Message = {
body: string
type: ChatItemType
codeReference?: ReferenceTrackerInformation[]
relatedContent?: {
title?: string
content: SourceLink[]
}
messageId?: string
userIntent?: UserIntent
origin?: Origin
userInputMessageContext?: UserInputMessageContext
toolUses?: ToolUse[]
}

/**
* Converts Message to CodeWhisperer Streaming ChatMessage
*/
export function messageToChatMessage(msg: Message): ChatMessage {
return msg.type === ('answer' as ChatItemType)
? {
assistantResponseMessage: {
messageId: msg.messageId,
content: msg.body,
references: msg.codeReference || [],
toolUses: msg.toolUses || [],
},
}
: {
userInputMessage: {
content: msg.body,
userIntent: msg.userIntent,
origin: msg.origin || 'IDE',
userInputMessageContext: msg.userInputMessageContext || {},
},
}
}

/**
* Converts Message to MynahUI Chat Item
*/
export function messageToChatItem(msg: Message): ChatItem {
return {
body: msg.body,
type: msg.type as ChatItemType,
codeReference: msg.codeReference,
relatedContent: msg.relatedContent && msg.relatedContent?.content.length > 0 ? msg.relatedContent : undefined,
}
}

/**
*
* This adapter implements the LokiPersistenceAdapter interface for file system operations using web-compatible shared fs utils.
Expand Down Expand Up @@ -107,7 +167,7 @@ export class FileSystemAdapter implements LokiPersistenceAdapter {
export function updateOrCreateConversation(
conversations: Conversation[],
conversationId: string,
newMessage: ChatItem
newMessage: Message
): Conversation[] {
const existingConversation = conversations.find((conv) => conv.conversationId === conversationId)

Expand Down
Loading