use @ import alias
All checks were successful
Build static content / build (push) Successful in 10m51s

This commit is contained in:
2024-10-14 18:09:07 +08:00
parent 1c3c94bae4
commit f0f040c42c
25 changed files with 209 additions and 180 deletions

View File

@@ -1,7 +1,7 @@
import { useState } from "preact/hooks";
import { ChatStore } from "./app";
import { MessageDetail } from "./chatgpt";
import { Tr } from "./translate";
import { ChatStore } from "@/app";
import { MessageDetail } from "@/chatgpt";
import { Tr } from "@/translate";
interface Props {
chatStore: ChatStore;

View File

@@ -1,14 +1,14 @@
import { IDBPDatabase, openDB } from "idb";
import { useEffect, useState } from "preact/hooks";
import "./global.css";
import "@/global.css";
import { calculate_token_length, Logprobs, Message } from "./chatgpt";
import getDefaultParams from "./getDefaultParam";
import ChatBOX from "./chatbox";
import models, { defaultModel } from "./models";
import { Tr, langCodeContext, LANG_OPTIONS } from "./translate";
import { calculate_token_length, Logprobs, Message } from "@/chatgpt";
import getDefaultParams from "@/getDefaultParam";
import ChatBOX from "@/chatbox";
import models, { defaultModel } from "@/models";
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 {
hide: boolean;
@@ -88,7 +88,7 @@ export const newChatStore = (
image_gen_api = "https://api.openai.com/v1/images/generations",
image_gen_key = "",
json_mode = false,
logprobs = false
logprobs = false,
): ChatStore => {
return {
chatgpt_api_web_version: CHATGPT_API_WEB_VERSION,
@@ -100,7 +100,7 @@ export const newChatStore = (
totalTokens: 0,
maxTokens: getDefaultParams(
"max",
models[getDefaultParams("model", model)]?.maxToken ?? 2048
models[getDefaultParams("model", model)]?.maxToken ?? 2048,
),
maxGenTokens: 2048,
maxGenTokens_enabled: false,
@@ -152,7 +152,7 @@ export function addTotalCost(cost: number) {
export function getTotalCost(): number {
let totalCost = parseFloat(
localStorage.getItem(STORAGE_NAME_TOTALCOST) ?? "0"
localStorage.getItem(STORAGE_NAME_TOTALCOST) ?? "0",
);
return totalCost;
}
@@ -190,7 +190,7 @@ export function BuildFiledForSearch(chatStore: ChatStore): string[] {
export function App() {
// init selected index
const [selectedChatIndex, setSelectedChatIndex] = useState(
parseInt(localStorage.getItem(STORAGE_NAME_SELECTED) ?? "1")
parseInt(localStorage.getItem(STORAGE_NAME_SELECTED) ?? "1"),
);
console.log("selectedChatIndex", selectedChatIndex);
useEffect(() => {
@@ -207,7 +207,7 @@ export function App() {
// copy from localStorage to indexedDB
const allChatStoreIndexes: number[] = JSON.parse(
localStorage.getItem(STORAGE_NAME_INDEXES) ?? "[]"
localStorage.getItem(STORAGE_NAME_INDEXES) ?? "[]",
);
let keyCount = 0;
for (const i of allChatStoreIndexes) {
@@ -221,7 +221,7 @@ export function App() {
setSelectedChatIndex(keyCount);
if (keyCount > 0) {
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 && oldVersion >= 1) {
alert(
"Start upgrading storage, just a sec... (Click OK to continue)"
"Start upgrading storage, just a sec... (Click OK to continue)",
);
}
if (
@@ -247,7 +247,7 @@ export function App() {
{
multiEntry: true,
unique: false,
}
},
);
// iter through all chatStore and update contents_for_index
@@ -294,7 +294,7 @@ export function App() {
const max = chatStore.maxTokens - chatStore.tokenMargin;
let sum = 0;
chatStore.postBeginIndex = chatStore.history.filter(
({ hide }) => !hide
({ hide }) => !hide,
).length;
for (const msg of chatStore.history
.filter(({ hide }) => !hide)
@@ -309,7 +309,7 @@ export function App() {
// manually estimate token
chatStore.totalTokens = calculate_token_length(
chatStore.systemMessageContent
chatStore.systemMessageContent,
);
for (const msg of chatStore.history
.filter(({ hide }) => !hide)
@@ -331,7 +331,7 @@ export function App() {
// all chat store indexes
const [allChatStoreIndexes, setAllChatStoreIndexes] = useState<IDBValidKey>(
[]
[],
);
const handleNewChatStoreWithOldOne = async (chatStore: ChatStore) => {
@@ -358,8 +358,8 @@ export function App() {
chatStore.image_gen_api,
chatStore.image_gen_key,
chatStore.json_mode,
false // logprobs default to false
)
false, // logprobs default to false
),
);
setSelectedChatIndex(newKey as number);
setAllChatStoreIndexes(await (await db).getAllKeys(STORAGE_NAME));
@@ -445,7 +445,7 @@ export function App() {
return;
console.log(
"remove item",
`${STORAGE_NAME}-${selectedChatIndex}`
`${STORAGE_NAME}-${selectedChatIndex}`,
);
(await db).delete(STORAGE_NAME, selectedChatIndex);
const newAllChatStoreIndexes = await (
@@ -473,7 +473,7 @@ export function App() {
onClick={async () => {
if (
!confirm(
"Are you sure you want to delete **ALL** chat history?"
"Are you sure you want to delete **ALL** chat history?",
)
)
return;

View File

@@ -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 { createRef } from "preact";
import { StateUpdater, useEffect, useState, Dispatch } from "preact/hooks";
import { Tr, langCodeContext, LANG_OPTIONS } from "@/translate";
import {
ChatStore,
ChatStoreMessage,
@@ -15,7 +27,7 @@ import {
TemplateTools,
addTotalCost,
getTotalCost,
} from "./app";
} from "@/app";
import ChatGPT, {
calculate_token_length,
ChunkMessage,
@@ -24,28 +36,16 @@ import ChatGPT, {
MessageDetail,
ToolCall,
Logprobs,
} from "./chatgpt";
import Message from "./message";
import models from "./models";
import Settings from "./settings";
import getDefaultParams from "./getDefaultParam";
import { AddImage } from "./addImage";
import { ListAPIs } from "./listAPIs";
import { ListToolsTempaltes } from "./listToolsTemplates";
import { autoHeight } from "./textarea";
import Search from "./search";
import { IDBPDatabase } from "idb";
import {
MagnifyingGlassIcon,
CubeIcon,
BanknotesIcon,
DocumentTextIcon,
ChatBubbleLeftEllipsisIcon,
ScissorsIcon,
SwatchIcon,
SparklesIcon,
} from "@heroicons/react/24/outline";
} from "@/chatgpt";
import Message from "@/message";
import models from "@/models";
import Settings from "@/settings";
import getDefaultParams from "@/getDefaultParam";
import { AddImage } from "@/addImage";
import { ListAPIs } from "@/listAPIs";
import { ListToolsTempaltes } from "@/listToolsTemplates";
import { autoHeight } from "@/textarea";
import Search from "@/search";
export interface TemplateChatStore extends ChatStore {
name: string;
}
@@ -96,7 +96,7 @@ export default function ChatBOX(props: {
const update_total_tokens = () => {
// manually estimate token
client.total_tokens = calculate_token_length(
chatStore.systemMessageContent
chatStore.systemMessageContent,
);
for (const msg of chatStore.history
.filter(({ hide }) => !hide)
@@ -152,7 +152,7 @@ export default function ChatBOX(props: {
// update tool call arguments
const tool = allChunkTool.find(
(tool) => tool.index === tool_call.index
(tool) => tool.index === tool_call.index,
);
if (!tool) {
@@ -167,7 +167,7 @@ export default function ChatBOX(props: {
allChunkMessage.join("") +
allChunkTool.map((tool) => {
return `Tool Call ID: ${tool.id}\nType: ${tool.type}\nFunction: ${tool.function.name}\nArguments: ${tool.function.arguments}`;
})
}),
);
}
setShowGenerating(false);
@@ -305,7 +305,7 @@ export default function ChatBOX(props: {
setShowGenerating(true);
const response = await client._fetch(
chatStore.streamMode,
chatStore.logprobs
chatStore.logprobs,
);
const contentType = response.headers.get("content-type");
if (contentType?.startsWith("text/event-stream")) {
@@ -375,33 +375,33 @@ export default function ChatBOX(props: {
const [templates, _setTemplates] = useState(
JSON.parse(
localStorage.getItem(STORAGE_NAME_TEMPLATE) || "[]"
) as TemplateChatStore[]
localStorage.getItem(STORAGE_NAME_TEMPLATE) || "[]",
) as TemplateChatStore[],
);
const [templateAPIs, _setTemplateAPIs] = useState(
JSON.parse(
localStorage.getItem(STORAGE_NAME_TEMPLATE_API) || "[]"
) as TemplateAPI[]
localStorage.getItem(STORAGE_NAME_TEMPLATE_API) || "[]",
) as TemplateAPI[],
);
const [templateAPIsWhisper, _setTemplateAPIsWhisper] = useState(
JSON.parse(
localStorage.getItem(STORAGE_NAME_TEMPLATE_API_WHISPER) || "[]"
) as TemplateAPI[]
localStorage.getItem(STORAGE_NAME_TEMPLATE_API_WHISPER) || "[]",
) as TemplateAPI[],
);
const [templateAPIsTTS, _setTemplateAPIsTTS] = useState(
JSON.parse(
localStorage.getItem(STORAGE_NAME_TEMPLATE_API_TTS) || "[]"
) as TemplateAPI[]
localStorage.getItem(STORAGE_NAME_TEMPLATE_API_TTS) || "[]",
) as TemplateAPI[],
);
const [templateAPIsImageGen, _setTemplateAPIsImageGen] = useState(
JSON.parse(
localStorage.getItem(STORAGE_NAME_TEMPLATE_API_IMAGE_GEN) || "[]"
) as TemplateAPI[]
localStorage.getItem(STORAGE_NAME_TEMPLATE_API_IMAGE_GEN) || "[]",
) as TemplateAPI[],
);
const [toolsTemplates, _setToolsTemplates] = useState(
JSON.parse(
localStorage.getItem(STORAGE_NAME_TEMPLATE_TOOLS) || "[]"
) as TemplateTools[]
localStorage.getItem(STORAGE_NAME_TEMPLATE_TOOLS) || "[]",
) as TemplateTools[],
);
const setTemplates = (templates: TemplateChatStore[]) => {
localStorage.setItem(STORAGE_NAME_TEMPLATE, JSON.stringify(templates));
@@ -410,35 +410,35 @@ export default function ChatBOX(props: {
const setTemplateAPIs = (templateAPIs: TemplateAPI[]) => {
localStorage.setItem(
STORAGE_NAME_TEMPLATE_API,
JSON.stringify(templateAPIs)
JSON.stringify(templateAPIs),
);
_setTemplateAPIs(templateAPIs);
};
const setTemplateAPIsWhisper = (templateAPIWhisper: TemplateAPI[]) => {
localStorage.setItem(
STORAGE_NAME_TEMPLATE_API_WHISPER,
JSON.stringify(templateAPIWhisper)
JSON.stringify(templateAPIWhisper),
);
_setTemplateAPIsWhisper(templateAPIWhisper);
};
const setTemplateAPIsTTS = (templateAPITTS: TemplateAPI[]) => {
localStorage.setItem(
STORAGE_NAME_TEMPLATE_API_TTS,
JSON.stringify(templateAPITTS)
JSON.stringify(templateAPITTS),
);
_setTemplateAPIsTTS(templateAPITTS);
};
const setTemplateAPIsImageGen = (templateAPIImageGen: TemplateAPI[]) => {
localStorage.setItem(
STORAGE_NAME_TEMPLATE_API_IMAGE_GEN,
JSON.stringify(templateAPIImageGen)
JSON.stringify(templateAPIImageGen),
);
_setTemplateAPIsImageGen(templateAPIImageGen);
};
const setTemplateTools = (templateTools: TemplateTools[]) => {
localStorage.setItem(
STORAGE_NAME_TEMPLATE_TOOLS,
JSON.stringify(templateTools)
JSON.stringify(templateTools),
);
_setToolsTemplates(templateTools);
};
@@ -478,7 +478,11 @@ export default function ChatBOX(props: {
<div className="navbar bg-base-100 p-0">
<div className="navbar-start">
<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
xmlns="http://www.w3.org/2000/svg"
className="h-6 w-6"
@@ -556,7 +560,9 @@ export default function ChatBOX(props: {
<ChatBubbleLeftEllipsisIcon className="h-10 w-10" />
</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>
@@ -565,7 +571,9 @@ export default function ChatBOX(props: {
<ScissorsIcon className="h-10 w-10" />
</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">
Max: {chatStore.history.filter(({ hide }) => !hide).length}
</div>
@@ -801,49 +809,49 @@ export default function ChatBOX(props: {
if (!newChatStore.apiEndpoint) {
newChatStore.apiEndpoint = getDefaultParams(
"api",
chatStore.apiEndpoint
chatStore.apiEndpoint,
);
}
if (!newChatStore.apiKey) {
newChatStore.apiKey = getDefaultParams(
"key",
chatStore.apiKey
chatStore.apiKey,
);
}
if (!newChatStore.whisper_api) {
newChatStore.whisper_api = getDefaultParams(
"whisper-api",
chatStore.whisper_api
chatStore.whisper_api,
);
}
if (!newChatStore.whisper_key) {
newChatStore.whisper_key = getDefaultParams(
"whisper-key",
chatStore.whisper_key
chatStore.whisper_key,
);
}
if (!newChatStore.tts_api) {
newChatStore.tts_api = getDefaultParams(
"tts-api",
chatStore.tts_api
chatStore.tts_api,
);
}
if (!newChatStore.tts_key) {
newChatStore.tts_key = getDefaultParams(
"tts-key",
chatStore.tts_key
chatStore.tts_key,
);
}
if (!newChatStore.image_gen_api) {
newChatStore.image_gen_api = getDefaultParams(
"image-gen-api",
chatStore.image_gen_api
chatStore.image_gen_api,
);
}
if (!newChatStore.image_gen_key) {
newChatStore.image_gen_key = getDefaultParams(
"image-gen-key",
chatStore.image_gen_key
chatStore.image_gen_key,
);
}
newChatStore.cost = 0;
@@ -900,7 +908,7 @@ export default function ChatBOX(props: {
<br />{Tr("Click the conor to create a new chat")}
<br />
{Tr(
"All chat history and settings are stored in the local browser"
"All chat history and settings are stored in the local browser",
)}
<br />
</p>
@@ -1143,7 +1151,7 @@ export default function ChatBOX(props: {
} else {
return content.map((c) => c?.text).join(" ");
}
})
}),
)
.concat([inputMsg])
.join(" ");
@@ -1157,7 +1165,7 @@ export default function ChatBOX(props: {
await navigator.mediaDevices.getUserMedia({
audio: true,
}),
{ audioBitsPerSecond: 64 * 1000 }
{ audioBitsPerSecond: 64 * 1000 },
);
// mount mediaRecorder to ref

View File

@@ -1,4 +1,4 @@
import { defaultModel } from "./models";
import { defaultModel } from "@/models";
export interface ImageURL {
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
export function calculate_token_length(
content: string | MessageDetail[]
content: string | MessageDetail[],
): number {
if (typeof content === "string") {
return calculate_token_length_from_text(content);
@@ -165,7 +165,7 @@ class Chat {
presence_penalty = 0,
frequency_penalty = 0,
json_mode = false,
} = {}
} = {},
) {
this.OPENAI_API_KEY = OPENAI_API_KEY ?? "";
this.messages = [];
@@ -200,14 +200,14 @@ class Chat {
}
if (msg.role === "system") {
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) {
if (msg.name && msg.role !== "system") {
console.log(
"Warning: detected message where name field set but role is system"
"Warning: detected message where name field set but role is system",
);
}
}

View File

@@ -1,10 +1,8 @@
import { Tr, langCodeContext, LANG_OPTIONS, tr } from "./translate";
import { useState, useEffect, StateUpdater,Dispatch } from "preact/hooks";
import { ChatStore, ChatStoreMessage } from "./app";
import { calculate_token_length, getMessageText } from "./chatgpt";
import { isVailedJSON } from "./message";
import { EditMessageString } from "./editMessageString";
import { EditMessageDetail } from "./editMessageDetail";
import { useState, useEffect, StateUpdater, Dispatch } from "preact/hooks";
import { Tr, langCodeContext, LANG_OPTIONS, tr } from "@/translate";
import { ChatStore, ChatStoreMessage } from "@/app";
import { EditMessageString } from "@/editMessageString";
import { EditMessageDetail } from "@/editMessageDetail";
interface EditMessageProps {
chat: ChatStoreMessage;
@@ -49,7 +47,7 @@ export function EditMessage(props: EditMessageProps) {
className="w-full m-2 p-1 rounded bg-red-500"
onClick={() => {
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;

View File

@@ -1,6 +1,6 @@
import { ChatStore, ChatStoreMessage } from "./app";
import { calculate_token_length } from "./chatgpt";
import { Tr } from "./translate";
import { ChatStore, ChatStoreMessage } from "@/app";
import { calculate_token_length } from "@/chatgpt";
import { Tr } from "@/translate";
interface Props {
chat: ChatStoreMessage;

View File

@@ -1,7 +1,7 @@
import { ChatStore, ChatStoreMessage } from "./app";
import { isVailedJSON } from "./message";
import { calculate_token_length } from "./chatgpt";
import { Tr } from "./translate";
import { ChatStore, ChatStoreMessage } from "@/app";
import { isVailedJSON } from "@/message";
import { calculate_token_length } from "@/chatgpt";
import { Tr } from "@/translate";
interface Props {
chat: ChatStoreMessage;
@@ -69,7 +69,7 @@ export function EditMessageString({
onClick={() => {
if (!chat.tool_calls) return;
chat.tool_calls = chat.tool_calls.filter(
(tc) => tc.id !== tool_call.id
(tc) => tc.id !== tool_call.id,
);
setChatStore({ ...chatStore });
}}

View File

@@ -79,8 +79,14 @@ body::-webkit-scrollbar {
white-space: break-space;
background-color: rgba(175, 184, 193, 0.2);
border-radius: 6px;
font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas,
Liberation Mono, monospace;
font-family:
ui-monospace,
SFMono-Regular,
SF Mono,
Menlo,
Consolas,
Liberation Mono,
monospace;
}
.markup > pre {

View File

@@ -1,5 +1,5 @@
import { ChatStore, TemplateAPI } from "./app";
import { Tr } from "./translate";
import { ChatStore, TemplateAPI } from "@/app";
import { Tr } from "@/translate";
interface Props {
chatStore: ChatStore;
@@ -62,7 +62,7 @@ export function ListAPIs({
onClick={() => {
if (
!confirm(
`Are you sure to delete this **${label}** template?`
`Are you sure to delete this **${label}** template?`,
)
) {
return;

View File

@@ -1,5 +1,5 @@
import { ChatStore, TemplateTools } from "./app";
import { Tr } from "./translate";
import { ChatStore, TemplateTools } from "@/app";
import { Tr } from "@/translate";
interface Props {
templateTools: TemplateTools[];

View File

@@ -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 { render } from "preact";
import { useState, useEffect } from "preact/hooks";
import { App } from "@/app";
import { Tr, langCodeContext, LANG_OPTIONS } from "@/translate";
function Base() {
const [langCode, _setLangCode] = useState("en-US");

View File

@@ -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 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 => {
try {
@@ -213,7 +214,7 @@ export default function Message(props: Props) {
chatStore.history.splice(messageIndex, 1);
chatStore.postBeginIndex = Math.max(
chatStore.postBeginIndex - 1,
0
0,
);
//chatStore.totalTokens =
chatStore.totalTokens = 0;

View File

@@ -1,4 +1,4 @@
import { ChatStoreMessage } from "./app";
import { ChatStoreMessage } from "@/app";
interface Props {
chat: ChatStoreMessage;
@@ -28,7 +28,7 @@ export function MessageDetail({ chat, renderMarkdown }: Props) {
window.open(mdt.image_url?.url, "_blank");
}}
/>
)
),
)}
</div>
);

View File

@@ -1,5 +1,5 @@
import { ChatStoreMessage } from "./app";
import { getMessageText } from "./chatgpt";
import { ChatStoreMessage } from "@/app";
import { getMessageText } from "@/chatgpt";
interface Props {
chat: ChatStoreMessage;

View File

@@ -1,4 +1,4 @@
import { ChatStoreMessage } from "./app";
import { ChatStoreMessage } from "@/app";
interface Props {
chat: ChatStoreMessage;

View File

@@ -1,4 +1,4 @@
import { ChatStoreMessage } from "./app";
import { ChatStoreMessage } from "@/app";
interface Props {
chat: ChatStoreMessage;

View File

@@ -13,7 +13,7 @@ const models: Record<string, Model> = {
},
"gpt-4o-2024-08-06": {
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": {
maxToken: 128000,

View File

@@ -1,7 +1,8 @@
import { IDBPDatabase } from "idb";
import { ChatStore } from "./app";
import { StateUpdater, useRef, useState, Dispatch } from "preact/hooks";
import { ChatStore } from "@/app";
interface ChatStoreSearchResult {
key: IDBValidKey;
cs: ChatStore;
@@ -77,7 +78,7 @@ export default function Search(props: {
}
const now = Math.floor(
(result.length / resultKeys.length) * 100
(result.length / resultKeys.length) * 100,
);
if (now !== searchingNow) setSearchingNow(now);
@@ -89,7 +90,7 @@ export default function Search(props: {
const beginIndex: number = content.indexOf(query);
const preview = content.slice(
Math.max(0, beginIndex - 100),
Math.min(content.length, beginIndex + 239)
Math.min(content.length, beginIndex + 239),
);
result.push({
key,

View File

@@ -1,5 +1,5 @@
import { TemplateAPI } from "./app";
import { Tr } from "./translate";
import { TemplateAPI } from "@/app";
import { Tr } from "@/translate";
interface Props {
tmps: TemplateAPI[];

View File

@@ -1,21 +1,4 @@
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 p from "preact-markdown";
import { isVailedJSON } from "./message";
import { SetAPIsTemplate } from "./setAPIsTemplate";
import { autoHeight } from "./textarea";
import getDefaultParams from "./getDefaultParam";
import { themeChange } from "theme-change";
import {
InformationCircleIcon,
CheckIcon,
@@ -30,7 +13,28 @@ import {
ListBulletIcon,
} 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[] = [
"alloy",
@@ -109,7 +113,7 @@ const SelectModel = (props: {
props.chatStore.model = model;
props.chatStore.maxTokens = getDefaultParams(
"max",
models[model].maxToken
models[model].maxToken,
);
props.setChatStore({ ...props.chatStore });
}}
@@ -435,11 +439,11 @@ export default (props: {
location.host +
location.pathname +
`?key=${encodeURIComponent(
props.chatStore.apiKey
props.chatStore.apiKey,
)}&api=${encodeURIComponent(props.chatStore.apiEndpoint)}&mode=${
props.chatStore.streamMode ? "stream" : "fetch"
}&model=${props.chatStore.model}&sys=${encodeURIComponent(
props.chatStore.systemMessageContent
props.chatStore.systemMessageContent,
)}`;
if (props.chatStore.develop_mode) {
link = link + `&dev=true`;
@@ -529,7 +533,7 @@ export default (props: {
className="btn"
onClick={() => {
const name = prompt(
`Give this **Tools** template a name:`
`Give this **Tools** template a name:`,
);
if (!name) {
alert("No template name specified");
@@ -632,12 +636,12 @@ export default (props: {
onClick={() => {
if (
!confirm(
tr("Are you sure to clear all history?", langCode)
tr("Are you sure to clear all history?", langCode),
)
)
return;
props.chatStore.history = props.chatStore.history.filter(
(msg) => msg.example && !msg.hide
(msg) => msg.example && !msg.hide,
);
props.chatStore.postBeginIndex = 0;
props.setChatStore({ ...props.chatStore });
@@ -651,13 +655,13 @@ export default (props: {
let dataStr =
"data:text/json;charset=utf-8," +
encodeURIComponent(
JSON.stringify(props.chatStore, null, "\t")
JSON.stringify(props.chatStore, null, "\t"),
);
let downloadAnchorNode = document.createElement("a");
downloadAnchorNode.setAttribute("href", dataStr);
downloadAnchorNode.setAttribute(
"download",
`chatgpt-api-web-${props.selectedChatStoreIndex}.json`
`chatgpt-api-web-${props.selectedChatStoreIndex}.json`,
);
document.body.appendChild(downloadAnchorNode); // required for firefox
downloadAnchorNode.click();
@@ -670,7 +674,7 @@ export default (props: {
className="btn btn-sm btn-outline btn-neural"
onClick={() => {
const name = prompt(
tr("Give this template a name:", langCode)
tr("Give this template a name:", langCode),
);
if (!name) {
alert(tr("No template name specified", langCode));
@@ -702,8 +706,8 @@ export default (props: {
!confirm(
tr(
"This will OVERWRITE the current chat history! Continue?",
langCode
)
langCode,
),
)
)
return;
@@ -734,18 +738,19 @@ export default (props: {
}
try {
const newChatStore: ChatStore = JSON.parse(
reader.result as string
reader.result as string,
);
if (!newChatStore.chatgpt_api_web_version) {
throw tr(
"This is not an exported chatgpt-api-web chatstore file. The key 'chatgpt_api_web_version' is missing!",
langCode
langCode,
);
}
props.setChatStore({ ...newChatStore });
} catch (e) {
alert(
tr(`Import error on parsing json:`, langCode) + `${e}`
tr(`Import error on parsing json:`, langCode) +
`${e}`,
);
}
};

View File

@@ -3,7 +3,7 @@ export const autoHeight = (target: any) => {
// max 70% of screen height
target.style.height = `${Math.min(
target.scrollHeight,
window.innerHeight * 0.7
window.innerHeight * 0.7,
)}px`;
console.log("set auto height", target.style.height);
};

View File

@@ -1,5 +1,5 @@
import { createContext } from "preact";
import MAP_zh_CN from "./zh_CN";
import MAP_zh_CN from "@/translate/zh_CN";
interface LangOption {
name: string;

View File

@@ -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 { useMemo, useState } from "preact/hooks";
import { ChatStore, ChatStoreMessage, addTotalCost } from "@/app";
import { Message, getMessageText } from "@/chatgpt";
interface TTSProps {
chatStore: ChatStore;

View File

@@ -1,5 +1,9 @@
{
"compilerOptions": {
"baseUrl": "src",
"paths": {
"@/*": ["*"]
},
"target": "ESNext",
"useDefineForClassFields": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],

View File

@@ -1,8 +1,14 @@
import { defineConfig } from 'vite'
import preact from '@preact/preset-vite'
import path from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [preact()],
base: './',
resolve: {
alias: {
'@': path.resolve(__dirname, 'src')
}
}
})