feat: 新增 Computer Use Agent 初步支持

This commit is contained in:
mofeng-git
2026-06-15 22:24:40 +08:00
parent 5c98aea7e3
commit 4b7be20fe0
20 changed files with 2518 additions and 2 deletions

View File

@@ -0,0 +1,92 @@
import { ref, onUnmounted } from 'vue'
import { buildWsUrl } from '@/types/websocket'
import type { ComputerUseScreenshot, ComputerUseSession, ComputerUseAction } from '@/api'
export type ComputerUseServerMessage =
| { type: 'session_updated'; session: ComputerUseSession }
| { type: 'screenshot_requested'; request_id: string }
| { type: 'screenshot_captured'; screenshot: ComputerUseScreenshot }
| { type: 'step_started'; step: number }
| { type: 'actions_executed'; actions: ComputerUseAction[] }
| { type: 'error'; message: string }
export function useComputerUseSocket(options: {
onMessage: (message: ComputerUseServerMessage) => void
onScreenshotRequested: (requestId: string) => Promise<ComputerUseScreenshot | null>
}) {
const connected = ref(false)
const error = ref<string | null>(null)
const clientId = crypto.randomUUID()
let ws: WebSocket | null = null
let connectPromise: Promise<void> | null = null
function connect(): Promise<void> {
if (ws && ws.readyState === WebSocket.OPEN) return Promise.resolve()
if (connectPromise) return connectPromise
ws = new WebSocket(buildWsUrl(`/api/ws/computer-use?client_id=${encodeURIComponent(clientId)}`))
connectPromise = new Promise((resolve, reject) => {
if (!ws) {
reject(new Error('Computer use WebSocket failed'))
return
}
ws.onopen = () => {
connected.value = true
error.value = null
connectPromise = null
resolve()
}
ws.onerror = () => {
error.value = 'Computer use WebSocket failed'
connectPromise = null
reject(new Error(error.value))
}
})
ws.onclose = () => {
connected.value = false
connectPromise = null
}
ws.onmessage = async (event) => {
try {
const message = JSON.parse(event.data) as ComputerUseServerMessage
options.onMessage(message)
if (message.type === 'screenshot_requested') {
const screenshot = await options.onScreenshotRequested(message.request_id)
if (screenshot && ws?.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({
type: 'screenshot_result',
request_id: message.request_id,
screenshot,
}))
}
}
} catch (err) {
console.error('[ComputerUse] Failed to handle WS message:', err)
}
}
return connectPromise
}
function disconnect() {
ws?.close()
ws = null
connected.value = false
connectPromise = null
}
onUnmounted(disconnect)
return {
connected,
error,
clientId,
connect,
disconnect,
}
}