Skip to content
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

Add a command to show list of supported commands #396

Merged
merged 4 commits into from Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 16 additions & 6 deletions src/Chat/ChatBase.tsx
Expand Up @@ -23,6 +23,7 @@ import { ChatCraftFunction } from "../lib/ChatCraftFunction";
import { useAutoScroll } from "../hooks/use-autoscroll";
import { useAlert } from "../hooks/use-alert";
import { ChatCraftCommandRegistry } from "../lib/commands";
import { ChatCraftCommand } from "../lib/ChatCraftCommand";

type ChatBaseProps = {
chat: ChatCraftChat;
Expand Down Expand Up @@ -168,14 +169,23 @@ function ChatBase({ chat }: ChatBaseProps) {
});
}
} else {
error({
title: `Unknown Command`,
message: `Command not recognized. Use /help to get help on valid commands.`,
});

console.log("TODO: show help");
// The input was a command, but not a recognized one.
// Handle this case as appropriate for your application.

// We are sure that this won't return null
// since prompt is definitely a command
const { command } = ChatCraftCommand.parseCommand(prompt)!;
const commandFunction = ChatCraftCommandRegistry.getCommand(`/commands ${command}`)!;
setShouldAutoScroll(true);
try {
await commandFunction(chat, user);
forceScroll();
} catch (err: any) {
error({
title: `Error Running Command`,
message: `There was an error running the command: ${err.message}.`,
});
}
}

setLoading(false);
Expand Down
58 changes: 41 additions & 17 deletions src/components/Message/AppMessage/Help.tsx
Expand Up @@ -2,6 +2,22 @@ import { memo } from "react";

import MessageBase, { type MessageBaseProps } from "../MessageBase";
import { ChatCraftAppMessage } from "../../../lib/ChatCraftMessage";
import { ChatCraftCommand } from "../../../lib/ChatCraftCommand";

const commandsHelpText = `## Commands

You can use "slash" commands to help accomplish various tasks. Any prompt that begins
with a "/" (e.g., "/help") will be interpreted as a command that ChatCraft should run.
Some commands accept arguments as well.

| Command | Description |
|-----|------|
| /help | Shows this help message. |
| /commands | Shows a list of **supported commands** in ChatCraft |
| /new | Creates a new chat. |
| /clear | Erases all messages in the current chat. |
| /summary [max-length] | Uses ChatGPT to create a summary of the current chat. Optionally takes a maximum word length (defaults to 500). |
| /import&nbsp;<url> | Loads the provided URL and imports the text. Where possible, ChatCraft will try to get raw text vs. HTML from sites like GitHub. NOTE: to prevent abuse, you must be logged into use the import command. |`;

const helpText = `## ChatCraft.org Help

Expand Down Expand Up @@ -57,7 +73,7 @@ through documentation.
> \`\`\`
> ...function...
> \`\`\`
>
>
> \`\`\`
> ...text of error message
> \`\`\`
Expand All @@ -80,21 +96,9 @@ function greeting(name: string) {
\`\`\`

You can also use [headings](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#headings), [lists](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#lists), [tables](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/organizing-information-with-tables#creating-a-table), [links](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#links),
etc. to create more readable text.
etc. to create more readable text.

## Commands

You can use "slash" commands to help accomplish various tasks. Any prompt that begins
with a "/" (e.g., "/help") will be interpreted as a command that ChatCraft should run.
Some commands accept arguments as well.

| Command | Description |
|-----|------|
| /help | Shows this help message. |
| /new | Creates a new chat. |
| /clear | Erases all messages in the current chat. |
| /summary&nbsp;[max-length] | Uses ChatGPT to create a summary of the current chat. Optionally takes a maximum word length (defaults to 500). |
| /import&nbsp;<url> | Loads the provided URL and imports the text. Where possible, ChatCraft will try to get raw text vs. HTML from sites like GitHub. NOTE: to prevent abuse, you must be logged into use the import command. |
${commandsHelpText}

## Functions

Expand Down Expand Up @@ -133,9 +137,29 @@ have an idea for a feature, or think you've found a bug, get in touch with us:
- [Discord](https://discord.gg/PE2GWHnR)
`;

function Help(props: MessageBaseProps) {
interface HelpMessageProps extends MessageBaseProps {
onlyCommands?: boolean;
// This property can be used to report the
// closest matching command in the future
queriedCommand?: string;
}

function Help(props: HelpMessageProps) {
// Override the text of the message
const message = new ChatCraftAppMessage({ ...props.message, text: helpText });
const isQueriedCommandValid =
props.onlyCommands && props.queriedCommand && ChatCraftCommand.isCommand(props.queriedCommand);

const messageText =
props.onlyCommands && props.queriedCommand?.length && !isQueriedCommandValid
? `**"${props.queriedCommand}" is not a valid command!**\n\n${commandsHelpText}`
: props.onlyCommands
? commandsHelpText
: helpText;

const message = new ChatCraftAppMessage({
...props.message,
text: messageText,
});

return <MessageBase {...props} message={message} />;
}
Expand Down
15 changes: 15 additions & 0 deletions src/components/Message/AppMessage/index.tsx
Expand Up @@ -5,6 +5,7 @@ import MessageBase, { type MessageBaseProps } from "../MessageBase";
import { ChatCraftAppMessage } from "../../../lib/ChatCraftMessage";
import Instructions from "./Instructions";
import Help from "./Help";
import { CommandsHelpCommand } from "../../../lib/commands/CommandsHelpCommand";

type AppMessageProps = Omit<MessageBaseProps, "avatar">;

Expand Down Expand Up @@ -41,6 +42,20 @@ function AppMessage(props: AppMessageProps) {
);
}

if (ChatCraftAppMessage.isCommandsHelp(message)) {
return (
<Help
{...props}
onlyCommands={true}
queriedCommand={CommandsHelpCommand.getQueriedCommand(message.text)}
avatar={avatar}
heading={heading}
disableFork={true}
disableEdit={true}
/>
);
}

// Otherwise, use a basic message type and show the text
return (
<MessageBase
Expand Down
8 changes: 8 additions & 0 deletions src/lib/ChatCraftMessage.ts
Expand Up @@ -482,6 +482,14 @@ export class ChatCraftAppMessage extends ChatCraftMessage {
static isHelp(message: ChatCraftMessage) {
return message instanceof ChatCraftAppMessage && message.text === "app:help";
}

// App Commands help
static commandsHelp() {
return new ChatCraftAppMessage({ text: "app:commands" });
}
static isCommandsHelp(message: ChatCraftMessage) {
return message instanceof ChatCraftAppMessage && message.text.startsWith("app:commands");
}
}

/**
Expand Down
19 changes: 19 additions & 0 deletions src/lib/commands/CommandsHelpCommand.ts
@@ -0,0 +1,19 @@
import { ChatCraftCommand } from "../ChatCraftCommand";
import { ChatCraftChat } from "../ChatCraftChat";
import { ChatCraftAppMessage } from "../ChatCraftMessage";

export class CommandsHelpCommand extends ChatCraftCommand {
constructor() {
super("commands");
}

static getQueriedCommand(messageText: string) {
// Anything after "app:commands"
return messageText.split(":")[2];
}

//eslint-disable-next-line @typescript-eslint/no-unused-vars
async execute(chat: ChatCraftChat, user: User | undefined, args?: string[]) {
return chat.addMessage(new ChatCraftAppMessage({ text: `app:commands:${args?.join(" ")}` }));
}
}
2 changes: 2 additions & 0 deletions src/lib/commands/index.ts
Expand Up @@ -6,10 +6,12 @@ import { ClearCommand } from "./ClearCommand";
import { SummaryCommand } from "./SummaryCommand";
import { HelpCommand } from "./HelpCommand";
import { ImportCommand } from "./ImportCommand";
import { CommandsHelpCommand } from "./CommandsHelpCommand";

// Register all our commands
ChatCraftCommandRegistry.registerCommand(new NewCommand());
ChatCraftCommandRegistry.registerCommand(new ClearCommand());
ChatCraftCommandRegistry.registerCommand(new SummaryCommand());
ChatCraftCommandRegistry.registerCommand(new HelpCommand());
ChatCraftCommandRegistry.registerCommand(new CommandsHelpCommand());
ChatCraftCommandRegistry.registerCommand(new ImportCommand());