mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-27 16:04:21 +00:00
4f2ec195fc
* feat: add WebChat adapter for pipeline debugging - Create WebChatAdapter for handling debug messages in pipeline testing - Add HTTP API endpoints for debug message sending and retrieval - Implement frontend debug dialog with session switching (private/group chat) - Add Chinese i18n translations for debug interface - Auto-create default WebChat bot during database initialization - Support fixed session IDs: webchatperson and webchatgroup for testing Co-Authored-By: Junyan Qin <Chin>, 秦骏言 in Chinese, you can call me my english name Rock Chin. <rockchinq@gmail.com> * perf: ui for webchat * feat: complete webchat backend * feat: core chat apis * perf: button style in pipeline card * perf: log btn in bot card * perf: webchat entities definition * fix: bugs * perf: web chat * perf: dialog styles * perf: styles * perf: styles * fix: group invalid in webchat * perf: simulate real im message * perf: group timeout toast * feat(webchat): add supports for mentioning bot in group * perf(webchat): at component styles * perf: at badge display in message * fix: linter errors * fix: webchat was listed on adapter list --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Junyan Qin <Chin>, 秦骏言 in Chinese, you can call me my english name Rock Chin. <rockchinq@gmail.com>
175 lines
5.6 KiB
TypeScript
175 lines
5.6 KiB
TypeScript
'use client';
|
|
import { useState, useEffect } from 'react';
|
|
import CreateCardComponent from '@/app/infra/basic-component/create-card-component/CreateCardComponent';
|
|
import PipelineFormComponent from './components/pipeline-form/PipelineFormComponent';
|
|
import { httpClient } from '@/app/infra/http/HttpClient';
|
|
import { PipelineCardVO } from '@/app/home/pipelines/components/pipeline-card/PipelineCardVO';
|
|
import PipelineCard from '@/app/home/pipelines/components/pipeline-card/PipelineCard';
|
|
import { PipelineFormEntity } from '@/app/infra/entities/pipeline';
|
|
import styles from './pipelineConfig.module.css';
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
} from '@/components/ui/dialog';
|
|
import { toast } from 'sonner';
|
|
import { useTranslation } from 'react-i18next';
|
|
import DebugDialog from './debug-dialog/DebugDialog';
|
|
|
|
export default function PluginConfigPage() {
|
|
const { t } = useTranslation();
|
|
const [modalOpen, setModalOpen] = useState<boolean>(false);
|
|
const [isEditForm, setIsEditForm] = useState(false);
|
|
const [pipelineList, setPipelineList] = useState<PipelineCardVO[]>([]);
|
|
const [selectedPipelineId, setSelectedPipelineId] = useState('');
|
|
const [selectedPipelineFormValue, setSelectedPipelineFormValue] =
|
|
useState<PipelineFormEntity>({
|
|
basic: {},
|
|
ai: {},
|
|
trigger: {},
|
|
safety: {},
|
|
output: {},
|
|
});
|
|
const [disableForm, setDisableForm] = useState(false);
|
|
const [selectedPipelineIsDefault, setSelectedPipelineIsDefault] =
|
|
useState(false);
|
|
const [debugDialogOpen, setDebugDialogOpen] = useState(false);
|
|
const [debugPipelineId, setDebugPipelineId] = useState('');
|
|
|
|
useEffect(() => {
|
|
getPipelines();
|
|
}, []);
|
|
|
|
function getPipelines() {
|
|
httpClient
|
|
.getPipelines()
|
|
.then((value) => {
|
|
const currentTime = new Date();
|
|
const pipelineList = value.pipelines.map((pipeline) => {
|
|
const lastUpdatedTimeAgo = Math.floor(
|
|
(currentTime.getTime() -
|
|
new Date(
|
|
pipeline.updated_at ?? currentTime.getTime(),
|
|
).getTime()) /
|
|
1000 /
|
|
60 /
|
|
60 /
|
|
24,
|
|
);
|
|
|
|
const lastUpdatedTimeAgoText =
|
|
lastUpdatedTimeAgo > 0
|
|
? ` ${lastUpdatedTimeAgo} ${t('pipelines.daysAgo')}`
|
|
: t('pipelines.today');
|
|
|
|
return new PipelineCardVO({
|
|
lastUpdatedTimeAgo: lastUpdatedTimeAgoText,
|
|
description: pipeline.description,
|
|
id: pipeline.uuid ?? '',
|
|
name: pipeline.name,
|
|
isDefault: pipeline.is_default ?? false,
|
|
});
|
|
});
|
|
setPipelineList(pipelineList);
|
|
})
|
|
.catch((error) => {
|
|
console.log(error);
|
|
toast.error(t('pipelines.getPipelineListError') + error.message);
|
|
});
|
|
}
|
|
|
|
function getSelectedPipelineForm(id?: string) {
|
|
httpClient.getPipeline(id ?? selectedPipelineId).then((value) => {
|
|
setSelectedPipelineFormValue({
|
|
ai: value.pipeline.config.ai,
|
|
basic: {
|
|
description: value.pipeline.description,
|
|
name: value.pipeline.name,
|
|
},
|
|
output: value.pipeline.config.output,
|
|
safety: value.pipeline.config.safety,
|
|
trigger: value.pipeline.config.trigger,
|
|
});
|
|
setSelectedPipelineIsDefault(value.pipeline.is_default ?? false);
|
|
setDisableForm(false);
|
|
});
|
|
}
|
|
|
|
const handleDebug = (pipelineId: string) => {
|
|
setDebugPipelineId(pipelineId);
|
|
setDebugDialogOpen(true);
|
|
};
|
|
|
|
return (
|
|
<div className={styles.configPageContainer}>
|
|
<Dialog open={modalOpen} onOpenChange={setModalOpen}>
|
|
<DialogContent className="w-[700px] max-h-[80vh] p-0 flex flex-col">
|
|
<DialogHeader className="px-6 pt-6 pb-4">
|
|
<DialogTitle>
|
|
{isEditForm
|
|
? t('pipelines.editPipeline')
|
|
: t('pipelines.createPipeline')}
|
|
</DialogTitle>
|
|
</DialogHeader>
|
|
<div className="flex-1 overflow-y-auto px-6">
|
|
<PipelineFormComponent
|
|
onNewPipelineCreated={(pipelineId) => {
|
|
setDisableForm(true);
|
|
setIsEditForm(true);
|
|
setModalOpen(true);
|
|
setSelectedPipelineId(pipelineId);
|
|
getSelectedPipelineForm(pipelineId);
|
|
}}
|
|
onFinish={() => {
|
|
getPipelines();
|
|
setModalOpen(false);
|
|
}}
|
|
isEditMode={isEditForm}
|
|
pipelineId={selectedPipelineId}
|
|
disableForm={disableForm}
|
|
initValues={selectedPipelineFormValue}
|
|
isDefaultPipeline={selectedPipelineIsDefault}
|
|
/>
|
|
</div>
|
|
</DialogContent>
|
|
</Dialog>
|
|
|
|
<div className={styles.pipelineListContainer}>
|
|
<CreateCardComponent
|
|
width={'100%'}
|
|
height={'10rem'}
|
|
plusSize={'90px'}
|
|
onClick={() => {
|
|
setIsEditForm(false);
|
|
setModalOpen(true);
|
|
}}
|
|
/>
|
|
|
|
{pipelineList.map((pipeline) => {
|
|
return (
|
|
<div
|
|
key={pipeline.id}
|
|
onClick={() => {
|
|
setDisableForm(true);
|
|
setIsEditForm(true);
|
|
setModalOpen(true);
|
|
setSelectedPipelineId(pipeline.id);
|
|
getSelectedPipelineForm(pipeline.id);
|
|
}}
|
|
>
|
|
<PipelineCard cardVO={pipeline} onDebug={handleDebug} />
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
|
|
<DebugDialog
|
|
open={debugDialogOpen}
|
|
onOpenChange={setDebugDialogOpen}
|
|
pipelineId={debugPipelineId}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|