fix: 浏览器控制器推迟到 app ready 后构造;pnpm 放行 electron postinstall

This commit is contained in:
Rick Ye
2026-09-07 12:02:23 +08:00
parent eafbe8c15d
commit 29eb566059
2 changed files with 26 additions and 18 deletions
+6
View File
@@ -0,0 +1,6 @@
onlyBuiltDependencies:
- '@google/genai'
- electron
- electron-winstaller
- esbuild
- protobufjs
+20 -18
View File
@@ -1,4 +1,4 @@
import { BrowserWindow, dialog, ipcMain, shell } from 'electron' import { app, BrowserWindow, dialog, ipcMain, shell } from 'electron'
import { mkdirSync } from 'node:fs' import { mkdirSync } from 'node:fs'
import { userInfo } from 'node:os' import { userInfo } from 'node:os'
import { AgentService } from './pi/agent-service' import { AgentService } from './pi/agent-service'
@@ -260,12 +260,14 @@ export function registerIpc(): AgentService {
}) })
// ---- 内置受管浏览器 ---- // ---- 内置受管浏览器 ----
const browser = getBrowserController() // 控制器构造会调 session.fromPartition,必须等 app ready;
// 面板状态广播(与 agent:event 同样转发到所有窗口) // IPC 处理器在渲染层就绪后才可能被调用,惰性取用是安全的
browser.onState((state) => { void app.whenReady().then(() => {
for (const win of BrowserWindow.getAllWindows()) { getBrowserController().onState((state) => {
if (!win.isDestroyed()) win.webContents.send('browser:event', { type: 'state', state }) for (const win of BrowserWindow.getAllWindows()) {
} if (!win.isDestroyed()) win.webContents.send('browser:event', { type: 'state', state })
}
})
}) })
const browserPass = <T,>(fn: () => T): T => { const browserPass = <T,>(fn: () => T): T => {
@@ -276,24 +278,24 @@ export function registerIpc(): AgentService {
} }
} }
ipcMain.handle('browser:getState', () => browser.getState()) ipcMain.handle('browser:getState', () => browserPass(() => getBrowserController().getState()))
ipcMain.handle('browser:navigate', (_e, input: unknown) => ipcMain.handle('browser:navigate', (_e, input: unknown) =>
browserPass(() => browser.navigateDisplay(typeof input === 'string' ? input : '')) browserPass(() => getBrowserController().navigateDisplay(typeof input === 'string' ? input : ''))
) )
ipcMain.handle('browser:goBack', () => browserPass(() => browser.goBack())) ipcMain.handle('browser:goBack', () => browserPass(() => getBrowserController().goBack()))
ipcMain.handle('browser:goForward', () => browserPass(() => browser.goForward())) ipcMain.handle('browser:goForward', () => browserPass(() => getBrowserController().goForward()))
ipcMain.handle('browser:reload', () => browserPass(() => browser.reload())) ipcMain.handle('browser:reload', () => browserPass(() => getBrowserController().reload()))
ipcMain.handle('browser:newTab', (_e, url: unknown) => ipcMain.handle('browser:newTab', (_e, url: unknown) =>
browserPass(() => browser.newTab(typeof url === 'string' && url ? url : undefined, false)) browserPass(() => getBrowserController().newTab(typeof url === 'string' && url ? url : undefined, false))
) )
ipcMain.handle('browser:selectTab', (_e, tabId: unknown) => ipcMain.handle('browser:selectTab', (_e, tabId: unknown) =>
browserPass(() => browser.selectTab(typeof tabId === 'string' ? tabId : '')) browserPass(() => getBrowserController().selectTab(typeof tabId === 'string' ? tabId : ''))
) )
ipcMain.handle('browser:closeTab', (_e, tabId: unknown) => ipcMain.handle('browser:closeTab', (_e, tabId: unknown) =>
browserPass(() => browser.closeTab(typeof tabId === 'string' ? tabId : undefined)) browserPass(() => getBrowserController().closeTab(typeof tabId === 'string' ? tabId : undefined))
) )
ipcMain.handle('browser:close', () => browserPass(() => browser.close())) ipcMain.handle('browser:close', () => browserPass(() => getBrowserController().close()))
ipcMain.handle('browser:acknowledgeRisk', () => browserPass(() => browser.acknowledgeRisk())) ipcMain.handle('browser:acknowledgeRisk', () => browserPass(() => getBrowserController().acknowledgeRisk()))
// 渲染层 BrowserSlot 量出的占位矩形(原生 WebContentsView 对齐到 DOM 布局) // 渲染层 BrowserSlot 量出的占位矩形(原生 WebContentsView 对齐到 DOM 布局)
ipcMain.handle('browser:layout', (_e, layout: unknown) => { ipcMain.handle('browser:layout', (_e, layout: unknown) => {
const l = layout as { tabId?: unknown; visible?: unknown; revision?: unknown; bounds?: unknown } const l = layout as { tabId?: unknown; visible?: unknown; revision?: unknown; bounds?: unknown }
@@ -314,7 +316,7 @@ export function registerIpc(): AgentService {
) { ) {
throw new Error('invalid browser layout') throw new Error('invalid browser layout')
} }
return browserPass(() => browser.applyLayout({ tabId, visible, revision, bounds: { x, y, width, height } })) return browserPass(() => getBrowserController().applyLayout({ tabId, visible, revision, bounds: { x, y, width, height } }))
}) })
// ---- 本地浏览器配置导入 ---- // ---- 本地浏览器配置导入 ----