refactor(beaver): 移除Hermes相关引用和迁移代码,完善Beaver后端主线实现

移除了所有Hermes相关的命名引用,包括:
- 从.gitignore中清理相关构建缓存文件
- 将README中的beaver-home路径配置更新
- 完善backend/README.md文档说明Beaver后端主线实现
- 移除Hermes风格的相关注释和兼容性代码
- 清理nanobot环境变量兼容性处理
- 删除技能迁移和服务迁移相关功能代码
- 更新测试用例中相关命名和函数名

BREAKING CHANGE: 移除了Hermes迁移相关API和CLI命令,不再支持nanobot环境变量兼容性
This commit is contained in:
2026-05-14 17:20:32 +08:00
parent b59968167e
commit 3b0af173cc
57 changed files with 245 additions and 4109 deletions

View File

@ -40,7 +40,7 @@ export function AppRuntimeBridge() {
const sessionId = useChatStore((state) => state.sessionId);
const setSessions = useChatStore((state) => state.setSessions);
const setWsStatus = useChatStore((state) => state.setWsStatus);
const setNanobotReady = useChatStore((state) => state.setNanobotReady);
const setBeaverReady = useChatStore((state) => state.setBeaverReady);
const resetProcessState = useChatStore((state) => state.resetProcessState);
const ingestProcessEvent = useChatStore((state) => state.ingestProcessEvent);
const statusCheckCleanupRef = React.useRef<(() => void) | null>(null);
@ -63,14 +63,14 @@ export function AppRuntimeBridge() {
statusCheckInFlightRef.current = true;
try {
await getStatus();
setNanobotReady(true);
setBeaverReady(true);
} catch {
setNanobotReady(false);
setBeaverReady(false);
} finally {
statusCheckInFlightRef.current = false;
}
});
}, [setNanobotReady]);
}, [setBeaverReady]);
React.useEffect(() => {
void loadSessions();
@ -89,7 +89,7 @@ export function AppRuntimeBridge() {
} else {
statusCheckCleanupRef.current?.();
statusCheckCleanupRef.current = null;
setNanobotReady(null);
setBeaverReady(null);
}
});
@ -98,7 +98,7 @@ export function AppRuntimeBridge() {
statusCheckCleanupRef.current = null;
unsubStatus();
};
}, [scheduleStatusCheck, setNanobotReady, setWsStatus]);
}, [scheduleStatusCheck, setBeaverReady, setWsStatus]);
React.useEffect(() => {
const unsubMessage = wsManager.onMessage((data) => {

View File

@ -3,7 +3,7 @@
import React from 'react';
import Link from 'next/link';
import { usePathname, useRouter } from 'next/navigation';
import { Bell, Bot, ChevronDown, FolderOpen, ListTodo, LogOut, Mail, MessageSquare, PackageOpen, Puzzle, Settings, Store, Wrench } from 'lucide-react';
import { Bell, Bot, ChevronDown, FolderOpen, ListTodo, LogOut, Mail, MessageSquare, Puzzle, Settings, Store, Wrench } from 'lucide-react';
import { logout } from '@/lib/api';
import { LanguageSwitcher } from '@/components/LanguageSwitcher';
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
@ -15,7 +15,7 @@ import { useAppI18n } from '@/lib/i18n/provider';
import { useChatStore } from '@/lib/store';
type NavItem = {
key: 'chat' | 'tasks' | 'notifications' | 'skills' | 'files' | 'tools' | 'agents' | 'outlook' | 'marketplace' | 'plugins' | 'settings';
key: 'chat' | 'tasks' | 'notifications' | 'skills' | 'files' | 'tools' | 'agents' | 'outlook' | 'marketplace' | 'settings';
href: string;
icon: React.ComponentType<{ className?: string }>;
matchPrefixes?: string[];
@ -23,7 +23,7 @@ type NavItem = {
const NAV_ITEMS: NavItem[] = [
{ key: 'chat', href: '/', icon: MessageSquare },
{ key: 'tasks', href: '/tasks', icon: ListTodo, matchPrefixes: ['/tasks', '/office', '/cron'] },
{ key: 'tasks', href: '/tasks', icon: ListTodo, matchPrefixes: ['/tasks', '/cron'] },
{ key: 'notifications', href: '/notifications', icon: Bell, matchPrefixes: ['/notifications'] },
{ key: 'skills', href: '/skills', icon: Puzzle },
{ key: 'files', href: '/files', icon: FolderOpen, matchPrefixes: ['/files'] },
@ -31,7 +31,6 @@ const NAV_ITEMS: NavItem[] = [
{ key: 'agents', href: '/agents', icon: Bot, matchPrefixes: ['/agents'] },
{ key: 'outlook', href: '/outlook', icon: Mail, matchPrefixes: ['/outlook'] },
{ key: 'marketplace', href: '/marketplace', icon: Store, matchPrefixes: ['/marketplace'] },
{ key: 'plugins', href: '/plugins', icon: PackageOpen, matchPrefixes: ['/plugins'] },
{
key: 'settings',
href: '/settings',
@ -43,12 +42,12 @@ const NAV_ITEMS: NavItem[] = [
function ConnectionDot() {
const { locale } = useAppI18n();
const wsStatus = useChatStore((s) => s.wsStatus);
const nanobotReady = useChatStore((s) => s.nanobotReady);
const beaverReady = useChatStore((s) => s.beaverReady);
const isOnline = wsStatus === 'connected' && nanobotReady === true;
const isChecking = wsStatus === 'connected' && nanobotReady === null;
const isOnline = wsStatus === 'connected' && beaverReady === true;
const isChecking = wsStatus === 'connected' && beaverReady === null;
const isConnecting = wsStatus === 'connecting' || isChecking;
const isOffline = wsStatus === 'disconnected' || (wsStatus === 'connected' && nanobotReady === false);
const isOffline = wsStatus === 'disconnected' || (wsStatus === 'connected' && beaverReady === false);
const color = isOnline
? 'bg-[#869683]'
@ -56,7 +55,7 @@ function ConnectionDot() {
? 'bg-[#8B7E77]'
: 'bg-[#5F5550]';
const label = appConnectionStatusLabel(wsStatus, nanobotReady, locale);
const label = appConnectionStatusLabel(wsStatus, beaverReady, locale);
return (
<div className="flex items-center gap-1.5 text-xs text-muted-foreground">
@ -84,7 +83,6 @@ const Header = () => {
if (key === 'agents') return pickAppText(locale, '智能体', 'Agents');
if (key === 'outlook') return 'Outlook';
if (key === 'marketplace') return pickAppText(locale, '市场', 'Marketplace');
if (key === 'plugins') return pickAppText(locale, '插件', 'Plugins');
return pickAppText(locale, '配置', 'Settings');
}, [locale]);

View File

@ -1,11 +1,10 @@
'use client';
import React from 'react';
import { CheckCircle2, Loader2, Sparkles, Square } from 'lucide-react';
import { CheckCircle2, Loader2, Sparkles } from 'lucide-react';
import type { ProcessArtifact, ProcessEvent, ProcessRun } from '@/types';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { appArtifactPreview, appFeedRoleLabel, appStatusLabel } from '@/lib/i18n/common';
import { pickAppText } from '@/lib/i18n/core';
import { useAppI18n } from '@/lib/i18n/provider';
@ -410,7 +409,6 @@ export function AgentTeamBlock({
artifacts,
selectedRunId,
onSelectRun,
onCancelRun,
}: {
rootRun: ProcessRun;
memberRuns: ProcessRun[];
@ -418,7 +416,6 @@ export function AgentTeamBlock({
artifacts: ProcessArtifact[];
selectedRunId: string | null;
onSelectRun: (runId: string) => void;
onCancelRun: (runId: string) => void;
}) {
const { locale } = useAppI18n();
const phases = useRunCardPhases(memberRuns);
@ -435,10 +432,6 @@ export function AgentTeamBlock({
const terminalRuns = sortedRuns.filter((run) => TERMINAL_STATUSES.has(run.status));
const collapsedRuns = sortedRuns.filter((run) => phases[run.run_id] === 'collapsed');
const liveCount = liveRuns.filter((run) => !TERMINAL_STATUSES.has(run.status)).length;
const canCancelRoot =
!rootRun.parent_run_id &&
(rootRun.status === 'running' || rootRun.status === 'waiting');
if (liveRuns.length === 0 && terminalRuns.length > 0) {
return (
<div className="inline-flex max-w-full flex-wrap items-start gap-2 rounded-2xl border border-border/60 bg-card/35 px-3 py-3 backdrop-blur-sm">
@ -486,12 +479,6 @@ export function AgentTeamBlock({
</p>
</div>
<div className="flex items-center gap-2">
{canCancelRoot && (
<Button variant="outline" size="sm" className="bg-background/60" onClick={() => onCancelRun(rootRun.run_id)}>
<Square className="mr-1.5 h-3.5 w-3.5" />
{pickAppText(locale, '取消', 'Cancel')}
</Button>
)}
<Badge variant="outline" className="border-border/70 bg-background/55 text-foreground/85">
{pickAppText(locale, `${memberRuns.length} 个子任务`, `${memberRuns.length} subtasks`)}
</Badge>

View File

@ -15,7 +15,6 @@ export function ChatWorkbench({
processArtifacts,
selectedRunId,
onSelectRun,
onCancelRun,
onFeedback,
}: {
messages: ChatMessage[];
@ -27,7 +26,6 @@ export function ChatWorkbench({
processArtifacts: ProcessArtifact[];
selectedRunId: string | null;
onSelectRun: (runId: string) => void;
onCancelRun: (runId: string) => void;
onFeedback: (runId: string, feedbackType: 'satisfied' | 'revise' | 'abandon', comment?: string) => void;
}) {
return (
@ -42,7 +40,6 @@ export function ChatWorkbench({
processArtifacts={processArtifacts}
selectedRunId={selectedRunId}
onSelectRun={onSelectRun}
onCancelRun={onCancelRun}
onFeedback={onFeedback}
/>
</div>

View File

@ -329,7 +329,6 @@ export function MessageList({
processArtifacts,
selectedRunId,
onSelectRun,
onCancelRun,
onFeedback,
}: {
messages: ChatMessage[];
@ -341,7 +340,6 @@ export function MessageList({
processArtifacts: ProcessArtifact[];
selectedRunId: string | null;
onSelectRun: (runId: string) => void;
onCancelRun: (runId: string) => void;
onFeedback: (runId: string, feedbackType: 'satisfied' | 'revise' | 'abandon', comment?: string) => void;
}) {
const { locale } = useAppI18n();
@ -411,7 +409,6 @@ export function MessageList({
artifacts={processArtifacts}
selectedRunId={selectedRunId}
onSelectRun={onSelectRun}
onCancelRun={onCancelRun}
/>
)
)}

View File

@ -3,14 +3,14 @@
import { useAppI18n } from '@/lib/i18n/provider';
import { Badge } from '@/components/ui/badge';
import { cn } from '@/lib/utils';
import type { OfficeTaskStatus, OfficeZoneView } from '@/lib/office';
import { officeTaskStatusLabel } from '@/lib/office';
import type { TaskRuntimeStatus } from '@/lib/task-runtime';
import { taskRuntimeStatusLabel } from '@/lib/task-runtime';
export function OfficeStatusBadge({
export function TaskRuntimeStatusBadge({
status,
className,
}: {
status: OfficeTaskStatus;
status: TaskRuntimeStatus;
className?: string;
}) {
const { locale } = useAppI18n();
@ -30,12 +30,12 @@ export function OfficeStatusBadge({
className
)}
>
{officeTaskStatusLabel(status, locale)}
{taskRuntimeStatusLabel(status, locale)}
</Badge>
);
}
export function formatOfficeTime(value?: string | null, locale: 'zh-CN' | 'en-US' = 'zh-CN'): string {
export function formatTaskRuntimeTime(value?: string | null, locale: 'zh-CN' | 'en-US' = 'zh-CN'): string {
if (!value) return '-';
const date = new Date(value);
if (Number.isNaN(date.getTime())) return value;
@ -47,7 +47,7 @@ export function formatOfficeTime(value?: string | null, locale: 'zh-CN' | 'en-US
}).format(date);
}
export function formatOfficeDuration(durationMs: number | null, locale: 'zh-CN' | 'en-US' = 'zh-CN'): string {
export function formatTaskRuntimeDuration(durationMs: number | null, locale: 'zh-CN' | 'en-US' = 'zh-CN'): string {
if (durationMs === null || durationMs < 0) return '-';
if (durationMs < 1000) return locale === 'en-US' ? '<1s' : '<1秒';
@ -65,15 +65,3 @@ export function progressPercent(value: number | null, max: number | null): numbe
if (value === null || max === null || max <= 0) return 0;
return Math.max(0, Math.min(100, Math.round((value / max) * 100)));
}
export function zonePanelClassName(zone: OfficeZoneView): string {
return cn(
'relative min-h-[220px] overflow-hidden rounded-2xl border p-4 shadow-sm',
'before:pointer-events-none before:absolute before:inset-0 before:bg-[radial-gradient(circle_at_top_left,rgba(255,255,255,0.9),transparent_40%)]',
zone.tone === 'info' && 'border-[#BCC4CE] bg-[#E4E7EB]/70',
zone.tone === 'warn' && 'border-[#B8AEA8] bg-[#E7E2DE]/70',
zone.tone === 'danger' && 'border-[#B8AEA8] bg-[#E7E2DE]/80',
zone.tone === 'success' && 'border-[#B7C2B5] bg-[#E3E8E2]/75',
zone.tone === 'neutral' && 'border-border bg-card'
);
}