Skip to content

Commit 8ca7366

Browse files
authored
Merge pull request #292 from esokullu/main
bugfixes
2 parents 71df10f + 97c02a8 commit 8ca7366

18 files changed

Lines changed: 468 additions & 33 deletions

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "webbrain",
3-
"version": "21.5.0",
3+
"version": "21.5.1",
44
"description": "Open-source AI browser agent — chat with pages, automate tasks, multi-provider LLM support.",
55
"private": true,
66
"type": "module",

src/chrome/ARCHITECTURE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# WebBrain Chrome/Edge Extension — Architecture
22

3-
> Version 21.5.0 · Manifest V3 · Service Worker background
3+
> Version 21.5.1 · Manifest V3 · Service Worker background
44
55
## High-Level Overview
66

src/chrome/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifest_version": 3,
33
"name": "WebBrain",
4-
"version": "21.5.0",
4+
"version": "21.5.1",
55
"description": "Open-source AI browser agent — chat with pages, automate tasks, multi-provider LLM support.",
66
"permissions": [
77
"sidePanel",

src/chrome/src/agent/agent.js

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ export class Agent {
7575
this._progressSessionCounter = 0;
7676
this.conversationModes = new Map(); // tabId -> 'ask' | 'act' | 'dev'
7777
this.conversationIds = new Map(); // tabId -> stable conversationId (regenerated on clearConversation)
78+
this.plannerFollowUpSkipTabs = new Set(); // tabIds allowed one short follow-up after an approved try-mode plan
7879
this.hydratedTabs = new Set(); // tabIds we've already pulled from storage
7980
this.persistTimers = new Map(); // tabId -> debounce handle
8081
this.abortFlags = new Map(); // tabId -> boolean
@@ -287,6 +288,7 @@ export class Agent {
287288
}
288289

289290
clearScratchpad(tabId) {
291+
this.plannerFollowUpSkipTabs.delete(tabId);
290292
const messages = this.conversations.get(tabId);
291293
if (!messages) {
292294
return { success: true, existed: false, note: 'scratchpad already empty' };
@@ -3896,6 +3898,44 @@ Rules: no prose intro, no conclusion, no "this screenshot shows...", no layout d
38963898
return this._plannerMode() !== 'off';
38973899
}
38983900

3901+
_messageHasPlannerFollowUpAttachmentBlocks(message) {
3902+
const content = message?.content ?? message;
3903+
if (!Array.isArray(content)) return false;
3904+
return content.some(block => {
3905+
if (!block || typeof block !== 'object') return false;
3906+
if (block.type !== 'text') return true;
3907+
const text = String(block.text || '');
3908+
return text.startsWith('[UNTRUSTED USER ATTACHMENTS') || text.startsWith('[UNTRUSTED DOCUMENT');
3909+
});
3910+
}
3911+
3912+
_plannerFollowUpText(message) {
3913+
const text = this._stripInjectedTaskContext(userMessageToText(message));
3914+
return text.replace(/\s+/g, ' ').trim();
3915+
}
3916+
3917+
_plannerFollowUpHasExplicitUrl(text) {
3918+
return /(?:https?:\/\/|www\.)\S+|\b(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}(?:\/[^\s]*)?/i.test(String(text || ''));
3919+
}
3920+
3921+
_hasApprovedPlannerHandoff(messages) {
3922+
const idx = this._findScratchpadIndex(messages || []);
3923+
if (idx < 0) return false;
3924+
const body = this._extractScratchpadBody(messages[idx].content);
3925+
return /\[Approved plan\b[^\]]*pinned by planner\]/.test(body);
3926+
}
3927+
3928+
_shouldSkipPlannerForShortFollowUp(tabId, priorMessages, enriched, plannerMode) {
3929+
if (plannerMode !== 'try') return false;
3930+
if (this._normalizePlanReviewMode(this.planReviewMode) === 'always') return false;
3931+
if (!this.plannerFollowUpSkipTabs.has(tabId)) return false;
3932+
if (!this._hasApprovedPlannerHandoff(priorMessages)) return false;
3933+
if (this._messageHasPlannerFollowUpAttachmentBlocks(enriched)) return false;
3934+
const text = this._plannerFollowUpText(enriched);
3935+
if (!text || text.length > 100) return false;
3936+
return !this._plannerFollowUpHasExplicitUrl(text);
3937+
}
3938+
38993939
/**
39003940
* Plan-before-Act gate: push user message, pin approved plan after it, or stop early.
39013941
*/
@@ -3910,7 +3950,15 @@ Rules: no prose intro, no conclusion, no "this screenshot shows...", no layout d
39103950
const priorMessages = runPlanner ? messages.slice() : null;
39113951
messages.push(enriched);
39123952
this._persist(tabId);
3913-
if (!runPlanner) return { proceed: true };
3953+
if (!runPlanner) {
3954+
this.plannerFollowUpSkipTabs.delete(tabId);
3955+
return { proceed: true };
3956+
}
3957+
if (this._shouldSkipPlannerForShortFollowUp(tabId, priorMessages, enriched, plannerMode)) {
3958+
this.plannerFollowUpSkipTabs.delete(tabId);
3959+
return { proceed: true };
3960+
}
3961+
this.plannerFollowUpSkipTabs.delete(tabId);
39143962

39153963
const historyDigest = this._buildPlannerHistoryDigest(priorMessages);
39163964
const gate = await this._runPlannerGate(tabId, enriched, onUpdate, costState, runId, historyDigest, tabInfo, plannerMode);
@@ -3935,6 +3983,7 @@ Rules: no prose intro, no conclusion, no "this screenshot shows...", no layout d
39353983
// Note: the "Plan approved — running…" confirmation is rendered locally
39363984
// by submitPlanReview in the sidepanel, so there's no plan_approved
39373985
// agent_update to emit here (no handler consumed it).
3986+
if (plannerMode === 'try') this.plannerFollowUpSkipTabs.add(tabId);
39383987
}
39393988
this._persist(tabId);
39403989
}
@@ -4962,6 +5011,7 @@ Rules: no prose intro, no conclusion, no "this screenshot shows...", no layout d
49625011
this._cancelClarifications(tabId, 'conversation cleared');
49635012
this._cancelPendingPlans(tabId, 'conversation cleared');
49645013
this.conversations.delete(tabId);
5014+
this.plannerFollowUpSkipTabs.delete(tabId);
49655015
this.progressLedgers.delete(tabId);
49665016
this.progressPageScopes.delete(tabId);
49675017
this.progressSessions.delete(tabId);

src/chrome/src/ui/settings.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919

2020
// Version shown in the subtitle. Kept here so it only needs one update per
2121
// release; the subtitle string itself is translated.
22-
const EXT_VERSION = '21.5.0';
22+
const EXT_VERSION = '21.5.1';
2323

2424
const providersContainer = document.getElementById('providers');
2525
const displaySettings = document.getElementById('display-settings');

src/chrome/src/ui/sidepanel.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,6 +1464,7 @@ async function handleScheduledJobEvent(data, tabId) {
14641464
isProcessing = true;
14651465
abortRequested = false;
14661466
syncSendButtonState();
1467+
hideRecommendedActions();
14671468
currentAssistantEl = addMessage('assistant', '');
14681469
if (jobId) currentAssistantEl.dataset.scheduledJobId = jobId;
14691470
showActivity(t('sp.scheduled.running', { title }));
@@ -1481,6 +1482,7 @@ async function handleScheduledJobEvent(data, tabId) {
14811482
clearActiveChatPayloadForTab(tabId ?? currentTabId);
14821483
isProcessing = true;
14831484
syncSendButtonState();
1485+
hideRecommendedActions();
14841486
} else {
14851487
isProcessing = false;
14861488
syncSendButtonState();
@@ -2077,6 +2079,7 @@ function conversationHasUserMessages() {
20772079
}
20782080

20792081
function hideRecommendedActions() {
2082+
recommendationsRequestId += 1;
20802083
if (!recommendedActionsEl || !recommendedActionsListEl) return;
20812084
recommendedActionsListEl.replaceChildren();
20822085
recommendedActionsEl.classList.add('hidden');
@@ -3790,6 +3793,7 @@ function renderClarifyCard(data) {
37903793
const tabId = data?.scheduledTabId ?? data?.tabId ?? currentTabId;
37913794
if (tabId == null) return;
37923795
const scheduledJobId = data?.scheduledJobId ? String(data.scheduledJobId) : '';
3796+
if (scheduledJobId) hideRecommendedActions();
37933797
let assistantEl = currentAssistantEl;
37943798
if (scheduledJobId && data.forceNewScheduledCard) {
37953799
assistantEl = addMessage('assistant', '');
@@ -4133,6 +4137,7 @@ function submitClarify(card, tabId, clarifyId, answer, source) {
41334137
}
41344138
isProcessing = true;
41354139
syncSendButtonState();
4140+
hideRecommendedActions();
41364141
showActivity(t('sp.activity.thinking'));
41374142
}
41384143
sendToBackground('clarify_response', { tabId, clarifyId, answer, source })

0 commit comments

Comments
 (0)