feat(ext): ask user approval for MCP task

This commit is contained in:
Simon
2026-03-18 19:14:44 +08:00
parent c0510b2235
commit 61d598142d
6 changed files with 191 additions and 62 deletions

View File

@@ -70,6 +70,7 @@ export class HubWs {
#ws: WebSocket | null = null
#state: HubWsState = 'disconnected'
#busy = false
#approved = false
#handlers: HubWsHandlers
#port: number
#onStateChange: (state: HubWsState) => void
@@ -103,6 +104,7 @@ export class HubWs {
ws.addEventListener('close', () => {
this.#ws = null
this.#busy = false
this.#approved = false
this.#setState('disconnected')
})
@@ -115,6 +117,7 @@ export class HubWs {
this.#ws?.close()
this.#ws = null
this.#busy = false
this.#approved = false
this.#setState('disconnected')
}
@@ -130,7 +133,7 @@ export class HubWs {
}
}
#handleMessage(raw: string) {
async #handleMessage(raw: string) {
let msg: InboundMessage
try {
msg = JSON.parse(raw)
@@ -138,6 +141,11 @@ export class HubWs {
return
}
if (!(await this.#checkApproval())) {
this.#send({ type: 'error', message: 'User denied the connection request.' })
return
}
switch (msg.type) {
case 'execute':
this.#handleExecute(msg)
@@ -148,6 +156,22 @@ export class HubWs {
}
}
async #checkApproval(): Promise<boolean> {
if (this.#approved) return true
const { allowAllHubConnection } = await chrome.storage.local.get('allowAllHubConnection')
if (allowAllHubConnection === true) {
this.#approved = true
return true
}
const ok = window.confirm(
'An external application is requesting to control your browser via Page Agent Ext.\nAllow this session?'
)
if (ok) this.#approved = true
return ok
}
async #handleExecute(msg: ExecuteMessage) {
if (this.#busy) {
this.#send({ type: 'error', message: 'Hub is busy with another task' })