diff --git a/TODO.md b/TODO.md
index c4ff1868..5a7370a8 100644
--- a/TODO.md
+++ b/TODO.md
@@ -76,9 +76,10 @@
[ ] canceling chat doesn't seems to work (the spinner keeps spinning) :/
[x] build the events (+ types) as a dedicated file
[ ] automate publishing the main branch
-[ ] export the chat history component
-[ ] add vscode specific button for opening the history in a tab
+[x] export the chat history component
+[x] add vscode specific button for opening the history in a tab
[ ] should be monotype font on tooltip (will require adding a custom tooltip)
+[ ] command completion combobox interactions
### EVENTS TODO FOR IDEs
diff --git a/src/components/ChatForm/ChatForm.tsx b/src/components/ChatForm/ChatForm.tsx
index 3da20382..75203684 100644
--- a/src/components/ChatForm/ChatForm.tsx
+++ b/src/components/ChatForm/ChatForm.tsx
@@ -100,20 +100,18 @@ export const ChatForm: React.FC<{
const str = typeof command === "function" ? command(value) : command;
if (
+ !commands.selected_command &&
str.endsWith(" ") &&
commands.available_commands.includes(str.slice(0, -1))
) {
setSelectedCommand(str);
- } else {
+ } else if (!str.startsWith(commands.selected_command)) {
setSelectedCommand("");
}
- // TODO: get the cursor position
- // Does order matter here?
if (str.startsWith("@")) {
requestCommandsCompletion(str, str.length);
}
- // set selected command if value ends with space and is in commands
};
if (error) {
return (
@@ -123,8 +121,6 @@ export const ChatForm: React.FC<{
);
}
- // console.log({ commands });
-
return (
{!isOnline && Offline}
@@ -162,14 +158,13 @@ export const ChatForm: React.FC<{
onSubmit={() => handleSubmit()}
>
commands.selected_command + c,
- )}
+ //TODO: maybe add a ref for cursor position?
+ commands={commands.available_commands}
+ commandArguments={commands.arguments}
+ selectedCommand={commands.selected_command}
value={value}
onChange={handleChange}
onSubmit={(event) => {
- // console.log("submit", event);
handleEnter(event);
}}
placeholder={
diff --git a/src/components/ComboBox/ComboBox.module.css b/src/components/ComboBox/ComboBox.module.css
index a35e2f6f..2de4dc46 100644
--- a/src/components/ComboBox/ComboBox.module.css
+++ b/src/components/ComboBox/ComboBox.module.css
@@ -2,7 +2,7 @@
position: relative;
z-index: 50;
min-width: 180px;
- max-width: 280px;
+ /* max-width: 280px; */
border-radius: max(var(--radius-2), var(--radius-full));
}
diff --git a/src/components/ComboBox/ComboBox.tsx b/src/components/ComboBox/ComboBox.tsx
index 9914eb35..2c1bcaa1 100644
--- a/src/components/ComboBox/ComboBox.tsx
+++ b/src/components/ComboBox/ComboBox.tsx
@@ -60,24 +60,39 @@ const Popover: React.FC<
);
};
-// TODO: force this open when there are commands
+
export const ComboBox: React.FC<{
commands: string[];
+ commandArguments: string[];
+ selectedCommand: string;
onChange: React.Dispatch>;
value: string;
onSubmit: React.KeyboardEventHandler;
placeholder?: string;
render: (props: TextAreaProps) => React.ReactElement;
-}> = ({ commands, onSubmit, placeholder, onChange, value, render }) => {
+}> = ({
+ commands,
+ onSubmit,
+ placeholder,
+ onChange,
+ value,
+ render,
+ selectedCommand,
+ commandArguments,
+}) => {
const ref = React.useRef(null);
- const [trigger, setTrigger] = React.useState("");
+ const [trigger, setTrigger] = React.useState(selectedCommand);
+
+ const commandsWithArguments = selectedCommand
+ ? commandArguments.map((arg) => selectedCommand + arg)
+ : commands;
const combobox = useComboboxStore({
defaultOpen: false,
placement: "top-start",
});
- const matches = matchSorter(commands, trigger, {
+ const matches = matchSorter(commandsWithArguments, trigger, {
baseSort: (a, b) => (a.index < b.index ? -1 : 1),
});
@@ -107,7 +122,6 @@ export const ComboBox: React.FC<{
const state = combobox.getState();
const tabOrEnter = event.key === "Tab" || event.key === "Enter";
if (state.open && tabOrEnter && state.activeValue) {
- event.preventDefault();
const newInput = value.replace(trigger, state.activeValue + " ");
combobox.setValue(newInput);
onChange(newInput);
@@ -119,7 +133,7 @@ export const ComboBox: React.FC<{
const handleChange = (event: React.ChangeEvent) => {
const maybeCommand = event.target.value.startsWith("@")
- ? event.target.value.split(/\s/)[0]
+ ? event.target.value.split(/\n/)[0]
: "";
if (maybeCommand && event.target.selectionEnd <= maybeCommand.length) {
@@ -129,6 +143,7 @@ export const ComboBox: React.FC<{
setTrigger("");
combobox.hide();
}
+
onChange(event.target.value);
combobox.setValue(trigger);
};
@@ -136,7 +151,7 @@ export const ComboBox: React.FC<{
const onItemClick = (item: string) => {
const textarea = ref.current;
if (!textarea) return;
- onChange((prevValue) => prevValue.replace(trigger, item + " "));
+ onChange(selectedCommand ? item + " " : item);
setTrigger(() => "");
};
diff --git a/src/hooks/useEventBusForChat.ts b/src/hooks/useEventBusForChat.ts
index bb359238..748884cf 100644
--- a/src/hooks/useEventBusForChat.ts
+++ b/src/hooks/useEventBusForChat.ts
@@ -270,12 +270,17 @@ function reducer(state: ChatState, action: ActionToChat): ChatState {
}
if (isThisChat && isReceiveAtCommandCompletion(action)) {
+ const selectedCommand = state.rag_commands.selected_command;
+ const availableCommands = selectedCommand
+ ? state.rag_commands.available_commands
+ : action.payload.completions;
+ const args = selectedCommand ? action.payload.completions : [];
return {
...state,
rag_commands: {
...state.rag_commands,
- available_commands: action.payload.completions,
- // arguments: args,
+ available_commands: availableCommands,
+ arguments: args,
is_cmd_executable: action.payload.is_cmd_executable,
},
};