Skip to content

Commit 1c8bde4

Browse files
committed
feat(gpt-runner-web): add all file paths as prompt support
1 parent 0060b32 commit 1c8bde4

File tree

6 files changed

+91
-19
lines changed

6 files changed

+91
-19
lines changed

packages/gpt-runner-web/client/src/helpers/utils.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,8 @@ export function getErrorMsg(error: any) {
5050
export function formatNumWithK(num: number) {
5151
return `${(num / 1000).toFixed(1)}k`
5252
}
53+
54+
export function countTokenQuick(text: string) {
55+
// int
56+
return Math.floor(text.length / 3.5)
57+
}

packages/gpt-runner-web/client/src/pages/chat/chat.styles.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,11 @@ export const FileTreeItemRightWrapper = styled.div`
7878

7979
export const FileTreeSidebarUnderSearchWrapper = styled.div`
8080
font-size: var(--type-ramp-base-font-size);
81-
margin: 0.5rem 0;
81+
margin: 0.25rem 0 0.5rem 0;
82+
background: linear-gradient(-135deg, var(--list-hover-background) 10%, transparent 70%);
83+
color: var(--input-foreground);
84+
padding: 0.5rem 0;
85+
border-radius: 0.25rem;
8286
`
8387

8488
export const FileTreeSidebarHighlight = styled.span`

packages/gpt-runner-web/client/src/pages/chat/file-tree.tsx

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,24 @@
11
import { type FC, useCallback, useEffect, useRef, useState } from 'react'
22
import { useQuery } from '@tanstack/react-query'
3-
import { type FileInfoTreeItem, travelTree, travelTreeDeepFirst } from '@nicepkg/gpt-runner-shared/common'
3+
import { travelTree, travelTreeDeepFirst } from '@nicepkg/gpt-runner-shared/common'
44
import clsx from 'clsx'
55
import { VSCodeCheckbox, VSCodeLink } from '@vscode/webview-ui-toolkit/react'
66
import type { SidebarProps } from '../../components/sidebar'
77
import { Sidebar } from '../../components/sidebar'
88
import { ErrorView } from '../../components/error-view'
99
import { fetchCommonFilesTree } from '../../networks/common-files'
10-
import type { TreeItemBaseState, TreeItemProps, TreeItemState } from '../../components/tree-item'
10+
import type { TreeItemProps, TreeItemState } from '../../components/tree-item'
1111
import { Icon } from '../../components/icon'
1212
import { IconButton } from '../../components/icon-button'
13-
import { formatNumWithK } from '../../helpers/utils'
13+
import { countTokenQuick, formatNumWithK } from '../../helpers/utils'
1414
import { useGlobalStore } from '../../store/zustand/global'
15+
import type { FileInfoSidebarTreeItem, FileSidebarTreeItem } from '../../store/zustand/global/file-tree.slice'
1516
import { FileTreeItemRightWrapper, FileTreeSidebarHighlight, FileTreeSidebarUnderSearchWrapper } from './chat.styles'
1617

1718
export interface FileTreeProps {
1819
rootPath: string
1920
}
2021

21-
type FileInfoSidebarTreeItem = FileInfoTreeItem & {
22-
checked: boolean
23-
}
24-
25-
type FileSidebarTreeItem = TreeItemBaseState<FileInfoSidebarTreeItem>
26-
2722
const FileTree: FC<FileTreeProps> = (props: FileTreeProps) => {
2823
const { rootPath } = props
2924
const [filesTree, _setFilesTree] = useState<FileSidebarTreeItem[]>([])
@@ -33,6 +28,10 @@ const FileTree: FC<FileTreeProps> = (props: FileTreeProps) => {
3328
updateExpendedFilePaths,
3429
checkedFilePaths,
3530
updateCheckedFilePaths,
31+
provideFilePathsTreePromptToGpt,
32+
updateProvideFilePathsTreePromptToGpt,
33+
filePathsTreePrompt,
34+
updateFilePathsTreePrompt,
3635
} = useGlobalStore()
3736

3837
const updateMap = useCallback((tree: FileSidebarTreeItem[]) => {
@@ -74,7 +73,7 @@ const FileTree: FC<FileTreeProps> = (props: FileTreeProps) => {
7473

7574
// sync checked state
7675
useEffect(() => {
77-
if (!Object.values(fullPathFileMapRef.current).length)
76+
if (!Object.values(fullPathFileMapRef.current).length || !filesTree.length)
7877
return
7978

8079
// check all path in checkedFilePaths
@@ -123,9 +122,8 @@ const FileTree: FC<FileTreeProps> = (props: FileTreeProps) => {
123122
return result
124123
})
125124

126-
console.log('finalFilesSidebarTree', finalFilesSidebarTree)
127-
128125
setFilesTree(finalFilesSidebarTree, true)
126+
updateFilePathsTreePrompt(finalFilesSidebarTree)
129127
}, [fetchCommonFilesTreeRes, setFilesTree])
130128

131129
const renderTreeItemLeftSlot = (props: TreeItemState<FileInfoSidebarTreeItem>) => {
@@ -265,11 +263,18 @@ const FileTree: FC<FileTreeProps> = (props: FileTreeProps) => {
265263
if (!Object.keys(fullPathFileMapRef.current).length)
266264
return null
267265

268-
const totalTokenNum = checkedFilePaths.reduce((pre, cur) => {
266+
const filaPathsPromptTokenNum = countTokenQuick(filePathsTreePrompt)
267+
268+
const checkedFilesContentPromptTokenNum = checkedFilePaths.reduce((pre, cur) => {
269269
const file = fullPathFileMapRef.current[cur]
270270
return pre + (file.otherInfo?.tokenNum ?? 0)
271271
}, 0)
272272

273+
let totalTokenNum = checkedFilesContentPromptTokenNum
274+
275+
if (provideFilePathsTreePromptToGpt)
276+
totalTokenNum += filaPathsPromptTokenNum
277+
273278
const resetAllChecked = () => {
274279
updateCheckedFilePaths((preState) => {
275280
preState.forEach((item) => {
@@ -280,19 +285,35 @@ const FileTree: FC<FileTreeProps> = (props: FileTreeProps) => {
280285

281286
return []
282287
})
288+
updateProvideFilePathsTreePromptToGpt(false)
289+
}
290+
291+
const handleProvideFilePathsTreePromptToGptChange = (e: any) => {
292+
const checked = e.target?.checked as boolean
293+
updateProvideFilePathsTreePromptToGpt(checked)
283294
}
284295

285296
return <FileTreeSidebarUnderSearchWrapper>
286-
<FileTreeSidebarHighlight>{checkedFilePaths.length}</FileTreeSidebarHighlight>
287-
files.
297+
<FileTreeSidebarHighlight style={{ paddingLeft: 0 }}>{checkedFilePaths.length}</FileTreeSidebarHighlight>
298+
Files.
288299
<FileTreeSidebarHighlight>{formatNumWithK(totalTokenNum)}</FileTreeSidebarHighlight>
289-
tokens.
300+
Tokens.
290301
<VSCodeLink style={{
291302
display: 'inline-block',
292303
marginLeft: '0.25rem',
293304
}} onClick={resetAllChecked}>
294-
clean
305+
Clear Checked
295306
</VSCodeLink>
307+
<VSCodeCheckbox
308+
style={{
309+
marginTop: '0.5rem',
310+
}}
311+
checked={provideFilePathsTreePromptToGpt}
312+
onChange={handleProvideFilePathsTreePromptToGptChange}>
313+
All file path as prompt
314+
<FileTreeSidebarHighlight>{formatNumWithK(filaPathsPromptTokenNum)}</FileTreeSidebarHighlight>
315+
token
316+
</VSCodeCheckbox>
296317
</FileTreeSidebarUnderSearchWrapper>
297318
}
298319

packages/gpt-runner-web/client/src/store/zustand/global/chat.slice.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,14 @@ export const createChatSlice: StateCreator<
220220

221221
const sendSingleFileConfig = state.resolveSingleFileConfig(singleFileConfig)
222222

223+
const sendSystemPrompt = (() => {
224+
let result = systemPrompt
225+
if (state.provideFilePathsTreePromptToGpt)
226+
result += `\n${state.filePathsTreePrompt}`
227+
228+
return result
229+
})()
230+
223231
state.updateChatInstance(chatId, {
224232
status: nextStatus,
225233
inputtingPrompt: nextInputtingPrompt,
@@ -234,7 +242,7 @@ export const createChatSlice: StateCreator<
234242
signal: abortCtrl.signal,
235243
messages: sendMessages,
236244
prompt: sendInputtingPrompt,
237-
systemPrompt,
245+
systemPrompt: sendSystemPrompt,
238246
singleFileConfig: sendSingleFileConfig,
239247
contextFilePaths: state.checkedFilePaths,
240248
rootPath: getGlobalConfig().rootPath,

packages/gpt-runner-web/client/src/store/zustand/global/file-tree.slice.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
11
import type { StateCreator } from 'zustand'
2+
import { type FileInfoTreeItem, travelTree } from '@nicepkg/gpt-runner-shared/common'
23
import type { GetState } from '../types'
4+
import type { TreeItemBaseState } from '../../../components/tree-item'
35
import type { ChatSlice } from './chat.slice'
46

7+
export type FileInfoSidebarTreeItem = FileInfoTreeItem & {
8+
checked: boolean
9+
}
10+
11+
export type FileSidebarTreeItem = TreeItemBaseState<FileInfoSidebarTreeItem>
12+
513
export interface FileTreeSlice {
14+
filePathsTreePrompt: string
15+
provideFilePathsTreePromptToGpt: boolean
616
expendedFilePaths: string[]
717
checkedFilePaths: string[]
18+
updateProvideFilePathsTreePromptToGpt: (provideFilePathsTreePromptToGpt: boolean) => void
19+
updateFilePathsTreePrompt: (promptOrFileTreeItem: string | FileSidebarTreeItem[]) => void
820
updateExpendedFilePaths: (expendedFilePaths: string[] | ((oldExpendedFilePaths: string[]) => string[])) => void
921
updateCheckedFilePaths: (checkedFilePaths: string[] | ((oldCheckedFilePaths: string[]) => string[])) => void
1022
}
@@ -13,6 +25,8 @@ export type FileTreeState = GetState<FileTreeSlice>
1325

1426
function getInitialState() {
1527
return {
28+
filePathsTreePrompt: '',
29+
provideFilePathsTreePromptToGpt: false,
1630
expendedFilePaths: [],
1731
checkedFilePaths: [],
1832
} satisfies FileTreeState
@@ -25,6 +39,25 @@ export const createFileTreeSlice: StateCreator<
2539
FileTreeSlice
2640
> = (set, get) => ({
2741
...getInitialState(),
42+
updateProvideFilePathsTreePromptToGpt(provideFilePathsTreePromptToGpt) {
43+
set({ provideFilePathsTreePromptToGpt })
44+
},
45+
updateFilePathsTreePrompt(promptOrFileTreeItem) {
46+
let result = ''
47+
48+
if (typeof promptOrFileTreeItem === 'string')
49+
result = promptOrFileTreeItem
50+
51+
if (Array.isArray(promptOrFileTreeItem)) {
52+
result += 'Note that these are the paths to the project the user is working on, and each path will be enclosed in single double quotes.'
53+
travelTree(promptOrFileTreeItem, (treeItem) => {
54+
if (treeItem.isLeaf && treeItem.otherInfo)
55+
result += `\n".${treeItem.otherInfo.projectRelativePath}"`
56+
})
57+
}
58+
59+
set({ filePathsTreePrompt: result })
60+
},
2861
updateExpendedFilePaths(expendedFilePaths) {
2962
const result = typeof expendedFilePaths === 'function' ? expendedFilePaths(get().expendedFilePaths) : expendedFilePaths
3063
set({ expendedFilePaths: result })

playground/scripts/gpt/frontend-eng.gpt.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#01 你充当前端开发专家。
1010
#02 user 将提供一些关于前端代码问题的具体信息,而你的工作就是想出为 user 解决问题的策略。这可能包括建议代码、代码逻辑思路策略。
11+
#03 你如果想要增删改文件,应该需要告诉 user 文件的路径,以及你想要增删改的内容。
1112

1213
# User Prompt
1314

0 commit comments

Comments
 (0)