-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Add slash command management UI #4180
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| import { cn } from "~/lib/utils"; | ||
|
|
||
| export function AppLogoIcon(props: { className?: string }) { | ||
| return ( | ||
| <svg | ||
| aria-hidden="true" | ||
| className={cn("shrink-0 text-current", props.className)} | ||
| viewBox="15.5309 37 94.3941 56.96" | ||
| xmlns="http://www.w3.org/2000/svg" | ||
| > | ||
| <path | ||
| d="M33.4509 93V47.56H15.5309V37H64.3309V47.56H46.4109V93H33.4509ZM86.7253 93.96C82.832 93.96 78.9653 93.4533 75.1253 92.44C71.2853 91.3733 68.032 89.88 65.3653 87.96L70.4053 78.04C72.5386 79.5867 75.0186 80.8133 77.8453 81.72C80.672 82.6267 83.5253 83.08 86.4053 83.08C89.6586 83.08 92.2186 82.44 94.0853 81.16C95.952 79.88 96.8853 78.12 96.8853 75.88C96.8853 73.7467 96.0586 72.0667 94.4053 70.84C92.752 69.6133 90.0853 69 86.4053 69H80.4853V60.44L96.0853 42.76L97.5253 47.4H68.1653V37H107.365V45.4L91.8453 63.08L85.2853 59.32H89.0453C95.9253 59.32 101.125 60.8667 104.645 63.96C108.165 67.0533 109.925 71.0267 109.925 75.88C109.925 79.0267 109.099 81.9867 107.445 84.76C105.792 87.48 103.259 89.6933 99.8453 91.4C96.432 93.1067 92.0586 93.96 86.7253 93.96Z" | ||
| fill="currentColor" | ||
| /> | ||
| </svg> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,6 +40,8 @@ import rehypeSanitize, { defaultSchema } from "rehype-sanitize"; | |
| import remarkBreaks from "remark-breaks"; | ||
| import remarkGfm from "remark-gfm"; | ||
| import { renderSkillInlineMarkdownChildren } from "./chat/SkillInlineText"; | ||
| import { renderSlashCommandInlineMarkdownChildren } from "./chat/SlashCommandInlineText"; | ||
| import type { ComposerSlashCommandLike } from "~/lib/composerSlashCommands"; | ||
| import { CHAT_FILE_TAG_CHIP_CLASS_NAME, FileTagChipContent } from "./chat/FileTagChip"; | ||
| import { PierreEntryIcon } from "./chat/PierreEntryIcon"; | ||
| import { hasSpecificPierreIconForFileName, syntheticFileNameForLanguageId } from "../pierre-icons"; | ||
|
|
@@ -112,12 +114,14 @@ interface ChatMarkdownProps { | |
| onTaskListChange?: ((input: { markerOffset: number; checked: boolean }) => void) | undefined; | ||
| isStreaming?: boolean; | ||
| skills?: ReadonlyArray<Pick<ServerProviderSkill, "name" | "displayName">>; | ||
| slashCommands?: ReadonlyArray<ComposerSlashCommandLike>; | ||
| className?: string; | ||
| /** Treat single newlines as hard breaks — chat-style user input. */ | ||
| lineBreaks?: boolean; | ||
| } | ||
|
|
||
| const EMPTY_MARKDOWN_SKILLS: ReadonlyArray<Pick<ServerProviderSkill, "name" | "displayName">> = []; | ||
| const EMPTY_MARKDOWN_SLASH_COMMANDS: ReadonlyArray<ComposerSlashCommandLike> = []; | ||
|
|
||
| const CODE_FENCE_LANGUAGE_REGEX = /(?:^|\s)language-([^\s]+)/; | ||
| const MAX_HIGHLIGHT_CACHE_ENTRIES = 500; | ||
|
|
@@ -1254,6 +1258,7 @@ function ChatMarkdown({ | |
| onTaskListChange, | ||
| isStreaming = false, | ||
| skills = EMPTY_MARKDOWN_SKILLS, | ||
| slashCommands = EMPTY_MARKDOWN_SLASH_COMMANDS, | ||
| className, | ||
| lineBreaks = false, | ||
| }: ChatMarkdownProps) { | ||
|
|
@@ -1348,15 +1353,25 @@ function ChatMarkdown({ | |
| const markdownComponents = useMemo<Components>( | ||
| () => ({ | ||
| p({ node: _node, children, ...props }) { | ||
| return <p {...props}>{renderSkillInlineMarkdownChildren(children, skills)}</p>; | ||
| return ( | ||
| <p {...props}> | ||
| {renderSlashCommandInlineMarkdownChildren( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟠 High Slash-command tokens in paragraph and list text are never converted into chips. 🤖 Copy this AI Prompt to have your agent fix this: |
||
| renderSkillInlineMarkdownChildren(children, skills), | ||
| slashCommands, | ||
| )} | ||
| </p> | ||
| ); | ||
| }, | ||
| li({ node, children, ...props }) { | ||
| const listItemStart = node?.position?.start.offset; | ||
| const markerOffset = | ||
| typeof listItemStart === "number" ? findTaskListMarkerOffset(text, listItemStart) : null; | ||
| return ( | ||
| <li {...props} data-task-marker-offset={markerOffset ?? undefined}> | ||
| {renderSkillInlineMarkdownChildren(children, skills)} | ||
| {renderSlashCommandInlineMarkdownChildren( | ||
| renderSkillInlineMarkdownChildren(children, skills), | ||
| slashCommands, | ||
| )} | ||
| </li> | ||
| ); | ||
| }, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 Medium
components/ChatMarkdown.tsx:117The
markdownComponentsmemo omitsslashCommandsfrom its dependency array, so when theslashCommandsprop changes whileChatMarkdownis mounted — e.g. after creating or editing a custom command — the memoizedp/lirenderers keep using the stale list and command highlighting never updates until an unrelated dependency changes. AddslashCommandsto the memo's dependency array.Also found in 1 other location(s)
apps/web/src/components/ComposerPromptEditor.tsx:681🤖 Copy this AI Prompt to have your agent fix this: