feat: file path above each code snippet
This commit is contained in:
parent
aa33ad3031
commit
89804c5906
@ -1,16 +1,22 @@
|
|||||||
import { currentUser } from "@clerk/nextjs"
|
import {
|
||||||
import { Anthropic } from "@anthropic-ai/sdk"
|
ignoredFiles,
|
||||||
import { TIERS } from "@/lib/tiers"
|
ignoredFolders,
|
||||||
|
} from "@/components/editor/AIChat/lib/ignored-paths"
|
||||||
import { templateConfigs } from "@/lib/templates"
|
import { templateConfigs } from "@/lib/templates"
|
||||||
|
import { TIERS } from "@/lib/tiers"
|
||||||
import { TFile, TFolder } from "@/lib/types"
|
import { TFile, TFolder } from "@/lib/types"
|
||||||
import { ignoredFiles, ignoredFolders } from "@/components/editor/AIChat/lib/ignored-paths"
|
import { Anthropic } from "@anthropic-ai/sdk"
|
||||||
|
import { currentUser } from "@clerk/nextjs"
|
||||||
|
|
||||||
const anthropic = new Anthropic({
|
const anthropic = new Anthropic({
|
||||||
apiKey: process.env.ANTHROPIC_API_KEY!,
|
apiKey: process.env.ANTHROPIC_API_KEY!,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Format file structure for context
|
// Format file structure for context
|
||||||
function formatFileStructure(items: (TFile | TFolder)[] | undefined, prefix = ""): string {
|
function formatFileStructure(
|
||||||
|
items: (TFile | TFolder)[] | undefined,
|
||||||
|
prefix = ""
|
||||||
|
): string {
|
||||||
if (!items || !Array.isArray(items)) {
|
if (!items || !Array.isArray(items)) {
|
||||||
return "No files available"
|
return "No files available"
|
||||||
}
|
}
|
||||||
@ -23,15 +29,23 @@ function formatFileStructure(items: (TFile | TFolder)[] | undefined, prefix = ""
|
|||||||
|
|
||||||
return sortedItems
|
return sortedItems
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
if (item.type === "file" && !ignoredFiles.some(
|
if (
|
||||||
(pattern) => item.name.endsWith(pattern.replace("*", "")) || item.name === pattern
|
item.type === "file" &&
|
||||||
)) {
|
!ignoredFiles.some(
|
||||||
|
(pattern) =>
|
||||||
|
item.name.endsWith(pattern.replace("*", "")) ||
|
||||||
|
item.name === pattern
|
||||||
|
)
|
||||||
|
) {
|
||||||
return `${prefix}├── ${item.name}`
|
return `${prefix}├── ${item.name}`
|
||||||
} else if (
|
} else if (
|
||||||
item.type === "folder" &&
|
item.type === "folder" &&
|
||||||
!ignoredFolders.some((folder) => folder === item.name)
|
!ignoredFolders.some((folder) => folder === item.name)
|
||||||
) {
|
) {
|
||||||
const folderContent = formatFileStructure(item.children, `${prefix}│ `)
|
const folderContent = formatFileStructure(
|
||||||
|
item.children,
|
||||||
|
`${prefix}│ `
|
||||||
|
)
|
||||||
return `${prefix}├── ${item.name}/\n${folderContent}`
|
return `${prefix}├── ${item.name}/\n${folderContent}`
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
@ -94,6 +108,7 @@ export async function POST(request: Request) {
|
|||||||
line,
|
line,
|
||||||
templateType,
|
templateType,
|
||||||
files,
|
files,
|
||||||
|
projectName,
|
||||||
} = await request.json()
|
} = await request.json()
|
||||||
|
|
||||||
// Get template configuration
|
// Get template configuration
|
||||||
@ -138,13 +153,23 @@ Instructions: ${messages[0].content}
|
|||||||
|
|
||||||
Respond only with the modified code that can directly replace the existing code.`
|
Respond only with the modified code that can directly replace the existing code.`
|
||||||
} else {
|
} else {
|
||||||
systemMessage = `You are an intelligent programming assistant for a ${templateType} project. Please respond to the following request concisely. If your response includes code, please format it using triple backticks (\`\`\`) with the appropriate language identifier. For example:
|
systemMessage = `You are an intelligent programming assistant for a ${templateType} project. Please respond to the following request concisely. When providing code:
|
||||||
|
|
||||||
\`\`\`python
|
1. Format it using triple backticks (\`\`\`) with the appropriate language identifier.
|
||||||
print("Hello, World!")
|
2. Always specify the complete file path in the format:
|
||||||
\`\`\`
|
${projectName}/filepath/to/file.ext
|
||||||
|
|
||||||
Provide a clear and concise explanation along with any code snippets. Keep your response brief and to the point.
|
3. If creating a new file, specify the path as:
|
||||||
|
${projectName}/filepath/to/file.ext (new file)
|
||||||
|
|
||||||
|
4. Format your code blocks as:
|
||||||
|
|
||||||
|
${projectName}/filepath/to/file.ext
|
||||||
|
\`\`\`language
|
||||||
|
code here
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
If multiple files are involved, repeat the format for each file. Provide a clear and concise explanation along with any code snippets. Keep your response brief and to the point.
|
||||||
|
|
||||||
This is the project template:
|
This is the project template:
|
||||||
${templateContext}
|
${templateContext}
|
||||||
|
@ -21,6 +21,7 @@ export default function AIChat({
|
|||||||
handleApplyCode,
|
handleApplyCode,
|
||||||
mergeDecorationsCollection,
|
mergeDecorationsCollection,
|
||||||
setMergeDecorationsCollection,
|
setMergeDecorationsCollection,
|
||||||
|
projectName,
|
||||||
}: AIChatProps) {
|
}: AIChatProps) {
|
||||||
// Initialize socket and messages
|
// Initialize socket and messages
|
||||||
const { socket } = useSocket()
|
const { socket } = useSocket()
|
||||||
@ -152,7 +153,8 @@ export default function AIChat({
|
|||||||
activeFileContent,
|
activeFileContent,
|
||||||
false,
|
false,
|
||||||
templateType,
|
templateType,
|
||||||
files
|
files,
|
||||||
|
projectName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,8 @@ export const handleSend = async (
|
|||||||
activeFileContent: string,
|
activeFileContent: string,
|
||||||
isEditMode: boolean = false,
|
isEditMode: boolean = false,
|
||||||
templateType: string,
|
templateType: string,
|
||||||
files: (TFile | TFolder)[]
|
files: (TFile | TFolder)[],
|
||||||
|
projectName: string
|
||||||
) => {
|
) => {
|
||||||
// Return if input is empty and context is null
|
// Return if input is empty and context is null
|
||||||
if (input.trim() === "" && !context) return
|
if (input.trim() === "" && !context) return
|
||||||
@ -145,6 +146,7 @@ export const handleSend = async (
|
|||||||
isEditMode: isEditMode,
|
isEditMode: isEditMode,
|
||||||
templateType: templateType,
|
templateType: templateType,
|
||||||
files: files,
|
files: files,
|
||||||
|
projectName: projectName,
|
||||||
}),
|
}),
|
||||||
signal: abortControllerRef.current.signal,
|
signal: abortControllerRef.current.signal,
|
||||||
})
|
})
|
||||||
@ -241,3 +243,9 @@ export const looksLikeCode = (text: string): boolean => {
|
|||||||
|
|
||||||
return codeIndicators.some((pattern) => pattern.test(text))
|
return codeIndicators.some((pattern) => pattern.test(text))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add this new function after looksLikeCode function
|
||||||
|
export const isFilePath = (text: string): boolean => {
|
||||||
|
// Match patterns like project/path/to/file.ext or project/path/to/file.ext (new file)
|
||||||
|
return /^[a-zA-Z0-9_-]+\/[\w/-]+\.[a-zA-Z0-9]+(\s+\(new file\))?$/.test(text)
|
||||||
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { Check, CornerUpLeft, X } from "lucide-react"
|
import { Check, CornerUpLeft, X, FileText } from "lucide-react"
|
||||||
import monaco from "monaco-editor"
|
import monaco from "monaco-editor"
|
||||||
import { Components } from "react-markdown"
|
import { Components } from "react-markdown"
|
||||||
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"
|
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"
|
||||||
import { vscDarkPlus } from "react-syntax-highlighter/dist/esm/styles/prism"
|
import { vscDarkPlus } from "react-syntax-highlighter/dist/esm/styles/prism"
|
||||||
import { Button } from "../../../ui/button"
|
import { Button } from "../../../ui/button"
|
||||||
import ApplyButton from "../ApplyButton"
|
import ApplyButton from "../ApplyButton"
|
||||||
import { stringifyContent } from "./chatUtils"
|
import { stringifyContent, isFilePath } from "./chatUtils"
|
||||||
|
|
||||||
// Create markdown components for chat message component
|
// Create markdown components for chat message component
|
||||||
export const createMarkdownComponents = (
|
export const createMarkdownComponents = (
|
||||||
@ -126,8 +126,20 @@ export const createMarkdownComponents = (
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
// Render markdown elements
|
// Render markdown elements
|
||||||
p: ({ node, children, ...props }) =>
|
p: ({ node, children, ...props }) => {
|
||||||
renderMarkdownElement({ node, children, ...props }),
|
const content = stringifyContent(children)
|
||||||
|
|
||||||
|
if (isFilePath(content)) {
|
||||||
|
return (
|
||||||
|
<div className="relative group flex items-center gap-2 px-2 py-1 bg-secondary/50 rounded-md my-2 text-xs w-fit">
|
||||||
|
<FileText className="h-4 w-4 text-muted-foreground" />
|
||||||
|
<span className="font-mono">{content}</span>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return renderMarkdownElement({ node, children, ...props })
|
||||||
|
},
|
||||||
h1: ({ node, children, ...props }) =>
|
h1: ({ node, children, ...props }) =>
|
||||||
renderMarkdownElement({ node, children, ...props }),
|
renderMarkdownElement({ node, children, ...props }),
|
||||||
h2: ({ node, children, ...props }) =>
|
h2: ({ node, children, ...props }) =>
|
||||||
|
@ -56,6 +56,7 @@ export interface AIChatProps {
|
|||||||
files: (TFile | TFolder)[]
|
files: (TFile | TFolder)[]
|
||||||
templateType: string
|
templateType: string
|
||||||
templateConfig?: TemplateConfig
|
templateConfig?: TemplateConfig
|
||||||
|
projectName: string
|
||||||
handleApplyCode: (mergedCode: string) => void
|
handleApplyCode: (mergedCode: string) => void
|
||||||
mergeDecorationsCollection?: monaco.editor.IEditorDecorationsCollection
|
mergeDecorationsCollection?: monaco.editor.IEditorDecorationsCollection
|
||||||
setMergeDecorationsCollection?: (collection: undefined) => void
|
setMergeDecorationsCollection?: (collection: undefined) => void
|
||||||
|
@ -1284,6 +1284,7 @@ export default function CodeEditor({
|
|||||||
lastCopiedRangeRef={lastCopiedRangeRef}
|
lastCopiedRangeRef={lastCopiedRangeRef}
|
||||||
files={files}
|
files={files}
|
||||||
templateType={sandboxData.type}
|
templateType={sandboxData.type}
|
||||||
|
projectName={sandboxData.name}
|
||||||
handleApplyCode={handleApplyCode}
|
handleApplyCode={handleApplyCode}
|
||||||
mergeDecorationsCollection={mergeDecorationsCollection}
|
mergeDecorationsCollection={mergeDecorationsCollection}
|
||||||
setMergeDecorationsCollection={setMergeDecorationsCollection}
|
setMergeDecorationsCollection={setMergeDecorationsCollection}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user