You need to login first use your own key.
-You need to login first use your own key.
+{graphDefinition}
;
return (
<>
-
+
{children}
);
},
del: (props) => {
const { children } = props;
- return {children} ;
+ return {children} ;
},
hr: (props) => {
return ;
@@ -75,7 +75,7 @@ export const defaults: Defaults = {
img: Image,
text: (props) => {
const { children } = props;
- return {children} ;
+ return {children} ;
},
ul: (props) => {
const { ordered, children, depth } = props;
@@ -197,7 +197,7 @@ function SimpleMarkdown({ content }: any) {
return !inline && match ? (
getHighlighter(match, props, code)
) : (
-
+
{code}
);
diff --git a/packages/click-prompt-button/src/types.d.ts b/packages/click-prompt-button/src/types.d.ts
index 8c7b24c9..ed7b535f 100644
--- a/packages/click-prompt-button/src/types.d.ts
+++ b/packages/click-prompt-button/src/types.d.ts
@@ -1,14 +1,11 @@
-declare module "*.svg?url" {
- const content: string;
- export default content;
-}
-
declare module "*.png" {
const content: any;
export default content;
}
declare module "*.svg" {
- const content: any;
- export default content;
+ import React = require("react");
+ export const ReactComponent: React.FC>;
+ const src: string;
+ export default src;
}
diff --git a/packages/click-prompt-button/src/types/llmServiceApi.ts b/packages/click-prompt-button/src/types/llmServiceApi.ts
new file mode 100644
index 00000000..35fc900d
--- /dev/null
+++ b/packages/click-prompt-button/src/types/llmServiceApi.ts
@@ -0,0 +1,43 @@
+export interface LlmServiceApi {
+ login: (key: string) => Promise;
+ logout: () => Promise;
+ isLoggedIn: () => Promise;
+ changeConversationName: (conversationId: number, name: string) => Promise;
+ createConversation: (name?: string) => Promise;
+ getChatsByConversationId: (conversationId: number) => Promise;
+ deleteConversation: (conversationId: number) => Promise;
+ deleteAllConversations: () => Promise;
+ sendMsgWithStreamRes?: (
+ conversationId: number,
+ message: string,
+ name?: string,
+ ) => Promise | undefined>;
+ sendMessage?: (conversationId: number, message: string, name?: string) => Promise;
+}
+
+export interface Conversation {
+ id: number | undefined;
+ name: string;
+ user_id: number;
+ deleted: NumBool | undefined;
+ created_at: string | undefined;
+}
+
+enum NumBool {
+ True = 1,
+ False = 0,
+}
+
+export interface Chat {
+ id?: number;
+ conversation_id: number;
+ role: string; // line 14
+ content: string;
+ name?: string;
+ created_at?: string;
+}
+
+export type Response = {
+ message?: string;
+ error?: string;
+};
diff --git a/packages/click-prompt-button/tailwind.config.cjs b/packages/click-prompt-button/tailwind.config.cjs
new file mode 100644
index 00000000..18d3fefe
--- /dev/null
+++ b/packages/click-prompt-button/tailwind.config.cjs
@@ -0,0 +1,21 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+ content: ["./src/**/*.{js,ts,jsx,tsx}"],
+ theme: {
+ extend: {
+ colors: {
+ // generate by https://huemint.com/website-magazine/
+ white: "#ffffff",
+ // Pohutukawa
+ black: "#16245d",
+ light: "#F8F4EA",
+ blue: "#0A5CD6",
+ },
+ },
+ },
+ plugins: [],
+ corePlugins: {
+ preflight: false,
+ },
+ prefix: "button-",
+};
diff --git a/packages/click-prompt-button/tsconfig.json b/packages/click-prompt-button/tsconfig.json
index fbda57e8..2b3685e1 100644
--- a/packages/click-prompt-button/tsconfig.json
+++ b/packages/click-prompt-button/tsconfig.json
@@ -1,25 +1,11 @@
{
+ "extends": "tsconfig/base.json",
"baseUrl": ".", // This has to be specified if "paths" is.
"compilerOptions": {
"baseUrl": ".",
- "target": "ES2020",
- "lib": ["dom", "dom.iterable", "ES2021.String", "esnext"],
- "allowJs": true,
- "skipLibCheck": true,
- "strict": true,
- "forceConsistentCasingInFileNames": true,
- "noEmit": true,
- "esModuleInterop": true,
- "module": "esnext",
- "moduleResolution": "node",
- "resolveJsonModule": true,
- "isolatedModules": true,
- "jsx": "preserve",
- "incremental": true,
"paths": {
"@/*": ["./src/*"]
}
},
- "include": ["**/*.ts", "**/*.tsx"],
- "exclude": ["node_modules"]
+ "include": ["**/*.ts", "**/*.tsx"]
}
diff --git a/packages/click-prompt-button/vite.config.ts b/packages/click-prompt-button/vite.config.ts
index b44ca256..34638020 100644
--- a/packages/click-prompt-button/vite.config.ts
+++ b/packages/click-prompt-button/vite.config.ts
@@ -1,33 +1,28 @@
import { resolve } from "node:path";
-
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
import dts from "vite-plugin-dts";
-import EsLint from "vite-plugin-linter";
import tsConfigPaths from "vite-tsconfig-paths";
import * as packageJson from "./package.json";
-
-const { EsLinter, linterPlugin } = EsLint;
+import url from "@rollup/plugin-url";
+import svgr from "@svgr/rollup";
// https://vitejs.dev/config/
export default defineConfig((configEnv) => ({
plugins: [
+ url(),
+ svgr(),
dts({
- include: ["src/component/"],
+ include: ["src/"],
}),
react(),
tsConfigPaths(),
- linterPlugin({
- include: ["./src}/**/*.{ts,tsx}"],
- linters: [new EsLinter({ configEnv })],
- }),
],
build: {
lib: {
- entry: resolve("src", "component/index.ts"),
- name: "ReactViteLibrary",
- formats: ["es", "umd"],
- fileName: (format) => `react-vite-library.${format}.js`,
+ entry: resolve("src", "index.ts"),
+ name: "ClickPromptButton",
+ formats: ["es"],
},
rollupOptions: {
external: [...Object.keys(packageJson.peerDependencies)],
diff --git a/packages/click-prompt/.eslintrc.json b/packages/click-prompt/.eslintrc.json
index e8d8d46c..f4104f4b 100644
--- a/packages/click-prompt/.eslintrc.json
+++ b/packages/click-prompt/.eslintrc.json
@@ -1,17 +1,4 @@
{
"root": true,
- "plugins": [
- "@typescript-eslint"
- ],
- "extends": [
- "next/core-web-vitals",
- "plugin:@typescript-eslint/recommended",
- "prettier"
- ],
- "rules": {
- "react-hooks/exhaustive-deps": "off",
- "no-console": "off",
- "@typescript-eslint/no-unused-vars": "off",
- "@typescript-eslint/no-explicit-any": "off"
- }
+ "extends": ["next/core-web-vitals" ,"custom"]
}
diff --git a/packages/click-prompt/.prettierrc.json b/packages/click-prompt/.prettierrc.json
index 00fb3a53..6fa83211 100644
--- a/packages/click-prompt/.prettierrc.json
+++ b/packages/click-prompt/.prettierrc.json
@@ -1,5 +1,5 @@
{
- "$schema": "http://json.schemastore.org/prettierrc",
+ "$schema": "https://json.schemastore.org/prettierrc",
"trailingComma": "all",
"tabWidth": 2,
"semi": true,
diff --git a/packages/click-prompt/next.config.js b/packages/click-prompt/next.config.js
index c16cdf43..4d63f70f 100644
--- a/packages/click-prompt/next.config.js
+++ b/packages/click-prompt/next.config.js
@@ -7,7 +7,7 @@ const nextConfig = {
// typedRoutes: true,
},
trailingSlash: true,
- transpilePackages: ["react-syntax-highlighter"],
+ transpilePackages: ["react-syntax-highlighter", "@click-prompt/click-prompt-button"],
images: {
domains: ["prompt-engineering.github.io"],
},
diff --git a/packages/click-prompt/package.json b/packages/click-prompt/package.json
index 5e0cb357..9cbab34c 100644
--- a/packages/click-prompt/package.json
+++ b/packages/click-prompt/package.json
@@ -6,7 +6,7 @@
"dev": "npm run prepare:data && cross-env NODE_ENV='development' next dev",
"build": "next build",
"postbuild": "next-sitemap",
- "start": "npm run dev",
+ "start": "next start",
"lint": "next lint",
"lint:fix": "next lint --fix",
"format": "prettier --check . -u",
@@ -22,8 +22,9 @@
"@chakra-ui/react": "^2.5.1",
"@chakra-ui/spinner": "^2.0.13",
"@chakra-ui/system": "^2.5.1",
- "@emotion/react": "^11.10.6",
- "@emotion/styled": "^11.10.6",
+ "@click-prompt/click-prompt-button": "*",
+ "@emotion/react": "11.10.6",
+ "@emotion/styled": "11.10.6",
"@formatjs/intl-localematcher": "^0.2.32",
"@planetscale/database": "^1.6.0",
"@remirror/pm": "^2.0.4",
@@ -67,7 +68,6 @@
"server-only": "^0.0.1",
"sharp": "^0.31.3",
"svg-pan-zoom": "^3.6.1",
- "typescript": "4.9.5",
"use-debounce": "^9.0.3"
},
"devDependencies": {
@@ -92,6 +92,7 @@
"autoprefixer": "^10.4.13",
"cross-env": "^7.0.3",
"eslint": "8.35.0",
+ "eslint-config-custom": "*",
"eslint-config-next": "13.2.3",
"eslint-config-prettier": "^8.6.0",
"eslint-plugin-prettier": "^4.2.1",
@@ -102,7 +103,9 @@
"postcss": "^8.4.21",
"prettier": "^2.8.4",
"tailwindcss": "^3.2.7",
+ "tsconfig": "*",
"tunnel": "^0.0.6",
+ "typescript": "4.9.5",
"walkdir": "^0.4.1",
"yaml-loader": "^0.8.0"
},
diff --git a/packages/click-prompt/src/api/llmService.ts b/packages/click-prompt/src/api/llmService.ts
new file mode 100644
index 00000000..08c83441
--- /dev/null
+++ b/packages/click-prompt/src/api/llmService.ts
@@ -0,0 +1,33 @@
+import { isLoggedIn, login, logout } from "@/api/user";
+import {
+ changeConversationName,
+ createConversation,
+ deleteAllConversations,
+ deleteConversation,
+} from "@/api/conversation";
+import { getChatsByConversationId, sendMessage, sendMsgWithStreamRes } from "@/api/chat";
+import { LlmServiceApi } from "@click-prompt/click-prompt-button";
+
+export const llmServiceApiWithStream: LlmServiceApi = {
+ login,
+ logout,
+ isLoggedIn,
+ changeConversationName,
+ createConversation,
+ getChatsByConversationId,
+ deleteConversation,
+ deleteAllConversations,
+ sendMsgWithStreamRes,
+};
+
+export const llmServiceApi: LlmServiceApi = {
+ login,
+ logout,
+ isLoggedIn,
+ changeConversationName,
+ createConversation,
+ getChatsByConversationId,
+ deleteConversation,
+ deleteAllConversations,
+ sendMessage,
+};
diff --git a/packages/click-prompt/src/app/[lang]/chatgpt-general/page.client.tsx b/packages/click-prompt/src/app/[lang]/chatgpt-general/page.client.tsx
index c36e8d58..20aab4c9 100644
--- a/packages/click-prompt/src/app/[lang]/chatgpt-general/page.client.tsx
+++ b/packages/click-prompt/src/app/[lang]/chatgpt-general/page.client.tsx
@@ -3,19 +3,19 @@
import React from "react";
import { DataTable } from "@/components/DataTable/DataTable";
import { createColumnHelper } from "@tanstack/react-table";
-import { ClickPromptButton } from "@/components/ClickPrompt/ClickPromptButton";
+import { ClickPromptButton } from "@/components/ClickPromptButton";
import gptCategorySamples from "@/assets/chatgpt/category/index.json";
import {
- Flex,
- Heading,
+ Alert,
+ AlertIcon,
+ AlertTitle,
Box,
Card,
CardBody,
CardHeader,
- AlertIcon,
- AlertTitle,
- Alert,
+ Flex,
+ Heading,
Link as NavLink,
SimpleGrid,
} from "@/components/ChakraUI";
@@ -23,6 +23,7 @@ import SimpleMarkdown from "@/components/markdown/SimpleMarkdown";
import { ExternalLinkIcon } from "@chakra-ui/icons";
import { CP_GITHUB_ASSETS } from "@/configs/constants";
import styled from "@emotion/styled";
+import { llmServiceApiWithStream } from "@/api/llmService";
type GeneralCommand = {
type: string;
@@ -64,7 +65,9 @@ function ChatGptGeneral({ locale, i18n, chatgptSpecific }: { chatgptSpecific: Ch
}),
columnHelper.accessor("clickPrompt", {
cell: (info) => {
- return info.row.original.prompt !== "" ? : null;
+ return info.row.original.prompt !== "" ? (
+
+ ) : null;
},
header: "",
}),
@@ -98,7 +101,7 @@ function ChatGptGeneral({ locale, i18n, chatgptSpecific }: { chatgptSpecific: Ch
{sample.name}
-
+
diff --git a/packages/click-prompt/src/app/[lang]/chatgpt-generator-cot/page.client.tsx b/packages/click-prompt/src/app/[lang]/chatgpt-generator-cot/page.client.tsx
index 9fe1b230..8436ce3f 100644
--- a/packages/click-prompt/src/app/[lang]/chatgpt-generator-cot/page.client.tsx
+++ b/packages/click-prompt/src/app/[lang]/chatgpt-generator-cot/page.client.tsx
@@ -9,7 +9,8 @@ import { Form, Formik } from "formik";
import { numberToChineseOrdinal } from "chinese-numbering";
import CopyComponent from "@/components/CopyComponent";
-import { ClickPromptButton } from "@/components/ClickPrompt/ClickPromptButton";
+import { ClickPromptButton } from "@/components/ClickPromptButton";
+import { llmServiceApiWithStream } from "@/api/llmService";
function ChatGptCotGenerator({ i18n, locale }: GeneralI18nProps) {
const dict = i18n.dict;
@@ -86,7 +87,7 @@ ${dict["introduction-tail"]}`.replaceAll("", name),
-
+
, highlight: string) => [
}),
columnHelper.accessor("clickPrompt", {
cell: (info) => {
- return info.row.original.prompt !== "" ? : null;
+ return info.row.original.prompt !== "" ? (
+
+ ) : null;
},
header: "",
}),
diff --git a/packages/click-prompt/src/app/[lang]/chatgpt-samples/[id]/page.tsx b/packages/click-prompt/src/app/[lang]/chatgpt-samples/[id]/page.tsx
index 4de0a0bd..5522b707 100644
--- a/packages/click-prompt/src/app/[lang]/chatgpt-samples/[id]/page.tsx
+++ b/packages/click-prompt/src/app/[lang]/chatgpt-samples/[id]/page.tsx
@@ -2,22 +2,23 @@ import React, { Fragment } from "react";
import CopyComponent from "@/components/CopyComponent";
import SimpleMarkdown from "@/components/markdown/SimpleMarkdown";
import { ChatGptIcon } from "@/components/CustomIcon";
-import { ClickPromptButton } from "@/components/ClickPrompt/ClickPromptButton";
+import { ClickPromptButton } from "@/components/ClickPromptButton";
import {
Avatar,
Box,
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
+ Flex,
Heading,
SimpleGrid,
- Flex,
} from "@/components/ChakraUI";
import { notFound } from "next/navigation";
import { AiBlock } from "@/components/chatgpt/AiBlock";
import { HumanBlock } from "@/components/chatgpt/HumanBlock";
import { getAppData } from "@/i18n";
import type { Sample, SampleDetail } from "../type";
+import { llmServiceApiWithStream } from "@/api/llmService";
const getSampleNames = async (locale: GeneralI18nProps["locale"]) => {
const index = await import(`@/assets/chatgpt/samples/index_${locale}.json`).then((mod) => mod.default);
@@ -76,7 +77,7 @@ async function ChatGptSampleDetail({ params }: { params: { id: string } }) {
-
+
diff --git a/packages/click-prompt/src/app/[lang]/chatgpt-samples/page.client.tsx b/packages/click-prompt/src/app/[lang]/chatgpt-samples/page.client.tsx
index 90598149..e5441476 100644
--- a/packages/click-prompt/src/app/[lang]/chatgpt-samples/page.client.tsx
+++ b/packages/click-prompt/src/app/[lang]/chatgpt-samples/page.client.tsx
@@ -5,27 +5,26 @@ import {
Alert,
AlertIcon,
AlertTitle,
+ Box,
Button,
- Flex,
Card,
CardBody,
CardFooter,
CardHeader,
+ Flex,
Heading,
Link as NavLink,
SimpleGrid,
Stack,
- Box,
Text,
} from "@chakra-ui/react";
-
import Link from "next/link";
-
import { ExternalLinkIcon } from "@chakra-ui/icons";
import SimpleMarkdown from "@/components/markdown/SimpleMarkdown";
-import { ClickPromptButton } from "@/components/ClickPrompt/ClickPromptButton";
+import { ClickPromptButton } from "@/components/ClickPromptButton";
import { CP_GITHUB_ASSETS } from "@/configs/constants";
import type { Sample } from "./type";
+import { llmServiceApiWithStream } from "@/api/llmService";
function ChatGptSamples({ i18n, samples }: { samples: Sample[] } & GeneralI18nProps) {
const chatgptLink = `${CP_GITHUB_ASSETS}/chatgpt`;
@@ -63,7 +62,7 @@ function ChatGptSamples({ i18n, samples }: { samples: Sample[] } & GeneralI18nPr
-
+
diff --git a/packages/click-prompt/src/app/[lang]/chatgpt-visual-novel/page.client.tsx b/packages/click-prompt/src/app/[lang]/chatgpt-visual-novel/page.client.tsx
deleted file mode 100644
index b72476fb..00000000
--- a/packages/click-prompt/src/app/[lang]/chatgpt-visual-novel/page.client.tsx
+++ /dev/null
@@ -1,287 +0,0 @@
-"use client";
-
-import { useState, MouseEventHandler, useMemo, ChangeEventHandler } from "react";
-import { Box, Card, CardBody, CardFooter, CardHeader, Flex, Text, Link, Stack, Select } from "@chakra-ui/react";
-import { ArrowDownIcon } from "@chakra-ui/icons";
-import girl1_neutral from "@/assets/images/visual-novel/00055-3317647877.png";
-import girl1_happy from "@/assets/images/visual-novel/00057-3317647877.png";
-import girl1_sad from "@/assets/images/visual-novel/00059-3317647877.png";
-import girl1_closed_eyes from "@/assets/images/visual-novel/00061-3317647877.png";
-import girl1_suprised from "@/assets/images/visual-novel/00063-3317647877.png";
-
-import girl2_neutral from "@/assets/images/visual-novel/00063-3415190727.png";
-import girl2_happy from "@/assets/images/visual-novel/00065-3415190727.png";
-import girl2_sad from "@/assets/images/visual-novel/00067-3415190727.png";
-import girl2_suprised from "@/assets/images/visual-novel/00071-3415190727.png";
-import girl2_closed_eyes from "@/assets/images/visual-novel/00073-3415190727.png";
-
-import girl3_neutral from "@/assets/images/visual-novel/00073-645522131.png";
-import girl3_happy from "@/assets/images/visual-novel/00075-645522131.png";
-import girl3_sad from "@/assets/images/visual-novel/00077-645522131.png";
-import girl3_suprised from "@/assets/images/visual-novel/00079-645522131.png";
-import girl3_closed_eyes from "@/assets/images/visual-novel/00081-645522131.png";
-
-import player_neutral from "@/assets/images/visual-novel/00144-1619487309.png";
-import player_happy from "@/assets/images/visual-novel/00089-1619487309.png";
-import player_sad from "@/assets/images/visual-novel/00091-1619487309.png";
-import player_suprised from "@/assets/images/visual-novel/00093-1619487309.png";
-import player_closed_eyes from "@/assets/images/visual-novel/00095-1619487309.png";
-
-import room from "@/assets/images/visual-novel/00115-1693129910.png";
-import lobby from "@/assets/images/visual-novel/00116-767133290.png";
-import garden from "@/assets/images/visual-novel/00117-1865753899.png";
-import restaurant from "@/assets/images/visual-novel/00146-2156326714.png";
-
-import Image, { StaticImageData } from "next/image";
-import { upperFirst } from "lodash-es";
-import ExecutePromptButton from "@/components/ClickPrompt/ExecutePromptButton";
-import { ResponseSend } from "@/pages/api/chatgpt/chat";
-import SimpleMarkdown from "@/components/markdown/SimpleMarkdown";
-import CopyComponent from "@/components/CopyComponent";
-import { fontSize } from "@mui/system";
-
-type StoryLine = {
- speaker: string;
- dialogue: string;
- mood: string;
- location: string;
-};
-
-type Scene = {
- speaker: string;
- girls: string[];
- story: StoryLine[];
-};
-
-function ChatGptVisualNovel({ i18n }: GeneralI18nProps) {
- const dict = i18n.dict;
- const genres = ["romance", "fantasy", "horror", "sci-fi", "crime"];
- const [genre, setGenre] = useState(dict[genres[0]]);
- const [scene, setScene] = useState({} as Scene);
- const [conversationId, setConversationId] = useState(undefined as number | undefined);
- const girls: { [key: string]: StaticImageData }[] = [
- {
- neutral: girl1_neutral,
- happy: girl1_happy,
- sad: girl1_sad,
- closed_eyes: girl1_closed_eyes,
- surprised: girl1_suprised,
- },
- {
- neutral: girl2_neutral,
- happy: girl2_happy,
- sad: girl2_sad,
- closed_eyes: girl2_closed_eyes,
- surprised: girl2_suprised,
- },
- {
- neutral: girl3_neutral,
- happy: girl3_happy,
- sad: girl3_sad,
- closed_eyes: girl3_closed_eyes,
- surprised: girl3_suprised,
- },
- ];
- const player: { [key: string]: StaticImageData } = {
- neutral: player_neutral,
- happy: player_happy,
- sad: player_sad,
- closed_eyes: player_closed_eyes,
- surprised: player_suprised,
- };
- const locations: { [key: string]: StaticImageData } = {
- lobby: lobby,
- room: room,
- garden: garden,
- restaurant: restaurant,
- };
- const prompt = `${dict["prompt_start"]}${genre}${dict["prompt_after_story_genre"]} ${girls.length} ${
- dict["prompt_after_number_of_girls"]
- }\n{speaker: "", girls: [""], story: [{"speaker": "", "dialogue": "", "mood": "", "location": ""}]}\n${
- dict["prompt_follow_rules"]
- } ${Object.keys(girls[0]).join(", ")}\n${dict["prompt_locations"]} ${Object.keys(locations).join(", ")}\n${
- dict["prompt_end"]
- }`;
- // Using only English for the continuing prompt as ChatGPT does not follow correctly with Chinese prompt
- const promptContinue = "Please continue on the previous story and remove the previous dialogues from the JSON.";
- const [step, setStep] = useState(0);
- const [characterMap, setCharacterMap] = useState({} as { [key: string]: number });
-
- const handleGenreChange: ChangeEventHandler = (e) => {
- setGenre(genres.indexOf(e.target.value) ? dict[e.target.value] : dict[genres[0]]);
- };
-
- const handleStoryNextStep: MouseEventHandler = (e) => {
- if (step < scene.story.length - 1) {
- setStep(step + 1);
- }
- };
-
- const handleResponse = (response: ResponseSend) => {
- try {
- const newScene = JSON.parse(response[0].content.trim()) as Scene;
- if ("speaker" in newScene && "girls" in newScene && "story" in newScene) {
- const newCharacterMap = characterMap;
- for (const girlIndex in newScene.girls) {
- const girl = newScene.girls[girlIndex].toLowerCase();
- const girlCount = Object.keys(newCharacterMap).length;
- if (!(girl in newCharacterMap) && Object.keys(newCharacterMap).length < girls.length) {
- newCharacterMap[girl] = girlCount;
- }
- }
- setStep(0);
- setCharacterMap(newCharacterMap);
- setScene(newScene);
- } else {
- console.log(newScene);
- }
- } catch (e) {
- console.log(response);
- console.error(e);
- }
- };
-
- const updateConversationId = (id: number) => {
- setConversationId(id);
- };
-
- const character = useMemo(() => {
- if (!(scene && scene.speaker)) return;
- const speaker = scene.story[step].speaker.toLowerCase();
- if (speaker == scene.speaker.toLowerCase() || speaker == "narrator")
- return player[scene.story[step].mood.toLowerCase()];
- if (speaker in characterMap) return girls[characterMap[speaker]][scene.story[step].mood.toLowerCase()];
- }, [step, scene, characterMap]);
-
- return (
- <>
- {!(scene && scene.speaker) && (
-
-
- {dict["select_genre"]}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )}
- {scene && scene.speaker && (
-
-
-
-
-
- {upperFirst(scene.story[step].speaker)}
-
- {scene.story[step].dialogue}
- {step < scene.story.length - 1 ? (
-
- ) : (
-
-
-
- )}
-
- {dict["sd_note_prefix"]}
-
- Stable Diffusion
-
- {dict["sd_note_model"]}
-
- AbyssOrangeMix3
-
-
-
-
- )}
- >
- );
-}
-
-export default ChatGptVisualNovel;
diff --git a/packages/click-prompt/src/app/[lang]/chatgpt-visual-novel/page.tsx b/packages/click-prompt/src/app/[lang]/chatgpt-visual-novel/page.tsx
deleted file mode 100644
index 720afc8b..00000000
--- a/packages/click-prompt/src/app/[lang]/chatgpt-visual-novel/page.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import "server-only";
-
-import ChatGptVisualNovel from "./page.client";
-import { SupportedLocale, getAppData } from "@/i18n";
-
-async function prepareData(locale: SupportedLocale) {
- return import(`@/assets/resources/prompts_${locale}.json`).then((mod) => mod.default);
-}
-
-export default async function ChatGptPromptRolePlay() {
- const { locale, pathname, i18n } = await getAppData();
- const i18nProps: GeneralI18nProps = {
- locale,
- pathname,
- i18n: {
- dict: i18n.dict,
- },
- };
- const prompts = await prepareData(locale);
-
- return ;
-}
diff --git a/packages/click-prompt/src/app/[lang]/chatgpt/page.tsx b/packages/click-prompt/src/app/[lang]/chatgpt/page.tsx
index 713ee74e..c24defef 100644
--- a/packages/click-prompt/src/app/[lang]/chatgpt/page.tsx
+++ b/packages/click-prompt/src/app/[lang]/chatgpt/page.tsx
@@ -3,15 +3,16 @@ import "server-only";
import React from "react";
import { cookies } from "next/headers";
import { SITE_USER_COOKIE } from "@/configs/constants";
-import { ChatGPTApp } from "@/components/chatgpt/ChatGPTApp";
-import * as UserAPI from "@/api/user";
+import { ChatGPTApp } from "@/components/ClickPromptButton";
+import { isLoggedIn } from "@/api/user";
+import { llmServiceApiWithStream } from "@/api/llmService";
export default async function ChatGPTPage() {
const hashedKey = cookies().get(SITE_USER_COOKIE)?.value as string;
let isLoggedin = false;
try {
- isLoggedin = await UserAPI.isLoggedIn(hashedKey);
+ isLoggedin = await isLoggedIn(hashedKey);
} catch (e) {
console.error(e);
isLoggedin = false;
@@ -19,7 +20,7 @@ export default async function ChatGPTPage() {
return (
-
+
);
}
diff --git a/packages/click-prompt/src/app/[lang]/click-flow/[id]/StartlingStepDetail.tsx b/packages/click-prompt/src/app/[lang]/click-flow/[id]/StartlingStepDetail.tsx
index 04244973..235eb861 100644
--- a/packages/click-prompt/src/app/[lang]/click-flow/[id]/StartlingStepDetail.tsx
+++ b/packages/click-prompt/src/app/[lang]/click-flow/[id]/StartlingStepDetail.tsx
@@ -3,20 +3,20 @@
import React, { useEffect } from "react";
import styled from "@emotion/styled";
import { Flex } from "@chakra-ui/react";
-
import { HumanBlock } from "@/components/chatgpt/HumanBlock";
import { Avatar, Box } from "@/components/ChakraUI";
import SimpleMarkdown from "@/components/markdown/SimpleMarkdown";
import { AiBlock } from "@/components/chatgpt/AiBlock";
import { ChatGptIcon } from "@/components/CustomIcon";
import { StartlingFlow } from "@/flows/types/click-flow";
-import { ResponseSend } from "@/pages/api/chatgpt/chat";
-import ExecutePromptButton from "@/components/ClickPrompt/ExecutePromptButton";
+import type { Chat } from "@/components/ClickPromptButton";
+import { ExecutePromptButton } from "@/components/ClickPromptButton";
import { AskRenderer } from "@/app/[lang]/click-flow/[id]/AskRenderer";
import CopyComponent from "@/components/CopyComponent";
import PostFlowAction from "@/flows/components/PostFlowAction";
import PreFlowAction from "@/flows/components/PreFlowAction";
import { fillStepWithValued, FlowStep } from "@/flows/types/flow-step";
+import { llmServiceApi } from "@/api/llmService";
type StepProps = {
index: number;
@@ -41,8 +41,12 @@ function StartlingStepDetail({
}: StepProps) {
const [response, setResponse] = React.useState(undefined);
- const handleResponse = (response: ResponseSend) => {
- const assistantMessage = response.filter((message) => message.role === "assistant");
+ const handleResponse = (response: ReadableStream | Chat[] | null) => {
+ if (!response || !Array.isArray(response)) {
+ console.error("We assume response is an array of Chat instead of a stream");
+ }
+
+ const assistantMessage = (response as Chat[]).filter((message) => message.role === "assistant");
const assistantResponse = assistantMessage[0].content;
setResponse(assistantResponse);
onStepComplete(index);
@@ -101,10 +105,10 @@ function StartlingStepDetail({
)}
)}
diff --git a/packages/click-prompt/src/app/[lang]/page.client.tsx b/packages/click-prompt/src/app/[lang]/page.client.tsx
new file mode 100644
index 00000000..d2676772
--- /dev/null
+++ b/packages/click-prompt/src/app/[lang]/page.client.tsx
@@ -0,0 +1,59 @@
+"use client";
+
+import { Box, Button, Container, Heading, Stack, Text } from "@/components/ChakraUI";
+import { ClickPromptHome } from "@/components/CustomIcon";
+import { GITHUB_URL } from "@/configs/constants";
+import { ClickPromptButton } from "@/components/ClickPromptButton";
+import React from "react";
+import { llmServiceApiWithStream } from "@/api/llmService";
+
+export const HomeClient = ({ dict }: { dict: Record }) => {
+ return (
+
+
+
+
+
+
+ {dict["title"]}
+
+
+
+ {dict["description"]}
+
+
+
+
+ GitHub
+
+
+
+
+
+
+
+ );
+};
diff --git a/packages/click-prompt/src/app/[lang]/page.tsx b/packages/click-prompt/src/app/[lang]/page.tsx
index e8f04d48..3c315244 100644
--- a/packages/click-prompt/src/app/[lang]/page.tsx
+++ b/packages/click-prompt/src/app/[lang]/page.tsx
@@ -1,56 +1,11 @@
import React from "react";
-import { Box, Button, Container, Heading, Stack, Text } from "@/components/ChakraUI";
-import { ClickPromptHome } from "@/components/CustomIcon";
-import { GITHUB_URL } from "@/configs/constants";
-import { ClickPromptButton } from "@/components/ClickPrompt/ClickPromptButton";
import { getAppData } from "@/i18n";
+import { HomeClient } from "@/app/[lang]/page.client";
async function Page() {
const { i18n } = await getAppData();
- const t = i18n.tFactory("/");
- return (
-
-
-
-
-
-
- {t("title")}
-
-
-
- {t("description")}
-
-
-
-
- GitHub
-
-
-
-
-
-
-
- );
+ return ;
}
export default Page;
diff --git a/packages/click-prompt/src/app/[lang]/stable-diffusion-generator/page.client.tsx b/packages/click-prompt/src/app/[lang]/stable-diffusion-generator/page.client.tsx
index 39ea908c..5b40cae8 100644
--- a/packages/click-prompt/src/app/[lang]/stable-diffusion-generator/page.client.tsx
+++ b/packages/click-prompt/src/app/[lang]/stable-diffusion-generator/page.client.tsx
@@ -4,21 +4,21 @@ import React, { ChangeEvent, useEffect, useMemo, useState } from "react";
import {
Button,
Flex,
+ FormControl,
Grid,
Heading,
Input,
InputGroup,
InputRightElement,
Link,
+ Radio,
+ RadioGroup,
SimpleGrid,
Stack,
- Text,
Tag,
TagCloseButton,
- FormControl,
TagLabel,
- RadioGroup,
- Radio,
+ Text,
} from "@chakra-ui/react";
import { useFormik } from "formik";
import Image from "next/image";
@@ -26,10 +26,11 @@ import CopyComponent from "@/components/CopyComponent";
import PromptFieldForm, { SdPromptField } from "@/app/[lang]/stable-diffusion-generator/PromptFieldForm";
import sdImage from "@/assets/images/stable-diffusion-demo.jpeg";
import { WebStorage } from "@/storage/webstorage";
-import { ClickPromptButton } from "@/components/ClickPrompt/ClickPromptButton";
+import { ClickPromptButton } from "@/components/ClickPromptButton";
import { HuggingFaceTxt2Img } from "@/components/StableDiffusion/HuggingFaceTxt2Img";
import { SdPrompt } from "@/components/StableDiffusion/SdPrompt";
import { StableDiffusionGenData } from "@/data-processor/StableDiffusionGenData";
+import { llmServiceApiWithStream } from "@/api/llmService";
const sdDetailedPromptFields: SdPromptField[] = [
{
@@ -520,7 +521,7 @@ function StableDiffusionGenerator({ i18n }: GeneralI18nProps) {
-
+
diff --git a/packages/click-prompt/src/components/ClickPrompt/Button.shared.tsx b/packages/click-prompt/src/components/ClickPrompt/Button.shared.tsx
deleted file mode 100644
index 87b880e5..00000000
--- a/packages/click-prompt/src/components/ClickPrompt/Button.shared.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-"use client";
-
-import Image from "next/image";
-import React, { MouseEventHandler } from "react";
-import styled from "@emotion/styled";
-
-export type ButtonSize = "sm" | "md" | "lg";
-
-export const StyledBird = styled(Image)`
- position: absolute;
- top: -20px;
- right: -20px;
-`;
-
-export const StyledPromptButton = styled.div`
- position: relative;
- width: min-content;
-`;
-
-export type CPButtonProps = {
- loading?: boolean;
- onClick?: MouseEventHandler;
- size?: ButtonSize;
- text: string;
- children?: React.ReactNode;
- [key: string]: any;
-};
diff --git a/packages/click-prompt/src/components/ClickPrompt/ClickPromptButton.tsx b/packages/click-prompt/src/components/ClickPrompt/ClickPromptButton.tsx
deleted file mode 100644
index 0d13c9c8..00000000
--- a/packages/click-prompt/src/components/ClickPrompt/ClickPromptButton.tsx
+++ /dev/null
@@ -1,72 +0,0 @@
-"use client";
-
-import React, { useState } from "react";
-import { Box, Text, Tooltip, useDisclosure } from "@chakra-ui/react";
-import { Button } from "@/components/ChakraUI";
-import { BeatLoader } from "react-spinners";
-import { ClickPromptSmall } from "@/components/CustomIcon";
-import clickPromptLogo from "@/assets/clickprompt-light.svg?url";
-import { CPButtonProps, StyledBird, StyledPromptButton } from "@/components/ClickPrompt/Button.shared";
-import { LoggingDrawer } from "@/components/ClickPrompt/LoggingDrawer";
-import * as UserAPI from "@/api/user";
-
-export type ClickPromptBirdParams = { width?: number; height?: number };
-
-export function ClickPromptBird(props: ClickPromptBirdParams) {
- const width = props.width || 38;
- const height = props.height || 32;
-
- return ;
-}
-
-export function ClickPromptButton(props: CPButtonProps) {
- const [isLoading, setIsLoading] = useState(props.loading);
- const [isLoggedIn, setIsLoggedIn] = useState(false);
- const { isOpen, onOpen, onClose } = useDisclosure();
-
- const handleClick = async (event: any) => {
- setIsLoading(true);
- const isLoggedIn = await UserAPI.isLoggedIn();
- setIsLoggedIn(isLoggedIn);
- onOpen();
- props.onClick && props.onClick(event);
- };
-
- const handleClose = () => {
- setIsLoading(false);
- onClose();
- };
-
- function NormalSize() {
- return (
-
-
- {props.children}
- {!isLoading && Prompt }
- {isLoading && }
-
-
-
- );
- }
-
- function SmallSize() {
- return (
-
- {props.children}
-
-
-
-
- );
- }
-
- return (
-
- {props.size !== "sm" && }
- {props.size === "sm" && }
-
- {LoggingDrawer(isOpen, handleClose, isLoggedIn, props)}
-
- );
-}
diff --git a/packages/click-prompt/src/components/ClickPrompt/ExecutePromptButton.tsx b/packages/click-prompt/src/components/ClickPrompt/ExecutePromptButton.tsx
deleted file mode 100644
index 8b4fc324..00000000
--- a/packages/click-prompt/src/components/ClickPrompt/ExecutePromptButton.tsx
+++ /dev/null
@@ -1,102 +0,0 @@
-"use client";
-
-import React, { MouseEventHandler, useEffect, useState } from "react";
-import { Text, useDisclosure } from "@chakra-ui/react";
-import * as UserAPI from "@/api/user";
-import { ResponseCreateConversation } from "@/pages/api/chatgpt/conversation";
-import { createConversation } from "@/api/conversation";
-import { sendMessage } from "@/api/chat";
-import { ResponseSend } from "@/pages/api/chatgpt/chat";
-import { Button } from "@/components/ChakraUI";
-import { BeatLoader } from "react-spinners";
-import { ClickPromptBird } from "@/components/ClickPrompt/ClickPromptButton";
-import { ButtonSize, StyledPromptButton } from "./Button.shared";
-import { LoggingDrawer } from "@/components/ClickPrompt/LoggingDrawer";
-
-export type ExecButtonProps = {
- loading?: boolean;
- onClick?: MouseEventHandler;
- name: string;
- text: string;
- size?: ButtonSize;
- children?: React.ReactNode;
- handleResponse?: (response: ResponseSend) => void;
- conversationId?: number;
- updateConversationId?: (conversationId: number) => void;
-};
-
-function ExecutePromptButton(props: ExecButtonProps) {
- const [isLoading, setIsLoading] = useState(props.loading);
- const { isOpen, onOpen, onClose } = useDisclosure();
- const [hasLogin, setHasLogin] = useState(false);
-
- const handleClick = async () => {
- setIsLoading(true);
-
- try {
- const isLoggedIn = await UserAPI.isLoggedIn();
- if (!isLoggedIn) {
- onOpen();
- setIsLoading(false);
- return;
- }
- } catch (e) {
- console.log(e);
- setHasLogin(false);
- }
-
- let conversationId = props.conversationId;
- if (!props.conversationId) {
- const conversation: ResponseCreateConversation = await createConversation();
- if (!conversation) {
- return;
- }
-
- conversationId = conversation.id as number;
- props.updateConversationId ? props.updateConversationId(conversationId) : null;
- }
-
- if (conversationId) {
- const response: any = await sendMessage(conversationId, props.text);
- if (response && props.handleResponse) {
- props.handleResponse(response as ResponseSend);
- }
- }
-
- setIsLoading(false);
- };
-
- useEffect(() => {
- console.log(`hasLogin: ${hasLogin}`);
- if (hasLogin) {
- onClose();
- }
- }, [hasLogin]);
-
- const handleClose = () => {
- onClose();
- };
-
- const updateLoginStatus = (status: boolean) => {
- if (status) {
- setHasLogin(true);
- onClose();
- }
- };
-
- return (
- <>
-
-
- {props.children}
- {!isLoading && Prompt }
- {isLoading && }
-
-
-
- {!hasLogin && LoggingDrawer(isOpen, handleClose, hasLogin, props, updateLoginStatus)}
- >
- );
-}
-
-export default ExecutePromptButton;
diff --git a/packages/click-prompt/src/components/ClickPrompt/LoggingDrawer.tsx b/packages/click-prompt/src/components/ClickPrompt/LoggingDrawer.tsx
deleted file mode 100644
index fa38b142..00000000
--- a/packages/click-prompt/src/components/ClickPrompt/LoggingDrawer.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-"use client";
-
-import { Drawer, DrawerBody, DrawerCloseButton, DrawerContent, DrawerOverlay } from "@chakra-ui/react";
-import { ChatGPTApp } from "@/components/chatgpt/ChatGPTApp";
-import React from "react";
-import { CPButtonProps } from "@/components/ClickPrompt/Button.shared";
-
-export function LoggingDrawer(
- isOpen: boolean,
- handleClose: () => void,
- isLoggedIn: boolean,
- props: CPButtonProps,
- updateStatus?: (loggedIn: boolean) => void,
-) {
- return (
-
-
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/packages/click-prompt/src/components/ClickPromptButton/index.tsx b/packages/click-prompt/src/components/ClickPromptButton/index.tsx
new file mode 100644
index 00000000..0decded3
--- /dev/null
+++ b/packages/click-prompt/src/components/ClickPromptButton/index.tsx
@@ -0,0 +1,32 @@
+"use client";
+
+import "@click-prompt/click-prompt-button/style.css";
+import dynamic from "next/dynamic";
+import type { Chat, ClickPromptButtonProps, LlmServiceApi } from "@click-prompt/click-prompt-button";
+
+// TODO: investigate why this is needed - it should be possible to import the components directly(before monorepo it can)
+export const ClickPromptButton = (props: ClickPromptButtonProps) => {
+ const CPB = dynamic(() => import("@click-prompt/click-prompt-button").then((module) => module.ClickPromptButton), {
+ ssr: false,
+ });
+
+ return ;
+};
+
+export const ChatGPTApp = (props: ClickPromptButtonProps) => {
+ const GPT = dynamic(() => import("@click-prompt/click-prompt-button").then((module) => module.ChatGPTApp), {
+ ssr: false,
+ });
+
+ return ;
+};
+
+export const ExecutePromptButton = (props: ClickPromptButtonProps) => {
+ const EPB = dynamic(() => import("@click-prompt/click-prompt-button").then((module) => module.ExecutePromptButton), {
+ ssr: false,
+ });
+
+ return ;
+};
+
+export type { Chat, LlmServiceApi, ClickPromptButtonProps };
diff --git a/packages/click-prompt/src/components/chatgpt/ChatGPTApp.tsx b/packages/click-prompt/src/components/chatgpt/ChatGPTApp.tsx
deleted file mode 100644
index 8884d571..00000000
--- a/packages/click-prompt/src/components/chatgpt/ChatGPTApp.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-"use client";
-
-import { ChatRoom } from "@/components/chatgpt/ChatRoom";
-import { LoginPage } from "@/components/chatgpt/LoginPage";
-import React, { useEffect, useState } from "react";
-
-type ChatGPTAppProps = {
- loggedIn?: boolean;
- updateLoginStatus?: (loggedIn: boolean) => void;
- initMessage?: string;
-};
-export const ChatGPTApp = ({ loggedIn, initMessage, updateLoginStatus }: ChatGPTAppProps) => {
- const [isLoggedIn, setIsLoggedIn] = useState(loggedIn ?? false);
-
- useEffect(() => {
- if (updateLoginStatus) {
- updateLoginStatus(isLoggedIn);
- }
- }, [isLoggedIn]);
-
- return isLoggedIn ? (
-
- ) : (
-
- );
-};
diff --git a/packages/click-prompt/src/components/chatgpt/ChatRoom.tsx b/packages/click-prompt/src/components/chatgpt/ChatRoom.tsx
deleted file mode 100644
index 8d7df4e0..00000000
--- a/packages/click-prompt/src/components/chatgpt/ChatRoom.tsx
+++ /dev/null
@@ -1,439 +0,0 @@
-"use client";
-
-import NewChat from "@/assets/icons/new-chat.svg";
-import TrashcanIcon from "@/assets/icons/trashcan.svg";
-import LogoutIcon from "@/assets/icons/logout.svg";
-import Image from "next/image";
-import content from "@/assets/images/content.png";
-import send from "@/assets/icons/send.svg?url";
-import React, { Dispatch, SetStateAction, useEffect, useState } from "react";
-import styled from "@emotion/styled";
-import type { RequestGetConversations, ResponseGetConversations } from "@/pages/api/chatgpt/conversation";
-import { ResponseGetChats, ResponseSend } from "@/pages/api/chatgpt/chat";
-import { BeatLoader } from "react-spinners";
-import { useDebouncedCallback } from "use-debounce";
-import { Input } from "@chakra-ui/react";
-import * as ChatAPI from "@/api/chat";
-import * as ConversationAPI from "@/api/conversation";
-import * as UserAPI from "@/api/user";
-import SimpleMarkdown from "@/components/markdown/SimpleMarkdown";
-
-const ChatInput = styled("input")`
- background: #ffffff;
- border-radius: 8px;
- border: none;
- padding: 0.5rem 1rem;
- width: 768px;
- height: 48px;
- font-size: 1rem;
- font-weight: 500;
- color: #1e1e1e;
- outline: none;
- transition: all 0.2s ease-in-out;
-
- &:focus {
- box-shadow: 0 0 0 2px #1e1e1e;
- }
-
- &:focus::placeholder {
- color: #1e1e1e;
- }
-`;
-const ChatInputWrapper = styled("div")`
- position: absolute;
- bottom: 8px;
- width: 768px;
- height: 48px;
- background-color: #fff;
- border-radius: 8px;
-`;
-const ChatsWrapper = styled("div")`
- // good looking scrollbar
- &::-webkit-scrollbar {
- width: 8px;
- }
-
- &::-webkit-scrollbar-track {
- background: #f1f1f1;
- }
-
- &::-webkit-scrollbar-thumb {
- background: #888;
- }
-
- &::-webkit-scrollbar-thumb:hover {
- background: #555;
- }
-`;
-const ChatSendButton = styled("button")`
- position: absolute;
- top: 0;
- bottom: 0;
- right: 8px;
- width: 48px;
- height: 48px;
- background-image: url(${send});
- background-size: 24px;
- background-position: center;
- background-repeat: no-repeat;
- cursor: pointer;
- border: none;
- outline: none;
-`;
-
-export const ChatRoom = ({
- setIsLoggedIn,
- initMessage,
-}: {
- setIsLoggedIn: Dispatch>;
- initMessage?: string;
-}) => {
- const chatsWrapper = React.useRef(null);
- const [disable, setDisable] = React.useState(false);
- const [chatHistory, setChatHistory] = React.useState([]);
- const [message, setMessage] = React.useState(initMessage ?? "");
-
- const [conversations, setConversations] = useState([]);
- const [currentConversation, setCurrentConversation] = useState(null);
- // editing conversation name
- const [editing, setEditing] = useState(null);
- const [editingName, setEditingName] = useState("");
-
- // get conversations
- useEffect(() => {
- (async () => {
- try {
- const response = await fetch("/api/chatgpt/conversation", {
- method: "POST",
- body: JSON.stringify({
- action: "get_conversations",
- } as RequestGetConversations),
- });
- const data = (await response.json()) as ResponseGetConversations;
- if (!response.ok) {
- alert("Error: " + JSON.stringify((data as any).error));
- return;
- }
- setConversations(data);
- } catch (error) {
- setConversations([]);
- alert("Error: " + JSON.stringify(error));
- }
- })();
- }, []);
-
- // scroll to bottom
- useEffect(() => {
- setTimeout(() => {
- if (chatsWrapper.current) {
- chatsWrapper.current.scrollTop = chatsWrapper.current.scrollHeight;
- }
- });
- }, [chatHistory]);
-
- const onEnterForSendMessage: React.KeyboardEventHandler = (event) => {
- if (event.code === "Enter" || event.code === "NumpadEnter") {
- event.preventDefault();
-
- sendMessage();
- }
- };
-
- async function createConversation() {
- const data = await ConversationAPI.createConversation();
- if (!data) {
- return;
- }
-
- setConversations([data, ...conversations]);
- return data;
- }
-
- async function changeConversationName(conversationId: number, name: string) {
- await ConversationAPI.changeConversationName(conversationId, name);
-
- setConversations((c) =>
- c.map((conversation) => {
- if (conversation.id === conversationId) {
- return {
- ...conversation,
- name,
- };
- }
- return conversation;
- }),
- );
- }
-
- const handleConversation = useDebouncedCallback(
- async (conversationId: number | null, event: React.MouseEvent) => {
- if (event.detail > 1) {
- // double click
- if (conversationId == null) {
- return;
- }
- setEditingName(conversations.find((c) => c.id === conversationId)?.name ?? "");
- setEditing(conversationId);
- return;
- }
-
- if (conversationId == null) {
- setCurrentConversation(null);
- setChatHistory([]);
- return;
- }
- setDisable(true);
-
- try {
- setCurrentConversation(conversationId);
- const data = await ChatAPI.getChatsByConversationId(conversationId);
- if (!data) {
- return;
- }
- setChatHistory(data);
- } catch (e) {
- console.log("changeConversation: ", e);
- } finally {
- setDisable(false);
- }
- },
- 200,
- );
-
- async function deleteConversation(conversationId: number) {
- const data = await ConversationAPI.deleteConversation(conversationId);
- if (!data) {
- return;
- }
- setConversations(conversations.filter((conversation) => conversation.id !== conversationId));
- }
-
- async function deleteAllConversations() {
- const data = await ConversationAPI.deleteAllConversations();
- if (!data) {
- return;
- }
- setConversations([]);
- }
- // FIXME anti-pattern, should use `useState`
- let codeMark = "";
- async function sendMessage() {
- if (message.length === 0) {
- alert("Please enter your message first.");
- return;
- }
-
- try {
- setDisable(true);
- if (currentConversation == null) {
- const created = await createConversation();
- setCurrentConversation(created?.id ?? null);
- }
-
- setMessage("");
- let updatedHistory = [
- ...chatHistory,
- {
- role: "user",
- content: message,
- // TODO(CGQAQ): custom name of user
- // name: "User",
- },
- ] as ResponseSend;
-
- setChatHistory([...updatedHistory]);
-
- const data = await ChatAPI.sendMsgWithStreamRes(currentConversation as number, message);
- if (!data) {
- setDisable(false);
- setChatHistory([...updatedHistory.slice(0, updatedHistory.length - 1)]);
- return;
- }
- const reader = data.getReader();
- const decoder = new TextDecoder();
- let isDone = false;
- while (!isDone) {
- const { value, done } = await reader.read();
- isDone = done;
- const chunkValue = decoder.decode(value);
- const lines = chunkValue.split("\n").filter((line) => line.trim() !== "");
- for (const line of lines) {
- const message = line.replace(/^data: /, "");
- if (message === "[DONE]") {
- setDisable(false);
- } else {
- const parsed = JSON.parse(message).choices[0].delta;
- if (parsed && Object.keys(parsed).length > 0) {
- if (!!parsed.role) {
- parsed.content = "";
- updatedHistory = [...updatedHistory, parsed];
- } else if (!!parsed.content) {
- if (parsed.content === "```") {
- // code block start
- if (!codeMark) {
- codeMark = parsed.content;
- } else {
- // code block end remove it
- codeMark = "";
- }
- }
- updatedHistory[updatedHistory.length - 1].content += parsed.content;
- }
- setChatHistory([...updatedHistory]);
- }
- }
- }
- }
- } catch (err) {
- console.log(err);
- setDisable(false);
- } finally {
- // setDisable(false);
- }
- }
-
- async function logout() {
- await UserAPI.logout();
- setIsLoggedIn(false);
- }
-
- return (
-
- {/* left */}
-
-
-
- New chat
-
-
- {conversations.map((conversation) => (
- {
- handleConversation(conversation.id!, event);
- }}
- >
- {editing === conversation.id ? (
- {
- setEditingName(ev.currentTarget.value);
- }}
- onKeyDown={(ev) => {
- if (ev.key === "Enter" || ev.key === "NumpadEnter") {
- ev.preventDefault();
- changeConversationName(conversation.id!, ev.currentTarget.value).finally(() => {
- setEditing(null);
- });
- } else if (ev.key === "Escape") {
- ev.preventDefault();
- setEditing(null);
- }
- }}
- onBlur={async (ev) => {
- await changeConversationName(conversation.id!, ev.currentTarget.value);
- setEditing(null);
- }}
- />
- ) : (
- <>
-
- {conversation.name}
-
- {/* delete button */}
- {
- e.stopPropagation();
- if (confirm("Are you sure to delete this conversation?")) {
- deleteConversation(conversation.id!);
- }
- }}
- >
-
-
- >
- )}
-
- ))}
-
-
- {
- e.stopPropagation();
- if (confirm("Are you sure to delete ALL conversations?")) {
- deleteAllConversations();
- }
- }}
- >
-
- Clear conversations
-
-
-
- Log out
-
-
-
-
- {/* right */}
-
- {chatHistory.length === 0 && }
-
- {/* chats */}
-
- {chatHistory.map((chat, index) => {
- return (
-
- {chat.role === "user" ? (
-
- {/* chat bubble badge */}
-
-
-
-
- ) : (
-
-
-
-
-
- )}
-
- );
- })}
-
-
-
- setMessage(ev.target.value)}
- onKeyDown={onEnterForSendMessage}
- className='w-full pr-10 md:w-11/12 border-0 md:pr-0 focus:ring-0'
- />
- {disable ? (
-
- ) : (
-
- )}
-
-
-
- );
-};
diff --git a/packages/click-prompt/src/components/chatgpt/LoginPage.tsx b/packages/click-prompt/src/components/chatgpt/LoginPage.tsx
deleted file mode 100644
index 625a4c06..00000000
--- a/packages/click-prompt/src/components/chatgpt/LoginPage.tsx
+++ /dev/null
@@ -1,61 +0,0 @@
-"use client";
-
-import { Button, Input } from "@/components/ChakraUI";
-import React, { Dispatch, SetStateAction } from "react";
-import * as UserApi from "@/api/user";
-
-export const LoginPage = ({ setIsLoggedIn }: { setIsLoggedIn: Dispatch> }) => {
- const [openAiKey, setOpenAiKey] = React.useState("");
-
- async function login(key: string) {
- if (key.length === 0) {
- alert("Please enter your OpenAI API key first.");
- return;
- }
-
- const data = await UserApi.login(key);
- if (data) {
- setIsLoggedIn(true);
- } else {
- alert("Login failed. Please check your API key.");
- setIsLoggedIn(false);
- }
- }
-
- return (
-
- ChatGPT
- You need to login first use your own key.
-
-
- 1. Sign up for the
-
- OpenAI Platform.
-
-
-
- 2. Create a new secret key in
-
- Settings → API keys.
-
-
- 3. Copy and paste your API key here:
-
-
- setOpenAiKey(ev.target.value)}
- >
- {
- await login(openAiKey);
- }}
- >
- Login
-
-
-
- );
-};
diff --git a/packages/click-prompt/src/layout/NavBar.tsx b/packages/click-prompt/src/layout/NavBar.tsx
index 7c14615b..302ac913 100644
--- a/packages/click-prompt/src/layout/NavBar.tsx
+++ b/packages/click-prompt/src/layout/NavBar.tsx
@@ -32,7 +32,7 @@ export default async function NavBar({ locale }: { locale: string }) {
{ url: `/chatgpt-interactive-game/`, title: g("chatgpt-interactive-game") },
{ url: `/chatgpt-samples/`, title: g("chatgpt-samples") },
{ url: `/chatgpt/`, title: g("chatgpt") },
- { url: `/chatgpt-visual-novel/`, title: g("chatgpt-visual-novel") },
+ { url: `https://chatvisualnovel.com/`, title: g("chatgpt-visual-novel") },
],
},
{
diff --git a/packages/click-prompt/tsconfig.json b/packages/click-prompt/tsconfig.json
index b5cde3c3..ba94e280 100644
--- a/packages/click-prompt/tsconfig.json
+++ b/packages/click-prompt/tsconfig.json
@@ -1,26 +1,8 @@
{
+ "extends": "tsconfig/base.json",
"baseUrl": ".", // This has to be specified if "paths" is.
"compilerOptions": {
"baseUrl": ".",
- "target": "ES2020",
- "lib": [
- "dom",
- "dom.iterable",
- "ES2021.String",
- "esnext"
- ],
- "allowJs": true,
- "skipLibCheck": true,
- "strict": true,
- "forceConsistentCasingInFileNames": true,
- "noEmit": true,
- "esModuleInterop": true,
- "module": "esnext",
- "moduleResolution": "node",
- "resolveJsonModule": true,
- "isolatedModules": true,
- "jsx": "preserve",
- "incremental": true,
"plugins": [
{
"name": "next"
@@ -33,15 +15,13 @@
"@i18n/*": [
"./i18n/*"
]
- }
+ },
+ "strictNullChecks": true
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts"
- ],
- "exclude": [
- "node_modules"
]
}
diff --git a/packages/eslint-config-custom/index.js b/packages/eslint-config-custom/index.js
new file mode 100644
index 00000000..8ae4dd9f
--- /dev/null
+++ b/packages/eslint-config-custom/index.js
@@ -0,0 +1,11 @@
+module.exports = {
+ root: true,
+ plugins: ["@typescript-eslint"],
+ extends: ["plugin:@typescript-eslint/recommended", "prettier"],
+ rules: {
+ "react-hooks/exhaustive-deps": "off",
+ "no-console": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ },
+};
diff --git a/packages/eslint-config-custom/package.json b/packages/eslint-config-custom/package.json
new file mode 100644
index 00000000..2bb0b55d
--- /dev/null
+++ b/packages/eslint-config-custom/package.json
@@ -0,0 +1,8 @@
+{
+ "name": "eslint-config-custom",
+ "main": "index.js",
+ "version": "1.0.0",
+ "devDependencies": {
+ "eslint": "latest"
+ }
+}
diff --git a/packages/tsconfig/base.json b/packages/tsconfig/base.json
new file mode 100644
index 00000000..87ee9647
--- /dev/null
+++ b/packages/tsconfig/base.json
@@ -0,0 +1,21 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "compilerOptions": {
+ "target": "ESNext",
+ "lib": ["dom", "dom.iterable", "ES2021.String", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true,
+ "strictNullChecks": true
+ },
+ "exclude": ["node_modules"]
+}
diff --git a/packages/tsconfig/package.json b/packages/tsconfig/package.json
new file mode 100644
index 00000000..f4735add
--- /dev/null
+++ b/packages/tsconfig/package.json
@@ -0,0 +1,3 @@
+{
+ "name": "tsconfig"
+}
diff --git a/turbo.json b/turbo.json
index 5cd710a1..147d6d25 100644
--- a/turbo.json
+++ b/turbo.json
@@ -13,6 +13,11 @@
"lint": {
"dependsOn": ["format"]
},
- "dev": {}
+ "dev": {
+ "dependsOn": ["^build"]
+ },
+ "start": {
+ "dependsOn": ["build"]
+ }
}
}