feat(health): wire H5 health page, WeChat channel, and observation API.

Expose /health and /api/health/observations behind MEMIND_HEALTH_ENABLED, redirect ordinary chat health intents without persisting, and run a dedicated WeChat menu flow with confirm-before-write semantics.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-09-02 10:05:56 +08:00
parent f96fdcb3b9
commit 7bf16500a1
22 changed files with 1132 additions and 10 deletions
+28 -3
View File
@@ -1,4 +1,5 @@
import { useEffect, useMemo, useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useChat } from '../context/ChatProvider';
import { INSUFFICIENT_BALANCE_NOTICE } from '../hooks/useTKMindChat';
import { useGoalRunBanner } from '../hooks/useGoalRunBanner';
@@ -19,6 +20,10 @@ import { ChatHeaderMoreMenu } from './ChatHeaderMoreMenu';
import { NotificationCenter } from './NotificationCenter';
import { GoalRunAwaitingBanner } from './GoalRunAwaitingBanner';
import type { MindSpaceSaveCategory } from '../types';
import {
HEALTH_REDIRECT_COPY,
shouldRedirectOrdinaryChatToHealth,
} from '../../health-intent-rules.mjs';
function RecentSessionRail({
sessions,
@@ -222,7 +227,9 @@ export function ChatView({
uploadChatAttachment,
followAgentRun,
goalRunEnabled,
healthEnabled,
} = useChat();
const navigate = useNavigate();
const online = useNetworkStatus();
const goalRunBanner = useGoalRunBanner({
userId: user?.id,
@@ -312,6 +319,9 @@ export function ChatView({
...(onOpenAdmin
? [{ id: 'admin', label: '管理', onClick: () => onOpenAdmin() }]
: []),
...(healthEnabled
? [{ id: 'health', label: '健康', onClick: () => navigate('/health') }]
: []),
...(onLogout
? [{ id: 'logout', label: '登出', onClick: () => onLogout(), danger: true }]
: []),
@@ -409,6 +419,16 @@ export function ChatView({
</button>
)}
{healthEnabled && (
<button
type="button"
className="ghost-btn"
data-analytics-action="open_health"
onClick={() => navigate('/health')}
>
</button>
)}
{onOpenSpace && (
<button
ref={spaceButtonRef}
@@ -579,7 +599,12 @@ export function ChatView({
onGrantedSkillsUpdate={onGrantedSkillsUpdate}
onOpenRecharge={() => openRecharge(false)}
taskLoadingTip={taskLoadingTip}
onSubmit={(text, imageUrls, previewImageUrls, options) =>
onSubmit={(text, imageUrls, previewImageUrls, options) => {
if (healthEnabled && shouldRedirectOrdinaryChatToHealth(text) && !options?.selectedChatSkill) {
window.alert(HEALTH_REDIRECT_COPY);
navigate('/health');
return;
}
void submit(
text,
{
@@ -593,8 +618,8 @@ export function ChatView({
},
imageUrls,
previewImageUrls,
)
}
);
}}
onUploadImage={(file, onProgress, options) =>
uploadChatImage(file, onProgress, { messageId: options?.messageId })
}