Skip to content

Commit

Permalink
feat: support at-mentions context on edits (#3091)
Browse files Browse the repository at this point in the history
![edit-at](https://github.com/sourcegraph/cody/assets/68532117/3e593672-cf8f-4fe3-872c-c739da6e1459)

This commit adds the functionality to include the old context files from
the transcript to the chat context files map in the Chat component. It
creates a new map called contextFilesMap and populates it with the old
context files. This allows for easy access and reference to the context
files used in edit mode.

Also added telemetry around chat actions and edit buttons

## Test plan

<!-- Required. See
https://sourcegraph.com/docs/dev/background-information/testing_principles.
-->



https://github.com/sourcegraph/cody/assets/68532117/a9683af7-dca7-43f6-bc0c-80d7d31bfef1
  • Loading branch information
abeatrix authored Feb 9, 2024
1 parent 423938a commit 763cd92
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 43 deletions.
64 changes: 49 additions & 15 deletions lib/ui/src/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,11 @@ export const Chat: React.FunctionComponent<ChatProps> = ({
: messageAtIndex?.text
if (inputText) {
setFormInput(inputText)
if (messageAtIndex.contextFiles) {
useOldChatMessageContext(messageAtIndex.contextFiles)
}
}
// move focus back to chatbox
setInputFocus(true)
},
[messageBeingEdited, setFormInput, setMessageBeingEdited, transcript]
Expand All @@ -315,19 +319,30 @@ export const Chat: React.FunctionComponent<ChatProps> = ({
* Calls setEditMessageState() to reset any in-progress edit state.
* Sends a 'reset' command to postMessage to reset the chat on the server.
*/
const onChatResetClick = useCallback(() => {
setEditMessageState()
postMessage?.({ command: 'reset' })
}, [postMessage, setEditMessageState])
const onChatResetClick = useCallback(
(eventType: 'keyDown' | 'click' = 'click') => {
setEditMessageState()
postMessage?.({ command: 'reset' })
postMessage?.({
command: 'event',
eventName: 'CodyVSCodeExtension:chatActions:reset:executed',
properties: { source: 'chat', eventType },
})
},
[postMessage, setEditMessageState]
)

/**
* Resets the context selection and query state.
*/
const resetContextSelection = useCallback(() => {
setSelectedChatContext(0)
setCurrentChatContextQuery(undefined)
setContextSelection(null)
}, [setContextSelection])
const resetContextSelection = useCallback(
(eventType?: 'keyDown' | 'click') => {
setSelectedChatContext(0)
setCurrentChatContextQuery(undefined)
setContextSelection(null)
},
[setContextSelection]
)

/**
* Gets the display text for a context file to be completed into the chat when a user
Expand All @@ -345,6 +360,15 @@ export const Chat: React.FunctionComponent<ChatProps> = ({
return `@${displayPath(contextFile.uri)}${range}${symbolName}`
}

// Add old context files from the transcript to the map
const useOldChatMessageContext = (oldContextFiles: ContextFile[]) => {
const contextFilesMap = new Map<string, ContextFile>()
for (const file of oldContextFiles) {
contextFilesMap.set(getContextFileDisplayText(file), file)
}
setChatContextFiles(contextFilesMap)
}

/**
* Callback function called when a chat context file is selected from the context selector.
* This updates the chat input with the selected file context.
Expand Down Expand Up @@ -558,14 +582,20 @@ export const Chat: React.FunctionComponent<ChatProps> = ({
if (event.key === '/') {
event.preventDefault()
event.stopPropagation()
onChatResetClick()
onChatResetClick('keyDown')
return
}
// Ctrl/Cmd + K - When not already editing, edits the last human message
if (messageBeingEdited === undefined && event.key === 'k') {
event.preventDefault()
event.stopPropagation()
setEditMessageState(lastHumanMessageIndex)

postMessage?.({
command: 'event',
eventName: 'CodyVSCodeExtension:chatActions:editLast:executed',
properties: { source: 'chat', eventType: 'keyDown' },
})
return
}
}
Expand Down Expand Up @@ -693,12 +723,14 @@ export const Chat: React.FunctionComponent<ChatProps> = ({
} else {
setFormInput(newHistoryInput.inputText)
// chatContextFiles uses a map but history only stores a simple array.
const contextFilesMap = new Map<string, ContextFile>()
for (const file of newHistoryInput.inputContextFiles) {
contextFilesMap.set(getContextFileDisplayText(file), file)
}
setChatContextFiles(contextFilesMap)
useOldChatMessageContext(newHistoryInput.inputContextFiles)
}

postMessage?.({
command: 'event',
eventName: 'CodyVSCodeExtension:chatInputHistory:executed',
properties: { source: 'chat' },
})
}
}
},
Expand All @@ -718,6 +750,8 @@ export const Chat: React.FunctionComponent<ChatProps> = ({
onChatContextSelected,
enableNewChatMode,
resetContextSelection,
useOldChatMessageContext,
postMessage,
]
)

Expand Down
3 changes: 2 additions & 1 deletion vscode/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ This is a log of all notable changes to Cody for VS Code. [Unreleased] changes a

### Added

- Chat: Added support for `@-mentioned files` in mid sentences. [pull/3043](https://github.com/sourcegraph/cody/pull/3043)
- Chat: Support `@-mentioned` in mid sentences. [pull/3043](https://github.com/sourcegraph/cody/pull/3043)
- Chat: Support `@-mentioned` in editing mode. [pull/3091](https://github.com/sourcegraph/cody/pull/3091)

### Fixed

Expand Down
42 changes: 17 additions & 25 deletions vscode/test/e2e/chat-edits.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect } from '@playwright/test'

import { sidebarSignin } from './common'
import { test } from './helpers'
import { test, withPlatformSlashes } from './helpers'

const isPlatform = (platform: string) => process.platform === platform
const isMac = isPlatform('darwin')
Expand Down Expand Up @@ -104,34 +104,26 @@ test('editing follow-up messages in chat view', async ({ page, sidebar }) => {
await expect(cancelEditButton).not.toBeVisible()
await expect(chatInput).toBeEmpty()
await expect(chatFrame.getByText('Explain @Main.java')).toBeVisible()
await chatInput.press('Escape')

// Add a new at-file to an old messages
await chatInput.press(`${osKey}+k`)
await chatInput.type('and @vgo', { delay: 50 })
await chatInput.press('Tab')
await expect(chatInput).toHaveValue(
withPlatformSlashes('Explain @Main.java and @lib/batches/env/var.go ')
)
await chatInput.press('Enter')
// both main.java and var.go should be used
await expect(chatFrame.getByText(/Context: 2 files/)).toBeVisible()
await chatFrame.getByText(/Context: 2 files/).click()
await expect(chatFrame.getByRole('button', { name: 'Main.java' })).toBeVisible()
await expect(
chatFrame.getByRole('button', { name: withPlatformSlashes('lib/batches/env/var.go') })
).toBeVisible()

// Meta+/ also creates a new chat session
await chatInput.press(`${osKey}+/`)
await expect(chatFrame.getByText('The End')).not.toBeVisible()

// TODO (bee) - update after switching to the new keybinding for toggling "New Chat Mode"
await expect(startNewChatButton).not.toBeVisible()
// // "MetaKey(MacOS)/Control" + "Shift" to toggle "New Chat Mode" on and off
// // When it's on, the submit button will be replaced with "Start New Chat" button
// await expect(submitMessageButton).toBeVisible()
// await chatInput.press(`${osKey}+Shift`)
// await expect(submitMessageButton).not.toBeVisible()
// await expect(startNewChatButton).toBeVisible()
// await chatInput.press(`${osKey}+Shift`)
// await expect(startNewChatButton).not.toBeVisible()
// await chatInput.press(`${osKey}+Shift`)
// await expect(startNewChatButton).toBeVisible()

// // With "New Chat Mode" enabled, submit a new message to start a new chat
// // The new message should be "The End"
// // And the last message should not be visible anymore
// await chatInput.fill('The End')
// await chatInput.press('Enter')
// await expect(chatFrame.getByText('The End')).toBeVisible()
// await expect(chatFrame.getByText('Explain @Main.java')).not.toBeVisible()

// // Meta+/ also creates a new chat session
// await chatInput.press(`${osKey}+/`)
// await expect(chatFrame.getByText('The End')).not.toBeVisible()
})
11 changes: 9 additions & 2 deletions vscode/webviews/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import { EnhancedContextSettings } from './Components/EnhancedContextSettings'
import { FileLink } from './Components/FileLink'
import { SymbolLink } from './SymbolLink'
import { UserContextSelectorComponent } from './UserContextSelector'
import type { VSCodeWrapper } from './utils/VSCodeApi'
import { getVSCodeAPI, type VSCodeWrapper } from './utils/VSCodeApi'

import styles from './Chat.module.css'

Expand Down Expand Up @@ -427,7 +427,14 @@ const EditButton: React.FunctionComponent<EditButtonProps> = ({
title={disabled ? 'Cannot Edit Command' : 'Edit Your Message'}
type="button"
disabled={disabled}
onClick={() => setMessageBeingEdited(messageBeingEdited)}
onClick={() => {
setMessageBeingEdited(messageBeingEdited)
getVSCodeAPI().postMessage({
command: 'event',
eventName: 'CodyVSCodeExtension:chatEditButton:clicked',
properties: { source: 'chat' },
})
}}
>
<i className="codicon codicon-edit" />
</VSCodeButton>
Expand Down

0 comments on commit 763cd92

Please sign in to comment.