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:
John
2026-06-15 22:09:38 -07:00
parent 3cd322ccfe
commit 6ee6fd64dd
94 changed files with 7015 additions and 2136 deletions
+22 -16
View File
@@ -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>
</>
);