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 { 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;
|
||||
|
||||
44
src/app.tsx
44
src/app.tsx
@@ -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;
|
||||
|
||||
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 { 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
|
||||
|
||||
@@ -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",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 });
|
||||
}}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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[];
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ChatStoreMessage } from "./app";
|
||||
import { getMessageText } from "./chatgpt";
|
||||
import { ChatStoreMessage } from "@/app";
|
||||
import { getMessageText } from "@/chatgpt";
|
||||
|
||||
interface Props {
|
||||
chat: ChatStoreMessage;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ChatStoreMessage } from "./app";
|
||||
import { ChatStoreMessage } from "@/app";
|
||||
|
||||
interface Props {
|
||||
chat: ChatStoreMessage;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ChatStoreMessage } from "./app";
|
||||
import { ChatStoreMessage } from "@/app";
|
||||
|
||||
interface Props {
|
||||
chat: ChatStoreMessage;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { TemplateAPI } from "./app";
|
||||
import { Tr } from "./translate";
|
||||
import { TemplateAPI } from "@/app";
|
||||
import { Tr } from "@/translate";
|
||||
|
||||
interface Props {
|
||||
tmps: TemplateAPI[];
|
||||
|
||||
@@ -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}`,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "src",
|
||||
"paths": {
|
||||
"@/*": ["*"]
|
||||
},
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user