Add MindSpace page live edit, chat skills, and H5 deploy tooling.
Introduce page edit sessions with draft preview and patch API, chat skill picker, user memory profile, h5ApiBase resolution, voice WAV transport, and scripts for 105/g2 deployment and Plaza local dev. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useNetworkStatus } from '../hooks/useNetworkStatus';
|
||||
import { openAvatarPicker } from '../utils/userAvatar';
|
||||
import { buildPublishSkillPrompt } from '../utils/publishSkill';
|
||||
import { CHAT_SKILL_OPTIONS, filterChatSkills } from '../utils/chatSkills';
|
||||
import { AvatarPicker } from './AvatarPicker';
|
||||
import { ChatSkillPicker } from './ChatSkillPicker';
|
||||
import { MessageList } from './MessageList';
|
||||
import { PageSaveDialog } from './PageSaveDialog';
|
||||
import { VoiceInputButton } from './VoiceInputButton';
|
||||
@@ -22,6 +23,7 @@ export function ChatPanel({
|
||||
onStop,
|
||||
onApproveTool,
|
||||
onPageSaved,
|
||||
onClose,
|
||||
}: {
|
||||
variant: 'full' | 'compact';
|
||||
user?: PortalUser | null;
|
||||
@@ -39,6 +41,7 @@ export function ChatPanel({
|
||||
pageId?: string;
|
||||
categoryCode?: MindSpaceSaveCategory;
|
||||
}) => void;
|
||||
onClose?: () => void;
|
||||
}) {
|
||||
const online = useNetworkStatus();
|
||||
const [input, setInput] = useState('');
|
||||
@@ -50,11 +53,12 @@ export function ChatPanel({
|
||||
bottomRef.current?.scrollIntoView({ behavior: 'smooth' });
|
||||
}, [messages, chatState, pendingTool]);
|
||||
|
||||
const busy = chatState === 'streaming' || chatState === 'loading';
|
||||
const busy = chatState === 'streaming' || chatState === 'loading' || chatState === 'connecting';
|
||||
const offlineBlocked = !online;
|
||||
const publishSkillName = user?.publishSkillName ?? 'static-page-publish';
|
||||
const hasPublishSkill = grantedSkills?.includes(publishSkillName) ?? false;
|
||||
const canPublish = Boolean(capabilities?.static_publish) || hasPublishSkill;
|
||||
const chatSkills = filterChatSkills(CHAT_SKILL_OPTIONS, { grantedSkills, canPublish });
|
||||
const compact = variant === 'compact';
|
||||
|
||||
const handleSubmit = async () => {
|
||||
@@ -66,9 +70,11 @@ export function ChatPanel({
|
||||
|
||||
const placeholder = offlineBlocked
|
||||
? '网络断开,恢复连接后可继续输入'
|
||||
: compact
|
||||
? '在这里继续和 Agent 对话…'
|
||||
: '输入任务,例如:列出当前目录文件';
|
||||
: chatState === 'connecting'
|
||||
? '正在连接会话…'
|
||||
: compact
|
||||
? '在这里继续和 Agent 对话…'
|
||||
: '输入任务,例如:列出当前目录文件';
|
||||
|
||||
const handleVoiceSend = async (text: string) => {
|
||||
setVoiceNotice(null);
|
||||
@@ -152,18 +158,13 @@ export function ChatPanel({
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{!compact && canPublish && (
|
||||
<button
|
||||
type="button"
|
||||
className="ghost-btn chat-input-action"
|
||||
{chatSkills.length > 0 && (
|
||||
<ChatSkillPicker
|
||||
skills={chatSkills}
|
||||
disabled={voiceDisabled}
|
||||
title={`加载 ${publishSkillName} 技能并生成 HTML`}
|
||||
onClick={() => {
|
||||
setInput(buildPublishSkillPrompt(publishSkillName));
|
||||
}}
|
||||
>
|
||||
静态页面
|
||||
</button>
|
||||
onSelect={onSubmit}
|
||||
onPrefill={setInput}
|
||||
/>
|
||||
)}
|
||||
{chatState === 'streaming' ? (
|
||||
<button type="button" className="danger-btn chat-input-action" onClick={() => void onStop()}>
|
||||
@@ -180,6 +181,11 @@ export function ChatPanel({
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{compact && onClose && (
|
||||
<button type="button" className="space-chat-panel-dismiss" onClick={onClose}>
|
||||
关闭
|
||||
</button>
|
||||
)}
|
||||
</footer>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user