feat(agents): 支持个人微信发布与渠道会话
Electron E2E / Electron E2E (macos-latest) (push) Has been cancelled
Electron E2E / Electron E2E (ubuntu-latest) (push) Has been cancelled
Electron E2E / Electron E2E (windows-latest) (push) Has been cancelled

This commit is contained in:
brother7 committed 2026-09-13 16:22:36 +08:00
1 parent 03774d0625
commit 2e710db0fb
28 files changed
+2678 -31

No files matched your search

+14 -4
View File
@@ -9,6 +9,7 @@ import { cloudAgentsApi } from '@/lib/cloud-agents-api';
import { EMPTY_CLOUD_CONFIGURATION, type CloudAgentDraft, type CloudRecent, type CloudThread, type CloudScheduleProposal } from '../../../shared/cloud-agents';
import { ConfigurationFields } from './ConfigurationFields';
import { CloudChat } from './CloudChat';
import { CloudChannelConversations } from './CloudChannelConversations';
import { CloudAccessPanel } from './CloudAccess';
import { CloudSchedules } from './CloudSchedules';
import { CloudPendingContext, useCloudPendingState } from './CloudPending';
@@ -35,6 +36,8 @@ export function DraftEditor({ initial, recent, onBack, onSaved }: {
const [visited, setVisited] = useState<Set<Tab>>(() => new Set([initialTab]));
const [category, setCategory] = useState<Category>('instructions');
const [openedThread, setOpenedThread] = useState<CloudThread>();
const [conversationSource, setConversationSource] = useState<'desktop' | 'wechat'>('desktop');
const [wechatVisited, setWechatVisited] = useState(false);
const [scheduleProposal, setScheduleProposal] = useState<CloudScheduleProposal>();
const pending = useCloudPendingState();
const formalPending = useCloudPendingState();
@@ -142,20 +145,27 @@ export function DraftEditor({ initial, recent, onBack, onSaved }: {
</div>
<div hidden={tab !== 'chat'} className="agent-workspace-view p-6">
{visited.has('chat') && (saved.published_version ? <CloudPendingContext.Provider value={formalPending.report}>
<CloudChat key={openedThread?.thread_id ?? 'published'} slug={saved.slug} initialThread={openedThread} activeView={tab === 'chat'}
onSchedule={proposal => { setScheduleProposal(proposal); navigate('tasks'); }} /></CloudPendingContext.Provider>
<nav aria-label="对话来源" className="mb-3 flex shrink-0 gap-2">
<Button variant={conversationSource === 'desktop' ? 'secondary' : 'ghost'} disabled={formalPending.hasPending && conversationSource !== 'desktop'} onClick={() => setConversationSource('desktop')}>客户端对话</Button>
<Button variant={conversationSource === 'wechat' ? 'secondary' : 'ghost'} disabled={formalPending.hasPending && conversationSource !== 'wechat'} onClick={() => { setWechatVisited(true); setConversationSource('wechat'); }}>本人微信对话</Button>
</nav>
<div hidden={conversationSource !== 'desktop'} className="flex min-h-0 flex-1 flex-col">
<CloudChat key={openedThread?.thread_id ?? 'published'} slug={saved.slug} initialThread={openedThread} activeView={tab === 'chat' && conversationSource === 'desktop'}
onSchedule={proposal => { setScheduleProposal(proposal); navigate('tasks'); }} /></div>
<div hidden={conversationSource !== 'wechat'} className="min-h-0 flex-1 overflow-auto">{wechatVisited && <CloudChannelConversations slug={saved.slug} activeView={tab === 'chat' && conversationSource === 'wechat'} />}</div>
</CloudPendingContext.Provider>
: <p className="m-auto text-sm text-muted-foreground">先在编辑中试用,再发布智能体,即可开始正式对话。</p>)}
</div>
<div hidden={tab !== 'tasks'} className="agent-management-view">
{visited.has('tasks') && <CloudSchedules slug={saved.slug} proposal={scheduleProposal} onProposalClosed={() => setScheduleProposal(undefined)} onOpen={thread => {
if (formalPending.hasPending) { setError('正式对话还有未完成的输入,请先处理后再打开任务对话。'); navigate('chat'); return; }
setOpenedThread(thread); navigate('chat');
setOpenedThread(thread); setConversationSource('desktop'); navigate('chat');
}} />}
</div>
<div hidden={tab !== 'access'} className="agent-management-view">
{dirty && <p className="mb-4 text-sm text-muted-foreground">先保存草稿,再发布或调整访问。编辑中的内容仍保留。</p>}
<fieldset disabled={dirty || busy || remote !== null}>
{visited.has('access') && <CloudAccessPanel slug={saved.slug} revision={saved.draft_revision} onChanged={result => { setSaved(result); if (result.configuration?.model) setPreviewCreated(true); setDraft(current => !hasDraftChanges(current, saved) ? result : { ...current, draft_revision: result.draft_revision, published_version: result.published_version }); onSaved(result); }} onPublished={() => {
{visited.has('access') && <CloudAccessPanel activeView={tab === 'access'} slug={saved.slug} revision={saved.draft_revision} onChanged={result => { setSaved(result); if (result.configuration?.model) setPreviewCreated(true); setDraft(current => !hasDraftChanges(current, saved) ? result : { ...current, draft_revision: result.draft_revision, published_version: result.published_version }); onSaved(result); }} onPublished={() => {
void cloudAgentsApi.get(saved.slug).then(result => { if (alive.current) {
const publication = { published_version: result.published_version, enabled: result.enabled };
setSaved(current => ({ ...current, ...publication })); setDraft(current => ({ ...current, ...publication })); onSaved({ ...saved, ...publication });