feat: integrate Sentry + fix CI/CD issues
Sentry Integration (補強 SignOz): - Add @sentry/nextjs for frontend error tracking + session replay - Add sentry-sdk[fastapi] for backend error tracking - Create sentry.client/server/edge.config.ts - Integrate with next.config.js + instrumentation.ts - Add Sentry exception capture in FastAPI error handler - Create deployment scripts for Self-Hosted @ 192.168.0.110 CI/CD Fixes: - Fix F821 Undefined name 'Field' in incidents.py - Add NEXT_PUBLIC_API_URL env var to CI build step - Add build-arg to Docker build verification E2E Test Improvements: - Fix strict mode violations in dashboard-acceptance tests - Add timeout increase for Phase 4 demo tests - Make tests more resilient to UI variations Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -43,7 +43,7 @@ export function AICommandPanel({ className }: AICommandPanelProps) {
|
||||
const tApproval = useTranslations('approval')
|
||||
|
||||
// Store
|
||||
const { fetchPending, signApproval, startPolling, stopPolling } = useApprovalStore()
|
||||
const { fetchPending, signApproval, rejectApproval, startPolling, stopPolling } = useApprovalStore()
|
||||
const pendingApprovals = usePendingApprovals()
|
||||
|
||||
// Start polling on mount
|
||||
@@ -60,8 +60,7 @@ export function AICommandPanel({ className }: AICommandPanelProps) {
|
||||
|
||||
// Handle rejection
|
||||
const handleReject = async (id: string) => {
|
||||
// TODO: Implement rejection API
|
||||
console.log('[AICommandPanel] Reject:', id)
|
||||
await rejectApproval(id, 'demo-user', 'War Room User', 'Rejected via Command Center')
|
||||
await fetchPending()
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ export function HITLSection({ locale, className }: HITLSectionProps) {
|
||||
const tApproval = useTranslations('approval')
|
||||
|
||||
// Store
|
||||
const { fetchPending, signApproval, startPolling, stopPolling } = useApprovalStore()
|
||||
const { fetchPending, signApproval, rejectApproval, startPolling, stopPolling } = useApprovalStore()
|
||||
const pendingApprovals = usePendingApprovals()
|
||||
const addTimelineEvent = useTimelineStore((state) => state.addEvent)
|
||||
|
||||
@@ -256,9 +256,9 @@ export function HITLSection({ locale, className }: HITLSectionProps) {
|
||||
|
||||
// Handle rejection
|
||||
const handleReject = useCallback(async (id: string) => {
|
||||
// For demo, just refresh
|
||||
await rejectApproval(id, 'demo-user', currentUserName, 'Rejected via HITL Panel')
|
||||
await fetchPending()
|
||||
}, [fetchPending])
|
||||
}, [rejectApproval, fetchPending, currentUserName])
|
||||
|
||||
return (
|
||||
<section className={cn('space-y-6', className)}>
|
||||
|
||||
@@ -32,13 +32,17 @@ class AutoHealingErrorBoundaryInner extends Component<InnerProps, State> {
|
||||
retryCount: 0
|
||||
};
|
||||
|
||||
public static getDerivedStateFromError(_: Error): State {
|
||||
return { hasError: true, retryCount: 0 };
|
||||
public static getDerivedStateFromError(_: Error): Partial<State> {
|
||||
// 只設定 hasError,保留 retryCount 防止無限重試
|
||||
return { hasError: true };
|
||||
}
|
||||
|
||||
public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
||||
console.error('[AWOOOI] Frontend component crashed:', error, errorInfo);
|
||||
this.attemptAutoHealing();
|
||||
// 檢查是否已達重試上限
|
||||
if (this.state.retryCount < 3) {
|
||||
this.attemptAutoHealing();
|
||||
}
|
||||
}
|
||||
|
||||
private attemptAutoHealing = () => {
|
||||
|
||||
Reference in New Issue
Block a user