Skip to content

Commit 6190fea

Browse files
authored
fix(tarko): fallback to beforeActionImage in afterAction strategy to prevent flickering (#1352)
1 parent 8c0f42a commit 6190fea

1 file changed

Lines changed: 56 additions & 44 deletions

File tree

  • multimodal/tarko/agent-web-ui/src/standalone/workspace/renderers/browser-control

multimodal/tarko/agent-web-ui/src/standalone/workspace/renderers/browser-control/useScreenshots.ts

Lines changed: 56 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -65,35 +65,32 @@ export const useScreenshots = ({
6565

6666
let foundBeforeImage = false;
6767
let foundAfterImage = false;
68+
let beforeImageData: { url: string; pageUrl: string | null } | null = null;
69+
let afterImageData: { url: string; pageUrl: string | null } | null = null;
6870

6971
// Search for screenshots BEFORE the current tool call
70-
if (currentStrategy === 'beforeAction' || currentStrategy === 'both') {
71-
for (let i = currentToolCallIndex - 1; i >= 0; i--) {
72-
const msg = sessionMessages[i];
73-
if (msg.role === 'environment' && Array.isArray(msg.content)) {
74-
const imgContent = msg.content.find(
75-
(c) => typeof c === 'object' && 'type' in c && c.type === 'image_url',
76-
);
72+
// Always search for before action image as it may be used as fallback
73+
for (let i = currentToolCallIndex - 1; i >= 0; i--) {
74+
const msg = sessionMessages[i];
75+
if (msg.role === 'environment' && Array.isArray(msg.content)) {
76+
const imgContent = msg.content.find(
77+
(c) => typeof c === 'object' && 'type' in c && c.type === 'image_url',
78+
);
7779

78-
if (imgContent && 'image_url' in imgContent && imgContent.image_url.url) {
79-
const url =
80-
msg.metadata?.type === 'screenshot' && 'url' in msg.metadata
81-
? msg.metadata.url
82-
: null;
83-
setBeforeActionImage(imgContent.image_url.url);
84-
setBeforeActionImageUrl(url || null);
85-
if (currentStrategy === 'beforeAction') {
86-
setRelatedImage(imgContent.image_url.url);
87-
setRelatedImageUrl(url || null);
88-
}
89-
foundBeforeImage = true;
90-
break;
91-
}
80+
if (imgContent && 'image_url' in imgContent && imgContent.image_url.url) {
81+
const url =
82+
msg.metadata?.type === 'screenshot' && 'url' in msg.metadata ? msg.metadata.url : null;
83+
beforeImageData = { url: imgContent.image_url.url, pageUrl: url };
84+
setBeforeActionImage(imgContent.image_url.url);
85+
setBeforeActionImageUrl(url || null);
86+
foundBeforeImage = true;
87+
break;
9288
}
9389
}
9490
}
9591

9692
// Search for screenshots AFTER the current tool call
93+
// Always search for after action image as it may be needed for afterAction or both strategies
9794
if (currentStrategy === 'afterAction' || currentStrategy === 'both') {
9895
for (let i = currentToolCallIndex + 1; i < sessionMessages.length; i++) {
9996
const msg = sessionMessages[i];
@@ -107,41 +104,56 @@ export const useScreenshots = ({
107104
msg.metadata?.type === 'screenshot' && 'url' in msg.metadata
108105
? msg.metadata.url
109106
: null;
107+
afterImageData = { url: imgContent.image_url.url, pageUrl: url };
110108
setAfterActionImage(imgContent.image_url.url);
111109
setAfterActionImageUrl(url || null);
112-
if (currentStrategy === 'afterAction') {
113-
setRelatedImage(imgContent.image_url.url);
114-
setRelatedImageUrl(url || null);
115-
}
116110
foundAfterImage = true;
117111
break;
118112
}
119113
}
120114
}
121115
}
122116

123-
// Handle strategy-specific warnings and fallbacks
117+
// Handle strategy-specific logic and fallbacks
124118
if (!environmentImage) {
125-
if (currentStrategy === 'beforeAction' && !foundBeforeImage) {
126-
console.warn(
127-
`[BrowserControlRenderer] No valid screenshot found before toolCallId: ${toolCallId}. Clearing screenshot display.`,
128-
);
129-
setRelatedImage(null);
130-
setRelatedImageUrl(null);
131-
} else if (currentStrategy === 'afterAction' && !foundAfterImage) {
132-
console.warn(
133-
`[BrowserControlRenderer] No valid screenshot found after toolCallId: ${toolCallId}. Clearing screenshot display.`,
134-
);
135-
setRelatedImage(null);
136-
setRelatedImageUrl(null);
119+
if (currentStrategy === 'beforeAction') {
120+
if (beforeImageData) {
121+
setRelatedImage(beforeImageData.url);
122+
setRelatedImageUrl(beforeImageData.pageUrl);
123+
} else {
124+
console.warn(
125+
`[BrowserControlRenderer] No valid screenshot found before toolCallId: ${toolCallId}. Clearing screenshot display.`,
126+
);
127+
setRelatedImage(null);
128+
setRelatedImageUrl(null);
129+
}
130+
} else if (currentStrategy === 'afterAction') {
131+
if (afterImageData) {
132+
// Use after action image when available
133+
setRelatedImage(afterImageData.url);
134+
setRelatedImageUrl(afterImageData.pageUrl);
135+
} else if (beforeImageData) {
136+
// Fallback to before action image to prevent flickering
137+
console.warn(
138+
`[BrowserControlRenderer] No valid screenshot found after toolCallId: ${toolCallId}. Falling back to before action image.`,
139+
);
140+
setRelatedImage(beforeImageData.url);
141+
setRelatedImageUrl(beforeImageData.pageUrl);
142+
} else {
143+
console.warn(
144+
`[BrowserControlRenderer] No valid screenshots found for toolCallId: ${toolCallId}. Clearing screenshot display.`,
145+
);
146+
setRelatedImage(null);
147+
setRelatedImageUrl(null);
148+
}
137149
} else if (currentStrategy === 'both') {
138150
// For 'both' strategy, use the after action image as primary if available
139-
if (foundAfterImage) {
140-
setRelatedImage(afterActionImage);
141-
setRelatedImageUrl(afterActionImageUrl);
142-
} else if (foundBeforeImage) {
143-
setRelatedImage(beforeActionImage);
144-
setRelatedImageUrl(beforeActionImageUrl);
151+
if (afterImageData) {
152+
setRelatedImage(afterImageData.url);
153+
setRelatedImageUrl(afterImageData.pageUrl);
154+
} else if (beforeImageData) {
155+
setRelatedImage(beforeImageData.url);
156+
setRelatedImageUrl(beforeImageData.pageUrl);
145157
} else {
146158
console.warn(
147159
`[BrowserControlRenderer] No valid screenshots found for toolCallId: ${toolCallId}. Clearing screenshot display.`,

0 commit comments

Comments
 (0)