Compare commits
197 Commits
main
...
build/upda
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c4e63bc167 | ||
![]() |
6726ca102e | ||
![]() |
e135707f88 | ||
![]() |
f2765b9d31 | ||
![]() |
1e0877dcbf | ||
![]() |
9a65c3391b | ||
![]() |
ca9e23d6ea | ||
![]() |
c4d6f9e179 | ||
![]() |
0cec6195a3 | ||
![]() |
966d42a4db | ||
![]() |
15c33ba7f3 | ||
![]() |
ed7f74c99c | ||
![]() |
1db4139b5a | ||
![]() |
0d85d44de5 | ||
![]() |
f0f1bfa5d9 | ||
![]() |
9161ce481e | ||
![]() |
c760902e72 | ||
![]() |
7c8c15ef1a | ||
![]() |
765eb282f3 | ||
![]() |
0e2b38dddc | ||
![]() |
92e4b3304c | ||
![]() |
c777d55a1c | ||
![]() |
cd27ae4319 | ||
![]() |
bd82c7edac | ||
![]() |
d5043c6628 | ||
![]() |
d9a0584052 | ||
![]() |
3e011109ad | ||
![]() |
bdb990eb90 | ||
![]() |
ae00211691 | ||
![]() |
0ef35a0ee0 | ||
![]() |
9a9d90ad7f | ||
![]() |
606fc7be0c | ||
![]() |
d7def41acc | ||
![]() |
b6a560ce86 | ||
![]() |
25f34f6703 | ||
![]() |
7daa365564 | ||
![]() |
13ccd294cb | ||
![]() |
d357f359ab | ||
![]() |
474cedf653 | ||
![]() |
5d3c88a0b3 | ||
![]() |
ae2c76bda2 | ||
![]() |
c46b5f2fd0 | ||
![]() |
2cb7b73ee7 | ||
![]() |
8d8d5b5235 | ||
![]() |
15acfffd60 | ||
![]() |
18a266eac2 | ||
![]() |
7751070da8 | ||
![]() |
fa8c3d0d7b | ||
![]() |
a567cff809 | ||
![]() |
583b0e9f97 | ||
![]() |
5fddb23516 | ||
![]() |
0e52971997 | ||
![]() |
1387f406a3 | ||
![]() |
ff31f0540a | ||
![]() |
4873e6e2a1 | ||
![]() |
510ce057f7 | ||
![]() |
0e53cc0e8c | ||
![]() |
0b8c896481 | ||
![]() |
15fe635465 | ||
![]() |
f8c3189f4d | ||
![]() |
f215db87e3 | ||
![]() |
67d02212b4 | ||
![]() |
cff9adaf8e | ||
![]() |
cdd2a40086 | ||
![]() |
024028bc52 | ||
![]() |
0ae085b48a | ||
![]() |
2094c54951 | ||
![]() |
f4f11135d3 | ||
![]() |
8e9d7a229d | ||
![]() |
8f49572f85 | ||
![]() |
5aa7696cc3 | ||
![]() |
15dd79e822 | ||
![]() |
4651ab4195 | ||
![]() |
5e3160e6f6 | ||
![]() |
973cd126bb | ||
![]() |
ebaf8766ef | ||
![]() |
d2190e9c3a | ||
![]() |
37f55098fe | ||
![]() |
b1771194cc | ||
![]() |
0279bd8c75 | ||
![]() |
5e077e4ce8 | ||
![]() |
64067e1f20 | ||
![]() |
5295c72ca1 | ||
![]() |
1ecea62052 | ||
![]() |
307af29b65 | ||
![]() |
10190a9aa5 | ||
![]() |
7c5c35600c | ||
![]() |
63b333cdb1 | ||
![]() |
a6776190bd | ||
![]() |
9577cbac27 | ||
![]() |
f6ae13abad | ||
![]() |
f3d501e7d5 | ||
![]() |
2eab8fcc33 | ||
![]() |
bdb81fe20d | ||
![]() |
0f60fe7f2a | ||
![]() |
425f624de5 | ||
![]() |
b1919745e2 | ||
![]() |
9a242bcac9 | ||
![]() |
a6109a60b8 | ||
![]() |
28f7bbf83a | ||
![]() |
cac04c5f3c | ||
![]() |
18f5f9cc37 | ||
![]() |
1787c5c93f | ||
![]() |
f981494613 | ||
![]() |
fbc853af92 | ||
![]() |
1a64c660ba | ||
![]() |
846555af1b | ||
![]() |
bca94854f7 | ||
![]() |
1bd70bd8bf | ||
![]() |
d1dcd39191 | ||
![]() |
35384bda41 | ||
![]() |
89fb6eb648 | ||
![]() |
aa61a890b2 | ||
![]() |
31ece363c3 | ||
![]() |
70a5d78cc5 | ||
![]() |
57f4dfdb6f | ||
![]() |
aa9028a607 | ||
![]() |
d83f94c55c | ||
![]() |
a8c5e0b0b0 | ||
![]() |
177e8cbf73 | ||
![]() |
23828fd15a | ||
![]() |
2cc37ac8e5 | ||
![]() |
c9ee1e9ff2 | ||
![]() |
4f10f5d5f4 | ||
![]() |
c48c84674e | ||
![]() |
1e9fbbf41b | ||
![]() |
4dd144ce43 | ||
![]() |
a387ff1c38 | ||
![]() |
a9e367e6de | ||
![]() |
e2fec587f8 | ||
![]() |
39a6f0943d | ||
![]() |
684896d100 | ||
![]() |
54f911f6cd | ||
![]() |
0e5c16d0c2 | ||
![]() |
b8cd6ea478 | ||
![]() |
fc61fd0f50 | ||
![]() |
2fbfc988c4 | ||
![]() |
99f5fea001 | ||
![]() |
ecd2a1be9f | ||
![]() |
49ee9ca5f1 | ||
![]() |
6d0eef12b1 | ||
![]() |
c1e0a939b0 | ||
![]() |
060a894bd1 | ||
![]() |
c75e02b5b2 | ||
![]() |
fcf43ee845 | ||
![]() |
466f61d044 | ||
![]() |
27ae74af50 | ||
![]() |
8dd941e3d2 | ||
![]() |
dec4bf6b98 | ||
![]() |
e2c33fc40f | ||
![]() |
c74e59d1f4 | ||
![]() |
1fcb902715 | ||
![]() |
c08f98218c | ||
![]() |
c6377f6e38 | ||
![]() |
3cb0a5bd68 | ||
![]() |
95777d23e0 | ||
![]() |
e7dc16fd08 | ||
![]() |
495dec143c | ||
![]() |
4cc6dfa232 | ||
![]() |
d1452d4af4 | ||
![]() |
d68ca56b3a | ||
![]() |
49856d8d17 | ||
![]() |
902de72cc0 | ||
![]() |
76f6b8d104 | ||
![]() |
f111e605c4 | ||
![]() |
b358ed3a5b | ||
![]() |
88dbf639e0 | ||
![]() |
aa8b525b48 | ||
![]() |
c990bc61db | ||
![]() |
6d7588f236 | ||
![]() |
8257c7bf02 | ||
![]() |
946068967b | ||
![]() |
19f5684960 | ||
![]() |
6d62840aff | ||
![]() |
ab868ac979 | ||
![]() |
1d74e693ea | ||
![]() |
fa43d4202f | ||
![]() |
6b29860788 | ||
![]() |
36800eeaba | ||
![]() |
67acd174ac | ||
![]() |
b5edc64b2a | ||
![]() |
d00b2724cc | ||
![]() |
43f87c0b86 | ||
![]() |
7a43f48c95 | ||
![]() |
58a913b09d | ||
![]() |
cd03795f2c | ||
![]() |
36f8b5711d | ||
![]() |
f9c48e9ea9 | ||
![]() |
3b48f8c98e | ||
![]() |
cef1010cb5 | ||
![]() |
cb4875a3a7 | ||
![]() |
bbca708832 | ||
![]() |
05aec43ee3 | ||
![]() |
e8127756e0 | ||
![]() |
792595a46f | ||
![]() |
d7d7281c93 | ||
![]() |
21193c2fbf |
@ -1,11 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd web && npm install
|
||||
npm add -g pnpm@9.12.2
|
||||
cd web && pnpm install
|
||||
pipx install poetry
|
||||
|
||||
echo 'alias start-api="cd /workspaces/dify/api && poetry run python -m flask run --host 0.0.0.0 --port=5001 --debug"' >> ~/.bashrc
|
||||
echo 'alias start-worker="cd /workspaces/dify/api && poetry run python -m celery -A app.celery worker -P gevent -c 1 --loglevel INFO -Q dataset,generation,mail,ops_trace,app_deletion"' >> ~/.bashrc
|
||||
echo 'alias start-web="cd /workspaces/dify/web && npm run dev"' >> ~/.bashrc
|
||||
echo 'alias start-web="cd /workspaces/dify/web && pnpm dev"' >> ~/.bashrc
|
||||
echo 'alias start-containers="cd /workspaces/dify/docker && docker-compose -f docker-compose.middleware.yaml -p dify up -d"' >> ~/.bashrc
|
||||
|
||||
source /home/vscode/.bashrc
|
||||
source /home/vscode/.bashrc
|
||||
|
6
.github/workflows/style.yml
vendored
6
.github/workflows/style.yml
vendored
@ -76,16 +76,16 @@ jobs:
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
with:
|
||||
node-version: 20
|
||||
cache: yarn
|
||||
cache: pnpm
|
||||
cache-dependency-path: ./web/package.json
|
||||
|
||||
- name: Web dependencies
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
run: yarn install --frozen-lockfile
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Web style check
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
run: yarn run lint
|
||||
run: pnpm run lint
|
||||
|
||||
|
||||
superlinter:
|
||||
|
6
.github/workflows/tool-test-sdks.yaml
vendored
6
.github/workflows/tool-test-sdks.yaml
vendored
@ -32,10 +32,10 @@ jobs:
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: ''
|
||||
cache-dependency-path: 'yarn.lock'
|
||||
cache-dependency-path: 'pnpm-lock.yaml'
|
||||
|
||||
- name: Install Dependencies
|
||||
run: yarn install
|
||||
run: pnpm install
|
||||
|
||||
- name: Test
|
||||
run: yarn test
|
||||
run: pnpm test
|
||||
|
@ -38,11 +38,11 @@ jobs:
|
||||
|
||||
- name: Install dependencies
|
||||
if: env.FILES_CHANGED == 'true'
|
||||
run: yarn install --frozen-lockfile
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Run npm script
|
||||
if: env.FILES_CHANGED == 'true'
|
||||
run: npm run auto-gen-i18n
|
||||
run: pnpm run auto-gen-i18n
|
||||
|
||||
- name: Create Pull Request
|
||||
if: env.FILES_CHANGED == 'true'
|
||||
|
6
.github/workflows/web-tests.yml
vendored
6
.github/workflows/web-tests.yml
vendored
@ -34,13 +34,13 @@ jobs:
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
with:
|
||||
node-version: 20
|
||||
cache: yarn
|
||||
cache: pnpm
|
||||
cache-dependency-path: ./web/package.json
|
||||
|
||||
- name: Install dependencies
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
run: yarn install --frozen-lockfile
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Run tests
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
run: yarn test
|
||||
run: pnpm test
|
||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -189,4 +189,7 @@ pyrightconfig.json
|
||||
api/.vscode
|
||||
|
||||
.idea/
|
||||
.vscode
|
||||
.vscode
|
||||
|
||||
# pnpm
|
||||
/.pnpm-store
|
||||
|
@ -38,7 +38,6 @@ class AliYuqueDescribeDocumentContentTool(AliYuqueTool, BuiltinTool):
|
||||
book_id = index_page.get("data", {}).get("book", {}).get("id")
|
||||
if not book_id:
|
||||
raise Exception(f"can not parse book_id from {index_page}")
|
||||
|
||||
new_params["book_id"] = book_id
|
||||
new_params["id"] = doc_id
|
||||
data = self.request("GET", token, new_params, "/api/v2/repos/{book_id}/docs/{id}")
|
||||
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
"@babel/preset-env"
|
||||
]
|
||||
}
|
@ -10,6 +10,8 @@ NEXT_PUBLIC_API_PREFIX=http://localhost:5001/console/api
|
||||
# console or api domain.
|
||||
# example: http://udify.app/api
|
||||
NEXT_PUBLIC_PUBLIC_API_PREFIX=http://localhost:5001/api
|
||||
# The URL for MARKETPLACE
|
||||
NEXT_PUBLIC_MARKETPLACE_API_PREFIX=http://localhost:5002/api
|
||||
|
||||
# SENTRY
|
||||
NEXT_PUBLIC_SENTRY_DSN=
|
||||
|
@ -1,7 +0,0 @@
|
||||
/**/node_modules/*
|
||||
node_modules/
|
||||
|
||||
dist/
|
||||
build/
|
||||
out/
|
||||
.next/
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"extends": [
|
||||
"next",
|
||||
"@antfu",
|
||||
"plugin:storybook/recommended"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/consistent-type-definitions": [
|
||||
"error",
|
||||
"type"
|
||||
],
|
||||
"@typescript-eslint/no-var-requires": "off",
|
||||
"no-console": "off",
|
||||
"indent": "off",
|
||||
"@typescript-eslint/indent": [
|
||||
"error",
|
||||
2,
|
||||
{
|
||||
"SwitchCase": 1,
|
||||
"flatTernaryExpressions": false,
|
||||
"ignoredNodes": [
|
||||
"PropertyDefinition[decorators]",
|
||||
"TSUnionType",
|
||||
"FunctionExpression[params]:has(Identifier[decorators])"
|
||||
]
|
||||
}
|
||||
],
|
||||
"react-hooks/exhaustive-deps": "warn",
|
||||
"react/display-name": "warn"
|
||||
}
|
||||
}
|
9
web/.gitignore
vendored
9
web/.gitignore
vendored
@ -44,10 +44,9 @@ package-lock.json
|
||||
.pnp.cjs
|
||||
.pnp.loader.mjs
|
||||
.yarn/
|
||||
.yarnrc.yml
|
||||
|
||||
# pmpm
|
||||
pnpm-lock.yaml
|
||||
|
||||
.favorites.json
|
||||
*storybook.log
|
||||
|
||||
# storybook
|
||||
/storybook-static
|
||||
*storybook.log
|
||||
|
@ -1,6 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
# get the list of modified files
|
||||
files=$(git diff --cached --name-only)
|
||||
|
||||
@ -50,7 +47,7 @@ fi
|
||||
if $web_modified; then
|
||||
echo "Running ESLint on web module"
|
||||
cd ./web || exit 1
|
||||
npx lint-staged
|
||||
lint-staged
|
||||
|
||||
echo "Running unit tests check"
|
||||
modified_files=$(git diff --cached --name-only -- utils | grep -v '\.spec\.ts$' || true)
|
||||
@ -63,7 +60,7 @@ if $web_modified; then
|
||||
# check if the test file exists
|
||||
if [ -f "../$test_file" ]; then
|
||||
echo "Detected changes in $file, running corresponding unit tests..."
|
||||
npm run test "../$test_file"
|
||||
pnpm run test "../$test_file"
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Unit tests failed. Please fix the errors before committing."
|
||||
|
@ -1,19 +1,19 @@
|
||||
import type { StorybookConfig } from '@storybook/nextjs'
|
||||
|
||||
const config: StorybookConfig = {
|
||||
// stories: ['../stories/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
|
||||
stories: ['../app/components/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
|
||||
addons: [
|
||||
'@storybook/addon-onboarding',
|
||||
'@storybook/addon-links',
|
||||
'@storybook/addon-essentials',
|
||||
'@chromatic-com/storybook',
|
||||
'@storybook/addon-interactions',
|
||||
],
|
||||
framework: {
|
||||
name: '@storybook/nextjs',
|
||||
options: {},
|
||||
},
|
||||
staticDirs: ['../public'],
|
||||
// stories: ['../stories/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
|
||||
stories: ['../app/components/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
|
||||
addons: [
|
||||
'@storybook/addon-onboarding',
|
||||
'@storybook/addon-links',
|
||||
'@storybook/addon-essentials',
|
||||
'@chromatic-com/storybook',
|
||||
'@storybook/addon-interactions',
|
||||
],
|
||||
framework: {
|
||||
name: '@storybook/nextjs',
|
||||
options: {},
|
||||
},
|
||||
staticDirs: ['../public'],
|
||||
}
|
||||
export default config
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import type { Preview } from '@storybook/react'
|
||||
import { withThemeByDataAttribute } from '@storybook/addon-themes';
|
||||
import { withThemeByDataAttribute } from '@storybook/addon-themes'
|
||||
import I18nServer from '../app/components/i18n-server'
|
||||
|
||||
import '../app/styles/globals.css'
|
||||
@ -8,30 +8,30 @@ import '../app/styles/markdown.scss'
|
||||
import './storybook.css'
|
||||
|
||||
export const decorators = [
|
||||
withThemeByDataAttribute({
|
||||
themes: {
|
||||
light: 'light',
|
||||
dark: 'dark',
|
||||
},
|
||||
defaultTheme: 'light',
|
||||
attributeName: 'data-theme',
|
||||
}),
|
||||
Story => {
|
||||
return <I18nServer>
|
||||
<Story />
|
||||
</I18nServer>
|
||||
}
|
||||
];
|
||||
withThemeByDataAttribute({
|
||||
themes: {
|
||||
light: 'light',
|
||||
dark: 'dark',
|
||||
},
|
||||
defaultTheme: 'light',
|
||||
attributeName: 'data-theme',
|
||||
}),
|
||||
(Story) => {
|
||||
return <I18nServer>
|
||||
<Story />
|
||||
</I18nServer>
|
||||
},
|
||||
]
|
||||
|
||||
const preview: Preview = {
|
||||
parameters: {
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/i,
|
||||
},
|
||||
},
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/i,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export default preview
|
||||
|
3
web/.vscode/settings.example.json
vendored
3
web/.vscode/settings.example.json
vendored
@ -21,5 +21,6 @@
|
||||
"editor.defaultFormatter": "vscode.json-language-features"
|
||||
},
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||
"npm.packageManager": "pnpm"
|
||||
}
|
||||
|
@ -6,6 +6,9 @@ LABEL maintainer="takatost@gmail.com"
|
||||
# RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
||||
|
||||
RUN apk add --no-cache tzdata
|
||||
RUN npm install -g pnpm@9.12.2
|
||||
ENV PNPM_HOME="/pnpm"
|
||||
ENV PATH="$PNPM_HOME:$PATH"
|
||||
|
||||
|
||||
# install packages
|
||||
@ -14,12 +17,12 @@ FROM base AS packages
|
||||
WORKDIR /app/web
|
||||
|
||||
COPY package.json .
|
||||
COPY yarn.lock .
|
||||
COPY pnpm-lock.yaml .
|
||||
|
||||
# if you located in China, you can use taobao registry to speed up
|
||||
# RUN yarn install --frozen-lockfile --registry https://registry.npmmirror.com/
|
||||
# RUN pnpm install --frozen-lockfile --registry https://registry.npmmirror.com/
|
||||
|
||||
RUN yarn install --frozen-lockfile
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
# build resources
|
||||
FROM base AS builder
|
||||
@ -27,7 +30,7 @@ WORKDIR /app/web
|
||||
COPY --from=packages /app/web/ .
|
||||
COPY . .
|
||||
|
||||
RUN yarn build
|
||||
RUN pnpm build
|
||||
|
||||
|
||||
# production stage
|
||||
@ -57,8 +60,7 @@ COPY docker/entrypoint.sh ./entrypoint.sh
|
||||
|
||||
|
||||
# global runtime packages
|
||||
RUN yarn global add pm2 \
|
||||
&& yarn cache clean \
|
||||
RUN pnpm add -g pm2 \
|
||||
&& mkdir /.pm2 \
|
||||
&& chown -R 1001:0 /.pm2 /app/web \
|
||||
&& chmod -R g=u /.pm2 /app/web
|
||||
|
@ -6,14 +6,12 @@ This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next
|
||||
|
||||
### Run by source code
|
||||
|
||||
To start the web frontend service, you will need [Node.js v18.x (LTS)](https://nodejs.org/en) and [NPM version 8.x.x](https://www.npmjs.com/) or [Yarn](https://yarnpkg.com/).
|
||||
To start the web frontend service, you will need [Node.js v18.x (LTS)](https://nodejs.org/en) and [pnpm version 9.12.2](https://pnpm.io).
|
||||
|
||||
First, install the dependencies:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
# or
|
||||
yarn install --frozen-lockfile
|
||||
pnpm install
|
||||
```
|
||||
|
||||
Then, configure the environment variables. Create a file named `.env.local` in the current directory and copy the contents from `.env.example`. Modify the values of these environment variables according to your requirements:
|
||||
@ -43,9 +41,7 @@ NEXT_PUBLIC_SENTRY_DSN=
|
||||
Finally, run the development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
# or
|
||||
yarn dev
|
||||
pnpm run dev
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
@ -59,19 +55,19 @@ You can start editing the file under folder `app`. The page auto-updates as you
|
||||
First, build the app for production:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
pnpm run build
|
||||
```
|
||||
|
||||
Then, start the server:
|
||||
|
||||
```bash
|
||||
npm run start
|
||||
pnpm run start
|
||||
```
|
||||
|
||||
If you want to customize the host and port:
|
||||
|
||||
```bash
|
||||
npm run start --port=3001 --host=0.0.0.0
|
||||
pnpm run start --port=3001 --host=0.0.0.0
|
||||
```
|
||||
|
||||
## Storybook
|
||||
@ -81,7 +77,7 @@ This project uses [Storybook](https://storybook.js.org/) for UI component develo
|
||||
To start the storybook server, run:
|
||||
|
||||
```bash
|
||||
yarn storybook
|
||||
pnpm storybook
|
||||
```
|
||||
|
||||
Open [http://localhost:6006](http://localhost:6006) with your browser to see the result.
|
||||
@ -99,7 +95,7 @@ You can create a test file with a suffix of `.spec` beside the file that to be t
|
||||
Run test:
|
||||
|
||||
```bash
|
||||
npm run test
|
||||
pnpm run test
|
||||
```
|
||||
|
||||
If you are not familiar with writing tests, here is some code to refer to:
|
||||
|
@ -2,7 +2,7 @@ import React from 'react'
|
||||
import Main from '@/app/components/app/log-annotation'
|
||||
import { PageType } from '@/app/components/base/features/new-feature-panel/annotation-reply/type'
|
||||
|
||||
export type IProps = {
|
||||
export interface IProps {
|
||||
params: { appId: string }
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react'
|
||||
import { type Locale } from '@/i18n'
|
||||
import type { Locale } from '@/i18n'
|
||||
import DevelopMain from '@/app/components/develop'
|
||||
|
||||
export type IDevelopProps = {
|
||||
|
@ -4,7 +4,7 @@ import React from 'react'
|
||||
import cn from '@/utils/classnames'
|
||||
import Input from '@/app/components/base/input'
|
||||
|
||||
type Props = {
|
||||
interface Props {
|
||||
className?: string
|
||||
label: string
|
||||
labelClassName?: string
|
||||
|
@ -8,12 +8,11 @@ import { useBoolean } from 'ahooks'
|
||||
import {
|
||||
Cog8ToothIcon,
|
||||
// CommandLineIcon,
|
||||
Squares2X2Icon,
|
||||
// eslint-disable-next-line sort-imports
|
||||
PuzzlePieceIcon,
|
||||
DocumentTextIcon,
|
||||
PaperClipIcon,
|
||||
PuzzlePieceIcon,
|
||||
QuestionMarkCircleIcon,
|
||||
Squares2X2Icon,
|
||||
} from '@heroicons/react/24/outline'
|
||||
import {
|
||||
Cog8ToothIcon as Cog8ToothSolidIcon,
|
||||
|
18
web/app/(commonLayout)/plugins/page.tsx
Normal file
18
web/app/(commonLayout)/plugins/page.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import PluginPage from '@/app/components/plugins/plugin-page'
|
||||
import PluginsPanel from '@/app/components/plugins/plugin-page/plugins-panel'
|
||||
import Marketplace from '@/app/components/plugins/marketplace'
|
||||
|
||||
const PluginList = async () => {
|
||||
return (
|
||||
<PluginPage
|
||||
plugins={<PluginsPanel />}
|
||||
marketplace={<Marketplace />}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export const metadata = {
|
||||
title: 'Plugins - Dify',
|
||||
}
|
||||
|
||||
export default PluginList
|
14
web/app/(commonLayout)/plugins/test/card/actions.ts
Normal file
14
web/app/(commonLayout)/plugins/test/card/actions.ts
Normal file
@ -0,0 +1,14 @@
|
||||
'use server'
|
||||
|
||||
import { revalidatePath } from 'next/cache'
|
||||
|
||||
// Server Actions
|
||||
export async function handleDelete() {
|
||||
// revalidatePath only invalidates the cache when the included path is next visited.
|
||||
revalidatePath('/')
|
||||
}
|
||||
|
||||
export async function fetchPluginDetail(org: string, name: string) {
|
||||
// Fetch plugin detail TODO
|
||||
return { org, name }
|
||||
}
|
74
web/app/(commonLayout)/plugins/test/card/page.tsx
Normal file
74
web/app/(commonLayout)/plugins/test/card/page.tsx
Normal file
@ -0,0 +1,74 @@
|
||||
import { handleDelete } from './actions'
|
||||
import Card from '@/app/components/plugins/card'
|
||||
import { customTool, extensionDallE, modelGPT4, toolNotion } from '@/app/components/plugins/card/card-mock'
|
||||
import PluginItem from '@/app/components/plugins/plugin-item'
|
||||
import CardMoreInfo from '@/app/components/plugins/card/card-more-info'
|
||||
import ProviderCard from '@/app/components/plugins/provider-card'
|
||||
import Badge from '@/app/components/base/badge'
|
||||
|
||||
const PluginList = async () => {
|
||||
const pluginList = [toolNotion, extensionDallE, modelGPT4, customTool]
|
||||
|
||||
return (
|
||||
<div className='pb-3 bg-white'>
|
||||
<div className='mx-3 '>
|
||||
<h2 className='my-3'>Dify Plugin list</h2>
|
||||
<div className='grid grid-cols-2 gap-3'>
|
||||
{pluginList.map((plugin, index) => (
|
||||
<PluginItem
|
||||
key={index}
|
||||
payload={plugin as any}
|
||||
onDelete={handleDelete}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<h2 className='my-3'>Install Plugin / Package under bundle</h2>
|
||||
<div className='w-[512px] rounded-2xl bg-background-section-burn p-2'>
|
||||
<Card
|
||||
payload={toolNotion as any}
|
||||
descriptionLineRows={1}
|
||||
titleLeft={
|
||||
<Badge className='ml-1' text={toolNotion.version} />
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<h3 className='my-1'>Installed</h3>
|
||||
<div className='w-[512px] rounded-2xl bg-background-section-burn p-2'>
|
||||
<Card
|
||||
payload={toolNotion as any}
|
||||
descriptionLineRows={1}
|
||||
installed
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h3 className='my-1'>Install model provide</h3>
|
||||
<div className='grid grid-cols-2 gap-3'>
|
||||
{pluginList.map((plugin, index) => (
|
||||
<ProviderCard key={index} payload={plugin as any} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className='my-3 h-[px] bg-gray-50'></div>
|
||||
<h2 className='my-3'>Marketplace Plugin list</h2>
|
||||
<div className='grid grid-cols-4 gap-3'>
|
||||
{pluginList.map((plugin, index) => (
|
||||
<Card
|
||||
key={index}
|
||||
payload={plugin as any}
|
||||
footer={
|
||||
<CardMoreInfo downloadCount={index % 2 === 0 ? 1234 : 6} tags={index % 2 === 0 ? ['Search', 'Tag that has very very long name', 'Productivity', 'Tag2'] : []} />
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const metadata = {
|
||||
title: 'Plugins - Card',
|
||||
}
|
||||
|
||||
export default PluginList
|
20
web/app/(commonLayout)/plugins/test/other/page.tsx
Normal file
20
web/app/(commonLayout)/plugins/test/other/page.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
'use client'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import UpdatePlugin from '@/app/components/plugins/update-plugin'
|
||||
|
||||
const Page = () => {
|
||||
const [isShowUpdateModal, {
|
||||
setTrue: showUpdateModal,
|
||||
setFalse: hideUpdateModal,
|
||||
}] = useBoolean(false)
|
||||
return (
|
||||
<div>
|
||||
<div onClick={showUpdateModal}>Show Upgrade</div>
|
||||
{isShowUpdateModal && (
|
||||
<UpdatePlugin onHide={hideUpdateModal} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Page
|
39
web/app/(commonLayout)/plugins/test/tools-picker/page.tsx
Normal file
39
web/app/(commonLayout)/plugins/test/tools-picker/page.tsx
Normal file
@ -0,0 +1,39 @@
|
||||
'use client'
|
||||
import { useEffect, useState } from 'react'
|
||||
import AllTools from '@/app/components/workflow/block-selector/all-tools'
|
||||
import {
|
||||
fetchAllBuiltInTools,
|
||||
fetchAllCustomTools,
|
||||
fetchAllWorkflowTools,
|
||||
} from '@/service/tools'
|
||||
import type { ToolWithProvider } from '@/app/components/workflow/types'
|
||||
|
||||
const ToolsPicker = () => {
|
||||
const [buildInTools, setBuildInTools] = useState<ToolWithProvider[]>([])
|
||||
const [customTools, setCustomTools] = useState<ToolWithProvider[]>([])
|
||||
const [workflowTools, setWorkflowTools] = useState<ToolWithProvider[]>([])
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const buildInTools = await fetchAllBuiltInTools()
|
||||
const customTools = await fetchAllCustomTools()
|
||||
const workflowTools = await fetchAllWorkflowTools()
|
||||
setBuildInTools(buildInTools)
|
||||
setCustomTools(customTools)
|
||||
setWorkflowTools(workflowTools)
|
||||
})()
|
||||
})
|
||||
return (
|
||||
<div className="relative mt-5 mx-auto w-[320px] bg-white">
|
||||
<AllTools
|
||||
searchText=""
|
||||
onSelect={() => { }}
|
||||
buildInTools={buildInTools}
|
||||
customTools={customTools}
|
||||
workflowTools={workflowTools}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ToolsPicker
|
@ -1,8 +1,7 @@
|
||||
'use client'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Fragment } from 'react'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { Menu, Transition } from '@headlessui/react'
|
||||
import { Menu, MenuButton, MenuItem, MenuItems, Transition } from '@headlessui/react'
|
||||
import Avatar from '@/app/components/base/avatar'
|
||||
import { logout } from '@/service/common'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
@ -35,7 +34,7 @@ export default function AppSelector() {
|
||||
({ open }) => (
|
||||
<>
|
||||
<div>
|
||||
<Menu.Button
|
||||
<MenuButton
|
||||
className={`
|
||||
inline-flex items-center
|
||||
rounded-[20px] p-1x text-sm
|
||||
@ -45,10 +44,9 @@ export default function AppSelector() {
|
||||
`}
|
||||
>
|
||||
<Avatar name={userProfile.name} size={32} />
|
||||
</Menu.Button>
|
||||
</MenuButton>
|
||||
</div>
|
||||
<Transition
|
||||
as={Fragment}
|
||||
enter="transition ease-out duration-100"
|
||||
enterFrom="transform opacity-0 scale-95"
|
||||
enterTo="transform opacity-100 scale-100"
|
||||
@ -56,14 +54,14 @@ export default function AppSelector() {
|
||||
leaveFrom="transform opacity-100 scale-100"
|
||||
leaveTo="transform opacity-0 scale-95"
|
||||
>
|
||||
<Menu.Items
|
||||
<MenuItems
|
||||
className="
|
||||
absolute -right-2 -top-1 w-60 max-w-80
|
||||
divide-y divide-gray-100 origin-top-right rounded-lg bg-white
|
||||
shadow-lg
|
||||
"
|
||||
>
|
||||
<Menu.Item>
|
||||
<MenuItem>
|
||||
<div className='p-1'>
|
||||
<div className='flex flex-nowrap items-center px-3 py-2'>
|
||||
<div className='grow'>
|
||||
@ -73,8 +71,8 @@ export default function AppSelector() {
|
||||
<Avatar name={userProfile.name} size={32} />
|
||||
</div>
|
||||
</div>
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
</MenuItem>
|
||||
<MenuItem>
|
||||
<div className='p-1' onClick={() => handleLogout()}>
|
||||
<div
|
||||
className='flex items-center justify-start h-9 px-3 rounded-lg cursor-pointer group hover:bg-gray-50'
|
||||
@ -83,8 +81,8 @@ export default function AppSelector() {
|
||||
<div className='font-normal text-[14px] text-gray-700'>{t('common.userProfile.logout')}</div>
|
||||
</div>
|
||||
</div>
|
||||
</Menu.Item>
|
||||
</Menu.Items>
|
||||
</MenuItem>
|
||||
</MenuItems>
|
||||
</Transition>
|
||||
</>
|
||||
)
|
||||
|
@ -6,11 +6,11 @@ import useSWR from 'swr'
|
||||
import Input from '@/app/components/base/input'
|
||||
import { fetchAnnotationsCount } from '@/service/log'
|
||||
|
||||
export type QueryParam = {
|
||||
export interface QueryParam {
|
||||
keyword?: string
|
||||
}
|
||||
|
||||
type IFilterProps = {
|
||||
interface IFilterProps {
|
||||
appId: string
|
||||
queryParams: QueryParam
|
||||
setQueryParams: (v: QueryParam) => void
|
||||
|
@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React, { Fragment, useEffect, useState } from 'react'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
RiAddLine,
|
||||
@ -9,7 +9,7 @@ import { useContext } from 'use-context-selector'
|
||||
import {
|
||||
useCSVDownloader,
|
||||
} from 'react-papaparse'
|
||||
import { Menu, Transition } from '@headlessui/react'
|
||||
import { Menu, MenuButton, MenuItems, Transition } from '@headlessui/react'
|
||||
import Button from '../../../base/button'
|
||||
import AddAnnotationModal from '../add-annotation-modal'
|
||||
import type { AnnotationItemBasic } from '../type'
|
||||
@ -87,13 +87,12 @@ const HeaderOptions: FC<Props> = ({
|
||||
<span className={s.actionName}>{t('appAnnotation.table.header.bulkImport')}</span>
|
||||
</button>
|
||||
<Menu as="div" className="relative w-full h-full">
|
||||
<Menu.Button className={s.actionItem}>
|
||||
<MenuButton className={s.actionItem}>
|
||||
<FileDownload02 className={s.actionItemIcon} />
|
||||
<span className={s.actionName}>{t('appAnnotation.table.header.bulkExport')}</span>
|
||||
<ChevronRight className='shrink-0 w-[14px] h-[14px] text-gray-500' />
|
||||
</Menu.Button>
|
||||
</MenuButton>
|
||||
<Transition
|
||||
as={Fragment}
|
||||
enter="transition ease-out duration-100"
|
||||
enterFrom="transform opacity-0 scale-95"
|
||||
enterTo="transform opacity-100 scale-100"
|
||||
@ -101,7 +100,7 @@ const HeaderOptions: FC<Props> = ({
|
||||
leaveFrom="transform opacity-100 scale-100"
|
||||
leaveTo="transform opacity-0 scale-95"
|
||||
>
|
||||
<Menu.Items
|
||||
<MenuItems
|
||||
className={cn(
|
||||
`
|
||||
absolute top-[1px] py-1 min-w-[100px] z-10 bg-white border-[0.5px] border-gray-200
|
||||
@ -126,7 +125,7 @@ const HeaderOptions: FC<Props> = ({
|
||||
<button disabled={annotationUnavailable} className={cn(s.actionItem, '!border-0')} onClick={JSONLOutput}>
|
||||
<span className={s.actionName}>JSONL</span>
|
||||
</button>
|
||||
</Menu.Items>
|
||||
</MenuItems>
|
||||
</Transition>
|
||||
</Menu>
|
||||
</div>
|
||||
|
@ -27,7 +27,7 @@ import AnnotationFullModal from '@/app/components/billing/annotation-full/modal'
|
||||
import { Settings04 } from '@/app/components/base/icons/src/vender/line/general'
|
||||
import type { App } from '@/types/app'
|
||||
|
||||
type Props = {
|
||||
interface Props {
|
||||
appDetail: App
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ import RemoveAnnotationConfirmModal from './remove-annotation-confirm-modal'
|
||||
import cn from '@/utils/classnames'
|
||||
import useTimestamp from '@/hooks/use-timestamp'
|
||||
|
||||
type Props = {
|
||||
interface Props {
|
||||
list: AnnotationItem[]
|
||||
onRemove: (id: string) => void
|
||||
onView: (item: AnnotationItem) => void
|
||||
|
@ -3,7 +3,7 @@ import type { FC, ReactNode } from 'react'
|
||||
import React from 'react'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
export type IFeaturePanelProps = {
|
||||
export interface IFeaturePanelProps {
|
||||
className?: string
|
||||
headerIcon?: ReactNode
|
||||
title: ReactNode
|
||||
|
@ -9,7 +9,7 @@ import { MessageClockCircle } from '@/app/components/base/icons/src/vender/solid
|
||||
import I18n from '@/context/i18n'
|
||||
import { LanguagesSupported } from '@/i18n/language'
|
||||
|
||||
type Props = {
|
||||
interface Props {
|
||||
showWarning: boolean
|
||||
onShowEditModal: () => void
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import ConfirmAddVar from './confirm-add-var'
|
||||
import s from './style.module.css'
|
||||
import PromptEditorHeightResizeWrap from './prompt-editor-height-resize-wrap'
|
||||
import cn from '@/utils/classnames'
|
||||
import { type PromptVariable } from '@/models/debug'
|
||||
import type { PromptVariable } from '@/models/debug'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import type { CompletionParams } from '@/types/app'
|
||||
import { AppType } from '@/types/app'
|
||||
|
@ -3,7 +3,7 @@ import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
type Props = {
|
||||
interface Props {
|
||||
className?: string
|
||||
title: string
|
||||
children: JSX.Element
|
||||
|
@ -23,7 +23,7 @@ import { DEFAULT_VALUE_MAX_LEN } from '@/config'
|
||||
|
||||
const TEXT_MAX_LENGTH = 256
|
||||
|
||||
export type IConfigModalProps = {
|
||||
export interface IConfigModalProps {
|
||||
isCreate?: boolean
|
||||
payload?: InputVar
|
||||
isShow: boolean
|
||||
|
@ -3,7 +3,7 @@ import type { FC } from 'react'
|
||||
import React, { useEffect } from 'react'
|
||||
import Input from '@/app/components/base/input'
|
||||
|
||||
export type IConfigStringProps = {
|
||||
export interface IConfigStringProps {
|
||||
value: number | undefined
|
||||
maxLength: number
|
||||
modelId: string
|
||||
@ -28,7 +28,7 @@ const ConfigString: FC<IConfigStringProps> = ({
|
||||
min={1}
|
||||
value={value || ''}
|
||||
onChange={(e) => {
|
||||
let value = parseInt(e.target.value, 10)
|
||||
let value = Number.parseInt(e.target.value, 10)
|
||||
if (value > maxLength)
|
||||
value = maxLength
|
||||
|
||||
|
@ -3,7 +3,6 @@ import type { FC } from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import type { Timeout } from 'ahooks/lib/useRequest/src/types'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import produce from 'immer'
|
||||
import {
|
||||
@ -34,7 +33,7 @@ import { InputVarType } from '@/app/components/workflow/types'
|
||||
|
||||
export const ADD_EXTERNAL_DATA_TOOL = 'ADD_EXTERNAL_DATA_TOOL'
|
||||
|
||||
type ExternalDataToolParams = {
|
||||
interface ExternalDataToolParams {
|
||||
key: string
|
||||
type: string
|
||||
index: number
|
||||
@ -44,13 +43,13 @@ type ExternalDataToolParams = {
|
||||
icon_background?: string
|
||||
}
|
||||
|
||||
export type IConfigVarProps = {
|
||||
export interface IConfigVarProps {
|
||||
promptVariables: PromptVariable[]
|
||||
readonly?: boolean
|
||||
onPromptVariablesChange?: (promptVariables: PromptVariable[]) => void
|
||||
}
|
||||
|
||||
let conflictTimer: Timeout
|
||||
let conflictTimer: number
|
||||
|
||||
const ConfigVar: FC<IConfigVarProps> = ({ promptVariables, readonly, onPromptVariablesChange }) => {
|
||||
const { t } = useTranslation()
|
||||
@ -107,7 +106,7 @@ const ConfigVar: FC<IConfigVarProps> = ({ promptVariables, readonly, onPromptVar
|
||||
onPromptVariablesChange?.(newPromptVariables)
|
||||
}
|
||||
const updatePromptKey = (index: number, newKey: string) => {
|
||||
clearTimeout(conflictTimer)
|
||||
window.clearTimeout(conflictTimer)
|
||||
const { isValid, errorKey, errorMessageKey } = checkKeys([newKey], true)
|
||||
if (!isValid) {
|
||||
Toast.notify({
|
||||
@ -127,7 +126,7 @@ const ConfigVar: FC<IConfigVarProps> = ({ promptVariables, readonly, onPromptVar
|
||||
return item
|
||||
})
|
||||
|
||||
conflictTimer = setTimeout(() => {
|
||||
conflictTimer = window.setTimeout(() => {
|
||||
const isKeyExists = promptVariables.some(item => item.key?.trim() === newKey.trim())
|
||||
if (isKeyExists) {
|
||||
Toast.notify({
|
||||
|
@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next'
|
||||
import cn from '@/utils/classnames'
|
||||
import type { InputVarType } from '@/app/components/workflow/types'
|
||||
import InputVarTypeIcon from '@/app/components/workflow/nodes/_base/components/input-var-type-icon'
|
||||
export type ISelectTypeItemProps = {
|
||||
export interface ISelectTypeItemProps {
|
||||
type: InputVarType
|
||||
selected: boolean
|
||||
onClick: () => void
|
||||
|
@ -106,23 +106,22 @@ const SettingBuiltInTool: FC<Props> = ({
|
||||
</div>
|
||||
|
||||
{infoSchemas.length > 0 && (
|
||||
<div className='mt-6'>
|
||||
<div className='flex items-center mb-4 leading-[18px] text-xs font-semibold text-gray-500 uppercase'>
|
||||
<div className='mr-3'>{t('tools.setBuiltInTools.parameters')}</div>
|
||||
<div className='grow w-0 h-px bg-[#f3f4f6]'></div>
|
||||
<div className='my-2'>
|
||||
<div className='pt-3 text-text-secondary system-sm-semibold-uppercase'>
|
||||
{t('tools.setBuiltInTools.parameters')}
|
||||
</div>
|
||||
<div className='space-y-4'>
|
||||
<div className='py-2 space-y-3'>
|
||||
{infoSchemas.map((item: any, index) => (
|
||||
<div key={index}>
|
||||
<div className='flex items-center space-x-2 leading-[18px]'>
|
||||
<div className='text-[13px] font-semibold text-gray-900'>{item.label[language]}</div>
|
||||
<div className='text-xs font-medium text-gray-500'>{item.type === 'number-input' ? t('tools.setBuiltInTools.number') : t('tools.setBuiltInTools.string')}</div>
|
||||
<div key={index} className='py-1'>
|
||||
<div className='flex items-center gap-2'>
|
||||
<div className='text-text-secondary code-sm-semibold'>{item.label[language]}</div>
|
||||
<div className='text-text-tertiary system-xs-regular'>{item.type === 'number-input' ? t('tools.setBuiltInTools.number') : t('tools.setBuiltInTools.string')}</div>
|
||||
{item.required && (
|
||||
<div className='text-xs font-medium text-[#EC4A0A]'>{t('tools.setBuiltInTools.required')}</div>
|
||||
<div className='text-text-warning-secondary system-xs-medium'>{t('tools.setBuiltInTools.required')}</div>
|
||||
)}
|
||||
</div>
|
||||
{item.human_description && (
|
||||
<div className='mt-1 leading-[18px] text-xs font-normal text-gray-600'>
|
||||
<div className='mt-0.5 text-text-tertiary system-xs-regular'>
|
||||
{item.human_description?.[language]}
|
||||
</div>
|
||||
)}
|
||||
@ -192,9 +191,9 @@ const SettingBuiltInTool: FC<Props> = ({
|
||||
</>)}
|
||||
</div>
|
||||
)}
|
||||
panelClassName='mt-[65px] !w-[405px]'
|
||||
maxWidthClassName='!max-w-[405px]'
|
||||
height='calc(100vh - 65px)'
|
||||
panelClassName='mt-[64px] mb-2 !w-[420px]'
|
||||
maxWidthClassName='!max-w-[420px]'
|
||||
height='calc(100vh - 64px)'
|
||||
headerClassName='!border-b-black/5'
|
||||
body={
|
||||
<div className='h-full pt-3'>
|
||||
@ -203,7 +202,7 @@ const SettingBuiltInTool: FC<Props> = ({
|
||||
<Loading type='app' />
|
||||
</div>
|
||||
: (<div className='flex flex-col h-full'>
|
||||
<div className='grow h-0 overflow-y-auto px-6'>
|
||||
<div className='grow h-0 overflow-y-auto px-4'>
|
||||
{isInfoActive ? infoUI : settingUI}
|
||||
</div>
|
||||
{!readonly && !isInfoActive && (
|
||||
|
@ -34,7 +34,7 @@ import { LoveMessage } from '@/app/components/base/icons/src/vender/features'
|
||||
import type { AutomaticRes } from '@/service/debug'
|
||||
import { Generator } from '@/app/components/base/icons/src/vender/other'
|
||||
|
||||
export type IGetAutomaticResProps = {
|
||||
export interface IGetAutomaticResProps {
|
||||
mode: AppType
|
||||
model: Model
|
||||
isShow: boolean
|
||||
|
@ -11,7 +11,7 @@ import AgentTools from './agent/agent-tools'
|
||||
import ConfigContext from '@/context/debug-configuration'
|
||||
import ConfigPrompt from '@/app/components/app/configuration/config-prompt'
|
||||
import ConfigVar from '@/app/components/app/configuration/config-var'
|
||||
import { type ModelConfig, type PromptVariable } from '@/models/debug'
|
||||
import type { ModelConfig, PromptVariable } from '@/models/debug'
|
||||
import type { AppType } from '@/types/app'
|
||||
import { ModelModeType } from '@/types/app'
|
||||
|
||||
|
@ -25,7 +25,7 @@ import { useSelectedDatasetsMode } from '@/app/components/workflow/nodes/knowled
|
||||
import Switch from '@/app/components/base/switch'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
|
||||
type Props = {
|
||||
interface Props {
|
||||
datasetConfigs: DatasetConfigs
|
||||
onChange: (configs: DatasetConfigs, isRetrievalModeChange?: boolean) => void
|
||||
isInWorkflow?: boolean
|
||||
|
@ -18,7 +18,7 @@ import {
|
||||
getMultipleRetrievalConfig,
|
||||
} from '@/app/components/workflow/nodes/knowledge-retrieval/utils'
|
||||
|
||||
type ParamsConfigProps = {
|
||||
interface ParamsConfigProps {
|
||||
disabled?: boolean
|
||||
selectedDatasets: DataSet[]
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ import { ModelTypeEnum } from '@/app/components/header/account-setting/model-pro
|
||||
import { fetchMembers } from '@/service/common'
|
||||
import type { Member } from '@/models/common'
|
||||
|
||||
type SettingsModalProps = {
|
||||
interface SettingsModalProps {
|
||||
currentDataset: DataSet
|
||||
onCancel: () => void
|
||||
onSave: (newDataset: DataSet) => void
|
||||
|
@ -30,7 +30,7 @@ import { ModelFeatureEnum } from '@/app/components/header/account-setting/model-
|
||||
import { useFeatures } from '@/app/components/base/features/hooks'
|
||||
import type { InputForm } from '@/app/components/base/chat/chat/type'
|
||||
|
||||
type ChatItemProps = {
|
||||
interface ChatItemProps {
|
||||
modelAndParameter: ModelAndParameter
|
||||
}
|
||||
const ChatItem: FC<ChatItemProps> = ({
|
||||
|
@ -15,7 +15,7 @@ import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { useFeatures } from '@/app/components/base/features/hooks'
|
||||
|
||||
type TextGenerationItemProps = {
|
||||
interface TextGenerationItemProps {
|
||||
modelAndParameter: ModelAndParameter
|
||||
}
|
||||
const TextGenerationItem: FC<TextGenerationItemProps> = ({
|
||||
|
@ -27,10 +27,10 @@ import { useFeatures } from '@/app/components/base/features/hooks'
|
||||
import { getLastAnswer } from '@/app/components/base/chat/utils'
|
||||
import type { InputForm } from '@/app/components/base/chat/chat/type'
|
||||
|
||||
type DebugWithSingleModelProps = {
|
||||
interface DebugWithSingleModelProps {
|
||||
checkCanSend?: () => boolean
|
||||
}
|
||||
export type DebugWithSingleModelRefType = {
|
||||
export interface DebugWithSingleModelRefType {
|
||||
handleRestart: () => void
|
||||
}
|
||||
const DebugWithSingleModel = forwardRef<DebugWithSingleModelRefType, DebugWithSingleModelProps>(({
|
||||
|
@ -48,7 +48,7 @@ import PromptLogModal from '@/app/components/base/prompt-log-modal'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import { useFeatures, useFeaturesStore } from '@/app/components/base/features/hooks'
|
||||
|
||||
type IDebug = {
|
||||
interface IDebug {
|
||||
isAPIKeySet: boolean
|
||||
onSetting: () => void
|
||||
inputs: Inputs
|
||||
|
@ -59,7 +59,7 @@ import {
|
||||
useTextGenerationCurrentProviderAndModelAndModelList,
|
||||
} from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
import { fetchCollectionList } from '@/service/tools'
|
||||
import { type Collection } from '@/app/components/tools/types'
|
||||
import type { Collection } from '@/app/components/tools/types'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import {
|
||||
getMultipleRetrievalConfig,
|
||||
@ -72,7 +72,7 @@ import { SupportUploadFileTypes } from '@/app/components/workflow/types'
|
||||
import NewFeaturePanel from '@/app/components/base/features/new-feature-panel'
|
||||
import { fetchFileUploadConfig } from '@/service/common'
|
||||
|
||||
type PublishConfig = {
|
||||
interface PublishConfig {
|
||||
modelConfig: ModelConfig
|
||||
completionParams: FormValue
|
||||
}
|
||||
@ -156,7 +156,6 @@ const Configuration: FC = () => {
|
||||
const setCompletionParams = (value: FormValue) => {
|
||||
const params = { ...value }
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
if ((!params.stop || params.stop.length === 0) && (modeModeTypeRef.current === ModelModeType.completion)) {
|
||||
params.stop = getTempStop()
|
||||
setTempStop([])
|
||||
@ -351,7 +350,6 @@ const Configuration: FC = () => {
|
||||
const [canReturnToSimpleMode, setCanReturnToSimpleMode] = useState(true)
|
||||
const setPromptMode = async (mode: PromptMode) => {
|
||||
if (mode === PromptMode.advanced) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
await migrateToDefaultPrompt()
|
||||
setCanReturnToSimpleMode(true)
|
||||
}
|
||||
@ -589,7 +587,6 @@ const Configuration: FC = () => {
|
||||
annotation_reply: modelConfig.annotation_reply,
|
||||
external_data_tools: modelConfig.external_data_tools,
|
||||
dataSets: datasets || [],
|
||||
// eslint-disable-next-line multiline-ternary
|
||||
agentConfig: res.mode === 'agent-chat' ? {
|
||||
max_iteration: DEFAULT_AGENT_SETTING.max_iteration,
|
||||
...modelConfig.agent_mode,
|
||||
|
@ -23,7 +23,7 @@ import { DEFAULT_VALUE_MAX_LEN } from '@/config'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
export type IPromptValuePanelProps = {
|
||||
export interface IPromptValuePanelProps {
|
||||
appType: AppType
|
||||
onSend?: () => void
|
||||
inputs: Inputs
|
||||
|
@ -21,13 +21,13 @@ import { useToastContext } from '@/app/components/base/toast'
|
||||
import AppIcon from '@/app/components/base/app-icon'
|
||||
|
||||
const systemTypes = ['api']
|
||||
type ExternalDataToolModalProps = {
|
||||
interface ExternalDataToolModalProps {
|
||||
data: ExternalDataTool
|
||||
onCancel: () => void
|
||||
onSave: (externalDataTool: ExternalDataTool) => void
|
||||
onValidateBeforeSave?: (externalDataTool: ExternalDataTool) => boolean
|
||||
}
|
||||
type Provider = {
|
||||
interface Provider {
|
||||
key: string
|
||||
name: string
|
||||
form_schema?: CodeBasedExtensionItem['form_schema']
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Fragment, useCallback } from 'react'
|
||||
import { useCallback } from 'react'
|
||||
import type { ReactNode } from 'react'
|
||||
import { Dialog, Transition } from '@headlessui/react'
|
||||
import { Dialog, DialogPanel, Transition, TransitionChild } from '@headlessui/react'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
type DialogProps = {
|
||||
@ -18,10 +18,10 @@ const NewAppDialog = ({
|
||||
}: DialogProps) => {
|
||||
const close = useCallback(() => onClose?.(), [onClose])
|
||||
return (
|
||||
<Transition appear show={show} as={Fragment}>
|
||||
<Transition appear show={show}>
|
||||
<Dialog as="div" className="relative z-40" onClose={close}>
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
<TransitionChild
|
||||
as={'div'}
|
||||
enter="ease-out duration-300"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
@ -30,12 +30,11 @@ const NewAppDialog = ({
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="fixed inset-0 bg-black bg-opacity-25" />
|
||||
</Transition.Child>
|
||||
</TransitionChild>
|
||||
|
||||
<div className="fixed inset-0">
|
||||
<div className="flex flex-col items-center justify-center min-h-full pt-[56px]">
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
<TransitionChild
|
||||
enter="ease-out duration-300"
|
||||
enterFrom="opacity-0 scale-95"
|
||||
enterTo="opacity-100 scale-100"
|
||||
@ -43,10 +42,10 @@ const NewAppDialog = ({
|
||||
leaveFrom="opacity-100 scale-100"
|
||||
leaveTo="opacity-0 scale-95"
|
||||
>
|
||||
<Dialog.Panel className={cn('grow relative w-full h-[calc(100vh-56px)] p-0 overflow-hidden text-left align-middle transition-all transform bg-white shadow-xl rounded-t-xl', className)}>
|
||||
<DialogPanel className={cn('grow relative w-full h-[calc(100vh-56px)] p-0 overflow-hidden text-left align-middle transition-all transform bg-white shadow-xl rounded-t-xl', className)}>
|
||||
{children}
|
||||
</Dialog.Panel>
|
||||
</Transition.Child>
|
||||
</DialogPanel>
|
||||
</TransitionChild>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
|
@ -29,7 +29,7 @@ import Tooltip from '@/app/components/base/tooltip'
|
||||
import { NEED_REFRESH_APP_LIST_KEY } from '@/config'
|
||||
import { getRedirection } from '@/utils/app-redirection'
|
||||
|
||||
type CreateAppDialogProps = {
|
||||
interface CreateAppDialogProps {
|
||||
show: boolean
|
||||
onSuccess: () => void
|
||||
onClose: () => void
|
||||
|
@ -22,7 +22,7 @@ import { NEED_REFRESH_APP_LIST_KEY } from '@/config'
|
||||
import { getRedirection } from '@/utils/app-redirection'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
type CreateFromDSLModalProps = {
|
||||
interface CreateFromDSLModalProps {
|
||||
show: boolean
|
||||
onSuccess?: () => void
|
||||
onClose: () => void
|
||||
|
@ -13,7 +13,7 @@ import { useProviderContext } from '@/context/provider-context'
|
||||
import AppsFull from '@/app/components/billing/apps-full-in-dialog'
|
||||
import type { AppIconType } from '@/types/app'
|
||||
|
||||
export type DuplicateAppModalProps = {
|
||||
export interface DuplicateAppModalProps {
|
||||
appName: string
|
||||
icon_type: AppIconType | null
|
||||
icon: string
|
||||
|
@ -12,7 +12,7 @@ import { PageType } from '@/app/components/base/features/new-feature-panel/annot
|
||||
import TabSlider from '@/app/components/base/tab-slider-plain'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
|
||||
type Props = {
|
||||
interface Props {
|
||||
pageType: PageType
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ export const TIME_PERIOD_LIST = [
|
||||
{ value: 'all', name: 'allTime' },
|
||||
]
|
||||
|
||||
type IFilterProps = {
|
||||
interface IFilterProps {
|
||||
isChatMode?: boolean
|
||||
appId: string
|
||||
queryParams: QueryParam
|
||||
|
@ -17,11 +17,11 @@ import Loading from '@/app/components/base/loading'
|
||||
import { fetchChatConversations, fetchCompletionConversations } from '@/service/log'
|
||||
import { APP_PAGE_LIMIT } from '@/config'
|
||||
import type { App, AppMode } from '@/types/app'
|
||||
export type ILogsProps = {
|
||||
export interface ILogsProps {
|
||||
appDetail: App
|
||||
}
|
||||
|
||||
export type QueryParam = {
|
||||
export interface QueryParam {
|
||||
period?: number | string
|
||||
annotation_status?: string
|
||||
keyword?: string
|
||||
|
@ -47,7 +47,7 @@ import { getProcessedFilesFromResponse } from '@/app/components/base/file-upload
|
||||
dayjs.extend(utc)
|
||||
dayjs.extend(timezone)
|
||||
|
||||
type IConversationList = {
|
||||
interface IConversationList {
|
||||
logs?: ChatConversationsResponse | CompletionConversationsResponse
|
||||
appDetail: App
|
||||
onRefresh: () => void
|
||||
@ -55,7 +55,7 @@ type IConversationList = {
|
||||
|
||||
const defaultValue = 'N/A'
|
||||
|
||||
type IDrawerContext = {
|
||||
interface IDrawerContext {
|
||||
onClose: () => void
|
||||
appDetail?: App
|
||||
}
|
||||
@ -158,7 +158,7 @@ const getFormattedChatList = (messages: ChatMessage[], conversationId: string, t
|
||||
// const displayedParams = CompletionParams.slice(0, -2)
|
||||
const validatedParams = ['temperature', 'top_p', 'presence_penalty', 'frequency_penalty']
|
||||
|
||||
type IDetailPanel = {
|
||||
interface IDetailPanel {
|
||||
detail: any
|
||||
onFeedback: FeedbackFunc
|
||||
onSubmitAnnotation: SubmitAnnotationFunc
|
||||
|
@ -20,7 +20,7 @@ const Progress: FC<IProgressProps> = ({
|
||||
className={cn(s.bar, exhausted && s['bar-error'], 'absolute top-0 left-0 right-0 bottom-0')}
|
||||
style={{ width: `${value}%` }}
|
||||
/>
|
||||
{Array(10).fill(0).map((i, k) => (
|
||||
{Array.from({ length: 10 }).fill(0).map((i, k) => (
|
||||
<div key={k} className={s['bar-item']} />
|
||||
))}
|
||||
</div>
|
||||
|
@ -216,8 +216,8 @@ const Chart: React.FC<IChartProps> = ({
|
||||
return `<div style='color:#6B7280;font-size:12px'>${params.name}</div>
|
||||
<div style='font-size:14px;color:#1F2A37'>${valueFormatter((params.data as any)[yField])}
|
||||
${!CHART_TYPE_CONFIG[chartType].showTokens
|
||||
? ''
|
||||
: `<span style='font-size:12px'>
|
||||
? ''
|
||||
: `<span style='font-size:12px'>
|
||||
<span style='margin-left:4px;color:#6B7280'>(</span>
|
||||
<span style='color:#FF8A4C'>~$${get(params.data, 'total_price', 0)}</span>
|
||||
<span style='color:#6B7280'>)</span>
|
||||
@ -243,7 +243,7 @@ const Chart: React.FC<IChartProps> = ({
|
||||
? ''
|
||||
: <span>{t('appOverview.analysis.tokenUsage.consumed')} Tokens<span className='text-sm'>
|
||||
<span className='ml-1 text-gray-500'>(</span>
|
||||
<span className='text-orange-400'>~{sum(statistics.map(item => parseFloat(get(item, 'total_price', '0')))).toLocaleString('en-US', { style: 'currency', currency: 'USD', minimumFractionDigits: 4 })}</span>
|
||||
<span className='text-orange-400'>~{sum(statistics.map(item => Number.parseFloat(get(item, 'total_price', '0')))).toLocaleString('en-US', { style: 'currency', currency: 'USD', minimumFractionDigits: 4 })}</span>
|
||||
<span className='text-gray-500'>)</span>
|
||||
</span></span>}
|
||||
textStyle={{ main: `!text-3xl !font-normal ${sumData === 0 ? '!text-gray-300' : ''}` }} />
|
||||
|
@ -35,12 +35,12 @@ const OPTION_MAP = {
|
||||
`<script>
|
||||
window.difyChatbotConfig = {
|
||||
token: '${token}'${isTestEnv
|
||||
? `,
|
||||
? `,
|
||||
isDev: true`
|
||||
: ''}${IS_CE_EDITION
|
||||
? `,
|
||||
: ''}${IS_CE_EDITION
|
||||
? `,
|
||||
baseUrl: '${url}'`
|
||||
: ''}
|
||||
: ''}
|
||||
}
|
||||
</script>
|
||||
<script
|
||||
|
@ -22,7 +22,7 @@ import AppContext, { useAppContext } from '@/context/app-context'
|
||||
import type { AppIconSelection } from '@/app/components/base/app-icon-picker'
|
||||
import AppIconPicker from '@/app/components/base/app-icon-picker'
|
||||
|
||||
export type ISettingsModalProps = {
|
||||
export interface ISettingsModalProps {
|
||||
isChat: boolean
|
||||
appInfo: AppDetailResponse & Partial<AppSSO>
|
||||
isShow: boolean
|
||||
@ -31,7 +31,7 @@ export type ISettingsModalProps = {
|
||||
onSave?: (params: ConfigParams) => Promise<void>
|
||||
}
|
||||
|
||||
export type ConfigParams = {
|
||||
export interface ConfigParams {
|
||||
title: string
|
||||
description: string
|
||||
default_language: string
|
||||
|
@ -2,7 +2,7 @@ import { create } from 'zustand'
|
||||
import type { App, AppSSO } from '@/types/app'
|
||||
import type { IChatItem } from '@/app/components/base/chat/chat/type'
|
||||
|
||||
type State = {
|
||||
interface State {
|
||||
appDetail?: App & Partial<AppSSO>
|
||||
appSidebarExpand: string
|
||||
currentLogItem?: IChatItem
|
||||
@ -13,7 +13,7 @@ type State = {
|
||||
showAppConfigureFeaturesModal: boolean
|
||||
}
|
||||
|
||||
type Action = {
|
||||
interface Action {
|
||||
setAppDetail: (appDetail?: App & Partial<AppSSO>) => void
|
||||
setAppSiderbarExpand: (state: string) => void
|
||||
setCurrentLogItem: (item?: IChatItem) => void
|
||||
|
@ -25,7 +25,7 @@ import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/aler
|
||||
import AppIcon from '@/app/components/base/app-icon'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
|
||||
type SwitchAppModalProps = {
|
||||
interface SwitchAppModalProps {
|
||||
show: boolean
|
||||
appDetail: App
|
||||
onSuccess?: () => void
|
||||
|
@ -33,7 +33,7 @@ import { useChatContext } from '@/app/components/base/chat/chat/context'
|
||||
|
||||
const MAX_DEPTH = 3
|
||||
|
||||
export type IGenerationItemProps = {
|
||||
export interface IGenerationItemProps {
|
||||
isWorkflow?: boolean
|
||||
workflowProcessData?: WorkflowProcess
|
||||
className?: string
|
||||
|
@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next'
|
||||
import { RiCloseLine } from '@remixicon/react'
|
||||
import Run from '@/app/components/workflow/run'
|
||||
|
||||
type ILogDetail = {
|
||||
interface ILogDetail {
|
||||
runID: string
|
||||
onClose: () => void
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import type { QueryParam } from './index'
|
||||
import Chip from '@/app/components/base/chip'
|
||||
import Input from '@/app/components/base/input'
|
||||
|
||||
type IFilterProps = {
|
||||
interface IFilterProps {
|
||||
queryParams: QueryParam
|
||||
setQueryParams: (v: QueryParam) => void
|
||||
}
|
||||
|
@ -16,11 +16,11 @@ import { fetchWorkflowLogs } from '@/service/log'
|
||||
import { APP_PAGE_LIMIT } from '@/config'
|
||||
import type { App, AppMode } from '@/types/app'
|
||||
|
||||
export type ILogsProps = {
|
||||
export interface ILogsProps {
|
||||
appDetail: App
|
||||
}
|
||||
|
||||
export type QueryParam = {
|
||||
export interface QueryParam {
|
||||
status?: string
|
||||
keyword?: string
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import Indicator from '@/app/components/header/indicator'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import useTimestamp from '@/hooks/use-timestamp'
|
||||
|
||||
type ILogs = {
|
||||
interface ILogs {
|
||||
logs?: WorkflowLogsResponse
|
||||
appDetail?: App
|
||||
onRefresh: () => void
|
||||
|
@ -2,9 +2,7 @@
|
||||
|
||||
@layer components {
|
||||
.action-btn {
|
||||
@apply inline-flex justify-center items-center cursor-pointer text-text-tertiary
|
||||
hover:text-text-secondary
|
||||
hover:bg-state-base-hover
|
||||
@apply inline-flex justify-center items-center cursor-pointer text-text-tertiary hover:text-text-secondary hover:bg-state-base-hover
|
||||
}
|
||||
|
||||
.action-btn-disabled {
|
||||
@ -29,21 +27,15 @@
|
||||
}
|
||||
|
||||
.action-btn.action-btn-active {
|
||||
@apply
|
||||
text-text-accent
|
||||
bg-state-accent-active
|
||||
hover:bg-state-accent-active-alt
|
||||
@apply text-text-accent bg-state-accent-active hover:bg-state-accent-active-alt
|
||||
}
|
||||
|
||||
.action-btn.action-btn-disabled {
|
||||
@apply
|
||||
text-text-disabled
|
||||
@apply text-text-disabled
|
||||
}
|
||||
|
||||
.action-btn.action-btn-destructive {
|
||||
@apply
|
||||
text-text-destructive
|
||||
bg-state-destructive-hover
|
||||
@apply text-text-destructive bg-state-destructive-hover
|
||||
}
|
||||
|
||||
}
|
@ -28,7 +28,7 @@ const actionButtonVariants = cva(
|
||||
)
|
||||
|
||||
export type ActionButtonProps = {
|
||||
size?: 'xs' | 'm' | 'l' | 'xl'
|
||||
size?: 'xs' | 's' | 'm' | 'l' | 'xl'
|
||||
state?: ActionButtonState
|
||||
styleCss?: CSSProperties
|
||||
} & React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<typeof actionButtonVariants>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import AudioPlayer from '@/app/components/base/audio-btn/audio'
|
||||
declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
||||
// eslint-disable-next-line ts/consistent-type-definitions
|
||||
interface AudioPlayerManager {
|
||||
instance: AudioPlayerManager
|
||||
}
|
||||
@ -12,6 +12,7 @@ export class AudioPlayerManager {
|
||||
private audioPlayers: AudioPlayer | null = null
|
||||
private msgId: string | undefined
|
||||
|
||||
// eslint-disable-next-line
|
||||
private constructor() {
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ import Toast from '@/app/components/base/toast'
|
||||
import { textToAudioStream } from '@/service/share'
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
||||
// eslint-disable-next-line ts/consistent-type-definitions
|
||||
interface Window {
|
||||
ManagedMediaSource: any
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import Tooltip from '@/app/components/base/tooltip'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import { AudioPlayerManager } from '@/app/components/base/audio-btn/audio.player.manager'
|
||||
|
||||
type AudioBtnProps = {
|
||||
interface AudioBtnProps {
|
||||
id?: string
|
||||
voice?: string
|
||||
value?: string
|
||||
|
@ -55,7 +55,7 @@ const AudioPlayer: React.FC<AudioPlayerProps> = ({ src }) => {
|
||||
audio.load()
|
||||
|
||||
// Delayed generation of waveform data
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
// eslint-disable-next-line ts/no-use-before-define
|
||||
const timer = setTimeout(() => generateWaveformData(src), 1000)
|
||||
|
||||
return () => {
|
||||
|
@ -49,4 +49,6 @@ const AutoHeightTextarea = forwardRef<HTMLTextAreaElement, AutoHeightTextareaPro
|
||||
},
|
||||
)
|
||||
|
||||
AutoHeightTextarea.displayName = 'AutoHeightTextarea'
|
||||
|
||||
export default AutoHeightTextarea
|
||||
|
@ -5,22 +5,28 @@ type BadgeProps = {
|
||||
className?: string
|
||||
text: string
|
||||
uppercase?: boolean
|
||||
hasRedCornerMark?: boolean
|
||||
}
|
||||
|
||||
const Badge = ({
|
||||
className,
|
||||
text,
|
||||
uppercase = true,
|
||||
hasRedCornerMark,
|
||||
}: BadgeProps) => {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'inline-flex items-center px-[5px] h-5 rounded-[5px] border border-divider-deep leading-3 text-text-tertiary',
|
||||
'relative inline-flex items-center px-[5px] h-5 rounded-[5px] border border-divider-deep leading-3 text-text-tertiary',
|
||||
uppercase ? 'system-2xs-medium-uppercase' : 'system-xs-medium',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{text}
|
||||
{hasRedCornerMark && (
|
||||
<div className='absolute top-[-2px] right-[-2px] w-1.5 h-1.5 border border-components-badge-status-light-error-border-inner bg-components-badge-status-light-error-bg rounded-[2px] shadow-sm'>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
28
web/app/components/base/badge/index.css
Normal file
28
web/app/components/base/badge/index.css
Normal file
@ -0,0 +1,28 @@
|
||||
@tailwind components;
|
||||
|
||||
@layer components {
|
||||
.badge {
|
||||
@apply inline-flex justify-center items-center text-text-tertiary border border-divider-deep
|
||||
}
|
||||
|
||||
.badge-l {
|
||||
@apply rounded-md gap-1 min-w-6
|
||||
}
|
||||
|
||||
/* m is for the regular button */
|
||||
.badge-m {
|
||||
@apply rounded-md gap-[3px] min-w-5
|
||||
}
|
||||
|
||||
.badge-s {
|
||||
@apply rounded-[5px] gap-0.5 min-w-[18px]
|
||||
}
|
||||
|
||||
.badge.badge-warning {
|
||||
@apply text-text-warning border border-text-warning
|
||||
}
|
||||
|
||||
.badge.badge-accent {
|
||||
@apply text-text-accent-secondary border border-text-accent-secondary
|
||||
}
|
||||
}
|
81
web/app/components/base/badge/index.tsx
Normal file
81
web/app/components/base/badge/index.tsx
Normal file
@ -0,0 +1,81 @@
|
||||
import type { CSSProperties, ReactNode } from 'react'
|
||||
import React from 'react'
|
||||
import { type VariantProps, cva } from 'class-variance-authority'
|
||||
import classNames from '@/utils/classnames'
|
||||
import './index.css'
|
||||
|
||||
enum BadgeState {
|
||||
Warning = 'warning',
|
||||
Accent = 'accent',
|
||||
Default = '',
|
||||
}
|
||||
|
||||
const BadgeVariants = cva(
|
||||
'badge',
|
||||
{
|
||||
variants: {
|
||||
size: {
|
||||
s: 'badge-s',
|
||||
m: 'badge-m',
|
||||
l: 'badge-l',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
size: 'm',
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
type BadgeProps = {
|
||||
size?: 's' | 'm' | 'l'
|
||||
iconOnly?: boolean
|
||||
uppercase?: boolean
|
||||
state?: BadgeState
|
||||
styleCss?: CSSProperties
|
||||
children?: ReactNode
|
||||
} & React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof BadgeVariants>
|
||||
|
||||
function getBadgeState(state: BadgeState) {
|
||||
switch (state) {
|
||||
case BadgeState.Warning:
|
||||
return 'badge-warning'
|
||||
case BadgeState.Accent:
|
||||
return 'badge-accent'
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
const Badge: React.FC<BadgeProps> = ({
|
||||
className,
|
||||
size,
|
||||
state = BadgeState.Default,
|
||||
iconOnly = false,
|
||||
uppercase = false,
|
||||
styleCss,
|
||||
children,
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
BadgeVariants({ size, className }),
|
||||
getBadgeState(state),
|
||||
size === 's'
|
||||
? (iconOnly ? 'p-[3px]' : 'px-[5px] py-[3px]')
|
||||
: size === 'l'
|
||||
? (iconOnly ? 'p-1.5' : 'px-2 py-1')
|
||||
: (iconOnly ? 'p-1' : 'px-[5px] py-[2px]'),
|
||||
uppercase ? 'system-2xs-medium-uppercase' : 'system-2xs-medium',
|
||||
)}
|
||||
style={styleCss}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Badge.displayName = 'Badge'
|
||||
|
||||
export default Badge
|
||||
export { Badge, BadgeState, BadgeVariants }
|
@ -4,7 +4,7 @@ import React from 'react'
|
||||
import { RiAddLine } from '@remixicon/react'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
type Props = {
|
||||
interface Props {
|
||||
className?: string
|
||||
onClick: () => void
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'
|
||||
import { memo } from 'react'
|
||||
import Textarea from '@/app/components/base/textarea'
|
||||
|
||||
type InputProps = {
|
||||
interface InputProps {
|
||||
form: any
|
||||
value: string
|
||||
onChange: (variable: string, value: string) => void
|
||||
|
@ -16,7 +16,7 @@ import type {
|
||||
ConversationItem,
|
||||
} from '@/models/share'
|
||||
|
||||
export type ChatWithHistoryContextValue = {
|
||||
export interface ChatWithHistoryContextValue {
|
||||
appInfoError?: any
|
||||
appInfoLoading?: boolean
|
||||
appMeta?: AppMeta
|
||||
|
@ -20,7 +20,7 @@ import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import { checkOrSetAccessToken } from '@/app/components/share/utils'
|
||||
import AppUnavailable from '@/app/components/base/app-unavailable'
|
||||
|
||||
type ChatWithHistoryProps = {
|
||||
interface ChatWithHistoryProps {
|
||||
className?: string
|
||||
}
|
||||
const ChatWithHistory: FC<ChatWithHistoryProps> = ({
|
||||
@ -99,7 +99,7 @@ const ChatWithHistory: FC<ChatWithHistoryProps> = ({
|
||||
)
|
||||
}
|
||||
|
||||
export type ChatWithHistoryWrapProps = {
|
||||
export interface ChatWithHistoryWrapProps {
|
||||
installedAppInfo?: InstalledApp
|
||||
className?: string
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import Thought from '@/app/components/base/chat/chat/thought'
|
||||
import { FileList } from '@/app/components/base/file-uploader'
|
||||
import { getProcessedFilesFromResponse } from '@/app/components/base/file-uploader/utils'
|
||||
|
||||
type AgentContentProps = {
|
||||
interface AgentContentProps {
|
||||
item: ChatItem
|
||||
responding?: boolean
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import type { ChatItem } from '../../types'
|
||||
import { Markdown } from '@/app/components/base/markdown'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
type BasicContentProps = {
|
||||
interface BasicContentProps {
|
||||
item: ChatItem
|
||||
}
|
||||
const BasicContent: FC<BasicContentProps> = ({
|
||||
|
@ -23,7 +23,7 @@ import { ChevronRight } from '@/app/components/base/icons/src/vender/line/arrows
|
||||
import cn from '@/utils/classnames'
|
||||
import { FileList } from '@/app/components/base/file-uploader'
|
||||
|
||||
type AnswerProps = {
|
||||
interface AnswerProps {
|
||||
item: ChatItem
|
||||
question: string
|
||||
index: number
|
||||
|
@ -21,7 +21,7 @@ import {
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import Log from '@/app/components/base/chat/chat/log'
|
||||
|
||||
type OperationProps = {
|
||||
interface OperationProps {
|
||||
item: ChatItem
|
||||
question: string
|
||||
index: number
|
||||
|
@ -17,7 +17,7 @@ import { CheckCircle } from '@/app/components/base/icons/src/vender/solid/genera
|
||||
import { WorkflowRunningStatus } from '@/app/components/workflow/types'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
|
||||
type WorkflowProcessProps = {
|
||||
interface WorkflowProcessProps {
|
||||
data: WorkflowProcess
|
||||
item?: ChatItem
|
||||
expand?: boolean
|
||||
|
@ -33,7 +33,7 @@ import {
|
||||
} from '@/app/components/base/file-uploader/utils'
|
||||
|
||||
type GetAbortController = (abortController: AbortController) => void
|
||||
type SendCallback = {
|
||||
interface SendCallback {
|
||||
onGetConversationMessages?: (conversationId: string, getAbortController: GetAbortController) => Promise<any>
|
||||
onGetSuggestedQuestions?: (responseItemId: string, getAbortController: GetAbortController) => Promise<any>
|
||||
onConversationComplete?: (conversationId: string) => void
|
||||
|
@ -35,7 +35,7 @@ import PromptLogModal from '@/app/components/base/prompt-log-modal'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import type { AppData } from '@/models/share'
|
||||
|
||||
export type ChatProps = {
|
||||
export interface ChatProps {
|
||||
appData?: AppData
|
||||
chatList: ChatItem[]
|
||||
config?: ChatConfig
|
||||
|
@ -12,7 +12,7 @@ import { User } from '@/app/components/base/icons/src/public/avatar'
|
||||
import { Markdown } from '@/app/components/base/markdown'
|
||||
import { FileList } from '@/app/components/base/file-uploader'
|
||||
|
||||
type QuestionProps = {
|
||||
interface QuestionProps {
|
||||
item: ChatItem
|
||||
questionIcon?: ReactNode
|
||||
theme: Theme | null | undefined
|
||||
|
@ -4,7 +4,7 @@ import React from 'react'
|
||||
import type { ThoughtItem, ToolInfoInThought } from '../type'
|
||||
import ToolDetail from '@/app/components/base/chat/chat/answer/tool-detail'
|
||||
|
||||
export type IThoughtProps = {
|
||||
export interface IThoughtProps {
|
||||
thought: ThoughtItem
|
||||
isFinished: boolean
|
||||
}
|
||||
|
@ -4,13 +4,13 @@ import type { FileEntity } from '@/app/components/base/file-uploader/types'
|
||||
import type { InputVarType } from '@/app/components/workflow/types'
|
||||
import type { FileResponse } from '@/types/workflow'
|
||||
|
||||
export type MessageMore = {
|
||||
export interface MessageMore {
|
||||
time: string
|
||||
tokens: number
|
||||
latency: number | string
|
||||
}
|
||||
|
||||
export type FeedbackType = {
|
||||
export interface FeedbackType {
|
||||
rating: MessageRating
|
||||
content?: string | null
|
||||
}
|
||||
@ -26,7 +26,7 @@ export type SubmitAnnotationFunc = (
|
||||
|
||||
export type DisplayScene = 'web' | 'console'
|
||||
|
||||
export type ToolInfoInThought = {
|
||||
export interface ToolInfoInThought {
|
||||
name: string
|
||||
label: string
|
||||
input: string
|
||||
@ -34,7 +34,7 @@ export type ToolInfoInThought = {
|
||||
isFinished: boolean
|
||||
}
|
||||
|
||||
export type ThoughtItem = {
|
||||
export interface ThoughtItem {
|
||||
id: string
|
||||
tool: string // plugin or dataset. May has multi.
|
||||
thought: string
|
||||
@ -47,7 +47,7 @@ export type ThoughtItem = {
|
||||
message_files?: FileEntity[]
|
||||
}
|
||||
|
||||
export type CitationItem = {
|
||||
export interface CitationItem {
|
||||
content: string
|
||||
data_source_type: string
|
||||
dataset_name: string
|
||||
@ -62,7 +62,7 @@ export type CitationItem = {
|
||||
word_count: number
|
||||
}
|
||||
|
||||
export type IChatItem = {
|
||||
export interface IChatItem {
|
||||
id: string
|
||||
content: string
|
||||
citation?: CitationItem[]
|
||||
@ -104,7 +104,7 @@ export type IChatItem = {
|
||||
nextSibling?: string
|
||||
}
|
||||
|
||||
export type Metadata = {
|
||||
export interface Metadata {
|
||||
retriever_resources?: CitationItem[]
|
||||
annotation_reply: {
|
||||
id: string
|
||||
@ -115,20 +115,20 @@ export type Metadata = {
|
||||
}
|
||||
}
|
||||
|
||||
export type MessageEnd = {
|
||||
export interface MessageEnd {
|
||||
id: string
|
||||
metadata: Metadata
|
||||
files?: FileResponse[]
|
||||
}
|
||||
|
||||
export type MessageReplace = {
|
||||
export interface MessageReplace {
|
||||
id: string
|
||||
task_id: string
|
||||
answer: string
|
||||
conversation_id: string
|
||||
}
|
||||
|
||||
export type AnnotationReply = {
|
||||
export interface AnnotationReply {
|
||||
id: string
|
||||
task_id: string
|
||||
answer: string
|
||||
@ -137,7 +137,7 @@ export type AnnotationReply = {
|
||||
annotation_author_name: string
|
||||
}
|
||||
|
||||
export type InputForm = {
|
||||
export interface InputForm {
|
||||
type: InputVarType
|
||||
label: string
|
||||
variable: any
|
||||
|
@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'
|
||||
import { memo } from 'react'
|
||||
import Textarea from '@/app/components/base/textarea'
|
||||
|
||||
type InputProps = {
|
||||
interface InputProps {
|
||||
form: any
|
||||
value: string
|
||||
onChange: (variable: string, value: string) => void
|
||||
|
@ -15,7 +15,7 @@ import type {
|
||||
ConversationItem,
|
||||
} from '@/models/share'
|
||||
|
||||
export type EmbeddedChatbotContextValue = {
|
||||
export interface EmbeddedChatbotContextValue {
|
||||
appInfoError?: any
|
||||
appInfoLoading?: boolean
|
||||
appMeta?: AppMeta
|
||||
|
@ -14,32 +14,32 @@ export type {
|
||||
PromptVariable,
|
||||
} from '@/models/debug'
|
||||
|
||||
export type UserInputForm = {
|
||||
export interface UserInputForm {
|
||||
default: string
|
||||
label: string
|
||||
required: boolean
|
||||
variable: string
|
||||
}
|
||||
|
||||
export type UserInputFormTextInput = {
|
||||
export interface UserInputFormTextInput {
|
||||
'text-input': UserInputForm & {
|
||||
max_length: number
|
||||
}
|
||||
}
|
||||
|
||||
export type UserInputFormSelect = {
|
||||
'select': UserInputForm & {
|
||||
export interface UserInputFormSelect {
|
||||
select: UserInputForm & {
|
||||
options: string[]
|
||||
}
|
||||
}
|
||||
|
||||
export type UserInputFormParagraph = {
|
||||
'paragraph': UserInputForm
|
||||
export interface UserInputFormParagraph {
|
||||
paragraph: UserInputForm
|
||||
}
|
||||
|
||||
export type VisionConfig = VisionSettings
|
||||
|
||||
export type EnableType = {
|
||||
export interface EnableType {
|
||||
enabled: boolean
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ export type ChatConfig = Omit<ModelConfig, 'model'> & {
|
||||
supportCitationHitInfo?: boolean
|
||||
}
|
||||
|
||||
export type WorkflowProcess = {
|
||||
export interface WorkflowProcess {
|
||||
status: WorkflowRunningStatus
|
||||
tracing: NodeTracing[]
|
||||
expand?: boolean // for UI
|
||||
@ -73,10 +73,10 @@ export type OnSend = (message: string, files?: FileEntity[], last_answer?: ChatI
|
||||
|
||||
export type OnRegenerate = (chatItem: ChatItem) => void
|
||||
|
||||
export type Callback = {
|
||||
export interface Callback {
|
||||
onSuccess: () => void
|
||||
}
|
||||
|
||||
export type Feedback = {
|
||||
export interface Feedback {
|
||||
rating: 'like' | 'dislike' | null
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
'use client'
|
||||
import { useState } from 'react'
|
||||
import { t } from 'i18next'
|
||||
import { debounce } from 'lodash-es'
|
||||
import copy from 'copy-to-clipboard'
|
||||
import s from './style.module.css'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
@ -18,22 +19,29 @@ const CopyBtn = ({
|
||||
}: ICopyBtnProps) => {
|
||||
const [isCopied, setIsCopied] = useState(false)
|
||||
|
||||
const onClickCopy = debounce(() => {
|
||||
copy(value)
|
||||
setIsCopied(true)
|
||||
}, 100)
|
||||
|
||||
const onMouseLeave = debounce(() => {
|
||||
setIsCopied(false)
|
||||
}, 100)
|
||||
|
||||
return (
|
||||
<div className={`${className}`}>
|
||||
<Tooltip
|
||||
popupContent={(isCopied ? t('appApi.copied') : t('appApi.copy'))}
|
||||
>
|
||||
<div
|
||||
onMouseLeave={onMouseLeave}
|
||||
className={'box-border p-0.5 flex items-center justify-center rounded-md bg-white cursor-pointer'}
|
||||
style={!isPlain
|
||||
? {
|
||||
boxShadow: '0px 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06)',
|
||||
}
|
||||
: {}}
|
||||
onClick={() => {
|
||||
copy(value)
|
||||
setIsCopied(true)
|
||||
}}
|
||||
onClick={onClickCopy}
|
||||
>
|
||||
<div className={`w-6 h-6 rounded-md hover:bg-gray-50 ${s.copyIcon} ${isCopied ? s.copied : ''}`}></div>
|
||||
</div>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user