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: @ syntax for bringing files into chat context #475

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

weilirs
Copy link
Collaborator

@weilirs weilirs commented Nov 4, 2024

#467

If this looks good I'll

  • improve the autocomplete UI
  • not showing the absolute path but just the file name
@.syntax.mov

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Summary

Added @ syntax functionality for referencing files in chat context, enabling users to search and include files in conversations through an autocomplete interface.

  • Potential security risk in searchFiles function as it exposes file paths without proper validation or sanitization in electron/main/filesystem/filesystem.ts
  • File search implementation in searchFiles loads all files into memory before filtering, which could cause performance issues with large directories
  • Regex pattern /@([^@]+?\.md)/g in extractFileReferences is fragile and only handles .md files without validating existence
  • Caret position calculation in getCaretCoordinates creates/removes DOM elements frequently without debouncing
  • Missing error handling for file operations and IPC calls across multiple components

7 file(s) reviewed, 17 comment(s)
Edit PR Review Bot Settings | Greptile

@@ -217,3 +219,18 @@ export function splitDirectoryPathIntoBaseAndRepo(fullPath: string) {

return { localModelPath, repoName }
}

export const searchFiles = async (store: Store<StoreSchema>, searchTerm: string): Promise<string[]> => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Function marked as async but contains no await operations

@@ -217,3 +219,18 @@ export function splitDirectoryPathIntoBaseAndRepo(fullPath: string) {

return { localModelPath, repoName }
}

export const searchFiles = async (store: Store<StoreSchema>, searchTerm: string): Promise<string[]> => {
const vaultDirectory = store.get(StoreKeys.DirectoryFromPreviousSession)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: Using DirectoryFromPreviousSession instead of current window's vault directory could cause inconsistencies

Comment on lines +229 to +233
const allFiles = GetFilesInfoList(vaultDirectory)

const searchTermLower = searchTerm.toLowerCase()

const matchingFiles = allFiles.filter((file) => file.name.toLowerCase().startsWith(searchTermLower))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Loading all files into memory before filtering could be inefficient for large vaults. Consider using a streaming/iterative approach

Comment on lines +225 to +227
if (!vaultDirectory || typeof vaultDirectory !== 'string') {
throw new Error('No valid vault directory found')
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Error handling could provide more context about why the vault directory is invalid

Comment on lines +198 to +200
ipcMain.handle('search-files', async (_event, searchTerm: string) => {
return searchFiles(store, searchTerm)
})
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: No error handling for searchFiles - could throw unhandled exceptions if store is invalid or searchTerm is malformed. Consider wrapping in try/catch.

>
{files.map((file) => (
<div key={file} className="cursor-pointer px-4 py-2 hover:bg-neutral-700" onClick={() => onSelect(file)}>
{file.split('/').pop()}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: file.split('/').pop() could return undefined if path ends in /

Comment on lines 176 to 180
const handleFileSelect = (filePath: string) => {
const lastAtIndex = userTextFieldInput.lastIndexOf('@')
const newValue = `${userTextFieldInput.slice(0, lastAtIndex)}@${filePath} ${userTextFieldInput.slice(
lastAtIndex + searchTerm.length + 1,
)}`
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: Potential XSS vulnerability - filePath needs to be sanitized before being inserted into the text input

Comment on lines 114 to 121
// Create a hidden div with the same styling as textarea
const mirror = document.createElement('div')
mirror.style.cssText = window.getComputedStyle(element).cssText
mirror.style.height = 'auto'
mirror.style.position = 'absolute'
mirror.style.visibility = 'hidden'
mirror.style.whiteSpace = 'pre-wrap'
document.body.appendChild(mirror)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: Memory leak risk - mirror element needs cleanup if component unmounts while calculating coordinates

Comment on lines +20 to +21
const regex = /@([^@]+?\.md)/g
const matches = message.match(regex)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: regex pattern only matches .md files and doesn't handle spaces or special characters in filenames

Comment on lines 60 to 61
const fileRefs = extractFileReferences(userTextFieldInput || '')
// console.log('fileRefs', fileRefs)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: no validation that referenced files exist before adding to chat context

@milaiwi
Copy link
Collaborator

milaiwi commented Nov 4, 2024

Will take a look tonight

Edit: Delayed due to comment below.

@samlhuillier
Copy link
Collaborator

I'm afraid we'll need to hold off on merging this PR. I'm doing a bit of a revamp of chat to get it working nicely in the sidebar #472 so this feature can only be merged after that's done

@weilirs weilirs marked this pull request as draft November 5, 2024 01:54
@weilirs
Copy link
Collaborator Author

weilirs commented Nov 5, 2024

I'm afraid we'll need to hold off on merging this PR. I'm doing a bit of a revamp of chat to get it working nicely in the sidebar #472 so this feature can only be merged after that's done

Okay, this PR needs more work as well, just want some opinions from you guys.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants