Lucide icons and banned tokens gui
This commit is contained in:
parent
9726472a38
commit
6c8857478c
3
bun.lock
3
bun.lock
|
|
@ -14,6 +14,7 @@
|
||||||
"ace-builds": "1.36.3",
|
"ace-builds": "1.36.3",
|
||||||
"clsx": "2.1.1",
|
"clsx": "2.1.1",
|
||||||
"delay": "6.0.0",
|
"delay": "6.0.0",
|
||||||
|
"lucide-preact": "^0.577.0",
|
||||||
"preact": "10.22.0",
|
"preact": "10.22.0",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
@ -116,6 +117,8 @@
|
||||||
|
|
||||||
"lower-case": ["lower-case@1.1.4", "", {}, "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA=="],
|
"lower-case": ["lower-case@1.1.4", "", {}, "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA=="],
|
||||||
|
|
||||||
|
"lucide-preact": ["lucide-preact@0.577.0", "", { "peerDependencies": { "preact": "^10.27.2" } }, "sha512-fCY59YQ2OMYWqE1V7k8HwfXyiBMHAfTI1roCOasdc+Cekya7BIObSJ/cil+tVMSbU6siv4uZlaz5twAGmkYqIQ=="],
|
||||||
|
|
||||||
"mute-stream": ["mute-stream@1.0.0", "", {}, "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA=="],
|
"mute-stream": ["mute-stream@1.0.0", "", {}, "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA=="],
|
||||||
|
|
||||||
"no-case": ["no-case@2.3.2", "", { "dependencies": { "lower-case": "^1.1.1" } }, "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ=="],
|
"no-case": ["no-case@2.3.2", "", { "dependencies": { "lower-case": "^1.1.1" } }, "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ=="],
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,11 @@
|
||||||
"ace-builds": "1.36.3",
|
"ace-builds": "1.36.3",
|
||||||
"clsx": "2.1.1",
|
"clsx": "2.1.1",
|
||||||
"delay": "6.0.0",
|
"delay": "6.0.0",
|
||||||
|
"lucide-preact": "0.577.0",
|
||||||
"preact": "10.22.0"
|
"preact": "10.22.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "^1.3.10",
|
"@types/bun": "latest",
|
||||||
"@types/html-minifier": "4.0.5",
|
"@types/html-minifier": "4.0.5",
|
||||||
"@types/inquirer": "9.0.7",
|
"@types/inquirer": "9.0.7",
|
||||||
"@types/web-bluetooth": "0.0.21",
|
"@types/web-bluetooth": "0.0.21",
|
||||||
|
|
|
||||||
|
|
@ -114,3 +114,49 @@
|
||||||
background: var(--accent);
|
background: var(--accent);
|
||||||
color: var(--accent-text);
|
color: var(--accent-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.inputRow {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inputRow .input {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
height: 1px;
|
||||||
|
background: var(--border);
|
||||||
|
margin: 16px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tokenList {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tokenItem {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
background: var(--bg-active);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 4px;
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tokenRemoveButton {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0 2px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.emptyText {
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,27 @@
|
||||||
:root {
|
:root {
|
||||||
/* Monokai-inspired palette */
|
/* Monokai-inspired palette */
|
||||||
--bg: #272822;
|
--bg: #272822;
|
||||||
--bg-panel: #1e1f1a;
|
--bg-panel: #1e1f1a;
|
||||||
--bg-hover: #3e3d32;
|
--bg-hover: #3e3d32;
|
||||||
--bg-active: #49483e;
|
--bg-active: #49483e;
|
||||||
--border: #3e3d32;
|
--border: #3e3d32;
|
||||||
--accent: #f92672;
|
--accent: #f92672;
|
||||||
--accent-alt: #a6e22e;
|
--accent-alt: #a6e22e;
|
||||||
--text: #f8f8f2;
|
--text: #f8f8f2;
|
||||||
--text-muted: #75715e;
|
--text-muted: #75715e;
|
||||||
--text-dim: #cfcfc2;
|
--text-dim: #cfcfc2;
|
||||||
--yellow: #e6db74;
|
--yellow: #e6db74;
|
||||||
--orange: #fd971f;
|
--orange: #fd971f;
|
||||||
--blue: #66d9ef;
|
--blue: #66d9ef;
|
||||||
--purple: #ae81ff;
|
--purple: #ae81ff;
|
||||||
|
|
||||||
--radius: 4px;
|
--radius: 4px;
|
||||||
--transition: 0.15s ease;
|
--transition: 0.15s ease;
|
||||||
|
|
||||||
--textColor: #DCDCD2;
|
--textColor: #DCDCD2;
|
||||||
--italicColor: #AFAFAF;
|
--italicColor: #AFAFAF;
|
||||||
--quoteColor: #D4E5FF;
|
--quoteColor: #D4E5FF;
|
||||||
--codeBg: #49483e;
|
--codeBg: #49483e;
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
|
|
@ -51,6 +51,10 @@ button {
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
transition: color var(--transition), background var(--transition);
|
transition: color var(--transition), background var(--transition);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
import clsx from "clsx";
|
||||||
|
|
||||||
|
import { useInputState } from "@common/hooks/useInputState";
|
||||||
|
|
||||||
|
import { useAppState } from "../contexts/state";
|
||||||
|
import styles from "../assets/settings-modal.module.css";
|
||||||
|
import { X } from "lucide-preact";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
onClose: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const BannedTokensModal = ({ onClose }: Props) => {
|
||||||
|
const { bannedTokens, dispatch } = useAppState();
|
||||||
|
const [inputValue, setInputValue] = useInputState();
|
||||||
|
|
||||||
|
const handleAdd = () => {
|
||||||
|
const trimmed = inputValue.trim();
|
||||||
|
if (trimmed && !bannedTokens.includes(trimmed)) {
|
||||||
|
dispatch({
|
||||||
|
type: "SET_BANNED_TOKENS",
|
||||||
|
tokens: [...bannedTokens, trimmed],
|
||||||
|
});
|
||||||
|
setInputValue("");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRemove = (token: string) => {
|
||||||
|
dispatch({
|
||||||
|
type: "SET_BANNED_TOKENS",
|
||||||
|
tokens: bannedTokens.filter((t) => t !== token),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyDown = (e: KeyboardEvent) => {
|
||||||
|
if (e.key === "Enter") {
|
||||||
|
handleAdd();
|
||||||
|
} else if (e.key === "Escape") {
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const sortedTokens = [...bannedTokens].sort((a, b) =>
|
||||||
|
a.trim().toLowerCase().localeCompare(b.trim().toLowerCase())
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class={styles.overlay} onClick={onClose}>
|
||||||
|
<div class={styles.modal} onClick={(e) => e.stopPropagation()}>
|
||||||
|
<div class={styles.header}>
|
||||||
|
<h2 class={styles.title}>Banned Tokens</h2>
|
||||||
|
<button class={styles.closeButton} onClick={onClose}>
|
||||||
|
<X size={20} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class={styles.content}>
|
||||||
|
<div class={styles.inputRow}>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={inputValue}
|
||||||
|
onInput={setInputValue}
|
||||||
|
onKeyDown={handleKeyDown}
|
||||||
|
placeholder="Token to ban"
|
||||||
|
class={styles.input}
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
<button onClick={handleAdd} class={clsx(styles.button, styles.buttonPrimary)}>
|
||||||
|
Add
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class={styles.divider} />
|
||||||
|
<div class={styles.tokenList}>
|
||||||
|
{sortedTokens.length === 0 ? (
|
||||||
|
<p class={styles.emptyText}>No banned tokens</p>
|
||||||
|
) : (
|
||||||
|
sortedTokens.map((token) => (
|
||||||
|
<div key={token} class={styles.tokenItem}>
|
||||||
|
<span>{token}</span>
|
||||||
|
<button
|
||||||
|
onClick={() => handleRemove(token)}
|
||||||
|
class={styles.tokenRemoveButton}
|
||||||
|
>
|
||||||
|
<X size={12} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class={styles.footer}>
|
||||||
|
<button onClick={onClose} class={clsx(styles.button, styles.buttonSecondary)}>
|
||||||
|
Done
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { Sidebar } from "./sidebar";
|
import { Sidebar } from "./sidebar";
|
||||||
import { SettingsModal } from "./settings-modal";
|
import { SettingsModal } from "./settings-modal";
|
||||||
|
import { BannedTokensModal } from "./banned-tokens-modal";
|
||||||
import { useAppState } from "../contexts/state";
|
import { useAppState } from "../contexts/state";
|
||||||
import { useBool } from "@common/hooks/useBool";
|
import { useBool } from "@common/hooks/useBool";
|
||||||
import type { Story } from "../contexts/state";
|
import type { Story } from "../contexts/state";
|
||||||
import styles from '../assets/menu-sidebar.module.css';
|
import styles from '../assets/menu-sidebar.module.css';
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
|
import { Pencil, X, Plus, Settings, Ban } from "lucide-preact";
|
||||||
|
|
||||||
// ─── Story Item ───────────────────────────────────────────────────────────────
|
// ─── Story Item ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
@ -66,10 +68,10 @@ const StoryItem = ({ story, active, onSelect, onRename, onDelete }: StoryItemPro
|
||||||
</button>
|
</button>
|
||||||
<div class={styles.actions}>
|
<div class={styles.actions}>
|
||||||
<button class={styles.actionButton} onClick={() => setIsEditing(true)} title="Rename">
|
<button class={styles.actionButton} onClick={() => setIsEditing(true)} title="Rename">
|
||||||
✎
|
<Pencil size={14} />
|
||||||
</button>
|
</button>
|
||||||
<button class={styles.actionButton} onClick={onDelete} title="Delete">
|
<button class={styles.actionButton} onClick={onDelete} title="Delete">
|
||||||
×
|
<X size={14} />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -81,6 +83,7 @@ const StoryItem = ({ story, active, onSelect, onRename, onDelete }: StoryItemPro
|
||||||
export const MenuSidebar = () => {
|
export const MenuSidebar = () => {
|
||||||
const { stories, currentStory, dispatch } = useAppState();
|
const { stories, currentStory, dispatch } = useAppState();
|
||||||
const isSettingsOpen = useBool(false);
|
const isSettingsOpen = useBool(false);
|
||||||
|
const isBannedTokensOpen = useBool(false);
|
||||||
|
|
||||||
const handleCreate = () => {
|
const handleCreate = () => {
|
||||||
dispatch({ type: 'CREATE_STORY', title: 'New Story' });
|
dispatch({ type: 'CREATE_STORY', title: 'New Story' });
|
||||||
|
|
@ -106,7 +109,7 @@ export const MenuSidebar = () => {
|
||||||
<Sidebar side="left">
|
<Sidebar side="left">
|
||||||
<div class={styles.menu}>
|
<div class={styles.menu}>
|
||||||
<button class={styles.newButton} onClick={handleCreate}>
|
<button class={styles.newButton} onClick={handleCreate}>
|
||||||
+ New Story
|
<Plus size={16} /> New Story
|
||||||
</button>
|
</button>
|
||||||
<div class={styles.list}>
|
<div class={styles.list}>
|
||||||
{stories.map(story => (
|
{stories.map(story => (
|
||||||
|
|
@ -121,11 +124,17 @@ export const MenuSidebar = () => {
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div class={styles.bottomButtons}>
|
<div class={styles.bottomButtons}>
|
||||||
|
<button class={styles.settingsButton} onClick={isBannedTokensOpen.toggle}>
|
||||||
|
<Ban size={16} /> Banned Tokens
|
||||||
|
</button>
|
||||||
<button class={styles.settingsButton} onClick={isSettingsOpen.toggle}>
|
<button class={styles.settingsButton} onClick={isSettingsOpen.toggle}>
|
||||||
⚙ Settings
|
<Settings size={16} /> Settings
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{isBannedTokensOpen.value && (
|
||||||
|
<BannedTokensModal onClose={isBannedTokensOpen.toggle} />
|
||||||
|
)}
|
||||||
{isSettingsOpen.value && (
|
{isSettingsOpen.value && (
|
||||||
<SettingsModal onClose={isSettingsOpen.toggle} />
|
<SettingsModal onClose={isSettingsOpen.toggle} />
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import { useUpdate } from "@common/hooks/useUpdate";
|
||||||
import { useAppState } from "../contexts/state";
|
import { useAppState } from "../contexts/state";
|
||||||
import LLM from "../utils/llm";
|
import LLM from "../utils/llm";
|
||||||
import styles from "../assets/settings-modal.module.css";
|
import styles from "../assets/settings-modal.module.css";
|
||||||
|
import { X } from "lucide-preact";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
|
|
@ -100,7 +101,7 @@ export const SettingsModal = ({ onClose }: Props) => {
|
||||||
<div class={styles.header}>
|
<div class={styles.header}>
|
||||||
<h2 class={styles.title}>Settings</h2>
|
<h2 class={styles.title}>Settings</h2>
|
||||||
<button class={styles.closeButton} onClick={onClose}>
|
<button class={styles.closeButton} onClick={onClose}>
|
||||||
×
|
<X size={20} />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class={styles.content}>
|
<div class={styles.content}>
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import clsx from "clsx";
|
||||||
import type { ComponentChildren } from "preact";
|
import type { ComponentChildren } from "preact";
|
||||||
import { useBool } from "@common/hooks/useBool";
|
import { useBool } from "@common/hooks/useBool";
|
||||||
import styles from '../assets/sidebar.module.css';
|
import styles from '../assets/sidebar.module.css';
|
||||||
|
import { PanelLeftClose, PanelLeftOpen, PanelRightClose, PanelRightOpen } from "lucide-preact";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
side: 'left' | 'right';
|
side: 'left' | 'right';
|
||||||
|
|
@ -17,10 +18,15 @@ export const Sidebar = ({ side, children, onCollapseChanged }: Props) => {
|
||||||
onCollapseChanged?.(!open.value);
|
onCollapseChanged?.(!open.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isLeft = side === 'left';
|
||||||
|
const IconComponent = isLeft
|
||||||
|
? (open.value ? PanelLeftClose : PanelLeftOpen)
|
||||||
|
: (open.value ? PanelRightClose : PanelRightOpen);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={clsx(styles.sidebar, open.value ? styles.open : styles.closed)} data-side={side}>
|
<div class={clsx(styles.sidebar, open.value ? styles.open : styles.closed)} data-side={side}>
|
||||||
<button class={styles.toggle} onClick={handleToggle}>
|
<button class={styles.toggle} onClick={handleToggle}>
|
||||||
{side === 'left' ? (open.value ? '◀' : '▶') : (open.value ? '▶' : '◀')}
|
<IconComponent size={16} />
|
||||||
</button>
|
</button>
|
||||||
{open.value && (
|
{open.value && (
|
||||||
<div class={styles.content}>
|
<div class={styles.content}>
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ interface IState {
|
||||||
connection: LLM.Connection | null;
|
connection: LLM.Connection | null;
|
||||||
model: LLM.ModelInfo | null;
|
model: LLM.ModelInfo | null;
|
||||||
enableThinking: boolean;
|
enableThinking: boolean;
|
||||||
|
bannedTokens: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Actions ─────────────────────────────────────────────────────────────────
|
// ─── Actions ─────────────────────────────────────────────────────────────────
|
||||||
|
|
@ -45,7 +46,8 @@ type Action =
|
||||||
| { type: 'CLEAR_CHAT'; storyId: string }
|
| { type: 'CLEAR_CHAT'; storyId: string }
|
||||||
| { type: 'SET_CONNECTION'; connection: LLM.Connection | null }
|
| { type: 'SET_CONNECTION'; connection: LLM.Connection | null }
|
||||||
| { type: 'SET_MODEL'; model: LLM.ModelInfo | null }
|
| { type: 'SET_MODEL'; model: LLM.ModelInfo | null }
|
||||||
| { type: 'SET_ENABLE_THINKING'; enable: boolean };
|
| { type: 'SET_ENABLE_THINKING'; enable: boolean }
|
||||||
|
| { type: 'SET_BANNED_TOKENS'; tokens: string[] };
|
||||||
|
|
||||||
// ─── Initial State ───────────────────────────────────────────────────────────
|
// ─── Initial State ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
@ -55,6 +57,7 @@ const DEFAULT_STATE: IState = {
|
||||||
connection: null,
|
connection: null,
|
||||||
model: null,
|
model: null,
|
||||||
enableThinking: false,
|
enableThinking: false,
|
||||||
|
bannedTokens: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
// ─── Reducer ─────────────────────────────────────────────────────────────────
|
// ─── Reducer ─────────────────────────────────────────────────────────────────
|
||||||
|
|
@ -166,6 +169,12 @@ function reducer(state: IState, action: Action): IState {
|
||||||
enableThinking: action.enable,
|
enableThinking: action.enable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
case 'SET_BANNED_TOKENS': {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
bannedTokens: action.tokens,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -177,6 +186,7 @@ export interface AppState {
|
||||||
connection: LLM.Connection | null;
|
connection: LLM.Connection | null;
|
||||||
model: LLM.ModelInfo | null;
|
model: LLM.ModelInfo | null;
|
||||||
enableThinking: boolean;
|
enableThinking: boolean;
|
||||||
|
bannedTokens: string[];
|
||||||
dispatch: (action: Action) => void;
|
dispatch: (action: Action) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -195,6 +205,7 @@ export const StateContextProvider = ({ children }: { children?: any }) => {
|
||||||
connection: state.connection,
|
connection: state.connection,
|
||||||
model: state.model,
|
model: state.model,
|
||||||
enableThinking: state.enableThinking,
|
enableThinking: state.enableThinking,
|
||||||
|
bannedTokens: state.bannedTokens ?? [],
|
||||||
dispatch,
|
dispatch,
|
||||||
}), [state]);
|
}), [state]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ namespace Prompt {
|
||||||
model: model.id,
|
model: model.id,
|
||||||
messages,
|
messages,
|
||||||
tools: Tools.getTools(),
|
tools: Tools.getTools(),
|
||||||
// TODO banned_tokens
|
banned_tokens: state.bannedTokens,
|
||||||
enable_thinking: enableThinking,
|
enable_thinking: enableThinking,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue