use @ import alias
All checks were successful
Build static content / build (push) Successful in 10m51s
All checks were successful
Build static content / build (push) Successful in 10m51s
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
import { ChatStore } from "./app";
|
import { ChatStore } from "@/app";
|
||||||
import { MessageDetail } from "./chatgpt";
|
import { MessageDetail } from "@/chatgpt";
|
||||||
import { Tr } from "./translate";
|
import { Tr } from "@/translate";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
chatStore: ChatStore;
|
chatStore: ChatStore;
|
||||||
|
|||||||
44
src/app.tsx
44
src/app.tsx
@@ -1,14 +1,14 @@
|
|||||||
import { IDBPDatabase, openDB } from "idb";
|
import { IDBPDatabase, openDB } from "idb";
|
||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
import "./global.css";
|
import "@/global.css";
|
||||||
|
|
||||||
import { calculate_token_length, Logprobs, Message } from "./chatgpt";
|
import { calculate_token_length, Logprobs, Message } from "@/chatgpt";
|
||||||
import getDefaultParams from "./getDefaultParam";
|
import getDefaultParams from "@/getDefaultParam";
|
||||||
import ChatBOX from "./chatbox";
|
import ChatBOX from "@/chatbox";
|
||||||
import models, { defaultModel } from "./models";
|
import models, { defaultModel } from "@/models";
|
||||||
import { Tr, langCodeContext, LANG_OPTIONS } from "./translate";
|
import { Tr, langCodeContext, LANG_OPTIONS } from "@/translate";
|
||||||
|
|
||||||
import CHATGPT_API_WEB_VERSION from "./CHATGPT_API_WEB_VERSION";
|
import CHATGPT_API_WEB_VERSION from "@/CHATGPT_API_WEB_VERSION";
|
||||||
|
|
||||||
export interface ChatStoreMessage extends Message {
|
export interface ChatStoreMessage extends Message {
|
||||||
hide: boolean;
|
hide: boolean;
|
||||||
@@ -88,7 +88,7 @@ export const newChatStore = (
|
|||||||
image_gen_api = "https://api.openai.com/v1/images/generations",
|
image_gen_api = "https://api.openai.com/v1/images/generations",
|
||||||
image_gen_key = "",
|
image_gen_key = "",
|
||||||
json_mode = false,
|
json_mode = false,
|
||||||
logprobs = false
|
logprobs = false,
|
||||||
): ChatStore => {
|
): ChatStore => {
|
||||||
return {
|
return {
|
||||||
chatgpt_api_web_version: CHATGPT_API_WEB_VERSION,
|
chatgpt_api_web_version: CHATGPT_API_WEB_VERSION,
|
||||||
@@ -100,7 +100,7 @@ export const newChatStore = (
|
|||||||
totalTokens: 0,
|
totalTokens: 0,
|
||||||
maxTokens: getDefaultParams(
|
maxTokens: getDefaultParams(
|
||||||
"max",
|
"max",
|
||||||
models[getDefaultParams("model", model)]?.maxToken ?? 2048
|
models[getDefaultParams("model", model)]?.maxToken ?? 2048,
|
||||||
),
|
),
|
||||||
maxGenTokens: 2048,
|
maxGenTokens: 2048,
|
||||||
maxGenTokens_enabled: false,
|
maxGenTokens_enabled: false,
|
||||||
@@ -152,7 +152,7 @@ export function addTotalCost(cost: number) {
|
|||||||
|
|
||||||
export function getTotalCost(): number {
|
export function getTotalCost(): number {
|
||||||
let totalCost = parseFloat(
|
let totalCost = parseFloat(
|
||||||
localStorage.getItem(STORAGE_NAME_TOTALCOST) ?? "0"
|
localStorage.getItem(STORAGE_NAME_TOTALCOST) ?? "0",
|
||||||
);
|
);
|
||||||
return totalCost;
|
return totalCost;
|
||||||
}
|
}
|
||||||
@@ -190,7 +190,7 @@ export function BuildFiledForSearch(chatStore: ChatStore): string[] {
|
|||||||
export function App() {
|
export function App() {
|
||||||
// init selected index
|
// init selected index
|
||||||
const [selectedChatIndex, setSelectedChatIndex] = useState(
|
const [selectedChatIndex, setSelectedChatIndex] = useState(
|
||||||
parseInt(localStorage.getItem(STORAGE_NAME_SELECTED) ?? "1")
|
parseInt(localStorage.getItem(STORAGE_NAME_SELECTED) ?? "1"),
|
||||||
);
|
);
|
||||||
console.log("selectedChatIndex", selectedChatIndex);
|
console.log("selectedChatIndex", selectedChatIndex);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -207,7 +207,7 @@ export function App() {
|
|||||||
|
|
||||||
// copy from localStorage to indexedDB
|
// copy from localStorage to indexedDB
|
||||||
const allChatStoreIndexes: number[] = JSON.parse(
|
const allChatStoreIndexes: number[] = JSON.parse(
|
||||||
localStorage.getItem(STORAGE_NAME_INDEXES) ?? "[]"
|
localStorage.getItem(STORAGE_NAME_INDEXES) ?? "[]",
|
||||||
);
|
);
|
||||||
let keyCount = 0;
|
let keyCount = 0;
|
||||||
for (const i of allChatStoreIndexes) {
|
for (const i of allChatStoreIndexes) {
|
||||||
@@ -221,7 +221,7 @@ export function App() {
|
|||||||
setSelectedChatIndex(keyCount);
|
setSelectedChatIndex(keyCount);
|
||||||
if (keyCount > 0) {
|
if (keyCount > 0) {
|
||||||
alert(
|
alert(
|
||||||
"v2.0.0 Update: Imported chat history from localStorage to indexedDB. 🎉"
|
"v2.0.0 Update: Imported chat history from localStorage to indexedDB. 🎉",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -229,7 +229,7 @@ export function App() {
|
|||||||
if (oldVersion < 11) {
|
if (oldVersion < 11) {
|
||||||
if (oldVersion < 11 && oldVersion >= 1) {
|
if (oldVersion < 11 && oldVersion >= 1) {
|
||||||
alert(
|
alert(
|
||||||
"Start upgrading storage, just a sec... (Click OK to continue)"
|
"Start upgrading storage, just a sec... (Click OK to continue)",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
@@ -247,7 +247,7 @@ export function App() {
|
|||||||
{
|
{
|
||||||
multiEntry: true,
|
multiEntry: true,
|
||||||
unique: false,
|
unique: false,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// iter through all chatStore and update contents_for_index
|
// iter through all chatStore and update contents_for_index
|
||||||
@@ -294,7 +294,7 @@ export function App() {
|
|||||||
const max = chatStore.maxTokens - chatStore.tokenMargin;
|
const max = chatStore.maxTokens - chatStore.tokenMargin;
|
||||||
let sum = 0;
|
let sum = 0;
|
||||||
chatStore.postBeginIndex = chatStore.history.filter(
|
chatStore.postBeginIndex = chatStore.history.filter(
|
||||||
({ hide }) => !hide
|
({ hide }) => !hide,
|
||||||
).length;
|
).length;
|
||||||
for (const msg of chatStore.history
|
for (const msg of chatStore.history
|
||||||
.filter(({ hide }) => !hide)
|
.filter(({ hide }) => !hide)
|
||||||
@@ -309,7 +309,7 @@ export function App() {
|
|||||||
|
|
||||||
// manually estimate token
|
// manually estimate token
|
||||||
chatStore.totalTokens = calculate_token_length(
|
chatStore.totalTokens = calculate_token_length(
|
||||||
chatStore.systemMessageContent
|
chatStore.systemMessageContent,
|
||||||
);
|
);
|
||||||
for (const msg of chatStore.history
|
for (const msg of chatStore.history
|
||||||
.filter(({ hide }) => !hide)
|
.filter(({ hide }) => !hide)
|
||||||
@@ -331,7 +331,7 @@ export function App() {
|
|||||||
|
|
||||||
// all chat store indexes
|
// all chat store indexes
|
||||||
const [allChatStoreIndexes, setAllChatStoreIndexes] = useState<IDBValidKey>(
|
const [allChatStoreIndexes, setAllChatStoreIndexes] = useState<IDBValidKey>(
|
||||||
[]
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleNewChatStoreWithOldOne = async (chatStore: ChatStore) => {
|
const handleNewChatStoreWithOldOne = async (chatStore: ChatStore) => {
|
||||||
@@ -358,8 +358,8 @@ export function App() {
|
|||||||
chatStore.image_gen_api,
|
chatStore.image_gen_api,
|
||||||
chatStore.image_gen_key,
|
chatStore.image_gen_key,
|
||||||
chatStore.json_mode,
|
chatStore.json_mode,
|
||||||
false // logprobs default to false
|
false, // logprobs default to false
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
setSelectedChatIndex(newKey as number);
|
setSelectedChatIndex(newKey as number);
|
||||||
setAllChatStoreIndexes(await (await db).getAllKeys(STORAGE_NAME));
|
setAllChatStoreIndexes(await (await db).getAllKeys(STORAGE_NAME));
|
||||||
@@ -445,7 +445,7 @@ export function App() {
|
|||||||
return;
|
return;
|
||||||
console.log(
|
console.log(
|
||||||
"remove item",
|
"remove item",
|
||||||
`${STORAGE_NAME}-${selectedChatIndex}`
|
`${STORAGE_NAME}-${selectedChatIndex}`,
|
||||||
);
|
);
|
||||||
(await db).delete(STORAGE_NAME, selectedChatIndex);
|
(await db).delete(STORAGE_NAME, selectedChatIndex);
|
||||||
const newAllChatStoreIndexes = await (
|
const newAllChatStoreIndexes = await (
|
||||||
@@ -473,7 +473,7 @@ export function App() {
|
|||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
if (
|
if (
|
||||||
!confirm(
|
!confirm(
|
||||||
"Are you sure you want to delete **ALL** chat history?"
|
"Are you sure you want to delete **ALL** chat history?",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
|||||||
126
src/chatbox.tsx
126
src/chatbox.tsx
@@ -1,7 +1,19 @@
|
|||||||
import { Tr, langCodeContext, LANG_OPTIONS } from "./translate";
|
import {
|
||||||
|
MagnifyingGlassIcon,
|
||||||
|
CubeIcon,
|
||||||
|
BanknotesIcon,
|
||||||
|
DocumentTextIcon,
|
||||||
|
ChatBubbleLeftEllipsisIcon,
|
||||||
|
ScissorsIcon,
|
||||||
|
SwatchIcon,
|
||||||
|
SparklesIcon,
|
||||||
|
} from "@heroicons/react/24/outline";
|
||||||
|
|
||||||
|
import { IDBPDatabase } from "idb";
|
||||||
import structuredClone from "@ungap/structured-clone";
|
import structuredClone from "@ungap/structured-clone";
|
||||||
import { createRef } from "preact";
|
import { createRef } from "preact";
|
||||||
import { StateUpdater, useEffect, useState, Dispatch } from "preact/hooks";
|
import { StateUpdater, useEffect, useState, Dispatch } from "preact/hooks";
|
||||||
|
import { Tr, langCodeContext, LANG_OPTIONS } from "@/translate";
|
||||||
import {
|
import {
|
||||||
ChatStore,
|
ChatStore,
|
||||||
ChatStoreMessage,
|
ChatStoreMessage,
|
||||||
@@ -15,7 +27,7 @@ import {
|
|||||||
TemplateTools,
|
TemplateTools,
|
||||||
addTotalCost,
|
addTotalCost,
|
||||||
getTotalCost,
|
getTotalCost,
|
||||||
} from "./app";
|
} from "@/app";
|
||||||
import ChatGPT, {
|
import ChatGPT, {
|
||||||
calculate_token_length,
|
calculate_token_length,
|
||||||
ChunkMessage,
|
ChunkMessage,
|
||||||
@@ -24,28 +36,16 @@ import ChatGPT, {
|
|||||||
MessageDetail,
|
MessageDetail,
|
||||||
ToolCall,
|
ToolCall,
|
||||||
Logprobs,
|
Logprobs,
|
||||||
} from "./chatgpt";
|
} from "@/chatgpt";
|
||||||
import Message from "./message";
|
import Message from "@/message";
|
||||||
import models from "./models";
|
import models from "@/models";
|
||||||
import Settings from "./settings";
|
import Settings from "@/settings";
|
||||||
import getDefaultParams from "./getDefaultParam";
|
import getDefaultParams from "@/getDefaultParam";
|
||||||
import { AddImage } from "./addImage";
|
import { AddImage } from "@/addImage";
|
||||||
import { ListAPIs } from "./listAPIs";
|
import { ListAPIs } from "@/listAPIs";
|
||||||
import { ListToolsTempaltes } from "./listToolsTemplates";
|
import { ListToolsTempaltes } from "@/listToolsTemplates";
|
||||||
import { autoHeight } from "./textarea";
|
import { autoHeight } from "@/textarea";
|
||||||
import Search from "./search";
|
import Search from "@/search";
|
||||||
import { IDBPDatabase } from "idb";
|
|
||||||
import {
|
|
||||||
MagnifyingGlassIcon,
|
|
||||||
CubeIcon,
|
|
||||||
BanknotesIcon,
|
|
||||||
DocumentTextIcon,
|
|
||||||
ChatBubbleLeftEllipsisIcon,
|
|
||||||
ScissorsIcon,
|
|
||||||
SwatchIcon,
|
|
||||||
SparklesIcon,
|
|
||||||
} from "@heroicons/react/24/outline";
|
|
||||||
|
|
||||||
export interface TemplateChatStore extends ChatStore {
|
export interface TemplateChatStore extends ChatStore {
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
@@ -96,7 +96,7 @@ export default function ChatBOX(props: {
|
|||||||
const update_total_tokens = () => {
|
const update_total_tokens = () => {
|
||||||
// manually estimate token
|
// manually estimate token
|
||||||
client.total_tokens = calculate_token_length(
|
client.total_tokens = calculate_token_length(
|
||||||
chatStore.systemMessageContent
|
chatStore.systemMessageContent,
|
||||||
);
|
);
|
||||||
for (const msg of chatStore.history
|
for (const msg of chatStore.history
|
||||||
.filter(({ hide }) => !hide)
|
.filter(({ hide }) => !hide)
|
||||||
@@ -152,7 +152,7 @@ export default function ChatBOX(props: {
|
|||||||
|
|
||||||
// update tool call arguments
|
// update tool call arguments
|
||||||
const tool = allChunkTool.find(
|
const tool = allChunkTool.find(
|
||||||
(tool) => tool.index === tool_call.index
|
(tool) => tool.index === tool_call.index,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!tool) {
|
if (!tool) {
|
||||||
@@ -167,7 +167,7 @@ export default function ChatBOX(props: {
|
|||||||
allChunkMessage.join("") +
|
allChunkMessage.join("") +
|
||||||
allChunkTool.map((tool) => {
|
allChunkTool.map((tool) => {
|
||||||
return `Tool Call ID: ${tool.id}\nType: ${tool.type}\nFunction: ${tool.function.name}\nArguments: ${tool.function.arguments}`;
|
return `Tool Call ID: ${tool.id}\nType: ${tool.type}\nFunction: ${tool.function.name}\nArguments: ${tool.function.arguments}`;
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
setShowGenerating(false);
|
setShowGenerating(false);
|
||||||
@@ -305,7 +305,7 @@ export default function ChatBOX(props: {
|
|||||||
setShowGenerating(true);
|
setShowGenerating(true);
|
||||||
const response = await client._fetch(
|
const response = await client._fetch(
|
||||||
chatStore.streamMode,
|
chatStore.streamMode,
|
||||||
chatStore.logprobs
|
chatStore.logprobs,
|
||||||
);
|
);
|
||||||
const contentType = response.headers.get("content-type");
|
const contentType = response.headers.get("content-type");
|
||||||
if (contentType?.startsWith("text/event-stream")) {
|
if (contentType?.startsWith("text/event-stream")) {
|
||||||
@@ -375,33 +375,33 @@ export default function ChatBOX(props: {
|
|||||||
|
|
||||||
const [templates, _setTemplates] = useState(
|
const [templates, _setTemplates] = useState(
|
||||||
JSON.parse(
|
JSON.parse(
|
||||||
localStorage.getItem(STORAGE_NAME_TEMPLATE) || "[]"
|
localStorage.getItem(STORAGE_NAME_TEMPLATE) || "[]",
|
||||||
) as TemplateChatStore[]
|
) as TemplateChatStore[],
|
||||||
);
|
);
|
||||||
const [templateAPIs, _setTemplateAPIs] = useState(
|
const [templateAPIs, _setTemplateAPIs] = useState(
|
||||||
JSON.parse(
|
JSON.parse(
|
||||||
localStorage.getItem(STORAGE_NAME_TEMPLATE_API) || "[]"
|
localStorage.getItem(STORAGE_NAME_TEMPLATE_API) || "[]",
|
||||||
) as TemplateAPI[]
|
) as TemplateAPI[],
|
||||||
);
|
);
|
||||||
const [templateAPIsWhisper, _setTemplateAPIsWhisper] = useState(
|
const [templateAPIsWhisper, _setTemplateAPIsWhisper] = useState(
|
||||||
JSON.parse(
|
JSON.parse(
|
||||||
localStorage.getItem(STORAGE_NAME_TEMPLATE_API_WHISPER) || "[]"
|
localStorage.getItem(STORAGE_NAME_TEMPLATE_API_WHISPER) || "[]",
|
||||||
) as TemplateAPI[]
|
) as TemplateAPI[],
|
||||||
);
|
);
|
||||||
const [templateAPIsTTS, _setTemplateAPIsTTS] = useState(
|
const [templateAPIsTTS, _setTemplateAPIsTTS] = useState(
|
||||||
JSON.parse(
|
JSON.parse(
|
||||||
localStorage.getItem(STORAGE_NAME_TEMPLATE_API_TTS) || "[]"
|
localStorage.getItem(STORAGE_NAME_TEMPLATE_API_TTS) || "[]",
|
||||||
) as TemplateAPI[]
|
) as TemplateAPI[],
|
||||||
);
|
);
|
||||||
const [templateAPIsImageGen, _setTemplateAPIsImageGen] = useState(
|
const [templateAPIsImageGen, _setTemplateAPIsImageGen] = useState(
|
||||||
JSON.parse(
|
JSON.parse(
|
||||||
localStorage.getItem(STORAGE_NAME_TEMPLATE_API_IMAGE_GEN) || "[]"
|
localStorage.getItem(STORAGE_NAME_TEMPLATE_API_IMAGE_GEN) || "[]",
|
||||||
) as TemplateAPI[]
|
) as TemplateAPI[],
|
||||||
);
|
);
|
||||||
const [toolsTemplates, _setToolsTemplates] = useState(
|
const [toolsTemplates, _setToolsTemplates] = useState(
|
||||||
JSON.parse(
|
JSON.parse(
|
||||||
localStorage.getItem(STORAGE_NAME_TEMPLATE_TOOLS) || "[]"
|
localStorage.getItem(STORAGE_NAME_TEMPLATE_TOOLS) || "[]",
|
||||||
) as TemplateTools[]
|
) as TemplateTools[],
|
||||||
);
|
);
|
||||||
const setTemplates = (templates: TemplateChatStore[]) => {
|
const setTemplates = (templates: TemplateChatStore[]) => {
|
||||||
localStorage.setItem(STORAGE_NAME_TEMPLATE, JSON.stringify(templates));
|
localStorage.setItem(STORAGE_NAME_TEMPLATE, JSON.stringify(templates));
|
||||||
@@ -410,35 +410,35 @@ export default function ChatBOX(props: {
|
|||||||
const setTemplateAPIs = (templateAPIs: TemplateAPI[]) => {
|
const setTemplateAPIs = (templateAPIs: TemplateAPI[]) => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
STORAGE_NAME_TEMPLATE_API,
|
STORAGE_NAME_TEMPLATE_API,
|
||||||
JSON.stringify(templateAPIs)
|
JSON.stringify(templateAPIs),
|
||||||
);
|
);
|
||||||
_setTemplateAPIs(templateAPIs);
|
_setTemplateAPIs(templateAPIs);
|
||||||
};
|
};
|
||||||
const setTemplateAPIsWhisper = (templateAPIWhisper: TemplateAPI[]) => {
|
const setTemplateAPIsWhisper = (templateAPIWhisper: TemplateAPI[]) => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
STORAGE_NAME_TEMPLATE_API_WHISPER,
|
STORAGE_NAME_TEMPLATE_API_WHISPER,
|
||||||
JSON.stringify(templateAPIWhisper)
|
JSON.stringify(templateAPIWhisper),
|
||||||
);
|
);
|
||||||
_setTemplateAPIsWhisper(templateAPIWhisper);
|
_setTemplateAPIsWhisper(templateAPIWhisper);
|
||||||
};
|
};
|
||||||
const setTemplateAPIsTTS = (templateAPITTS: TemplateAPI[]) => {
|
const setTemplateAPIsTTS = (templateAPITTS: TemplateAPI[]) => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
STORAGE_NAME_TEMPLATE_API_TTS,
|
STORAGE_NAME_TEMPLATE_API_TTS,
|
||||||
JSON.stringify(templateAPITTS)
|
JSON.stringify(templateAPITTS),
|
||||||
);
|
);
|
||||||
_setTemplateAPIsTTS(templateAPITTS);
|
_setTemplateAPIsTTS(templateAPITTS);
|
||||||
};
|
};
|
||||||
const setTemplateAPIsImageGen = (templateAPIImageGen: TemplateAPI[]) => {
|
const setTemplateAPIsImageGen = (templateAPIImageGen: TemplateAPI[]) => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
STORAGE_NAME_TEMPLATE_API_IMAGE_GEN,
|
STORAGE_NAME_TEMPLATE_API_IMAGE_GEN,
|
||||||
JSON.stringify(templateAPIImageGen)
|
JSON.stringify(templateAPIImageGen),
|
||||||
);
|
);
|
||||||
_setTemplateAPIsImageGen(templateAPIImageGen);
|
_setTemplateAPIsImageGen(templateAPIImageGen);
|
||||||
};
|
};
|
||||||
const setTemplateTools = (templateTools: TemplateTools[]) => {
|
const setTemplateTools = (templateTools: TemplateTools[]) => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
STORAGE_NAME_TEMPLATE_TOOLS,
|
STORAGE_NAME_TEMPLATE_TOOLS,
|
||||||
JSON.stringify(templateTools)
|
JSON.stringify(templateTools),
|
||||||
);
|
);
|
||||||
_setToolsTemplates(templateTools);
|
_setToolsTemplates(templateTools);
|
||||||
};
|
};
|
||||||
@@ -478,7 +478,11 @@ export default function ChatBOX(props: {
|
|||||||
<div className="navbar bg-base-100 p-0">
|
<div className="navbar bg-base-100 p-0">
|
||||||
<div className="navbar-start">
|
<div className="navbar-start">
|
||||||
<div className="dropdown lg:hidden">
|
<div className="dropdown lg:hidden">
|
||||||
<div tabindex={0} role="button" className="btn btn-ghost btn-circle">
|
<div
|
||||||
|
tabindex={0}
|
||||||
|
role="button"
|
||||||
|
className="btn btn-ghost btn-circle"
|
||||||
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
className="h-6 w-6"
|
className="h-6 w-6"
|
||||||
@@ -556,7 +560,9 @@ export default function ChatBOX(props: {
|
|||||||
<ChatBubbleLeftEllipsisIcon className="h-10 w-10" />
|
<ChatBubbleLeftEllipsisIcon className="h-10 w-10" />
|
||||||
</div>
|
</div>
|
||||||
<div className="stat-title">Tokens</div>
|
<div className="stat-title">Tokens</div>
|
||||||
<div className="stat-value text-base">{chatStore.totalTokens}</div>
|
<div className="stat-value text-base">
|
||||||
|
{chatStore.totalTokens}
|
||||||
|
</div>
|
||||||
<div className="stat-desc">Max: {chatStore.maxTokens}</div>
|
<div className="stat-desc">Max: {chatStore.maxTokens}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -565,7 +571,9 @@ export default function ChatBOX(props: {
|
|||||||
<ScissorsIcon className="h-10 w-10" />
|
<ScissorsIcon className="h-10 w-10" />
|
||||||
</div>
|
</div>
|
||||||
<div className="stat-title">Cut</div>
|
<div className="stat-title">Cut</div>
|
||||||
<div className="stat-value text-base">{chatStore.postBeginIndex}</div>
|
<div className="stat-value text-base">
|
||||||
|
{chatStore.postBeginIndex}
|
||||||
|
</div>
|
||||||
<div className="stat-desc">
|
<div className="stat-desc">
|
||||||
Max: {chatStore.history.filter(({ hide }) => !hide).length}
|
Max: {chatStore.history.filter(({ hide }) => !hide).length}
|
||||||
</div>
|
</div>
|
||||||
@@ -801,49 +809,49 @@ export default function ChatBOX(props: {
|
|||||||
if (!newChatStore.apiEndpoint) {
|
if (!newChatStore.apiEndpoint) {
|
||||||
newChatStore.apiEndpoint = getDefaultParams(
|
newChatStore.apiEndpoint = getDefaultParams(
|
||||||
"api",
|
"api",
|
||||||
chatStore.apiEndpoint
|
chatStore.apiEndpoint,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!newChatStore.apiKey) {
|
if (!newChatStore.apiKey) {
|
||||||
newChatStore.apiKey = getDefaultParams(
|
newChatStore.apiKey = getDefaultParams(
|
||||||
"key",
|
"key",
|
||||||
chatStore.apiKey
|
chatStore.apiKey,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!newChatStore.whisper_api) {
|
if (!newChatStore.whisper_api) {
|
||||||
newChatStore.whisper_api = getDefaultParams(
|
newChatStore.whisper_api = getDefaultParams(
|
||||||
"whisper-api",
|
"whisper-api",
|
||||||
chatStore.whisper_api
|
chatStore.whisper_api,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!newChatStore.whisper_key) {
|
if (!newChatStore.whisper_key) {
|
||||||
newChatStore.whisper_key = getDefaultParams(
|
newChatStore.whisper_key = getDefaultParams(
|
||||||
"whisper-key",
|
"whisper-key",
|
||||||
chatStore.whisper_key
|
chatStore.whisper_key,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!newChatStore.tts_api) {
|
if (!newChatStore.tts_api) {
|
||||||
newChatStore.tts_api = getDefaultParams(
|
newChatStore.tts_api = getDefaultParams(
|
||||||
"tts-api",
|
"tts-api",
|
||||||
chatStore.tts_api
|
chatStore.tts_api,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!newChatStore.tts_key) {
|
if (!newChatStore.tts_key) {
|
||||||
newChatStore.tts_key = getDefaultParams(
|
newChatStore.tts_key = getDefaultParams(
|
||||||
"tts-key",
|
"tts-key",
|
||||||
chatStore.tts_key
|
chatStore.tts_key,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!newChatStore.image_gen_api) {
|
if (!newChatStore.image_gen_api) {
|
||||||
newChatStore.image_gen_api = getDefaultParams(
|
newChatStore.image_gen_api = getDefaultParams(
|
||||||
"image-gen-api",
|
"image-gen-api",
|
||||||
chatStore.image_gen_api
|
chatStore.image_gen_api,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!newChatStore.image_gen_key) {
|
if (!newChatStore.image_gen_key) {
|
||||||
newChatStore.image_gen_key = getDefaultParams(
|
newChatStore.image_gen_key = getDefaultParams(
|
||||||
"image-gen-key",
|
"image-gen-key",
|
||||||
chatStore.image_gen_key
|
chatStore.image_gen_key,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
newChatStore.cost = 0;
|
newChatStore.cost = 0;
|
||||||
@@ -900,7 +908,7 @@ export default function ChatBOX(props: {
|
|||||||
<br />↖{Tr("Click the conor to create a new chat")}
|
<br />↖{Tr("Click the conor to create a new chat")}
|
||||||
<br />⚠
|
<br />⚠
|
||||||
{Tr(
|
{Tr(
|
||||||
"All chat history and settings are stored in the local browser"
|
"All chat history and settings are stored in the local browser",
|
||||||
)}
|
)}
|
||||||
<br />
|
<br />
|
||||||
</p>
|
</p>
|
||||||
@@ -1143,7 +1151,7 @@ export default function ChatBOX(props: {
|
|||||||
} else {
|
} else {
|
||||||
return content.map((c) => c?.text).join(" ");
|
return content.map((c) => c?.text).join(" ");
|
||||||
}
|
}
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
.concat([inputMsg])
|
.concat([inputMsg])
|
||||||
.join(" ");
|
.join(" ");
|
||||||
@@ -1157,7 +1165,7 @@ export default function ChatBOX(props: {
|
|||||||
await navigator.mediaDevices.getUserMedia({
|
await navigator.mediaDevices.getUserMedia({
|
||||||
audio: true,
|
audio: true,
|
||||||
}),
|
}),
|
||||||
{ audioBitsPerSecond: 64 * 1000 }
|
{ audioBitsPerSecond: 64 * 1000 },
|
||||||
);
|
);
|
||||||
|
|
||||||
// mount mediaRecorder to ref
|
// mount mediaRecorder to ref
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { defaultModel } from "./models";
|
import { defaultModel } from "@/models";
|
||||||
|
|
||||||
export interface ImageURL {
|
export interface ImageURL {
|
||||||
url: string;
|
url: string;
|
||||||
@@ -110,7 +110,7 @@ function calculate_token_length_from_text(text: string): number {
|
|||||||
}
|
}
|
||||||
// https://help.openai.com/en/articles/4936856-what-are-tokens-and-how-to-count-them
|
// https://help.openai.com/en/articles/4936856-what-are-tokens-and-how-to-count-them
|
||||||
export function calculate_token_length(
|
export function calculate_token_length(
|
||||||
content: string | MessageDetail[]
|
content: string | MessageDetail[],
|
||||||
): number {
|
): number {
|
||||||
if (typeof content === "string") {
|
if (typeof content === "string") {
|
||||||
return calculate_token_length_from_text(content);
|
return calculate_token_length_from_text(content);
|
||||||
@@ -165,7 +165,7 @@ class Chat {
|
|||||||
presence_penalty = 0,
|
presence_penalty = 0,
|
||||||
frequency_penalty = 0,
|
frequency_penalty = 0,
|
||||||
json_mode = false,
|
json_mode = false,
|
||||||
} = {}
|
} = {},
|
||||||
) {
|
) {
|
||||||
this.OPENAI_API_KEY = OPENAI_API_KEY ?? "";
|
this.OPENAI_API_KEY = OPENAI_API_KEY ?? "";
|
||||||
this.messages = [];
|
this.messages = [];
|
||||||
@@ -200,14 +200,14 @@ class Chat {
|
|||||||
}
|
}
|
||||||
if (msg.role === "system") {
|
if (msg.role === "system") {
|
||||||
console.log(
|
console.log(
|
||||||
"Warning: detected system message in the middle of history"
|
"Warning: detected system message in the middle of history",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const msg of this.messages) {
|
for (const msg of this.messages) {
|
||||||
if (msg.name && msg.role !== "system") {
|
if (msg.name && msg.role !== "system") {
|
||||||
console.log(
|
console.log(
|
||||||
"Warning: detected message where name field set but role is system"
|
"Warning: detected message where name field set but role is system",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import { Tr, langCodeContext, LANG_OPTIONS, tr } from "./translate";
|
import { useState, useEffect, StateUpdater, Dispatch } from "preact/hooks";
|
||||||
import { useState, useEffect, StateUpdater,Dispatch } from "preact/hooks";
|
import { Tr, langCodeContext, LANG_OPTIONS, tr } from "@/translate";
|
||||||
import { ChatStore, ChatStoreMessage } from "./app";
|
import { ChatStore, ChatStoreMessage } from "@/app";
|
||||||
import { calculate_token_length, getMessageText } from "./chatgpt";
|
import { EditMessageString } from "@/editMessageString";
|
||||||
import { isVailedJSON } from "./message";
|
import { EditMessageDetail } from "@/editMessageDetail";
|
||||||
import { EditMessageString } from "./editMessageString";
|
|
||||||
import { EditMessageDetail } from "./editMessageDetail";
|
|
||||||
|
|
||||||
interface EditMessageProps {
|
interface EditMessageProps {
|
||||||
chat: ChatStoreMessage;
|
chat: ChatStoreMessage;
|
||||||
@@ -49,7 +47,7 @@ export function EditMessage(props: EditMessageProps) {
|
|||||||
className="w-full m-2 p-1 rounded bg-red-500"
|
className="w-full m-2 p-1 rounded bg-red-500"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const confirm = window.confirm(
|
const confirm = window.confirm(
|
||||||
"Change message type will clear the content, are you sure?"
|
"Change message type will clear the content, are you sure?",
|
||||||
);
|
);
|
||||||
if (!confirm) return;
|
if (!confirm) return;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { ChatStore, ChatStoreMessage } from "./app";
|
import { ChatStore, ChatStoreMessage } from "@/app";
|
||||||
import { calculate_token_length } from "./chatgpt";
|
import { calculate_token_length } from "@/chatgpt";
|
||||||
import { Tr } from "./translate";
|
import { Tr } from "@/translate";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
chat: ChatStoreMessage;
|
chat: ChatStoreMessage;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { ChatStore, ChatStoreMessage } from "./app";
|
import { ChatStore, ChatStoreMessage } from "@/app";
|
||||||
import { isVailedJSON } from "./message";
|
import { isVailedJSON } from "@/message";
|
||||||
import { calculate_token_length } from "./chatgpt";
|
import { calculate_token_length } from "@/chatgpt";
|
||||||
import { Tr } from "./translate";
|
import { Tr } from "@/translate";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
chat: ChatStoreMessage;
|
chat: ChatStoreMessage;
|
||||||
@@ -69,7 +69,7 @@ export function EditMessageString({
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!chat.tool_calls) return;
|
if (!chat.tool_calls) return;
|
||||||
chat.tool_calls = chat.tool_calls.filter(
|
chat.tool_calls = chat.tool_calls.filter(
|
||||||
(tc) => tc.id !== tool_call.id
|
(tc) => tc.id !== tool_call.id,
|
||||||
);
|
);
|
||||||
setChatStore({ ...chatStore });
|
setChatStore({ ...chatStore });
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -79,8 +79,14 @@ body::-webkit-scrollbar {
|
|||||||
white-space: break-space;
|
white-space: break-space;
|
||||||
background-color: rgba(175, 184, 193, 0.2);
|
background-color: rgba(175, 184, 193, 0.2);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas,
|
font-family:
|
||||||
Liberation Mono, monospace;
|
ui-monospace,
|
||||||
|
SFMono-Regular,
|
||||||
|
SF Mono,
|
||||||
|
Menlo,
|
||||||
|
Consolas,
|
||||||
|
Liberation Mono,
|
||||||
|
monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
.markup > pre {
|
.markup > pre {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ChatStore, TemplateAPI } from "./app";
|
import { ChatStore, TemplateAPI } from "@/app";
|
||||||
import { Tr } from "./translate";
|
import { Tr } from "@/translate";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
chatStore: ChatStore;
|
chatStore: ChatStore;
|
||||||
@@ -62,7 +62,7 @@ export function ListAPIs({
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (
|
if (
|
||||||
!confirm(
|
!confirm(
|
||||||
`Are you sure to delete this **${label}** template?`
|
`Are you sure to delete this **${label}** template?`,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ChatStore, TemplateTools } from "./app";
|
import { ChatStore, TemplateTools } from "@/app";
|
||||||
import { Tr } from "./translate";
|
import { Tr } from "@/translate";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
templateTools: TemplateTools[];
|
templateTools: TemplateTools[];
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import { render } from "preact";
|
|
||||||
import { App } from "./app";
|
|
||||||
import { useState, useEffect } from "preact/hooks";
|
|
||||||
import { Tr, langCodeContext, LANG_OPTIONS } from "./translate";
|
|
||||||
|
|
||||||
import { themeChange } from "theme-change";
|
import { themeChange } from "theme-change";
|
||||||
|
import { render } from "preact";
|
||||||
|
import { useState, useEffect } from "preact/hooks";
|
||||||
|
import { App } from "@/app";
|
||||||
|
import { Tr, langCodeContext, LANG_OPTIONS } from "@/translate";
|
||||||
|
|
||||||
function Base() {
|
function Base() {
|
||||||
const [langCode, _setLangCode] = useState("en-US");
|
const [langCode, _setLangCode] = useState("en-US");
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
import { Tr, langCodeContext, LANG_OPTIONS } from "./translate";
|
|
||||||
import { useState, useEffect, StateUpdater } from "preact/hooks";
|
|
||||||
import { ChatStore, ChatStoreMessage } from "./app";
|
|
||||||
import { calculate_token_length, getMessageText } from "./chatgpt";
|
|
||||||
import Markdown from "preact-markdown";
|
|
||||||
import TTSButton, { TTSPlay } from "./tts";
|
|
||||||
import { MessageHide } from "./messageHide";
|
|
||||||
import { MessageDetail } from "./messageDetail";
|
|
||||||
import { MessageToolCall } from "./messageToolCall";
|
|
||||||
import { MessageToolResp } from "./messageToolResp";
|
|
||||||
import { EditMessage } from "./editMessage";
|
|
||||||
import logprobToColor from "./logprob";
|
|
||||||
import { XMarkIcon } from "@heroicons/react/24/outline";
|
import { XMarkIcon } from "@heroicons/react/24/outline";
|
||||||
|
import Markdown from "preact-markdown";
|
||||||
|
import { useState, useEffect, StateUpdater } from "preact/hooks";
|
||||||
|
|
||||||
|
import { Tr, langCodeContext, LANG_OPTIONS } from "@/translate";
|
||||||
|
import { ChatStore, ChatStoreMessage } from "@/app";
|
||||||
|
import { calculate_token_length, getMessageText } from "@/chatgpt";
|
||||||
|
import TTSButton, { TTSPlay } from "@/tts";
|
||||||
|
import { MessageHide } from "@/messageHide";
|
||||||
|
import { MessageDetail } from "@/messageDetail";
|
||||||
|
import { MessageToolCall } from "@/messageToolCall";
|
||||||
|
import { MessageToolResp } from "@/messageToolResp";
|
||||||
|
import { EditMessage } from "@/editMessage";
|
||||||
|
import logprobToColor from "@/logprob";
|
||||||
|
|
||||||
export const isVailedJSON = (str: string): boolean => {
|
export const isVailedJSON = (str: string): boolean => {
|
||||||
try {
|
try {
|
||||||
@@ -213,7 +214,7 @@ export default function Message(props: Props) {
|
|||||||
chatStore.history.splice(messageIndex, 1);
|
chatStore.history.splice(messageIndex, 1);
|
||||||
chatStore.postBeginIndex = Math.max(
|
chatStore.postBeginIndex = Math.max(
|
||||||
chatStore.postBeginIndex - 1,
|
chatStore.postBeginIndex - 1,
|
||||||
0
|
0,
|
||||||
);
|
);
|
||||||
//chatStore.totalTokens =
|
//chatStore.totalTokens =
|
||||||
chatStore.totalTokens = 0;
|
chatStore.totalTokens = 0;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ChatStoreMessage } from "./app";
|
import { ChatStoreMessage } from "@/app";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
chat: ChatStoreMessage;
|
chat: ChatStoreMessage;
|
||||||
@@ -28,7 +28,7 @@ export function MessageDetail({ chat, renderMarkdown }: Props) {
|
|||||||
window.open(mdt.image_url?.url, "_blank");
|
window.open(mdt.image_url?.url, "_blank");
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
),
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ChatStoreMessage } from "./app";
|
import { ChatStoreMessage } from "@/app";
|
||||||
import { getMessageText } from "./chatgpt";
|
import { getMessageText } from "@/chatgpt";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
chat: ChatStoreMessage;
|
chat: ChatStoreMessage;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ChatStoreMessage } from "./app";
|
import { ChatStoreMessage } from "@/app";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
chat: ChatStoreMessage;
|
chat: ChatStoreMessage;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ChatStoreMessage } from "./app";
|
import { ChatStoreMessage } from "@/app";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
chat: ChatStoreMessage;
|
chat: ChatStoreMessage;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const models: Record<string, Model> = {
|
|||||||
},
|
},
|
||||||
"gpt-4o-2024-08-06": {
|
"gpt-4o-2024-08-06": {
|
||||||
maxToken: 128000,
|
maxToken: 128000,
|
||||||
price: { prompt: 0.0025 / 1000, completion: 0.010 / 1000 },
|
price: { prompt: 0.0025 / 1000, completion: 0.01 / 1000 },
|
||||||
},
|
},
|
||||||
"gpt-4o-2024-05-13": {
|
"gpt-4o-2024-05-13": {
|
||||||
maxToken: 128000,
|
maxToken: 128000,
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { IDBPDatabase } from "idb";
|
import { IDBPDatabase } from "idb";
|
||||||
import { ChatStore } from "./app";
|
|
||||||
import { StateUpdater, useRef, useState, Dispatch } from "preact/hooks";
|
import { StateUpdater, useRef, useState, Dispatch } from "preact/hooks";
|
||||||
|
|
||||||
|
import { ChatStore } from "@/app";
|
||||||
|
|
||||||
interface ChatStoreSearchResult {
|
interface ChatStoreSearchResult {
|
||||||
key: IDBValidKey;
|
key: IDBValidKey;
|
||||||
cs: ChatStore;
|
cs: ChatStore;
|
||||||
@@ -77,7 +78,7 @@ export default function Search(props: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const now = Math.floor(
|
const now = Math.floor(
|
||||||
(result.length / resultKeys.length) * 100
|
(result.length / resultKeys.length) * 100,
|
||||||
);
|
);
|
||||||
if (now !== searchingNow) setSearchingNow(now);
|
if (now !== searchingNow) setSearchingNow(now);
|
||||||
|
|
||||||
@@ -89,7 +90,7 @@ export default function Search(props: {
|
|||||||
const beginIndex: number = content.indexOf(query);
|
const beginIndex: number = content.indexOf(query);
|
||||||
const preview = content.slice(
|
const preview = content.slice(
|
||||||
Math.max(0, beginIndex - 100),
|
Math.max(0, beginIndex - 100),
|
||||||
Math.min(content.length, beginIndex + 239)
|
Math.min(content.length, beginIndex + 239),
|
||||||
);
|
);
|
||||||
result.push({
|
result.push({
|
||||||
key,
|
key,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { TemplateAPI } from "./app";
|
import { TemplateAPI } from "@/app";
|
||||||
import { Tr } from "./translate";
|
import { Tr } from "@/translate";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
tmps: TemplateAPI[];
|
tmps: TemplateAPI[];
|
||||||
|
|||||||
@@ -1,21 +1,4 @@
|
|||||||
import { createRef } from "preact";
|
import { themeChange } from "theme-change";
|
||||||
import { StateUpdater, useContext, useEffect, useState, Dispatch } from "preact/hooks";
|
|
||||||
import {
|
|
||||||
ChatStore,
|
|
||||||
TemplateAPI,
|
|
||||||
TemplateTools,
|
|
||||||
clearTotalCost,
|
|
||||||
getTotalCost,
|
|
||||||
} from "./app";
|
|
||||||
import models from "./models";
|
|
||||||
import { TemplateChatStore } from "./chatbox";
|
|
||||||
import { tr, Tr, langCodeContext, LANG_OPTIONS } from "./translate";
|
|
||||||
import p from "preact-markdown";
|
|
||||||
import { isVailedJSON } from "./message";
|
|
||||||
import { SetAPIsTemplate } from "./setAPIsTemplate";
|
|
||||||
import { autoHeight } from "./textarea";
|
|
||||||
import getDefaultParams from "./getDefaultParam";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
InformationCircleIcon,
|
InformationCircleIcon,
|
||||||
CheckIcon,
|
CheckIcon,
|
||||||
@@ -30,7 +13,28 @@ import {
|
|||||||
ListBulletIcon,
|
ListBulletIcon,
|
||||||
} from "@heroicons/react/24/outline";
|
} from "@heroicons/react/24/outline";
|
||||||
|
|
||||||
import { themeChange } from "theme-change";
|
import { createRef } from "preact";
|
||||||
|
import {
|
||||||
|
StateUpdater,
|
||||||
|
useContext,
|
||||||
|
useEffect,
|
||||||
|
useState,
|
||||||
|
Dispatch,
|
||||||
|
} from "preact/hooks";
|
||||||
|
import {
|
||||||
|
ChatStore,
|
||||||
|
TemplateAPI,
|
||||||
|
TemplateTools,
|
||||||
|
clearTotalCost,
|
||||||
|
getTotalCost,
|
||||||
|
} from "@/app";
|
||||||
|
import models from "@/models";
|
||||||
|
import { TemplateChatStore } from "@/chatbox";
|
||||||
|
import { tr, Tr, langCodeContext, LANG_OPTIONS } from "@/translate";
|
||||||
|
import { isVailedJSON } from "@/message";
|
||||||
|
import { SetAPIsTemplate } from "@/setAPIsTemplate";
|
||||||
|
import { autoHeight } from "@/textarea";
|
||||||
|
import getDefaultParams from "@/getDefaultParam";
|
||||||
|
|
||||||
const TTS_VOICES: string[] = [
|
const TTS_VOICES: string[] = [
|
||||||
"alloy",
|
"alloy",
|
||||||
@@ -109,7 +113,7 @@ const SelectModel = (props: {
|
|||||||
props.chatStore.model = model;
|
props.chatStore.model = model;
|
||||||
props.chatStore.maxTokens = getDefaultParams(
|
props.chatStore.maxTokens = getDefaultParams(
|
||||||
"max",
|
"max",
|
||||||
models[model].maxToken
|
models[model].maxToken,
|
||||||
);
|
);
|
||||||
props.setChatStore({ ...props.chatStore });
|
props.setChatStore({ ...props.chatStore });
|
||||||
}}
|
}}
|
||||||
@@ -435,11 +439,11 @@ export default (props: {
|
|||||||
location.host +
|
location.host +
|
||||||
location.pathname +
|
location.pathname +
|
||||||
`?key=${encodeURIComponent(
|
`?key=${encodeURIComponent(
|
||||||
props.chatStore.apiKey
|
props.chatStore.apiKey,
|
||||||
)}&api=${encodeURIComponent(props.chatStore.apiEndpoint)}&mode=${
|
)}&api=${encodeURIComponent(props.chatStore.apiEndpoint)}&mode=${
|
||||||
props.chatStore.streamMode ? "stream" : "fetch"
|
props.chatStore.streamMode ? "stream" : "fetch"
|
||||||
}&model=${props.chatStore.model}&sys=${encodeURIComponent(
|
}&model=${props.chatStore.model}&sys=${encodeURIComponent(
|
||||||
props.chatStore.systemMessageContent
|
props.chatStore.systemMessageContent,
|
||||||
)}`;
|
)}`;
|
||||||
if (props.chatStore.develop_mode) {
|
if (props.chatStore.develop_mode) {
|
||||||
link = link + `&dev=true`;
|
link = link + `&dev=true`;
|
||||||
@@ -529,7 +533,7 @@ export default (props: {
|
|||||||
className="btn"
|
className="btn"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const name = prompt(
|
const name = prompt(
|
||||||
`Give this **Tools** template a name:`
|
`Give this **Tools** template a name:`,
|
||||||
);
|
);
|
||||||
if (!name) {
|
if (!name) {
|
||||||
alert("No template name specified");
|
alert("No template name specified");
|
||||||
@@ -632,12 +636,12 @@ export default (props: {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (
|
if (
|
||||||
!confirm(
|
!confirm(
|
||||||
tr("Are you sure to clear all history?", langCode)
|
tr("Are you sure to clear all history?", langCode),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
props.chatStore.history = props.chatStore.history.filter(
|
props.chatStore.history = props.chatStore.history.filter(
|
||||||
(msg) => msg.example && !msg.hide
|
(msg) => msg.example && !msg.hide,
|
||||||
);
|
);
|
||||||
props.chatStore.postBeginIndex = 0;
|
props.chatStore.postBeginIndex = 0;
|
||||||
props.setChatStore({ ...props.chatStore });
|
props.setChatStore({ ...props.chatStore });
|
||||||
@@ -651,13 +655,13 @@ export default (props: {
|
|||||||
let dataStr =
|
let dataStr =
|
||||||
"data:text/json;charset=utf-8," +
|
"data:text/json;charset=utf-8," +
|
||||||
encodeURIComponent(
|
encodeURIComponent(
|
||||||
JSON.stringify(props.chatStore, null, "\t")
|
JSON.stringify(props.chatStore, null, "\t"),
|
||||||
);
|
);
|
||||||
let downloadAnchorNode = document.createElement("a");
|
let downloadAnchorNode = document.createElement("a");
|
||||||
downloadAnchorNode.setAttribute("href", dataStr);
|
downloadAnchorNode.setAttribute("href", dataStr);
|
||||||
downloadAnchorNode.setAttribute(
|
downloadAnchorNode.setAttribute(
|
||||||
"download",
|
"download",
|
||||||
`chatgpt-api-web-${props.selectedChatStoreIndex}.json`
|
`chatgpt-api-web-${props.selectedChatStoreIndex}.json`,
|
||||||
);
|
);
|
||||||
document.body.appendChild(downloadAnchorNode); // required for firefox
|
document.body.appendChild(downloadAnchorNode); // required for firefox
|
||||||
downloadAnchorNode.click();
|
downloadAnchorNode.click();
|
||||||
@@ -670,7 +674,7 @@ export default (props: {
|
|||||||
className="btn btn-sm btn-outline btn-neural"
|
className="btn btn-sm btn-outline btn-neural"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const name = prompt(
|
const name = prompt(
|
||||||
tr("Give this template a name:", langCode)
|
tr("Give this template a name:", langCode),
|
||||||
);
|
);
|
||||||
if (!name) {
|
if (!name) {
|
||||||
alert(tr("No template name specified", langCode));
|
alert(tr("No template name specified", langCode));
|
||||||
@@ -702,8 +706,8 @@ export default (props: {
|
|||||||
!confirm(
|
!confirm(
|
||||||
tr(
|
tr(
|
||||||
"This will OVERWRITE the current chat history! Continue?",
|
"This will OVERWRITE the current chat history! Continue?",
|
||||||
langCode
|
langCode,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
@@ -734,18 +738,19 @@ export default (props: {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const newChatStore: ChatStore = JSON.parse(
|
const newChatStore: ChatStore = JSON.parse(
|
||||||
reader.result as string
|
reader.result as string,
|
||||||
);
|
);
|
||||||
if (!newChatStore.chatgpt_api_web_version) {
|
if (!newChatStore.chatgpt_api_web_version) {
|
||||||
throw tr(
|
throw tr(
|
||||||
"This is not an exported chatgpt-api-web chatstore file. The key 'chatgpt_api_web_version' is missing!",
|
"This is not an exported chatgpt-api-web chatstore file. The key 'chatgpt_api_web_version' is missing!",
|
||||||
langCode
|
langCode,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
props.setChatStore({ ...newChatStore });
|
props.setChatStore({ ...newChatStore });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
alert(
|
alert(
|
||||||
tr(`Import error on parsing json:`, langCode) + `${e}`
|
tr(`Import error on parsing json:`, langCode) +
|
||||||
|
`${e}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ export const autoHeight = (target: any) => {
|
|||||||
// max 70% of screen height
|
// max 70% of screen height
|
||||||
target.style.height = `${Math.min(
|
target.style.height = `${Math.min(
|
||||||
target.scrollHeight,
|
target.scrollHeight,
|
||||||
window.innerHeight * 0.7
|
window.innerHeight * 0.7,
|
||||||
)}px`;
|
)}px`;
|
||||||
console.log("set auto height", target.style.height);
|
console.log("set auto height", target.style.height);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { createContext } from "preact";
|
import { createContext } from "preact";
|
||||||
import MAP_zh_CN from "./zh_CN";
|
import MAP_zh_CN from "@/translate/zh_CN";
|
||||||
|
|
||||||
interface LangOption {
|
interface LangOption {
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { useMemo, useState } from "preact/hooks";
|
|
||||||
import { ChatStore, ChatStoreMessage, addTotalCost } from "./app";
|
|
||||||
import { Message, getMessageText } from "./chatgpt";
|
|
||||||
import { SpeakerWaveIcon } from "@heroicons/react/24/outline";
|
import { SpeakerWaveIcon } from "@heroicons/react/24/outline";
|
||||||
|
import { useMemo, useState } from "preact/hooks";
|
||||||
|
|
||||||
|
import { ChatStore, ChatStoreMessage, addTotalCost } from "@/app";
|
||||||
|
import { Message, getMessageText } from "@/chatgpt";
|
||||||
|
|
||||||
interface TTSProps {
|
interface TTSProps {
|
||||||
chatStore: ChatStore;
|
chatStore: ChatStore;
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"baseUrl": "src",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["*"]
|
||||||
|
},
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import preact from '@preact/preset-vite'
|
import preact from '@preact/preset-vite'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [preact()],
|
plugins: [preact()],
|
||||||
base: './',
|
base: './',
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': path.resolve(__dirname, 'src')
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user