Files
zclaw_openfang/desktop/src/components/ButlerPanel/index.tsx
iven 80cadd1158
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
feat(ui): add ButlerPanel — pain points, proposals, memory insights
- Add Butler types (PainPoint, Proposal, DelegationResult) to viking-client.ts
- Add butler API functions: getButlerInsights, getButlerProposals,
  recordButlerPainPoint, generateButlerSolution, updateButlerProposalStatus,
  butlerDelegateTask
- Create ButlerPanel with three sections:
  - InsightsSection: pain point cards with evidence chain, severity, confidence
  - ProposalsSection: solution cards with accept/reject actions
  - MemorySection: Viking memory entries per agent
- Create useButlerInsights hook for data fetching
- Add "管家" tab to RightPanel with ConciergeBell icon

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 09:30:28 +08:00

61 lines
1.8 KiB
TypeScript

import { useButlerInsights } from '../../hooks/useButlerInsights';
import { InsightsSection } from './InsightsSection';
import { ProposalsSection } from './ProposalsSection';
import { MemorySection } from './MemorySection';
interface ButlerPanelProps {
agentId: string | undefined;
}
export function ButlerPanel({ agentId }: ButlerPanelProps) {
const { painPoints, proposals, loading, error, refresh } = useButlerInsights(agentId);
if (!agentId) {
return (
<div className="flex items-center justify-center h-full">
<p className="text-sm text-gray-500 dark:text-gray-400"> Agent</p>
</div>
);
}
return (
<div className="space-y-6">
{error && (
<div className="rounded-lg bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 px-3 py-2 text-xs text-red-700 dark:text-red-300">
{error}
</div>
)}
{loading && (
<div className="flex items-center justify-center py-4">
<div className="w-5 h-5 border-2 border-gray-300 dark:border-gray-600 border-t-blue-500 rounded-full animate-spin" />
</div>
)}
{/* Insights section */}
<div>
<h3 className="text-sm font-semibold text-gray-900 dark:text-gray-100 mb-2">
</h3>
<InsightsSection painPoints={painPoints} />
</div>
{/* Proposals section */}
<div>
<h3 className="text-sm font-semibold text-gray-900 dark:text-gray-100 mb-2">
</h3>
<ProposalsSection proposals={proposals} onStatusChange={refresh} />
</div>
{/* Memory section */}
<div>
<h3 className="text-sm font-semibold text-gray-900 dark:text-gray-100 mb-2">
</h3>
<MemorySection agentId={agentId} />
</div>
</div>
);
}