| @@ -27,9 +27,8 @@ | ||
| 27 | 27 | getClientToolFallbackReply, |
| 28 | 28 | getClientTools, |
| 29 | 29 | } from '@agent/lib/client-tools'; |
| 30 | 30 | import { localPickWorkflow } from '@agent/lib/local-pick'; |
| 31 | -import { getRedirectUrl } from '@agent/lib/redirects'; | |
| 32 | 31 | import { doReload } from '@agent/lib/reload'; |
| 33 | 32 | import { useCanvasStore } from '@agent/state/canvas'; |
| 34 | 33 | import { useChatStore } from '@agent/state/chat'; |
| 35 | 34 | import { useGlobalStore } from '@agent/state/global'; |
| @@ -302,14 +301,15 @@ | ||
| 302 | 301 | setCanType(true); |
| 303 | 302 | }, [addMessage, pushStatus, whenFinishedToolProps, workflow]); |
| 304 | 303 | |
| 305 | 304 | const handleSubmit = useCallback( |
| 306 | - async (message, { hidden = false } = {}) => { | |
| 305 | + async (message, { hidden = false, step } = {}) => { | |
| 307 | 306 | // chat-submit events skip the textarea; disabling it isn't enough. |
| 308 | 307 | if (useQuickEditStore.getState().selected) return; |
| 309 | 308 | if (whenFinishedToolProps?.processing) return; |
| 310 | 309 | setWaitingOnToolOrUser(false); |
| 311 | 310 | agentWorking.current = false; |
| 311 | + if (step) addMessage('tool', { ...step, inputs: {}, fromCard: true }); | |
| 312 | 312 | addMessage('message', { role: 'user', content: message, hidden }); |
| 313 | 313 | |
| 314 | 314 | // Without this a typed message would drop the workflow and close the canvas. |
| 315 | 315 | if (canvasOpen && canvasAssist) return handleCanvasMessage(); |
| @@ -433,9 +433,10 @@ | ||
| 433 | 433 | useEffect(() => { |
| 434 | 434 | // Allow external messages to trigger the agent |
| 435 | 435 | const handleMessage = ({ detail }) => { |
| 436 | 436 | if (!detail?.message) return; |
| 437 | - handleSubmit(detail.message, { hidden: detail.hidden }); | |
| 437 | + const { message, hidden, step } = detail; | |
| 438 | + handleSubmit(message, { hidden, step }); | |
| 438 | 439 | }; |
| 439 | 440 | // Allow external code to clear the block and workflow |
| 440 | 441 | const handleCleanup = () => { |
| 441 | 442 | // cleanup() resets canType and agentWorking, so read them before it runs. |
| @@ -508,9 +509,9 @@ | ||
| 508 | 509 | whenFinishedToolProps |
| 509 | 510 | ? { ...whenFinishedToolProps, processing: true } |
| 510 | 511 | : null, |
| 511 | 512 | ); |
| 512 | - const { whenFinishedTool, answerId, redirectTo } = | |
| 513 | + const { whenFinishedTool, answerId } = | |
| 513 | 514 | whenFinishedToolProps?.agentResponse || {}; |
| 514 | 515 | const { id, labels } = whenFinishedTool || {}; |
| 515 | 516 | // Staged unanswered so its own component can show the run in progress. |
| 516 | 517 | const runMessageId = id ? addMessage('tool', { id, inputs: data }) : null; |
| @@ -569,14 +570,12 @@ | ||
| 569 | 570 | setLoop((prev) => prev + 1); |
| 570 | 571 | return; |
| 571 | 572 | } |
| 572 | 573 | |
| 573 | - const url = getRedirectUrl(redirectTo, whenFinishedToolProps?.inputs); | |
| 574 | 574 | // Reloading here unmounts a run component still watching its ability finish. |
| 575 | 575 | const refreshForAbility = |
| 576 | 576 | isAbilityTool(id) && shouldRefreshPage !== false; |
| 577 | - const willReload = | |
| 578 | - url || redirectUrl || shouldRefreshPage || refreshForAbility; | |
| 577 | + const willReload = redirectUrl || shouldRefreshPage || refreshForAbility; | |
| 579 | 578 | // A card shown now would flash just before the reload. |
| 580 | 579 | addMessage('workflow', { |
| 581 | 580 | status: 'completed', |
| 582 | 581 | label: labels?.confirm, |
| @@ -604,9 +603,9 @@ | ||
| 604 | 603 | } |
| 605 | 604 | setWorkflow(null); |
| 606 | 605 | useCanvasStore.getState().endSession(); |
| 607 | 606 | |
| 608 | - if (willReload) return doReload(url || redirectUrl); | |
| 607 | + if (willReload) return doReload(redirectUrl); | |
| 609 | 608 | cleanup(); |
| 610 | 609 | }; |
| 611 | 610 | const handleCancel = ({ detail }) => { |
| 612 | 611 | if (toolWorking.current) return; |