From 2a9f9d19795efe5a17700acc2db41ff5753e965a Mon Sep 17 00:00:00 2001 From: Pabloader Date: Fri, 1 Nov 2024 12:28:56 +0000 Subject: [PATCH] AIStory: mesage sound, connection, deletion, prompt format --- src/games/ai/assets/message.mp3 | Bin 0 -> 8816 bytes src/games/ai/assets/style.css | 102 +++++++++---- src/games/ai/components/chat.tsx | 3 +- src/games/ai/components/header.tsx | 39 ++++- src/games/ai/components/input.tsx | 6 +- src/games/ai/components/message.tsx | 33 +++-- src/games/ai/const.ts | 216 ++++++++++++++++++++++------ src/games/ai/context.tsx | 45 +++++- src/games/ai/globalConfig.ts | 2 +- src/games/ai/llm.ts | 10 +- src/games/ai/messages.ts | 78 +++++++++- 11 files changed, 428 insertions(+), 106 deletions(-) create mode 100644 src/games/ai/assets/message.mp3 diff --git a/src/games/ai/assets/message.mp3 b/src/games/ai/assets/message.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..673180fafe187b76b755a569bc1f78fa6be03165 GIT binary patch literal 8816 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 F{{nU*wW9z4 literal 0 HcmV?d00001 diff --git a/src/games/ai/assets/style.css b/src/games/ai/assets/style.css index 44f0dcf..cba440e 100644 --- a/src/games/ai/assets/style.css +++ b/src/games/ai/assets/style.css @@ -4,21 +4,35 @@ --color: #DCDCD2; --italicColor: #AFAFAF; --quoteColor: #D4E5FF; + --green: #AFAFAF; + --red: #7F0000; + --green: #007F00; + --shadeColor: rgba(0, 128, 128, 0.3); + + --border: 1px solid var(--color); --emojiFont: "Noto Emoji", sans-serif; --emojiColorFont: "Noto Color Emoji", sans-serif; } -textarea { +textarea, +input { color: var(--color); background-color: var(--backgroundColor); font-size: 1em; font-family: sans-serif; background-color: transparent; - resize: none; appearance: none; outline: none; +} + +input { + border: var(--border); +} + +textarea { border: none; + resize: none; width: 100%; scrollbar-width: thin; scrollbar-color: var(--color) transparent; @@ -48,8 +62,18 @@ body { display: flex; flex-direction: row; height: 36px; - background-color: yellow; width: 100%; + border: var(--border); + + >input { + &.valid { + background-color: var(--green); + } + + &.invalid { + background-color: var(--red); + } + } } >.chat { @@ -62,26 +86,68 @@ body { overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--color) transparent; - border: 1px solid var(--color); + border: var(--border); + border-bottom: none; + border-top: none; >.message { width: 100%; padding: 12px; - >.header { + &.role-user { + background-color: var(--shadeColor); + + :not(.last-user) .content .text { + opacity: 0.5; + } + } + + >.content { + white-space: pre-wrap; + line-height: 1.5; display: flex; flex-direction: row; - justify-content: space-between; - margin-bottom: 6px; + width: 100%; + gap: 8px; - >.name { - font-weight: bold; + >textarea { + background-color: var(--backgroundColorDark); + border: var(--border); + min-height: 100px; + height: unset; + resize: vertical; + line-height: 1.25; + padding: 5px; + border-radius: 3px; + } + + >.text { + flex-grow: 1; + width: 100%; + + >.bold { + font-weight: bold; + } + + >.italic { + font-style: italic; + color: var(--italicColor); + } + + >.quote { + color: var(--quoteColor); + } } >.buttons { + display: flex; + flex-direction: column; + gap: 8px; + >.icon { font-family: var(--emojiFont); font-weight: bold; + font-size: 20px; border: none; background: transparent; padding: 0; @@ -94,22 +160,6 @@ body { } } } - - >.content { - white-space: pre-wrap; - line-height: 1.5; - - >textarea { - background-color: var(--backgroundColorDark); - border: 1px solid var(--italicColor); - min-height: 100px; - height: unset; - resize: vertical; - line-height: 1.25; - padding: 5px; - border-radius: 3px; - } - } } } @@ -119,7 +169,7 @@ body { height: auto; min-height: 48px; width: 100%; - border: 1px solid var(--color); + border: var(--border); } } } \ No newline at end of file diff --git a/src/games/ai/components/chat.tsx b/src/games/ai/components/chat.tsx index 6011f13..2ebc2f2 100644 --- a/src/games/ai/components/chat.tsx +++ b/src/games/ai/components/chat.tsx @@ -9,6 +9,7 @@ export const Chat = () => { const lastMessage = messages.at(-1); const lastMessageSwipe = lastMessage?.swipes[lastMessage.currentSwipe]; const lastMessageContent = lastMessageSwipe?.displayContent ?? lastMessageSwipe.content; + const lastUserId = messages.findLastIndex(m => m.role === 'user'); useEffect(() => { if (chatRef.current) { @@ -22,7 +23,7 @@ export const Chat = () => { return (
{messages.map((m, i) => ( - + ))}
); diff --git a/src/games/ai/components/header.tsx b/src/games/ai/components/header.tsx index 8aa3adb..e6f1ff4 100644 --- a/src/games/ai/components/header.tsx +++ b/src/games/ai/components/header.tsx @@ -1,7 +1,44 @@ +import { useCallback, useContext, useEffect, useState } from "preact/hooks"; +import { GlobalContext } from "../context"; +import { LLM } from "../llm"; + export const Header = () => { + const { connectionUrl, setConnectionUrl } = useContext(GlobalContext); + const [urlValid, setUrlValid] = useState(false); + const [urlEditing, setUrlEditing] = useState(false); + + const handleEditUrl = useCallback((e: InputEvent) => { + if (e.target instanceof HTMLInputElement) { + setConnectionUrl(e.target.value.trim()); + } + }, [setConnectionUrl]); + + const handleFocusUrl = useCallback(() => setUrlEditing(true), []); + + const handleBlurUrl = useCallback(() => { + const regex = /^(?:http(s?):\/\/)?(.*?)\/?$/i + const normalizedConnectionUrl = connectionUrl.replace(regex, 'http$1://$2'); + console.log({ connectionUrl, normalizedConnectionUrl }) + setConnectionUrl(normalizedConnectionUrl); + setUrlEditing(false); + setUrlValid(false); + }, [connectionUrl, setConnectionUrl]); + + useEffect(() => { + if (!urlEditing) { + LLM.getContextLength().then(length => { + setUrlValid(length > 0); + }); + } + }, [connectionUrl, urlEditing]); + return (
- Header +
); } \ No newline at end of file diff --git a/src/games/ai/components/input.tsx b/src/games/ai/components/input.tsx index 7279273..69f121f 100644 --- a/src/games/ai/components/input.tsx +++ b/src/games/ai/components/input.tsx @@ -2,7 +2,7 @@ import { useCallback, useContext } from "preact/hooks"; import { GlobalContext } from "../context"; export const Input = () => { - const { input, setInput, addMessage } = useContext(GlobalContext); + const { input, setInput, addMessage, continueMessage } = useContext(GlobalContext); const handleChange = useCallback((e: Event) => { if (e.target instanceof HTMLTextAreaElement) { @@ -15,6 +15,8 @@ export const Input = () => { if (newInput) { addMessage(newInput, 'user', true); setInput(''); + } else { + continueMessage(); } }, [input]); @@ -28,7 +30,7 @@ export const Input = () => { return (