Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
87bdf12
feat: recut desktop grounding v1 into a clean review slice
Apr 12, 2026
a58a49d
feat(computer-use-mcp): add browser-native action routing for chrome_…
Apr 12, 2026
79414e7
feat(computer-use-mcp): add type/checkbox browser-dom routing (v2 sli…
Apr 12, 2026
81290f9
test(computer-use-mcp): comprehensive v2 browser action routing tests
Apr 12, 2026
6412278
test(computer-use-mcp): handler-level integration tests for desktop_c…
Apr 12, 2026
7620d30
feat(computer-use-mcp): desktop control v3 — agent-owned sessions + g…
Apr 12, 2026
3a5787b
feat(computer-use-mcp): auto-connect CDP bridge from chrome session
Apr 12, 2026
c6d8fb3
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 12, 2026
3ed270d
fix(desktop): wire extension bridge and iframe offsets
Apr 14, 2026
6829ef8
fix(desktop): close overlay readiness and browser-dom correctness gaps
Apr 14, 2026
3647af4
fix(computer-use-mcp): close chrome session and click state gaps
Apr 14, 2026
815eff9
fix(computer-use-mcp): restore iframe offsets and click target payloads
Apr 14, 2026
c22126b
fix(computer-use-mcp): bypass stale browser-dom typing route
Apr 14, 2026
3bb34a6
fix(desktop): revalidate chrome sessions and align overlay readiness
Apr 16, 2026
6138cdb
fix(computer-use-mcp): gate browser-dom writes on bridge capabilities
Apr 16, 2026
67f9855
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 16, 2026
5054ff3
fix(computer-use-mcp): harden extension bridge lifecycle
Apr 23, 2026
53c3c7e
fix(desktop): gate chrome session and bound overlay polls
Apr 23, 2026
2ffc4f2
fix(desktop): harden chrome session review gaps
Apr 24, 2026
d4ef214
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 24, 2026
4061e83
fix(desktop): preserve chrome approval semantics
Apr 24, 2026
0305af6
test: fix test boundary and signature in action-executor.test.ts
Apr 24, 2026
974fd52
test: fix signature of registerDesktopGroundingTools in tests
Apr 24, 2026
18a4784
test(computer-use-mcp): fix tests broken by desktop grounding refactor
Apr 24, 2026
8d4009a
chore: remove unused mineflayer patch and update lockfile
Apr 24, 2026
723040f
fix(stage-tamagotchi): export widgetsHideWindow in eventa index
Apr 24, 2026
79d64d5
fix(stage-tamagotchi): stabilize eventa types, widget size defaults a…
Apr 24, 2026
bdd16bc
Merge origin/main to resolve conflicts
Apr 24, 2026
2ef6a9d
[autofix.ci] apply automated fixes
autofix-ci[bot] Apr 24, 2026
e6675d8
Merge branch 'main' into codex/desktop-v3-agent-session
3361559784 Apr 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 16 additions & 15 deletions apps/stage-tamagotchi/src/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { Format, LogLevel, setGlobalFormat, setGlobalHookPostLog, setGlobalLogLe
import { createContext } from '@moeru/eventa/adapters/electron/main'
import { initScreenCaptureForMain } from '@proj-airi/electron-screen-capture/main'
import { app, ipcMain } from 'electron'
import { noop } from 'es-toolkit'
import { createLoggLogger, injeca, lifecycle } from 'injeca'
import { isLinux } from 'std-env'

Expand Down Expand Up @@ -112,9 +113,9 @@ app.whenReady().then(async () => {
build: ({ dependsOn }) => setupAutoUpdater({
getStoredUpdateLane: () => dependsOn.appConfig.get()?.updateChannel,
setStoredUpdateLane: (lane) => {
const current = dependsOn.appConfig.get()
const currentConfig = dependsOn.appConfig.get()
dependsOn.appConfig.update({
language: current?.language ?? 'en',
language: currentConfig?.language ?? 'en',
updateChannel: lane,
})
},
Expand Down Expand Up @@ -143,12 +144,22 @@ app.whenReady().then(async () => {
build: async () => setupMcpStdioManager(),
})

const widgetsManager = injeca.provide('windows:widgets', {
dependsOn: { serverChannel, i18n },
build: ({ dependsOn }) => setupWidgetsWindowManager(dependsOn),
})

const pluginHost = injeca.provide('modules:plugin-host', {
dependsOn: { serverChannel, widgetsManager },
build: ({ dependsOn }) => setupPluginHost(dependsOn),
})

const windowAuthManager = injeca.provide('services:window-auth-manager', () => createWindowAuthManagerService())

// BeatSync will create a background window to capture and process audio.
const beatSync = injeca.provide('windows:beat-sync', () => setupBeatSync())

const devtoolsWindow = injeca.provide('windows:devtools', () => setupDevtoolsWindow())
const devtoolsMarkdownStressWindow = injeca.provide('windows:devtools:markdown-stress', () => setupDevtoolsWindow())

const onboardingWindowManager = injeca.provide('windows:onboarding', {
dependsOn: { serverChannel, i18n, windowAuthManager },
Expand All @@ -160,16 +171,6 @@ app.whenReady().then(async () => {
build: ({ dependsOn }) => setupNoticeWindowManager(dependsOn),
})

const widgetsManager = injeca.provide('windows:widgets', {
dependsOn: { serverChannel, i18n },
build: ({ dependsOn }) => setupWidgetsWindowManager(dependsOn),
})

const pluginHost = injeca.provide('modules:plugin-host', {
dependsOn: { serverChannel, widgetsManager },
build: ({ dependsOn }) => setupPluginHost({ widgetsManager: dependsOn.widgetsManager }),
})

const aboutWindow = injeca.provide('windows:about', {
dependsOn: { autoUpdater, i18n, serverChannel },
build: ({ dependsOn }) => setupAboutWindowReusable(dependsOn),
Expand All @@ -181,7 +182,7 @@ app.whenReady().then(async () => {
})

const settingsWindow = injeca.provide('windows:settings', {
dependsOn: { widgetsManager, beatSync, autoUpdater, devtoolsWindow, serverChannel, godotStageManager, mcpStdioManager, i18n, windowAuthManager },
dependsOn: { widgetsManager, beatSync, autoUpdater, devtoolsWindow: devtoolsMarkdownStressWindow, serverChannel, godotStageManager, mcpStdioManager, i18n, windowAuthManager },
build: async ({ dependsOn }) => setupSettingsWindowReusableFunc(dependsOn),
})

Expand Down Expand Up @@ -212,7 +213,7 @@ app.whenReady().then(async () => {
// provider depends on 'windows:desktop-overlay'.
injeca.invoke({
dependsOn: { desktopOverlay },
callback: () => {},
callback: noop,
})
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export type { DesktopOverlayReadiness } from '../../../../shared/eventa'
export { getDesktopOverlayReadinessContract } from '../../../../shared/eventa'
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@ import type { BrowserWindow } from 'electron'
import type { I18n } from '../../../libs/i18n'
import type { ServerChannel } from '../../../services/airi/channel-server'
import type { McpStdioManager } from '../../../services/airi/mcp-servers'
import type { DesktopOverlayReadiness } from './contracts'

import { defineInvokeHandler } from '@moeru/eventa'
import { createContext } from '@moeru/eventa/adapters/electron/main'
import { ipcMain } from 'electron'

import { getDesktopOverlayReadinessContract } from '../../../../shared/eventa'
import { createMcpServersService } from '../../../services/airi/mcp-servers'
import { setupBaseWindowElectronInvokes } from '../../shared/window'

Expand All @@ -34,6 +37,23 @@ export async function setupDesktopOverlayElectronInvokes(params: {

const { context } = createContext(ipcMain, params.window)

await setupBaseWindowElectronInvokes({ context, window: params.window, i18n: params.i18n, serverChannel: params.serverChannel })
createMcpServersService({ context, manager: params.mcpStdioManager })
let readiness: DesktopOverlayReadiness = { state: 'booting' }

defineInvokeHandler(context, getDesktopOverlayReadinessContract, async () => {
return readiness
})

try {
await setupBaseWindowElectronInvokes({ context, window: params.window, i18n: params.i18n, serverChannel: params.serverChannel })
createMcpServersService({ context, manager: params.mcpStdioManager })
readiness = { state: 'ready' }
}
catch (error) {
readiness = {
state: 'degraded',
error: error instanceof Error ? error.message : String(error),
}
// We intentionally don't throw here so the window still opens and
// the renderer gracefully detects the degraded state via polling.
}
}
4 changes: 2 additions & 2 deletions apps/stage-tamagotchi/src/main/windows/widgets/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -435,8 +435,8 @@ export function setupWidgetsWindowManager(params: {
const minHeight = clamp(windowSize.minHeight ?? 160, 1, work.height)
const maxWidth = clamp(windowSize.maxWidth ?? work.width, minWidth, work.width)
const maxHeight = clamp(windowSize.maxHeight ?? work.height, minHeight, work.height)
const width = clamp(windowSize.width, minWidth, maxWidth)
const height = clamp(windowSize.height, minHeight, maxHeight)
const width = clamp(windowSize.width ?? minWidth, minWidth, maxWidth)
const height = clamp(windowSize.height ?? minHeight, minHeight, maxHeight)
const currentBounds = window.getBounds()

window.setMinimumSize(minWidth, minHeight)
Expand Down
Loading
Loading