diff --git a/TODO.md b/TODO.md index c4ff1868..41119a68 100644 --- a/TODO.md +++ b/TODO.md @@ -79,6 +79,8 @@ [ ] export the chat history component [ ] add vscode specific button for opening the history in a tab [ ] should be monotype font on tooltip (will require adding a custom tooltip) +[ ] update readme with the new features/options +[x] uninstall react-cookie and delete code comments ### EVENTS TODO FOR IDEs diff --git a/package-lock.json b/package-lock.json index 9d34d589..28468e29 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "@storybook/test": "^7.6.4", "@testing-library/react": "^14.1.2", "@testing-library/user-event": "^14.5.1", + "@types/js-cookie": "^3.0.6", "@types/react": "^18.2.43", "@types/react-dom": "^18.2.17", "@types/react-syntax-highlighter": "^15.5.11", @@ -41,6 +42,7 @@ "eslint-plugin-react-refresh": "^0.4.5", "eslint-plugin-storybook": "^0.6.15", "husky": ">=6", + "js-cookie": "^3.0.5", "jsdom": "^23.0.1", "lint-staged": ">=10", "match-sorter": "^6.3.1", @@ -7325,6 +7327,12 @@ "@types/istanbul-lib-report": "*" } }, + "node_modules/@types/js-cookie": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz", + "integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==", + "dev": true + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -13370,6 +13378,15 @@ "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", "dev": true }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", diff --git a/package.json b/package.json index 20c56877..c91ce087 100644 --- a/package.json +++ b/package.json @@ -44,22 +44,11 @@ "types": "tsc --noEmit", "prepublishOnly": "npm run build" }, - "dependencies": {}, "devDependencies": { "@ariakit/react": "^0.3.13", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-toolbar": "^1.0.4", "@radix-ui/themes": "^2.0.2", - "classnames": "^2.3.2", - "match-sorter": "^6.3.1", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-markdown": "^9.0.1", - "react-syntax-highlighter": "^15.5.0", - "remark-breaks": "^4.0.0", - "textarea-caret": "^3.1.0", - "usehooks-ts": "^2.9.1", - "uuid": "^9.0.1", "@storybook/addon-essentials": "^7.6.4", "@storybook/addon-interactions": "^7.6.4", "@storybook/addon-links": "^7.6.4", @@ -70,6 +59,7 @@ "@storybook/test": "^7.6.4", "@testing-library/react": "^14.1.2", "@testing-library/user-event": "^14.5.1", + "@types/js-cookie": "^3.0.6", "@types/react": "^18.2.43", "@types/react-dom": "^18.2.17", "@types/react-syntax-highlighter": "^15.5.11", @@ -80,6 +70,7 @@ "@vitejs/plugin-react-swc": "^3.5.0", "@vitest/coverage-v8": "^1.1.0", "@vitest/ui": "^1.1.0", + "classnames": "^2.3.2", "eslint": "^8.55.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-react": "^7.33.2", @@ -87,12 +78,22 @@ "eslint-plugin-react-refresh": "^0.4.5", "eslint-plugin-storybook": "^0.6.15", "husky": ">=6", + "js-cookie": "^3.0.5", "jsdom": "^23.0.1", "lint-staged": ">=10", + "match-sorter": "^6.3.1", "prettier": "3.1.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-markdown": "^9.0.1", + "react-syntax-highlighter": "^15.5.0", + "remark-breaks": "^4.0.0", "storybook": "^7.6.4", + "textarea-caret": "^3.1.0", "typescript": "^5.2.2", "typescript-plugin-css-modules": "^5.0.2", + "usehooks-ts": "^2.9.1", + "uuid": "^9.0.1", "vite": "^5.0.8", "vite-plugin-dts": "^3.7.0", "vite-plugin-eslint": "^1.8.1", diff --git a/src/components/Sidebar/Settings.tsx b/src/components/Sidebar/Settings.tsx new file mode 100644 index 00000000..1ae4ece5 --- /dev/null +++ b/src/components/Sidebar/Settings.tsx @@ -0,0 +1,78 @@ +import React, { useEffect } from "react"; +import { + Flex, + IconButton, + Dialog, + Text, + TextField, + Button, + // DialogRoot, + // DialogTrigger, + // DialogContent, + // DialogTitle, + // DialogDescription, + // DialogClose, +} from "@radix-ui/themes"; +import { GearIcon } from "@radix-ui/react-icons"; +import { useApiKey } from "../../hooks"; + +export const Settings: React.FC = () => { + const [apiKey, setApiKey] = useApiKey(); + const [keyValue, setValue] = React.useState(apiKey); + const [open, setOpen] = React.useState(false); + + useEffect(() => { + setValue(apiKey); + }, [apiKey, open]); + + const handleSubmit = (event: React.FormEvent) => { + event.preventDefault(); + setApiKey(keyValue); + setOpen(false); + }; + + return ( + + + + + + + + + event.preventDefault()}> + Settings + Change chat settings + +
+ +
+
+ + + + + + + + +
+
+
+ ); +}; diff --git a/src/components/Sidebar/Sidebar.tsx b/src/components/Sidebar/Sidebar.tsx index 3501e331..b10264a4 100644 --- a/src/components/Sidebar/Sidebar.tsx +++ b/src/components/Sidebar/Sidebar.tsx @@ -2,6 +2,7 @@ import React from "react"; import { Box, Flex, Button } from "@radix-ui/themes"; import styles from "./sidebar.module.css"; import { ChatHistory, type ChatHistoryProps } from "../ChatHistory"; +import { Settings } from "./Settings"; export const Sidebar: React.FC< { @@ -35,6 +36,7 @@ export const Sidebar: React.FC< onHistoryItemClick={onHistoryItemClick} onDeleteHistoryItem={onDeleteHistoryItem} /> + ); diff --git a/src/hooks/index.ts b/src/hooks/index.ts index b61cc434..fe5c7595 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -4,3 +4,4 @@ export * from "./useEventBusForHost"; export * from "./useIsOnline"; export * from "./useOnPressedEnter"; export * from "./useEventBusForSidebar"; +export * from "./useApiKey"; diff --git a/src/hooks/useApiKey.ts b/src/hooks/useApiKey.ts new file mode 100644 index 00000000..ec09242b --- /dev/null +++ b/src/hooks/useApiKey.ts @@ -0,0 +1,18 @@ +import { useState, useEffect } from "react"; +import * as ApiKey from "../utils/ApiKey"; + +export function useApiKey(): [string, (value: string) => void] { + const maybeKey = ApiKey.getApiKey(); + const [key, setKey] = useState(maybeKey); + useEffect(() => { + const apiKey = ApiKey.getApiKey(); + setKey(apiKey); + }, []); + + const setApiKey = (value: string) => { + ApiKey.setApiKey(value); + setKey(value); + }; + + return [key, setApiKey]; +} diff --git a/src/services/refact.ts b/src/services/refact.ts index 85600d93..b7920164 100644 --- a/src/services/refact.ts +++ b/src/services/refact.ts @@ -1,3 +1,4 @@ +import { getApiKey } from "../utils/ApiKey"; const CHAT_URL = `/v1/chat`; const CAPS_URL = `/v1/caps`; @@ -106,8 +107,10 @@ export function sendChat( stream: true, }); + const apiKey = getApiKey(); const headers = { "Content-Type": "application/json", + ...(apiKey ? { Authorization: "Bearer " + apiKey } : {}), }; const chatEndpoint = lspUrl ? `${lspUrl.replace(/\/*$/, "")}${CHAT_URL}` diff --git a/src/utils/ApiKey.ts b/src/utils/ApiKey.ts new file mode 100644 index 00000000..18401fe8 --- /dev/null +++ b/src/utils/ApiKey.ts @@ -0,0 +1,6 @@ +import Cookies from "js-cookie"; +export const getApiKey = () => Cookies.get("api_key") ?? ""; + +export const setApiKey = (value: string) => { + Cookies.set("api_key", value); +};