1
0
Fork 0
tsgames/src/games/ai-story/components/header/header.tsx

140 lines
6.2 KiB
TypeScript

import { useCallback, useContext, useMemo } from "preact/hooks";
import { useBool } from "@common/hooks/useBool";
import { Modal } from "@common/components/modal/Modal";
import { StateContext } from "../../contexts/state";
import { LLMContext } from "../../contexts/llm";
import { MiniChat } from "../minichat/minichat";
import { AutoTextarea } from "../autoTextarea";
import { Ace } from "../ace";
import { ConnectionEditor } from "./connectionEditor";
import styles from './header.module.css';
export const Header = () => {
const { contextLength, promptTokens, modelName, spentKudos } = useContext(LLMContext);
const {
messages, connection, systemPrompt, lore, userPrompt, bannedWords, summarizePrompt, summaryEnabled, totalSpentKudos,
setSystemPrompt, setLore, setUserPrompt, addSwipe, setBannedWords, setInstruct, setSummarizePrompt, setSummaryEnabled, setConnection,
} = useContext(StateContext);
const connectionsOpen = useBool();
const loreOpen = useBool();
const promptsOpen = useBool();
const genparamsOpen = useBool();
const assistantOpen = useBool();
const isOnline = useMemo(() => contextLength > 0, [contextLength]);
const bannedWordsInput = useMemo(() => bannedWords.join('\n'), [bannedWords]);
const handleAssistantAddSwipe = useCallback((answer: string) => {
const index = messages.findLastIndex(m => m.role === 'assistant');
addSwipe(index, answer);
assistantOpen.setFalse();
}, [addSwipe, messages]);
const handleSetBannedWords = useCallback((e: Event) => {
if (e.target instanceof HTMLTextAreaElement) {
const words = e.target.value.split('\n');
setBannedWords(words);
}
}, [setBannedWords]);
const handleBlurBannedWords = useCallback((e: Event) => {
if (e.target instanceof HTMLTextAreaElement) {
const words = e.target.value.toLowerCase().split('\n').sort();
setBannedWords(words);
}
}, [setBannedWords]);
const handleSetSummaryEnabled = useCallback((e: Event) => {
if (e.target instanceof HTMLInputElement) {
setSummaryEnabled(e.target.checked);
}
}, [setSummaryEnabled]);
return (
<div class={styles.header}>
<div class={styles.inputs}>
<div class={styles.buttons}>
<button class={`icon ${isOnline ? styles.online: styles.offline}`} onClick={connectionsOpen.setTrue} title='Connection settings'>
🔌
</button>
</div>
<div class={styles.info}>
<span>{modelName}</span>
<span>📃{promptTokens}/{contextLength}</span>
<span>💲{spentKudos}</span>
<span>💰{totalSpentKudos}</span>
</div>
</div>
<div class={styles.buttons}>
<button class='icon color' title='Edit lore' onClick={loreOpen.setTrue}>
🌍
</button>
<button class='icon color' title='Generation parameters' onClick={genparamsOpen.setTrue}>
</button>
<button class='icon color' title='Edit prompts' onClick={promptsOpen.setTrue}>
📃
</button>
</div>
<div class={styles.buttons}>
<button class='icon' onClick={assistantOpen.setTrue} title='Ask assistant'>
</button>
</div>
<Modal open={connectionsOpen.value} onClose={connectionsOpen.setFalse}>
<h3 class={styles.modalTitle}>Connection settings</h3>
<ConnectionEditor connection={connection} setConnection={setConnection} />
</Modal>
<Modal open={loreOpen.value} onClose={loreOpen.setFalse}>
<h3 class={styles.modalTitle}>Lore Editor</h3>
<AutoTextarea
value={lore}
onInput={setLore}
placeholder="Describe your world, for example: World of Awoo has big mountains and wide rivers."
/>
</Modal>
<Modal open={genparamsOpen.value} onClose={genparamsOpen.setFalse}>
<h3 class={styles.modalTitle}>Generation Parameters</h3>
<div className={styles.scrollPane}>
<h4 class={styles.modalTitle}>Banned phrases</h4>
<AutoTextarea
placeholder="Each phrase on separate line"
value={bannedWordsInput}
onInput={handleSetBannedWords}
onBlur={handleBlurBannedWords}
class={styles.template}
/>
</div>
</Modal>
<Modal open={promptsOpen.value} onClose={promptsOpen.setFalse}>
<h3 class={styles.modalTitle}>Prompts Editor</h3>
<div className={styles.scrollPane}>
<h4 class={styles.modalTitle}>System prompt</h4>
<AutoTextarea value={systemPrompt} onInput={setSystemPrompt} />
<hr />
<h4 class={styles.modalTitle}>User prompt template</h4>
<Ace value={userPrompt} onInput={setUserPrompt} />
<hr />
<h4 class={styles.modalTitle}>Summary template</h4>
<Ace value={summarizePrompt} onInput={setSummarizePrompt} />
<label>
<input type='checkbox' checked={summaryEnabled} onChange={handleSetSummaryEnabled} />
&nbsp;Enable summarization
</label>
<hr />
<h4 class={styles.modalTitle}>Instruct template</h4>
<Ace value={connection.instruct} onInput={setInstruct} />
</div>
</Modal>
<MiniChat
history={messages}
open={assistantOpen.value}
onClose={assistantOpen.setFalse}
buttons={{ 'Add swipe': handleAssistantAddSwipe }}
/>
</div>
);
}