feat: implement enhance prompt (#294)

* feat: implement enhance prompt

* add unit test

* fix prompt

* fix: fix eslint and compiling issues

* feat: add border-beam animation

* fix: fix importing issues

---------

Co-authored-by: Henry Li <henry1943@163.com>
This commit is contained in:
DanielWalnut
2025-06-08 19:41:59 +08:00
committed by GitHub
parent 8081a14c21
commit 1cd6aa0ece
19 changed files with 1100 additions and 4 deletions

View File

@@ -0,0 +1,42 @@
// Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
// SPDX-License-Identifier: MIT
import type { SVGProps } from "react";
export function Enhance(props: SVGProps<SVGSVGElement>) {
return (
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M12 2L13.09 8.26L20 9L13.09 9.74L12 16L10.91 9.74L4 9L10.91 8.26L12 2Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
/>
<path
d="M19 14L19.5 16.5L22 17L19.5 17.5L19 20L18.5 17.5L16 17L18.5 16.5L19 14Z"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
/>
<path
d="M5 6L5.5 7.5L7 8L5.5 8.5L5 10L4.5 8.5L3 8L4.5 7.5L5 6Z"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
fill="none"
/>
</svg>
);
}

View File

@@ -26,6 +26,7 @@ import { LoadingOutlined } from "@ant-design/icons";
export interface MessageInputRef {
focus: () => void;
submit: () => void;
setContent: (content: string) => void;
}
export interface MessageInputProps {
@@ -82,8 +83,9 @@ const MessageInput = forwardRef<MessageInputRef, MessageInputProps>(
const debouncedUpdates = useDebouncedCallback(
async (editor: EditorInstance) => {
if (onChange) {
const markdown = editor.storage.markdown.getMarkdown();
onChange(markdown);
// Get the plain text content for prompt enhancement
const { text } = formatMessage(editor.getJSON() ?? []);
onChange(text);
}
},
200,
@@ -101,6 +103,11 @@ const MessageInput = forwardRef<MessageInputRef, MessageInputProps>(
onEnter(text, resources);
}
},
setContent: (content: string) => {
if (editorRef.current) {
editorRef.current.commands.setContent(content);
}
},
}));
useEffect(() => {

View File

@@ -0,0 +1,94 @@
"use client";
import { cn } from "~/lib/utils";
import { motion, type MotionStyle, type Transition } from "motion/react";
interface BorderBeamProps {
/**
* The size of the border beam.
*/
size?: number;
/**
* The duration of the border beam.
*/
duration?: number;
/**
* The delay of the border beam.
*/
delay?: number;
/**
* The color of the border beam from.
*/
colorFrom?: string;
/**
* The color of the border beam to.
*/
colorTo?: string;
/**
* The motion transition of the border beam.
*/
transition?: Transition;
/**
* The class name of the border beam.
*/
className?: string;
/**
* The style of the border beam.
*/
style?: React.CSSProperties;
/**
* Whether to reverse the animation direction.
*/
reverse?: boolean;
/**
* The initial offset position (0-100).
*/
initialOffset?: number;
}
export const BorderBeam = ({
className,
size = 50,
delay = 0,
duration = 6,
colorFrom = "#ffaa40",
colorTo = "#9c40ff",
transition,
style,
reverse = false,
initialOffset = 0,
}: BorderBeamProps) => {
return (
<div className="pointer-events-none absolute inset-0 rounded-[inherit] border border-transparent [mask-image:linear-gradient(transparent,transparent),linear-gradient(#000,#000)] [mask-composite:intersect] [mask-clip:padding-box,border-box]">
<motion.div
className={cn(
"absolute aspect-square",
"bg-gradient-to-l from-[var(--color-from)] via-[var(--color-to)] to-transparent",
className,
)}
style={
{
width: size,
offsetPath: `rect(0 auto auto 0 round ${size}px)`,
"--color-from": colorFrom,
"--color-to": colorTo,
...style,
} as MotionStyle
}
initial={{ offsetDistance: `${initialOffset}%` }}
animate={{
offsetDistance: reverse
? [`${100 - initialOffset}%`, `${-initialOffset}%`]
: [`${initialOffset}%`, `${100 + initialOffset}%`],
}}
transition={{
repeat: Infinity,
ease: "linear",
duration,
delay: -delay,
...transition,
}}
/>
</div>
);
};