Skip to content

Commit

Permalink
feat(ui): optimize entire file context in sidepanel display (#3604)
Browse files Browse the repository at this point in the history
* feat(ui): optimize entire file context in sidepanel display

[autofix.ci] apply automated fixes

update: optional range field

update

update

update: simpify

update

cmt

update

* update

* [autofix.ci] apply automated fixes

* update

* [autofix.ci] apply automated fixes

* update cmts

* update

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
  • Loading branch information
liangfung and autofix-ci[bot] authored Dec 24, 2024
1 parent 9676a92 commit 2322c11
Show file tree
Hide file tree
Showing 11 changed files with 86 additions and 94 deletions.
3 changes: 2 additions & 1 deletion clients/tabby-chat-panel/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,9 @@ export interface FileLocation {
/**
* The location in the file.
* It could be a 1-based line number, a line range, a position or a position range.
* If the location is not provided, the whole file is considered.
*/
location: Location
location?: Location
}

/**
Expand Down
5 changes: 1 addition & 4 deletions clients/vscode/src/chat/fileContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,7 @@ export async function getFileContext(
start: editor.selection.start.line + 1,
end: editor.selection.end.line + 1,
}
: {
start: 1,
end: editor.document.lineCount,
};
: undefined;

const filepath = localUriToChatPanelFilepath(editor.document.uri, gitProvider);

Expand Down
5 changes: 4 additions & 1 deletion clients/vscode/src/chat/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@ export function chatPanelLineRangeToVSCodeRange(lineRange: LineRange): VSCodeRan
return new VSCodeRange(Math.max(0, lineRange.start - 1), 0, lineRange.end, 0);
}

export function chatPanelLocationToVSCodeRange(location: Location): VSCodeRange | null {
export function chatPanelLocationToVSCodeRange(location: Location | undefined): VSCodeRange | null {
if (!location) {
return null;
}
if (typeof location === "number") {
const position = new VSCodePosition(Math.max(0, location - 1), 0);
return new VSCodeRange(position, position);
Expand Down
26 changes: 5 additions & 21 deletions ee/tabby-ui/app/search/components/assistant-message-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,9 @@ export function AssistantMessageSection({
if (!clientCode?.length) return []
return (
clientCode.map(code => {
const { startLine, endLine } = getRangeFromAttachmentCode(code)

return {
kind: 'file',
range: {
start: startLine,
end: endLine
},
range: getRangeFromAttachmentCode(code),
filepath: code.filepath || '',
content: code.content,
git_url: relevantCodeGitURL
Expand All @@ -171,14 +166,9 @@ export function AssistantMessageSection({
const serverCodeContexts: RelevantCodeContext[] = useMemo(() => {
return (
message?.attachment?.code?.map(code => {
const { startLine, endLine } = getRangeFromAttachmentCode(code)

return {
kind: 'file',
range: {
start: startLine,
end: endLine
},
range: getRangeFromAttachmentCode(code),
filepath: code.filepath,
content: code.content,
git_url: code.gitUrl,
Expand Down Expand Up @@ -216,10 +206,7 @@ export function AssistantMessageSection({
searchParams.append('redirect_git_url', ctx.git_url)
url.search = searchParams.toString()

const lineHash = formatLineHashForCodeBrowser({
start: ctx.range.start,
end: ctx.range.end
})
const lineHash = formatLineHashForCodeBrowser(ctx.range)
if (lineHash) {
url.hash = lineHash
}
Expand All @@ -238,7 +225,7 @@ export function AssistantMessageSection({
}

const openCodeBrowserTab = (code: MessageAttachmentCode) => {
const { startLine, endLine } = getRangeFromAttachmentCode(code)
const range = getRangeFromAttachmentCode(code)

if (!code.filepath) return
const url = new URL(`${window.location.origin}/files`)
Expand All @@ -247,10 +234,7 @@ export function AssistantMessageSection({
searchParams.append('redirect_git_url', code.gitUrl)
url.search = searchParams.toString()

const lineHash = formatLineHashForCodeBrowser({
start: startLine,
end: endLine
})
const lineHash = formatLineHashForCodeBrowser(range)
if (lineHash) {
url.hash = lineHash
}
Expand Down
12 changes: 7 additions & 5 deletions ee/tabby-ui/components/chat/chat-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -284,10 +284,11 @@ function ChatPanelRenderer(
</motion.div>
) : null}
{relevantContext.map((item, idx) => {
// `git_url + filepath + range` as unique key
const key = `${item.git_url}_${item.filepath}_${item.range?.start}_${item.range?.end}`
return (
<motion.div
// `filepath + range` as unique key
key={item.filepath + item.range.start + item.range.end}
key={key}
initial={{ opacity: 0, scale: 0.9, y: -5 }}
animate={{ opacity: 1, scale: 1, y: 0 }}
transition={{
Expand Down Expand Up @@ -344,15 +345,16 @@ function ContextLabel({
className?: string
}) {
const [fileName] = context.filepath.split('/').slice(-1)
const line =
context.range.start === context.range.end
const line = context.range
? context.range.start === context.range.end
? `:${context.range.start}`
: `:${context.range.start}-${context.range.end}`
: ''

return (
<span className={cn('truncate', className)}>
{fileName}
<span className="text-muted-foreground">{line}</span>
{!!context.range && <span className="text-muted-foreground">{line}</span>}
</span>
)
}
2 changes: 1 addition & 1 deletion ee/tabby-ui/components/chat/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ function ChatRenderer(
clientSideFileContexts.map(o => ({
content: o.content,
filepath: o.filepath,
startLine: o.range.start
startLine: o.range?.start
}))

return [
Expand Down
25 changes: 15 additions & 10 deletions ee/tabby-ui/components/chat/code-references.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ function ContextItem({
}) {
const [tooltipOpen, setTooltipOpen] = useState(false)
const isMultiLine =
context.range &&
!isNil(context.range?.start) &&
!isNil(context.range?.end) &&
context.range.start < context.range.end
Expand Down Expand Up @@ -178,16 +179,20 @@ function ContextItem({
<IconFile className="shrink-0" />
<div className="flex-1 truncate" title={context.filepath}>
<span>{fileName}</span>
{context.range?.start && (
<span className="text-muted-foreground">
:{context.range.start}
</span>
)}
{isMultiLine && (
<span className="text-muted-foreground">
-{context.range.end}
</span>
)}
{context.range ? (
<>
{context.range?.start && (
<span className="text-muted-foreground">
:{context.range.start}
</span>
)}
{isMultiLine && (
<span className="text-muted-foreground">
-{context.range.end}
</span>
)}
</>
) : null}
<span className="ml-2 text-xs text-muted-foreground">{path}</span>
</div>
{showClientCodeIcon && (
Expand Down
66 changes: 31 additions & 35 deletions ee/tabby-ui/components/chat/question-answer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,10 @@ function UserMessageCard(props: { message: UserMessage }) {
selectCode = {
filepath,
isMultiLine:
!isNil(range?.start) && !isNil(range?.end) && range.start < range.end
!!range &&
!isNil(range?.start) &&
!isNil(range?.end) &&
range.start < range.end
}
}
return (
Expand Down Expand Up @@ -189,7 +192,7 @@ function UserMessageCard(props: { message: UserMessage }) {
<span>:{message.selectContext?.range.start}</span>
)}
{selectCode.isMultiLine && (
<span>-{message.selectContext?.range.end}</span>
<span>-{message.selectContext?.range?.end}</span>
)}
</p>
</div>
Expand Down Expand Up @@ -270,20 +273,13 @@ function AssistantMessageCard(props: AssistantMessageCardProps) {
React.useState<number | undefined>(undefined)
const serverCode: Array<Context> = React.useMemo(() => {
return (
message?.relevant_code?.map(code => {
const { startLine, endLine } = getRangeFromAttachmentCode(code)

return {
kind: 'file',
range: {
start: startLine,
end: endLine
},
filepath: code.filepath,
content: code.content,
git_url: code.gitUrl
}
}) ?? []
message?.relevant_code?.map(code => ({
kind: 'file',
range: getRangeFromAttachmentCode(code),
filepath: code.filepath,
content: code.content,
git_url: code.gitUrl
})) ?? []
)
}, [message?.relevant_code])

Expand All @@ -299,19 +295,22 @@ function AssistantMessageCard(props: AssistantMessageCardProps) {

const attachmentDocsLen = 0

const attachmentClientCode: Array<Omit<AttachmentCodeItem, '__typename'>> =
useMemo(() => {
const formatedAttachmentClientCode =
clientCode?.map(o => ({
content: o.content,
filepath: o.filepath,
gitUrl: o.git_url,
startLine: o.range.start,
language: filename2prism(o.filepath ?? '')[0],
isClient: true
})) ?? []
return formatedAttachmentClientCode
}, [clientCode])
const attachmentClientCode: Array<
Omit<AttachmentCodeItem, '__typename' | 'startLine'> & {
startLine: number | undefined
}
> = useMemo(() => {
const formatedAttachmentClientCode =
clientCode?.map(o => ({
content: o.content,
filepath: o.filepath,
gitUrl: o.git_url,
startLine: o.range ? o.range.start : undefined,
language: filename2prism(o.filepath ?? '')[0],
isClient: true
})) ?? []
return formatedAttachmentClientCode
}, [clientCode])

const attachmentCode: Array<Omit<AttachmentCodeItem, '__typename'>> =
useMemo(() => {
Expand All @@ -320,7 +319,8 @@ function AssistantMessageCard(props: AssistantMessageCardProps) {
content: o.content,
filepath: o.filepath,
gitUrl: o.git_url,
startLine: o.range.start,
// for server attachment code, startLine will not be undefined
startLine: o.range?.start ?? 1,
language: filename2prism(o.filepath ?? '')[0],
isClient: false
})) ?? []
Expand Down Expand Up @@ -352,16 +352,12 @@ function AssistantMessageCard(props: AssistantMessageCardProps) {
}

const onCodeCitationClick = (code: AttachmentCodeItem) => {
const { startLine, endLine } = getRangeFromAttachmentCode(code)
const ctx: Context = {
git_url: code.gitUrl,
content: code.content,
filepath: code.filepath,
kind: 'file',
range: {
start: startLine,
end: endLine
}
range: getRangeFromAttachmentCode(code)
}
onContextClick(ctx, code.isClient)
}
Expand Down
2 changes: 1 addition & 1 deletion ee/tabby-ui/components/message-markdown/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ export function MessageMarkdown({

setSymbolLocationMap(map => new Map(map.set(keyword, undefined)))
const hints: LookupSymbolHint[] = []
if (activeSelection) {
if (activeSelection && activeSelection?.range) {
// FIXME(@icycodes): this is intended to convert the filepath to Filepath type
// We should remove this after FileContext.filepath use type Filepath instead of string
let filepath: Filepath
Expand Down
6 changes: 5 additions & 1 deletion ee/tabby-ui/lib/types/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ import { ArrayElementType } from './common'
export interface FileContext {
kind: 'file'
filepath: string
range: { start: number; end: number }
/**
* The range of the selected content in the file.
* If the range is not provided, the whole file is considered.
*/
range?: { start: number; end: number }
content: string
git_url: string
}
Expand Down
28 changes: 14 additions & 14 deletions ee/tabby-ui/lib/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,15 +135,15 @@ export function formatLineHashForLocation(location: Location | undefined) {
const start = location.start
if (typeof start === 'number') {
const end = location.end as number
return `L${start}-${end}`
return `L${start}-L${end}`
}
if (
typeof start === 'object' &&
'line' in start &&
typeof start.line === 'number'
) {
const end = location.end as Position
return `L${start.line}-${end.line}`
return `L${start.line}-L${end.line}`
}
}
return ''
Expand All @@ -152,22 +152,22 @@ export function formatLineHashForLocation(location: Location | undefined) {
export function getRangeFromAttachmentCode(code: {
startLine?: Maybe<number>
content: string
}) {
const startLine = code?.startLine ?? 0
const lineCount = code?.content.split('\n').length
const endLine = startLine + lineCount - 1
}): LineRange | undefined {
if (!code?.startLine) return undefined

const start = code.startLine
const lineCount = code.content.split('\n').length
const end = start + lineCount - 1

return {
startLine,
endLine,
isValid: !!startLine,
isMultiLine: !!startLine && startLine <= endLine
start,
end
}
}

export function getRangeTextFromAttachmentCode(code: AttachmentCodeItem) {
const { startLine, endLine } = getRangeFromAttachmentCode(code)
return formatLineHashForCodeBrowser({ start: startLine, end: endLine })
const range = getRangeFromAttachmentCode(code)
return formatLineHashForCodeBrowser(range)
}

export function getContent(item: AttachmentDocItem) {
Expand Down Expand Up @@ -199,9 +199,9 @@ export function convertEditorContext(
editorContext: EditorContext
): FileContext {
const convertRange = (range: LineRange | PositionRange | undefined) => {
// FIXME: If the range is not provided, the whole file is considered.
// If the range is not provided, the whole file is considered.
if (!range) {
return { start: 0, end: 0 }
return undefined
}

if (typeof range.start === 'number') {
Expand Down

0 comments on commit 2322c11

Please sign in to comment.