style: 格式化 packages/@ant/ 下所有文件以通过 biome ci

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
claude-code-best
2026-05-01 21:55:51 +08:00
parent c32f26cf21
commit 9ea9859dce
92 changed files with 5903 additions and 5188 deletions

View File

@@ -9,9 +9,17 @@ import { readFileSync, unlinkSync } from 'fs'
import { tmpdir } from 'os'
import { join } from 'path'
import type {
AppInfo, AppsAPI, DisplayAPI, DisplayGeometry, InstalledApp,
PrepareDisplayResult, RunningApp, ScreenshotAPI, ScreenshotResult,
SwiftBackend, WindowDisplayInfo,
AppInfo,
AppsAPI,
DisplayAPI,
DisplayGeometry,
InstalledApp,
PrepareDisplayResult,
RunningApp,
ScreenshotAPI,
ScreenshotResult,
SwiftBackend,
WindowDisplayInfo,
} from '../types.js'
export type {
@@ -32,7 +40,8 @@ export type {
function jxaSync(script: string): string {
const result = Bun.spawnSync({
cmd: ['osascript', '-l', 'JavaScript', '-e', script],
stdout: 'pipe', stderr: 'pipe',
stdout: 'pipe',
stderr: 'pipe',
})
return new TextDecoder().decode(result.stdout).trim()
}
@@ -40,14 +49,16 @@ function jxaSync(script: string): string {
function osascriptSync(script: string): string {
const result = Bun.spawnSync({
cmd: ['osascript', '-e', script],
stdout: 'pipe', stderr: 'pipe',
stdout: 'pipe',
stderr: 'pipe',
})
return new TextDecoder().decode(result.stdout).trim()
}
async function osascript(script: string): Promise<string> {
const proc = Bun.spawn(['osascript', '-e', script], {
stdout: 'pipe', stderr: 'pipe',
stdout: 'pipe',
stderr: 'pipe',
})
const text = await new Response(proc.stdout).text()
await proc.exited
@@ -56,7 +67,8 @@ async function osascript(script: string): Promise<string> {
async function jxa(script: string): Promise<string> {
const proc = Bun.spawn(['osascript', '-l', 'JavaScript', '-e', script], {
stdout: 'pipe', stderr: 'pipe',
stdout: 'pipe',
stderr: 'pipe',
})
const text = await new Response(proc.stdout).text()
await proc.exited
@@ -101,8 +113,10 @@ export const display: DisplayAPI = {
JSON.stringify(result);
`)
return (JSON.parse(raw) as DisplayGeometry[]).map(d => ({
width: Number(d.width), height: Number(d.height),
scaleFactor: Number(d.scaleFactor), displayId: Number(d.displayId),
width: Number(d.width),
height: Number(d.height),
scaleFactor: Number(d.scaleFactor),
displayId: Number(d.displayId),
}))
} catch {
try {
@@ -126,8 +140,10 @@ export const display: DisplayAPI = {
JSON.stringify(result);
`)
return (JSON.parse(raw) as DisplayGeometry[]).map(d => ({
width: Number(d.width), height: Number(d.height),
scaleFactor: Number(d.scaleFactor), displayId: Number(d.displayId),
width: Number(d.width),
height: Number(d.height),
scaleFactor: Number(d.scaleFactor),
displayId: Number(d.displayId),
}))
} catch {
return [{ width: 1920, height: 1080, scaleFactor: 2, displayId: 1 }]
@@ -177,9 +193,15 @@ export const apps: AppsAPI = {
const dirs = ['/Applications', '~/Applications', '/System/Applications']
const allApps: InstalledApp[] = []
for (const dir of dirs) {
const expanded = dir.startsWith('~') ? join(process.env.HOME ?? '~', dir.slice(1)) : dir
const expanded = dir.startsWith('~')
? join(process.env.HOME ?? '~', dir.slice(1))
: dir
const proc = Bun.spawn(
['bash', '-c', `for f in "${expanded}"/*.app; do [ -d "$f" ] || continue; bid=$(mdls -name kMDItemCFBundleIdentifier "$f" 2>/dev/null | sed 's/.*= "//;s/"//'); name=$(basename "$f" .app); echo "$f|$name|$bid"; done`],
[
'bash',
'-c',
`for f in "${expanded}"/*.app; do [ -d "$f" ] || continue; bid=$(mdls -name kMDItemCFBundleIdentifier "$f" 2>/dev/null | sed 's/.*= "//;s/"//'); name=$(basename "$f" .app); echo "$f|$name|$bid"; done`,
],
{ stdout: 'pipe', stderr: 'pipe' },
)
const text = await new Response(proc.stdout).text()
@@ -245,10 +267,13 @@ export const apps: AppsAPI = {
// ScreenshotAPI
// ---------------------------------------------------------------------------
async function captureScreenToBase64(args: string[]): Promise<{ base64: string; width: number; height: number }> {
async function captureScreenToBase64(
args: string[],
): Promise<{ base64: string; width: number; height: number }> {
const tmpFile = join(tmpdir(), `cu-screenshot-${Date.now()}.png`)
const proc = Bun.spawn(['screencapture', ...args, tmpFile], {
stdout: 'pipe', stderr: 'pipe',
stdout: 'pipe',
stderr: 'pipe',
})
await proc.exited
try {
@@ -258,18 +283,36 @@ async function captureScreenToBase64(args: string[]): Promise<{ base64: string;
const height = buf.readUInt32BE(20)
return { base64, width, height }
} finally {
try { unlinkSync(tmpFile) } catch {}
try {
unlinkSync(tmpFile)
} catch {}
}
}
export const screenshot: ScreenshotAPI = {
async captureExcluding(_allowedBundleIds, _quality, _targetW, _targetH, displayId) {
async captureExcluding(
_allowedBundleIds,
_quality,
_targetW,
_targetH,
displayId,
) {
const args = ['-x']
if (displayId !== undefined) args.push('-D', String(displayId))
return captureScreenToBase64(args)
},
async captureRegion(_allowedBundleIds, x, y, w, h, _outW, _outH, _quality, displayId) {
async captureRegion(
_allowedBundleIds,
x,
y,
w,
h,
_outW,
_outH,
_quality,
displayId,
) {
const args = ['-x', '-R', `${x},${y},${w},${h}`]
if (displayId !== undefined) args.push('-D', String(displayId))
return captureScreenToBase64(args)

View File

@@ -8,9 +8,17 @@
*/
import type {
AppInfo, AppsAPI, DisplayAPI, DisplayGeometry, InstalledApp,
PrepareDisplayResult, RunningApp, ScreenshotAPI, ScreenshotResult,
SwiftBackend, WindowDisplayInfo,
AppInfo,
AppsAPI,
DisplayAPI,
DisplayGeometry,
InstalledApp,
PrepareDisplayResult,
RunningApp,
ScreenshotAPI,
ScreenshotResult,
SwiftBackend,
WindowDisplayInfo,
} from '../types.js'
// ---------------------------------------------------------------------------
@@ -34,7 +42,11 @@ async function runAsync(cmd: string[]): Promise<string> {
}
function commandExists(name: string): boolean {
const result = Bun.spawnSync({ cmd: ['which', name], stdout: 'pipe', stderr: 'pipe' })
const result = Bun.spawnSync({
cmd: ['which', name],
stdout: 'pipe',
stderr: 'pipe',
})
return result.exitCode === 0
}
@@ -85,7 +97,11 @@ export const display: DisplayAPI = {
// ---------------------------------------------------------------------------
export const apps: AppsAPI = {
async prepareDisplay(_allowlistBundleIds, _surrogateHost, _displayId): Promise<PrepareDisplayResult> {
async prepareDisplay(
_allowlistBundleIds,
_surrogateHost,
_displayId,
): Promise<PrepareDisplayResult> {
return { activated: '', hidden: [] }
},
@@ -100,7 +116,15 @@ export const apps: AppsAPI = {
async appUnderPoint(x, y): Promise<AppInfo | null> {
try {
// Move mouse to point, get window under cursor
const out = run(['xdotool', 'mousemove', '--sync', String(x), String(y), 'getmouselocation', '--shell'])
const out = run([
'xdotool',
'mousemove',
'--sync',
String(x),
String(y),
'getmouselocation',
'--shell',
])
const windowMatch = out.match(/WINDOW=(\d+)/)
if (!windowMatch) return null
@@ -109,10 +133,18 @@ export const apps: AppsAPI = {
if (!pidStr) return null
let exePath = ''
try { exePath = run(['readlink', '-f', `/proc/${pidStr}/exe`]) } catch { /* ignore */ }
try {
exePath = run(['readlink', '-f', `/proc/${pidStr}/exe`])
} catch {
/* ignore */
}
let appName = ''
try { appName = run(['cat', `/proc/${pidStr}/comm`]) } catch { /* ignore */ }
try {
appName = run(['cat', `/proc/${pidStr}/comm`])
} catch {
/* ignore */
}
if (!exePath && !appName) return null
return { bundleId: exePath || pidStr!, displayName: appName || 'unknown' }
@@ -124,14 +156,20 @@ export const apps: AppsAPI = {
async listInstalled(): Promise<InstalledApp[]> {
try {
// Read .desktop files from standard locations
const dirs = ['/usr/share/applications', '/usr/local/share/applications', `${process.env.HOME}/.local/share/applications`]
const dirs = [
'/usr/share/applications',
'/usr/local/share/applications',
`${process.env.HOME}/.local/share/applications`,
]
const apps: InstalledApp[] = []
for (const dir of dirs) {
let files: string
try {
files = run(['find', dir, '-name', '*.desktop', '-maxdepth', '1'])
} catch { continue }
} catch {
continue
}
for (const filepath of files.split('\n').filter(Boolean)) {
try {
@@ -146,11 +184,14 @@ export const apps: AppsAPI = {
if (!name) continue
apps.push({
bundleId: filepath.split('/').pop()?.replace('.desktop', '') ?? '',
bundleId:
filepath.split('/').pop()?.replace('.desktop', '') ?? '',
displayName: name,
path: exec.split(/\s+/)[0] ?? '',
})
} catch { /* skip unreadable files */ }
} catch {
/* skip unreadable files */
}
}
}
@@ -177,9 +218,17 @@ export const apps: AppsAPI = {
if (!pid || pid === '0') continue
let exePath = ''
try { exePath = run(['readlink', '-f', `/proc/${pid}/exe`]) } catch { /* ignore */ }
try {
exePath = run(['readlink', '-f', `/proc/${pid}/exe`])
} catch {
/* ignore */
}
let appName = ''
try { appName = run(['cat', `/proc/${pid}/comm`]) } catch { /* ignore */ }
try {
appName = run(['cat', `/proc/${pid}/comm`])
} catch {
/* ignore */
}
if (appName) {
apps.push({ bundleId: exePath || pid, displayName: appName })
@@ -187,11 +236,13 @@ export const apps: AppsAPI = {
}
// Deduplicate by bundleId
const seen = new Set<string>()
return apps.filter(a => {
if (seen.has(a.bundleId)) return false
seen.add(a.bundleId)
return true
}).slice(0, 50)
return apps
.filter(a => {
if (seen.has(a.bundleId)) return false
seen.add(a.bundleId)
return true
})
.slice(0, 50)
}
// Fallback: ps with visible processes
@@ -217,7 +268,9 @@ export const apps: AppsAPI = {
await runAsync(['gtk-launch', desktopName])
return
}
} catch { /* fall through */ }
} catch {
/* fall through */
}
await runAsync(['xdg-open', name])
},
@@ -232,7 +285,9 @@ export const apps: AppsAPI = {
// Try xdotool windowactivate with search by name
await runAsync(['xdotool', 'search', '--name', id, 'windowactivate'])
}
} catch { /* ignore failures for individual windows */ }
} catch {
/* ignore failures for individual windows */
}
}
},
}
@@ -244,7 +299,13 @@ export const apps: AppsAPI = {
const SCREENSHOT_PATH = '/tmp/cu-screenshot.png'
export const screenshot: ScreenshotAPI = {
async captureExcluding(_allowedBundleIds, _quality, _targetW, _targetH, _displayId): Promise<ScreenshotResult> {
async captureExcluding(
_allowedBundleIds,
_quality,
_targetW,
_targetH,
_displayId,
): Promise<ScreenshotResult> {
try {
await runAsync(['scrot', '-o', SCREENSHOT_PATH])
@@ -261,10 +322,26 @@ export const screenshot: ScreenshotAPI = {
}
},
async captureRegion(_allowedBundleIds, x, y, w, h, _outW, _outH, _quality, _displayId): Promise<ScreenshotResult> {
async captureRegion(
_allowedBundleIds,
x,
y,
w,
h,
_outW,
_outH,
_quality,
_displayId,
): Promise<ScreenshotResult> {
try {
// scrot -a x,y,w,h captures a specific region
await runAsync(['scrot', '-a', `${x},${y},${w},${h}`, '-o', SCREENSHOT_PATH])
await runAsync([
'scrot',
'-a',
`${x},${y},${w},${h}`,
'-o',
SCREENSHOT_PATH,
])
const file = Bun.file(SCREENSHOT_PATH)
const buffer = await file.arrayBuffer()

View File

@@ -6,13 +6,24 @@
*/
import type {
AppInfo, AppsAPI, DisplayAPI, DisplayGeometry, InstalledApp,
PrepareDisplayResult, RunningApp, ScreenshotAPI, ScreenshotResult,
SwiftBackend, WindowDisplayInfo,
AppInfo,
AppsAPI,
DisplayAPI,
DisplayGeometry,
InstalledApp,
PrepareDisplayResult,
RunningApp,
ScreenshotAPI,
ScreenshotResult,
SwiftBackend,
WindowDisplayInfo,
} from '../types.js'
import { listWindows } from 'src/utils/computerUse/win32/windowEnum.js'
import { captureWindow, captureWindowByHwnd } from 'src/utils/computerUse/win32/windowCapture.js'
import {
captureWindow,
captureWindowByHwnd,
} from 'src/utils/computerUse/win32/windowCapture.js'
// ---------------------------------------------------------------------------
// PowerShell helper
@@ -63,15 +74,18 @@ foreach ($s in [System.Windows.Forms.Screen]::AllScreens) {
}
$result -join "|"
`)
return raw.split('|').filter(Boolean).map(entry => {
const [w, h, id, primary] = entry.split(',')
return {
width: Number(w),
height: Number(h),
scaleFactor: 1, // Windows DPI scaling handled at system level
displayId: Number(id),
}
})
return raw
.split('|')
.filter(Boolean)
.map(entry => {
const [w, h, id, primary] = entry.split(',')
return {
width: Number(w),
height: Number(h),
scaleFactor: 1, // Windows DPI scaling handled at system level
displayId: Number(id),
}
})
} catch {
return [{ width: 1920, height: 1080, scaleFactor: 1, displayId: 0 }]
}
@@ -139,14 +153,17 @@ foreach ($p in $paths) {
}
$apps | Select-Object -Unique | Select-Object -First 200
`)
return raw.split('\n').filter(Boolean).map(line => {
const [name, path, id] = line.split('|', 3)
return {
bundleId: id ?? name ?? '',
displayName: name ?? '',
path: path ?? '',
}
})
return raw
.split('\n')
.filter(Boolean)
.map(line => {
const [name, path, id] = line.split('|', 3)
return {
bundleId: id ?? name ?? '',
displayName: name ?? '',
path: path ?? '',
}
})
} catch {
return []
}
@@ -204,7 +221,13 @@ if ($proc) { [WinShow]::ShowWindow($proc.MainWindowHandle, 9) | Out-Null; [WinSh
// ---------------------------------------------------------------------------
export const screenshot: ScreenshotAPI = {
async captureExcluding(_allowedBundleIds, _quality, _targetW, _targetH, displayId) {
async captureExcluding(
_allowedBundleIds,
_quality,
_targetW,
_targetH,
displayId,
) {
const raw = await psAsync(`
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
@@ -229,7 +252,17 @@ $ms.Dispose()
return { base64, width, height }
},
async captureRegion(_allowedBundleIds, x, y, w, h, _outW, _outH, _quality, _displayId) {
async captureRegion(
_allowedBundleIds,
x,
y,
w,
h,
_outW,
_outH,
_quality,
_displayId,
) {
const raw = await psAsync(`
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

View File

@@ -37,25 +37,52 @@ const backend = loadBackend()
export class ComputerUseAPI {
apps = backend?.apps ?? {
async prepareDisplay() { return { activated: '', hidden: [] } },
async previewHideSet() { return [] },
async findWindowDisplays(ids: string[]) { return ids.map((b: string) => ({ bundleId: b, displayIds: [] as number[] })) },
async appUnderPoint() { return null },
async listInstalled() { return [] },
iconDataUrl() { return null },
listRunning() { return [] },
async open() { throw new Error('@ant/computer-use-swift: macOS only') },
async prepareDisplay() {
return { activated: '', hidden: [] }
},
async previewHideSet() {
return []
},
async findWindowDisplays(ids: string[]) {
return ids.map((b: string) => ({
bundleId: b,
displayIds: [] as number[],
}))
},
async appUnderPoint() {
return null
},
async listInstalled() {
return []
},
iconDataUrl() {
return null
},
listRunning() {
return []
},
async open() {
throw new Error('@ant/computer-use-swift: macOS only')
},
async unhide() {},
}
display = backend?.display ?? {
getSize() { throw new Error('@ant/computer-use-swift: macOS only') },
listAll() { throw new Error('@ant/computer-use-swift: macOS only') },
getSize() {
throw new Error('@ant/computer-use-swift: macOS only')
},
listAll() {
throw new Error('@ant/computer-use-swift: macOS only')
},
}
screenshot = backend?.screenshot ?? {
async captureExcluding() { throw new Error('@ant/computer-use-swift: macOS only') },
async captureRegion() { throw new Error('@ant/computer-use-swift: macOS only') },
async captureExcluding() {
throw new Error('@ant/computer-use-swift: macOS only')
},
async captureRegion() {
throw new Error('@ant/computer-use-swift: macOS only')
},
}
async resolvePrepareCapture(
@@ -66,6 +93,12 @@ export class ComputerUseAPI {
targetH: number,
displayId?: number,
): Promise<ResolvePrepareCaptureResult> {
return this.screenshot.captureExcluding(allowedBundleIds, quality, targetW, targetH, displayId)
return this.screenshot.captureExcluding(
allowedBundleIds,
quality,
targetW,
targetH,
displayId,
)
}
}

View File

@@ -55,7 +55,11 @@ export interface DisplayAPI {
}
export interface AppsAPI {
prepareDisplay(allowlistBundleIds: string[], surrogateHost: string, displayId?: number): Promise<PrepareDisplayResult>
prepareDisplay(
allowlistBundleIds: string[],
surrogateHost: string,
displayId?: number,
): Promise<PrepareDisplayResult>
previewHideSet(bundleIds: string[], displayId?: number): Promise<AppInfo[]>
findWindowDisplays(bundleIds: string[]): Promise<WindowDisplayInfo[]>
appUnderPoint(x: number, y: number): Promise<AppInfo | null>
@@ -68,13 +72,22 @@ export interface AppsAPI {
export interface ScreenshotAPI {
captureExcluding(
allowedBundleIds: string[], quality: number,
targetW: number, targetH: number, displayId?: number,
allowedBundleIds: string[],
quality: number,
targetW: number,
targetH: number,
displayId?: number,
): Promise<ScreenshotResult>
captureRegion(
allowedBundleIds: string[],
x: number, y: number, w: number, h: number,
outW: number, outH: number, quality: number, displayId?: number,
x: number,
y: number,
w: number,
h: number,
outW: number,
outH: number,
quality: number,
displayId?: number,
): Promise<ScreenshotResult>
captureWindowTarget(titleOrHwnd: string | number): ScreenshotResult | null
}