Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
Commit ·
f8e758f
1
Parent(s): 6c9f1f6
fix: reset approval UI state when new approval round arrives
Browse filesAfter submitting a rejection with feedback, isSubmitting was never reset
on success. When the agent made a second tool call requiring approval,
the InlineApproval component was blocked by the stale isSubmitting=true.
Track submitted tool IDs and reset submission state when new (unseen)
pending tools arrive in the same ToolCallGroup instance.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
frontend/src/components/Chat/ToolCallGroup.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
import { useCallback, useMemo, useRef, useState } from 'react';
|
| 2 |
import { Box, Stack, Typography, Chip, Button, TextField, IconButton, Link, CircularProgress } from '@mui/material';
|
| 3 |
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';
|
| 4 |
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
|
|
@@ -282,6 +282,20 @@ export default function ToolCallGroup({ tools, approveTools }: ToolCallGroupProp
|
|
| 282 |
const [isSubmitting, setIsSubmitting] = useState(false);
|
| 283 |
const submittingRef = useRef(false);
|
| 284 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 285 |
const { scriptLabelMap, toolDisplayMap } = useMemo(() => {
|
| 286 |
const hfJobs = tools.filter(t => t.toolName === 'hf_jobs' && (t.input as Record<string, unknown>)?.script);
|
| 287 |
const scriptMap: Record<string, string> = {};
|
|
@@ -321,6 +335,8 @@ export default function ToolCallGroup({ tools, approveTools }: ToolCallGroupProp
|
|
| 321 |
|
| 322 |
const ok = await approveTools(approvals);
|
| 323 |
if (ok) {
|
|
|
|
|
|
|
| 324 |
lockPanel();
|
| 325 |
} else {
|
| 326 |
logger.error('Batch approval failed');
|
|
|
|
| 1 |
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
| 2 |
import { Box, Stack, Typography, Chip, Button, TextField, IconButton, Link, CircularProgress } from '@mui/material';
|
| 3 |
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';
|
| 4 |
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
|
|
|
|
| 282 |
const [isSubmitting, setIsSubmitting] = useState(false);
|
| 283 |
const submittingRef = useRef(false);
|
| 284 |
|
| 285 |
+
// Track which toolCallIds we've already submitted so we can detect new approval rounds
|
| 286 |
+
const submittedIdsRef = useRef<Set<string>>(new Set());
|
| 287 |
+
|
| 288 |
+
// Reset submission state when new (unseen) pending tools arrive — e.g. second approval round
|
| 289 |
+
useEffect(() => {
|
| 290 |
+
if (!isSubmitting || pendingTools.length === 0) return;
|
| 291 |
+
const hasNewPending = pendingTools.some(t => !submittedIdsRef.current.has(t.toolCallId));
|
| 292 |
+
if (hasNewPending) {
|
| 293 |
+
submittingRef.current = false;
|
| 294 |
+
setIsSubmitting(false);
|
| 295 |
+
setDecisions({});
|
| 296 |
+
}
|
| 297 |
+
}, [pendingTools, isSubmitting]);
|
| 298 |
+
|
| 299 |
const { scriptLabelMap, toolDisplayMap } = useMemo(() => {
|
| 300 |
const hfJobs = tools.filter(t => t.toolName === 'hf_jobs' && (t.input as Record<string, unknown>)?.script);
|
| 301 |
const scriptMap: Record<string, string> = {};
|
|
|
|
| 335 |
|
| 336 |
const ok = await approveTools(approvals);
|
| 337 |
if (ok) {
|
| 338 |
+
// Track which tool IDs were submitted so we can detect new approval rounds
|
| 339 |
+
for (const a of approvals) submittedIdsRef.current.add(a.tool_call_id);
|
| 340 |
lockPanel();
|
| 341 |
} else {
|
| 342 |
logger.error('Batch approval failed');
|