Compare commits

...

40 Commits

Author SHA1 Message Date
lloydzhou
a9c2dd6cc8 update version 2024-10-15 16:47:19 +08:00
lloydzhou
4148a50b7d Merge remote-tracking branch 'origin/main' into feature/aarch64 2024-10-15 16:39:41 +08:00
Dogtiti
cda4494cec Merge pull request #5632 from ConnectAI-E/feature/H0llyW00dzZ-updater
Feature/h0lly w00dz z updater
2024-10-15 14:31:49 +08:00
lloydzhou
87d85c10c3 update 2024-10-14 21:48:36 +08:00
Dogtiti
22f83c9e11 Merge pull request #5666 from ChatGPTNextWeb/dependabot/npm_and_yarn/types/jest-29.5.13
Bump @types/jest from 29.5.12 to 29.5.13
2024-10-14 20:36:53 +08:00
dependabot[bot]
7f454cbcec Bump @types/jest from 29.5.12 to 29.5.13
Bumps [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest) from 29.5.12 to 29.5.13.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest)

---
updated-dependencies:
- dependency-name: "@types/jest"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-14 10:49:46 +00:00
lloydzhou
426269d795 Merge remote-tracking branch 'connectai/main' into feature/H0llyW00dzZ-updater 2024-10-14 17:12:08 +08:00
Lloyd Zhou
370f143157 Merge pull request #5661 from ChatGPTNextWeb/remove-pr-preview
update test run target
2024-10-14 17:11:26 +08:00
lloydzhou
103106bb93 update test run target 2024-10-14 17:10:02 +08:00
lloydzhou
2419083adf Merge remote-tracking branch 'connectai/main' into feature/H0llyW00dzZ-updater 2024-10-14 17:04:12 +08:00
Lloyd Zhou
c25903bfb4 Merge pull request #5658 from ccq18/main
fix  o1系列模型超时时间改为4分钟,
2024-10-14 16:57:29 +08:00
Lloyd Zhou
e34c266438 Merge pull request #5660 from ChatGPTNextWeb/remove-pr-preview
update deploy_preview run target
2024-10-14 16:55:48 +08:00
lloydzhou
8c39a687b5 update deploy_preview run target 2024-10-14 16:53:46 +08:00
ccq18
592f62005b 仅修改o1的超时时间为4分钟,减少o1系列模型请求失败的情况 2024-10-14 16:31:17 +08:00
ccq18
12e7caa209 fix 默认超时时间改为3分钟,支持o1-mini 2024-10-14 16:03:01 +08:00
Lloyd Zhou
b016771555 Merge pull request #5599 from ConnectAI-E/feature/allow-send-image-only
feat: allow send image only
2024-10-14 15:11:28 +08:00
Dogtiti
a84383f919 Merge pull request #5647 from code-october/fix/setting-locale
修改“压缩模型”名称,增加“生成对话标题”的功能提示
2024-10-13 01:49:51 +08:00
code-october
7f68fb1ff2 修改“压缩模型”名称,增加“生成对话标题”的功能提示 2024-10-12 16:49:24 +00:00
Dogtiti
8d2003fe68 Merge pull request #5644 from ConnectAI-E/fix/siderbar-style
fix: sidebar style
2024-10-12 14:56:01 +08:00
Dogtiti
9961b513cc fix: sidebar style 2024-10-12 14:54:22 +08:00
Dogtiti
819238acaf fix: i18n 2024-10-11 20:49:43 +08:00
Dogtiti
ad49916b1c Merge pull request #5638 from ConnectAI-E/chore/test-action
chore: improve test
2024-10-11 20:44:20 +08:00
Dogtiti
d18bd8a48a Merge pull request #5640 from code-october/feature/enableCodeFold
支持前端使能/禁用代码折叠
2024-10-11 20:43:43 +08:00
code-october
4a1319f2c0 代码安全优化 2024-10-11 11:57:23 +00:00
code-october
8fd843d228 参考coderabbitai建议规范代码 2024-10-11 11:38:52 +00:00
code-october
6792d6e475 支持前端使能/禁用代码折叠 2024-10-11 11:19:36 +00:00
Dogtiti
bd43af3a8d chore: cache node_modules 2024-10-11 15:41:46 +08:00
Dogtiti
be98aa2078 chore: improve test 2024-10-11 15:17:38 +08:00
lloydzhou
a0d4a04192 update 2024-10-11 11:52:24 +08:00
lloydzhou
bd9de4dc4d fix version compare 2024-10-11 11:42:36 +08:00
lloydzhou
2eebfcf6fe client app tauri updater #2966 2024-10-11 11:29:22 +08:00
lloydzhou
49aeff4473 Merge remote-tracking branch 'origin/main' into feature/aarch64 2024-10-09 18:08:05 +08:00
Dogtiti
7d55a6d0e4 feat: allow send image only 2024-10-08 21:31:01 +08:00
lloydzhou
b7394bc10c Merge remote-tracking branch 'origin/main' into feature/aarch64 2024-09-26 20:37:30 +08:00
lloydzhou
f2aeb83e4e Merge remote-tracking branch 'origin/main' into feature/aarch64 2024-09-13 17:40:17 +08:00
lloydzhou
030234c498 test action 2024-09-11 14:26:27 +08:00
lloydzhou
77805a45b1 test action 2024-09-11 13:08:30 +08:00
lloydzhou
655332cca0 test action 2024-09-11 13:05:26 +08:00
lloydzhou
bb7c6c517b add linux aarch64 build app 2024-09-11 13:04:47 +08:00
lloydzhou
4624b9d778 add linux aarch64 build app 2024-09-11 11:48:57 +08:00
21 changed files with 208 additions and 59 deletions

View File

@@ -40,15 +40,9 @@ jobs:
fail-fast: false
matrix:
config:
- os: ubuntu-latest
arch: x86_64
rust_target: x86_64-unknown-linux-gnu
- os: macos-latest
- os: self-hosted
arch: aarch64
rust_target: x86_64-apple-darwin,aarch64-apple-darwin
- os: windows-latest
arch: x86_64
rust_target: x86_64-pc-windows-msvc
rust_target: aarch64-unknown-linux-gnu
runs-on: ${{ matrix.config.os }}
steps:
@@ -85,7 +79,7 @@ jobs:
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
with:
releaseId: ${{ needs.create-release.outputs.release_id }}
args: ${{ matrix.config.os == 'macos-latest' && '--target universal-apple-darwin' || '' }}
args: ${{ matrix.config.os == 'macos-latest' && '--target universal-apple-darwin' || matrix.config.os == 'ubuntu-latest' && matrix.config.arch == 'aarch64' && '--target aarch64-unknown-linux-gnu' || '' }}
publish-release:
permissions:

View File

@@ -3,9 +3,7 @@ name: VercelPreviewDeployment
on:
pull_request_target:
types:
- opened
- synchronize
- reopened
- review_requested
env:
VERCEL_TEAM: ${{ secrets.VERCEL_TEAM }}

39
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,39 @@
name: Run Tests
on:
push:
branches:
- main
tags:
- "!*"
pull_request:
types:
- review_requested
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: 18
cache: "yarn"
- name: Cache node_modules
uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-node_modules-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-node_modules-
- name: Install dependencies
run: yarn install
- name: Run Jest tests
run: yarn test:ci

View File

@@ -352,7 +352,7 @@ export class ChatGPTApi implements LLMApi {
// make a fetch request
const requestTimeoutId = setTimeout(
() => controller.abort(),
isDalle3 || isO1 ? REQUEST_TIMEOUT_MS * 2 : REQUEST_TIMEOUT_MS, // dalle3 using b64_json is slow.
isDalle3 || isO1 ? REQUEST_TIMEOUT_MS * 4 : REQUEST_TIMEOUT_MS, // dalle3 using b64_json is slow.
);
const res = await fetch(chatPath, chatPayload);

View File

@@ -115,11 +115,14 @@ import { getClientConfig } from "../config/client";
import { useAllModels } from "../utils/hooks";
import { MultimodalContent } from "../client/api";
const localStorage = safeLocalStorage();
import { ClientApi } from "../client/api";
import { createTTSPlayer } from "../utils/audio";
import { MsEdgeTTS, OUTPUT_FORMAT } from "../utils/ms_edge_tts";
import { isEmpty } from "lodash-es";
const localStorage = safeLocalStorage();
const ttsPlayer = createTTSPlayer();
const Markdown = dynamic(async () => (await import("./markdown")).Markdown, {
@@ -1015,7 +1018,7 @@ function _Chat() {
};
const doSubmit = (userInput: string) => {
if (userInput.trim() === "") return;
if (userInput.trim() === "" && isEmpty(attachImages)) return;
const matchCommand = chatCommands.match(userInput);
if (matchCommand.matched) {
setUserInput("");

View File

@@ -140,6 +140,9 @@
display: flex;
justify-content: space-between;
align-items: center;
&-narrow {
justify-content: center;
}
}
.sidebar-logo {

View File

@@ -169,6 +169,12 @@ export function PreCode(props: { children: any }) {
}
function CustomCode(props: { children: any; className?: string }) {
const chatStore = useChatStore();
const session = chatStore.currentSession();
const config = useAppConfig();
const enableCodeFold =
session.mask?.enableCodeFold !== false && config.enableCodeFold;
const ref = useRef<HTMLPreElement>(null);
const [collapsed, setCollapsed] = useState(true);
const [showToggle, setShowToggle] = useState(false);
@@ -184,25 +190,30 @@ function CustomCode(props: { children: any; className?: string }) {
const toggleCollapsed = () => {
setCollapsed((collapsed) => !collapsed);
};
const renderShowMoreButton = () => {
if (showToggle && enableCodeFold && collapsed) {
return (
<div className={`show-hide-button ${collapsed ? "collapsed" : "expanded"}`}>
<button onClick={toggleCollapsed}>{Locale.NewChat.More}</button>
</div>
);
}
return null;
};
return (
<>
<code
className={props?.className}
ref={ref}
style={{
maxHeight: collapsed ? "400px" : "none",
maxHeight: enableCodeFold && collapsed ? "400px" : "none",
overflowY: "hidden",
}}
>
{props.children}
</code>
{showToggle && collapsed && (
<div
className={`show-hide-button ${collapsed ? "collapsed" : "expanded"}`}
>
<button onClick={toggleCollapsed}>{Locale.NewChat.More}</button>
</div>
)}
{renderShowMoreButton()}
</>
);
}

View File

@@ -183,6 +183,23 @@ export function MaskConfig(props: {
></input>
</ListItem>
)}
{globalConfig.enableCodeFold && (
<ListItem
title={Locale.Mask.Config.CodeFold.Title}
subTitle={Locale.Mask.Config.CodeFold.SubTitle}
>
<input
aria-label={Locale.Mask.Config.CodeFold.Title}
type="checkbox"
checked={props.mask.enableCodeFold !== false}
onChange={(e) => {
props.updateMask((mask) => {
mask.enableCodeFold = e.currentTarget.checked;
});
}}
></input>
</ListItem>
)}
{!props.shouldSyncFromGlobal ? (
<ListItem

View File

@@ -49,7 +49,7 @@ import Locale, {
changeLang,
getLang,
} from "../locales";
import { copyToClipboard } from "../utils";
import { copyToClipboard, clientUpdate, semverCompare } from "../utils";
import Link from "next/link";
import {
Anthropic,
@@ -585,7 +585,7 @@ export function Settings() {
const [checkingUpdate, setCheckingUpdate] = useState(false);
const currentVersion = updateStore.formatVersion(updateStore.version);
const remoteId = updateStore.formatVersion(updateStore.remoteVersion);
const hasNewVersion = currentVersion !== remoteId;
const hasNewVersion = semverCompare(currentVersion, remoteId) === -1;
const updateUrl = getClientConfig()?.isApp ? RELEASE_URL : UPDATE_URL;
function checkUpdate(force = false) {
@@ -1357,9 +1357,17 @@ export function Settings() {
{checkingUpdate ? (
<LoadingIcon />
) : hasNewVersion ? (
<Link href={updateUrl} target="_blank" className="link">
{Locale.Settings.Update.GoToUpdate}
</Link>
clientConfig?.isApp ? (
<IconButton
icon={<ResetIcon></ResetIcon>}
text={Locale.Settings.Update.GoToUpdate}
onClick={() => clientUpdate()}
/>
) : (
<Link href={updateUrl} target="_blank" className="link">
{Locale.Settings.Update.GoToUpdate}
</Link>
)
) : (
<IconButton
icon={<ResetIcon></ResetIcon>}
@@ -1509,6 +1517,22 @@ export function Settings() {
}
></input>
</ListItem>
<ListItem
title={Locale.Mask.Config.CodeFold.Title}
subTitle={Locale.Mask.Config.CodeFold.SubTitle}
>
<input
aria-label={Locale.Mask.Config.CodeFold.Title}
type="checkbox"
checked={config.enableCodeFold}
data-testid="enable-code-fold-checkbox"
onChange={(e) =>
updateConfig(
(config) => (config.enableCodeFold = e.currentTarget.checked),
)
}
></input>
</ListItem>
</List>
<SyncItems />

View File

@@ -165,11 +165,17 @@ export function SideBarHeader(props: {
subTitle?: string | React.ReactNode;
logo?: React.ReactNode;
children?: React.ReactNode;
shouldNarrow?: boolean;
}) {
const { title, subTitle, logo, children } = props;
const { title, subTitle, logo, children, shouldNarrow } = props;
return (
<Fragment>
<div className={styles["sidebar-header"]} data-tauri-drag-region>
<div
className={`${styles["sidebar-header"]} ${
shouldNarrow ? styles["sidebar-header-narrow"] : ""
}`}
data-tauri-drag-region
>
<div className={styles["sidebar-title-container"]}>
<div className={styles["sidebar-title"]} data-tauri-drag-region>
{title}
@@ -227,6 +233,7 @@ export function SideBar(props: { className?: string }) {
title="NextChat"
subTitle="Build your own AI assistant."
logo={<ChatGptIcon />}
shouldNarrow={shouldNarrow}
>
<div className={styles["sidebar-header-bar"]}>
<IconButton

7
app/global.d.ts vendored
View File

@@ -26,6 +26,13 @@ declare interface Window {
isPermissionGranted(): Promise<boolean>;
sendNotification(options: string | Options): void;
};
updater: {
checkUpdate(): Promise<UpdateResult>;
installUpdate(): Promise<void>;
onUpdaterEvent(
handler: (status: UpdateStatusResult) => void,
): Promise<UnlistenFn>;
};
http: {
fetch<T>(
url: string,

View File

@@ -205,6 +205,8 @@ const cn = {
IsChecking: "正在检查更新...",
FoundUpdate: (x: string) => `发现新版本:${x}`,
GoToUpdate: "前往更新",
Success: "更新成功!",
Failed: "更新失败",
},
SendKey: "发送键",
Theme: "主题",
@@ -495,8 +497,8 @@ const cn = {
Model: "模型 (model)",
CompressModel: {
Title: "压缩模型",
SubTitle: "用于压缩历史记录的模型",
Title: "对话摘要模型",
SubTitle: "用于压缩历史记录、生成对话标题的模型",
},
Temperature: {
Title: "随机性 (temperature)",
@@ -665,6 +667,10 @@ const cn = {
Title: "启用Artifacts",
SubTitle: "启用之后可以直接渲染HTML页面",
},
CodeFold: {
Title: "启用代码折叠",
SubTitle: "启用之后可以自动折叠/展开过长的代码块",
},
Share: {
Title: "分享此面具",
SubTitle: "生成此面具的直达链接",

View File

@@ -207,6 +207,8 @@ const en: LocaleType = {
IsChecking: "Checking update...",
FoundUpdate: (x: string) => `Found new version: ${x}`,
GoToUpdate: "Update",
Success: "Update Successful.",
Failed: "Update Failed.",
},
SendKey: "Send Key",
Theme: "Theme",
@@ -500,8 +502,8 @@ const en: LocaleType = {
Model: "Model",
CompressModel: {
Title: "Compression Model",
SubTitle: "Model used to compress history",
Title: "Summary Model",
SubTitle: "Model used to compress history and generate title",
},
Temperature: {
Title: "Temperature",
@@ -675,6 +677,11 @@ const en: LocaleType = {
Title: "Enable Artifacts",
SubTitle: "Can render HTML page when enable artifacts.",
},
CodeFold: {
Title: "Enable CodeFold",
SubTitle:
"Automatically collapse/expand overly long code blocks when CodeFold is enabled",
},
Share: {
Title: "Share This Mask",
SubTitle: "Generate a link to this mask",

View File

@@ -372,22 +372,16 @@ export const useChatStore = createPersistStore(
if (attachImages && attachImages.length > 0) {
mContent = [
{
type: "text",
text: userContent,
},
...(userContent
? [{ type: "text" as const, text: userContent }]
: []),
...attachImages.map((url) => ({
type: "image_url" as const,
image_url: { url },
})),
];
mContent = mContent.concat(
attachImages.map((url) => {
return {
type: "image_url",
image_url: {
url: url,
},
};
}),
);
}
let userMessage: ChatMessage = createMessage({
role: "user",
content: mContent,

View File

@@ -52,6 +52,8 @@ export const DEFAULT_CONFIG = {
enableArtifacts: true, // show artifacts config
enableCodeFold: true, // code fold config
disablePromptHint: false,
dontShowMaskSplashScreen: false, // dont show splash screen when create chat

View File

@@ -19,6 +19,7 @@ export type Mask = {
builtin: boolean;
plugin?: string[];
enableArtifacts?: boolean;
enableCodeFold?: boolean;
};
export const DEFAULT_MASK_STATE = {

View File

@@ -6,6 +6,7 @@ import {
} from "../constant";
import { getClientConfig } from "../config/client";
import { createPersistStore } from "../utils/store";
import { clientUpdate } from "../utils";
import ChatGptIcon from "../icons/chatgpt.png";
import Locale from "../locales";
import { ClientApi } from "../client/api";
@@ -119,6 +120,7 @@ export const useUpdateStore = createPersistStore(
icon: `${ChatGptIcon.src}`,
sound: "Default",
});
clientUpdate();
}
}
});

View File

@@ -386,3 +386,37 @@ export function getOperationId(operation: {
`${operation.method.toUpperCase()}${operation.path.replaceAll("/", "_")}`
);
}
export function clientUpdate() {
// this a wild for updating client app
return window.__TAURI__?.updater
.checkUpdate()
.then((updateResult) => {
if (updateResult.shouldUpdate) {
window.__TAURI__?.updater
.installUpdate()
.then((result) => {
showToast(Locale.Settings.Update.Success);
})
.catch((e) => {
console.error("[Install Update Error]", e);
showToast(Locale.Settings.Update.Failed);
});
}
})
.catch((e) => {
console.error("[Check Update Error]", e);
showToast(Locale.Settings.Update.Failed);
});
}
// https://gist.github.com/iwill/a83038623ba4fef6abb9efca87ae9ccb
export function semverCompare(a: string, b: string) {
if (a.startsWith(b + "-")) return -1;
if (b.startsWith(a + "-")) return 1;
return a.localeCompare(b, undefined, {
numeric: true,
sensitivity: "case",
caseFirst: "upper",
});
}

View File

@@ -6,13 +6,13 @@
"mask": "npx tsx app/masks/build.ts",
"mask:watch": "npx watch \"yarn mask\" app/masks",
"dev": "concurrently -r \"yarn run mask:watch\" \"next dev\"",
"build": "yarn test:ci && yarn mask && cross-env BUILD_MODE=standalone next build",
"build": "yarn mask && cross-env BUILD_MODE=standalone next build",
"start": "next start",
"lint": "next lint",
"export": "yarn test:ci && yarn mask && cross-env BUILD_MODE=export BUILD_APP=1 next build",
"export": "yarn mask && cross-env BUILD_MODE=export BUILD_APP=1 next build",
"export:dev": "concurrently -r \"yarn mask:watch\" \"cross-env BUILD_MODE=export BUILD_APP=1 next dev\"",
"app:dev": "concurrently -r \"yarn mask:watch\" \"yarn tauri dev\"",
"app:build": "yarn test:ci && yarn mask && yarn tauri build",
"app:build": "yarn mask && yarn tauri build",
"prompts": "node ./scripts/fetch-prompts.mjs",
"prepare": "husky install",
"proxy-dev": "sh ./scripts/init-proxy.sh && proxychains -f ./scripts/proxychains.conf yarn dev",
@@ -58,7 +58,7 @@
"@tauri-apps/cli": "1.5.11",
"@testing-library/jest-dom": "^6.4.8",
"@testing-library/react": "^16.0.0",
"@types/jest": "^29.5.12",
"@types/jest": "^29.5.13",
"@types/js-yaml": "4.0.9",
"@types/lodash-es": "^4.17.12",
"@types/node": "^20.11.30",
@@ -88,4 +88,4 @@
"lint-staged/yaml": "^2.2.2"
},
"packageManager": "yarn@1.22.19"
}
}

View File

@@ -9,7 +9,7 @@
},
"package": {
"productName": "NextChat",
"version": "2.15.4"
"version": "2.15.5"
},
"tauri": {
"allowlist": {
@@ -99,7 +99,7 @@
"endpoints": [
"https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web/releases/latest/download/latest.json"
],
"dialog": false,
"dialog": true,
"windows": {
"installMode": "passive"
},

View File

@@ -2263,10 +2263,10 @@
dependencies:
"@types/istanbul-lib-report" "*"
"@types/jest@^29.5.12":
version "29.5.12"
resolved "https://registry.npmmirror.com/@types/jest/-/jest-29.5.12.tgz#7f7dc6eb4cf246d2474ed78744b05d06ce025544"
integrity sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==
"@types/jest@^29.5.13":
version "29.5.13"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.13.tgz#8bc571659f401e6a719a7bf0dbcb8b78c71a8adc"
integrity sha512-wd+MVEZCHt23V0/L642O5APvspWply/rGY5BcW4SUETo2UzPU3Z26qr8jC2qxpimI2jjx9h7+2cj2FwIr01bXg==
dependencies:
expect "^29.0.0"
pretty-format "^29.0.0"