From cd40c36c2b8db256cd9c2dda97ddea59d37f2b5c Mon Sep 17 00:00:00 2001 From: hugocasa Date: Thu, 8 Oct 2026 18:38:05 +0200 Subject: [PATCH] feat: prepare browser actions before approval, allow yolo in the panel, add the windmill icon Co-Authored-By: Claude Opus 5.5 --- browser_extension/README.md | 2 +- browser_extension/package.json | 2 +- browser_extension/src/panel.ts | 1 + browser_extension/static/icons/icon128.png | Bin 0 -> 17145 bytes browser_extension/static/icons/icon16.png | Bin 0 -> 1664 bytes browser_extension/static/icons/icon32.png | Bin 0 -> 3622 bytes browser_extension/static/icons/icon48.png | Bin 0 -> 5462 bytes browser_extension/static/manifest.json | 25 ++++++++++-- .../copilot/chat/AIChatDisplay.svelte | 6 +++ .../copilot/chat/AIChatManager.svelte.ts | 5 +-- .../components/copilot/chat/chatViewHost.ts | 2 + .../copilot/chat/global/browserTools.ts | 37 +++++++++--------- 12 files changed, 52 insertions(+), 28 deletions(-) create mode 100644 browser_extension/static/icons/icon128.png create mode 100644 browser_extension/static/icons/icon16.png create mode 100644 browser_extension/static/icons/icon32.png create mode 100644 browser_extension/static/icons/icon48.png diff --git a/browser_extension/README.md b/browser_extension/README.md index a8aef0dcf2..67ba034e7a 100644 --- a/browser_extension/README.md +++ b/browser_extension/README.md @@ -27,7 +27,7 @@ icon to open the panel. - Only the active tab of the panel's window is read or acted on. - Reading and screenshots run without asking. Each click, type and navigation waits for the chat's own approval card, which lives in Windmill's frame where the page cannot reach it. - YOLO auto-approval is unavailable in the panel. + The chat's Yolo mode skips the card, and its warning says pages can try to steer it. - Approval runs in two steps. When the card opens, the extension pins the target (tab, document and element, the element held in the extension's isolated world) and describes it for the card. After approval it acts only on that target, and refuses if the tab is no diff --git a/browser_extension/package.json b/browser_extension/package.json index 9a851c2bdb..436cefd554 100644 --- a/browser_extension/package.json +++ b/browser_extension/package.json @@ -3,7 +3,7 @@ "private": true, "version": "0.1.0", "scripts": { - "build": "rm -rf dist && tsc && cp static/* dist/" + "build": "rm -rf dist && tsc && cp -r static/. dist/" }, "devDependencies": { "@types/chrome": "^0.3.4", diff --git a/browser_extension/src/panel.ts b/browser_extension/src/panel.ts index 0d15e1ebf1..5f3f0608d3 100644 --- a/browser_extension/src/panel.ts +++ b/browser_extension/src/panel.ts @@ -210,6 +210,7 @@ function pageAction( el.innerText || input.placeholder || (input.type === 'submit' || input.type === 'button' ? input.value : '') || + el.title || input.name || '' ) diff --git a/browser_extension/static/icons/icon128.png b/browser_extension/static/icons/icon128.png new file mode 100644 index 0000000000000000000000000000000000000000..8453ee5e8c1b2afb6e5344284b0694938fc1ccd5 GIT binary patch literal 17145 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 literal 0 HcmV?d00001 diff --git a/browser_extension/static/icons/icon16.png b/browser_extension/static/icons/icon16.png new file mode 100644 index 0000000000000000000000000000000000000000..a68832bfd8afb26eddb2166cd6d1375ef1d7196f GIT binary patch literal 1664 zcmZ{kc~H{_7RP^30u&8LkpjV#5Dq1f7%p=ZghB#|kyAj9K*5BYkO&EgREXSofQo=} z70OXjK@oxyXtWd)91aOuqYzM`%25=7a2NqMyF0TpyEFS{zV9>h-hAf$_lkVHJirzoLG6D=TUF7$X{K-mU^J4SCjgwX003?-0LT?1?i>Jc&;YOy0RZ@`0HDvR z=KDG-7OKZ79s~sy^~tR#OM$Ohq~H_)P!9T6s)T|L#ZZk+_9Ut;XsBx&p<{&dBLD!R zkO@EdlSG`d^uz$-9$}WN0pV1pWz}+BF}ZA>`xCgm$kNxm0uPJ#xi2IXeiLVPqRI^lo3pd05?lL zb8l>HWi{u5x;+3%mu%GN*~BEIcKs+Gh@!$r?M<|yYD(%l6OUJK+MfWgj>gjK`matJ z8eVhqLvjjynmr#s+5KDzVq|ndSU}W-fLltg&6s-dq5j^eZyL)hCpI+?-78eY{P_p@$vT=Jd>0 zuAbMe$@~-%#CZ~&iZBy;K)aM5BHJ#j#6pUI&r8{zt!Qj=P0UH5Bk@ZCZQ3+O_bQ9N zBs1>9u5NpdNIrnaXrknDyZx-L>nYXUoDY3X3()wji}m0Mw_~#QDZ8ht?{4pQKU=)p z)v7<c#t?OlNV(oW-@|pwJH_z8s?X!%6hg}gzFO1CSj##Bl%Ss+)j$g`H z-<5iHc@tlvYiS1mBTF|Ae(6PGe@HvTxUT!=Und{C9Mj4|X`AaKGLwyS9n4?xm|k2; zLV|lsD_IiNGDo0_mt+=(H!~1#Hb2Pv5hb#Xvak0_ zPr%R3lR|UHYigxVBbP_`vd&N7`ZwLap1cui*!?YN-?GUq$G&B^;W)RC@pwp4u`Q#y z;pY7cv`R2PXrnp&fMn??sk9V+jtD<-9F5Y5wOwA*${^lvJiF@OptaXJJY=~yK0xL% zwQ{RTAQBB7@hTiHGv-VFoER5z9tyMPj4V*!*&+Mnuiaqs4ZmPHB5OUg?9PEx4L{vr zzHT)M9^M%``jkJ!cokk7oWK5eyGjMmbsB~VJgMQh(QdMJOHC6+a70pwF*<4wdczz- z*Ya*}{Jgkuf0Ql0R{sEZ$aBvMK9cgz@Qg&H`x=3;F!Li6#e%&9Wqad(+r2Gud`4$D zVRiJuxW{<+*@gV76rUjOMQ%29W*F4Pu`#^Ct*qbX3!&onunE`Y7JQlCMXayT{#keF zGXn&s8kYMN&D8>B(Rf&9D&?v@7Yd8g>Sx7`Ikq6|5g?7!QapBhK7a9ZXuPY55~C`3 zw3=RcNXld#QzdTY&RBIAS7Z>3dj!lL&4RaYs$P}1-rhRuG@f}km2DJ;S+G824XZ7s zx=ao&@@98HcSGy2wtqOg^uA=4L+S@P1BWgUT#|C63|ukR z*e^6rHpEjtR(<;G;hcsTp%;H&75^9K!v5?#mPpXHlm3ac_wQN!_a4b>D`j%Ceb--d zav9ZJ`jdGH&f<%3!Yy5t)tSGM0=ejnF;Mv_x^e~{DdcqYz~oC)0UfxJbg7Qy)E;v| z(xdVugZJwlt@*(Xad}$J>D~_0l$>8fGM?@m+Ig@G=BxgY=u*(qJnXK8sp37Vm0-V0 zaDHIpggrOk#K`~o?|`_sN|S{J!*Sv7P!aWmQ$Pu((3nixSpwzG?q^-%8LIvo4H*iF zV!b#mWIo~_6u||@LH<;}Eh$g8IM0}4SpvC12>Sh)g&yxE?Vg?c+8mv-xodv&KntNP z9jy4Y=4@gRn;yxI!qbwY6aZ||wg-_mXe1izZ*vfjcEF=;tk7sY8m-qF4f`*F!KBAU xr~iL}{&A{WA?*Lp1$G=GDuo@%VEvC{i^1Dt|9vF0ZL(b90A!*Uq0KcS`yY_3;er4F literal 0 HcmV?d00001 diff --git a/browser_extension/static/icons/icon32.png b/browser_extension/static/icons/icon32.png new file mode 100644 index 0000000000000000000000000000000000000000..8febd12a3e974303a22834df33d2a9ddbd2fd087 GIT binary patch literal 3622 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 literal 0 HcmV?d00001 diff --git a/browser_extension/static/manifest.json b/browser_extension/static/manifest.json index 8149c16370..752ac3b7ad 100644 --- a/browser_extension/static/manifest.json +++ b/browser_extension/static/manifest.json @@ -5,8 +5,25 @@ "description": "Windmill AI sessions in the side panel, with tools that act on the active tab.", "permissions": ["sidePanel", "storage", "scripting", "tabs"], "host_permissions": [""], - "background": { "service_worker": "background.js", "type": "module" }, - "action": { "default_title": "Open Windmill" }, - "side_panel": { "default_path": "panel.html" }, - "options_page": "options.html" + "background": { + "service_worker": "background.js", + "type": "module" + }, + "action": { + "default_title": "Open Windmill", + "default_icon": { + "16": "icons/icon16.png", + "32": "icons/icon32.png" + } + }, + "side_panel": { + "default_path": "panel.html" + }, + "options_page": "options.html", + "icons": { + "16": "icons/icon16.png", + "32": "icons/icon32.png", + "48": "icons/icon48.png", + "128": "icons/icon128.png" + } } diff --git a/frontend/src/lib/components/copilot/chat/AIChatDisplay.svelte b/frontend/src/lib/components/copilot/chat/AIChatDisplay.svelte index d5406aeca2..1254e19be6 100644 --- a/frontend/src/lib/components/copilot/chat/AIChatDisplay.svelte +++ b/frontend/src/lib/components/copilot/chat/AIChatDisplay.svelte @@ -1277,6 +1277,12 @@ the panel, or the Escape-to-stop focus check would wrongly reject them. --> ? 'This can result in edits being applied or tools being called without user confirmation.' : 'This can result in tools being called without user confirmation.'}

+ {#if chatHost.browserTools} +

+ That includes clicking, typing and navigating on your page, and a page you + visit can try to steer the assistant into doing so. +

+ {/if} {#if yoloBypassedTools.length > 0}

Bypassed in current mode:

    diff --git a/frontend/src/lib/components/copilot/chat/AIChatManager.svelte.ts b/frontend/src/lib/components/copilot/chat/AIChatManager.svelte.ts index dd49970051..bc9a8e986d 100644 --- a/frontend/src/lib/components/copilot/chat/AIChatManager.svelte.ts +++ b/frontend/src/lib/components/copilot/chat/AIChatManager.svelte.ts @@ -737,10 +737,7 @@ export class AIChatManager implements ChatViewHost { (this.autonomyMode === AIAutonomyMode.ACCEPT_EDIT || this.autonomyMode === AIAutonomyMode.YOLO) ) - // Never in the side panel: page content in context could steer an unconfirmed workspace tool. - autoAcceptToolConfirmationsAvailable = $derived( - !this.browserTools && supportsAutoAcceptToolConfirmations(this.mode) - ) + autoAcceptToolConfirmationsAvailable = $derived(supportsAutoAcceptToolConfirmations(this.mode)) autoAcceptToolConfirmationsActive = $derived( this.autonomyMode === AIAutonomyMode.YOLO && this.autoAcceptToolConfirmationsAvailable ) diff --git a/frontend/src/lib/components/copilot/chat/chatViewHost.ts b/frontend/src/lib/components/copilot/chat/chatViewHost.ts index bdacb57615..b9712c1a6f 100644 --- a/frontend/src/lib/components/copilot/chat/chatViewHost.ts +++ b/frontend/src/lib/components/copilot/chat/chatViewHost.ts @@ -157,6 +157,8 @@ export interface ChatViewHost { readonly autoAcceptEditsAvailable: boolean readonly autoAcceptToolConfirmationsAvailable: boolean readonly planModeAvailable: boolean + /** Hosted in the browser extension's side panel, with tools acting on the user's tab. */ + readonly browserTools?: boolean attachedFiles: AttachedFilesStore artifacts: SessionArtifactsStore openArtifact?: (artifactId: string, name: string, version?: ArtifactVersionTarget) => void diff --git a/frontend/src/lib/components/copilot/chat/global/browserTools.ts b/frontend/src/lib/components/copilot/chat/global/browserTools.ts index 4452653b6f..716f8976b2 100644 --- a/frontend/src/lib/components/copilot/chat/global/browserTools.ts +++ b/frontend/src/lib/components/copilot/chat/global/browserTools.ts @@ -18,8 +18,9 @@ type Action = 'click' | 'type' | 'navigate' let parentOrigin: string | undefined let connection: Promise | undefined const pending = new Map void; reject: (e: Error) => void }>() -/** By tool call: the extension's description of the target, made when the approval card opens. */ -const prepared = new Map>() +/** By the call's own `args` object, the one object the validation, the approval card and the + * tool all receive: the target the extension pinned and described before the card opened. */ +const prepared = new WeakMap() /** Resolves true once the extension framing this page answers the handshake, accepting only * its own window's messages. */ @@ -50,7 +51,6 @@ export function connectBrowserBridge(): Promise { export function cancelBrowserCalls() { for (const p of pending.values()) p.reject(new Error('Stopped by the user')) pending.clear() - prepared.clear() if (parentOrigin) window.parent.postMessage({ type: 'wm-browser:cancel' }, parentOrigin) } @@ -91,7 +91,9 @@ function fail(toolCallbacks: ToolCallbacks, toolId: string, content: string, e: } /** Click, type and navigate go through the chat's own approval card. The extension pins and - * describes the target as the card opens, and after approval runs only what it described. */ + * describes the target before the card opens, so Run is only offered on a described target, + * and after approval it runs only that. A call with nothing prepared is refused, never + * prepared again: a preparation made after consent would bind whatever the page holds then. */ function actionTool( tool: Action, schema: z.ZodObject, @@ -99,26 +101,25 @@ function actionTool( description: string, label: (args: any) => string ): SessionTool<{}> { - const prepare = (args: any) => callBrowser('prepare', { tool, args: schema.parse(args) }) return { requires: NONE, def: createToolDef(schema, name, description), showDetails: true, requiresConfirmation: true, - confirmationMessage: label, - onConfirmationRequested: ({ args, toolCallbacks, toolId }) => { - const p = prepare(args) - prepared.set(toolId, p) - p.then( - (r) => toolCallbacks.setToolStatus(toolId, { content: r.label }), - () => {} - ) - }, - fn: async ({ args, toolId, toolCallbacks }) => { - const p = prepared.get(toolId) ?? prepare(args) - prepared.delete(toolId) + validateBeforeConfirmation: async ({ args }) => { try { - const { approvalId, label: described } = await p + prepared.set(args, await callBrowser('prepare', { tool, args: schema.parse(args) })) + } catch (e) { + return `Failed: ${e instanceof Error ? e.message : String(e)}` + } + }, + confirmationMessage: (args) => prepared.get(args)?.label ?? label(args), + fn: async ({ args, toolId, toolCallbacks }) => { + const entry = prepared.get(args) + prepared.delete(args) + try { + if (!entry) throw new Error('This action was withdrawn. Ask again.') + const { approvalId, label: described } = entry const result = String(await callBrowser('act', { approvalId })) toolCallbacks.setToolStatus(toolId, { content: described, result, isLoading: false }) return result