From b42e744c3cc3b80bef241e2b4da57e6dafbf78b0 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 7 Nov 2026 12:02:29 +0800 Subject: [PATCH] refactor(cua): ignore native PID metadata in TypeScript Remove PID fields and dependencies from TypeScript discovery, permission metadata and helper handshakes while preserving native implementations and responses. Accept unused response fields, select applications by provider ID, bundle ID or name, and update consumers, guidance and fixtures. --- .../cua-macos/src/shared-native.ts | 4 +-- .../cua-macos/tests/guidance.spec.ts | 4 +-- .../cua-windows/src/native-runtime.ts | 8 +++--- .../cua-windows/tests/native-runtime.spec.ts | 7 ++++- packages/experimental/cua/src/access-types.ts | 1 - packages/experimental/cua/src/access.ts | 2 +- packages/experimental/cua/src/api.ts | 2 +- packages/experimental/cua/src/guidance.ts | 8 +++--- packages/experimental/cua/src/protocol.ts | 12 ++++----- packages/experimental/cua/src/types.ts | 6 ++--- .../experimental/cua/tests/access.spec.ts | 3 ++- packages/experimental/cua/tests/api.spec.ts | 27 ++++++++++++++----- .../experimental/cua/tests/bridge.spec.ts | 6 ++--- .../cua/tests/controller.client.spec.ts | 2 +- .../cua/tests/mount.client.spec.ts | 2 +- .../cua/tests/panel.client.spec.tsx | 10 +++---- .../extensions/tool-cordis/src/api-catalog.ts | 4 +-- 17 files changed, 63 insertions(+), 45 deletions(-) diff --git a/packages/experimental/cua-macos/src/shared-native.ts b/packages/experimental/cua-macos/src/shared-native.ts index 0fe2cf6436..7539276a8c 100644 --- a/packages/experimental/cua-macos/src/shared-native.ts +++ b/packages/experimental/cua-macos/src/shared-native.ts @@ -13,8 +13,8 @@ export type { NativeChannel } from '@deepseek-ai/dsh-cua/native-client' const Ready = z.object({ type: z.literal('ready'), protocol: z.literal(1), runtimeKey: z.string(), - pid: z.number().int().positive(), instanceId: z.string().min(1), -}).strict() + instanceId: z.string().min(1), +}) const Refusal = z.object({ type: z.literal('error'), code: z.string().min(1), message: z.string() }).strict() const handshakeByteLimit = 8192 type LauncherExit = [PromiseSettledResult, PromiseSettledResult] diff --git a/packages/experimental/cua-macos/tests/guidance.spec.ts b/packages/experimental/cua-macos/tests/guidance.spec.ts index f0f5679623..ae947d7ab7 100644 --- a/packages/experimental/cua-macos/tests/guidance.spec.ts +++ b/packages/experimental/cua-macos/tests/guidance.spec.ts @@ -56,8 +56,8 @@ it('inlines discovery, restoration, screenshot, and mouse-move return records', expect(lines.find(line => line.startsWith(`- ${name}(`))).toMatch(/ -> \(?\{ /) } expect(COMMON_GUIDANCE).toContain("{ platform: string, permissions: { accessibility: boolean, screenRecording: boolean }, appLevelAccessibility: boolean, keyboard: ('app' | 'window')[], sessionLocked: boolean | null, methods: string[], coordinateSpace: 'screenshot-pixels', browser: false }") - expect(COMMON_GUIDANCE).toContain('{ id: string, displayName: string, isRunning: true, pid: number }[]') - expect(COMMON_GUIDANCE).toContain('({ id: string, displayName: string, path: string } & ({ isRunning: true, pid: number } | { isRunning: false }))[]') + expect(COMMON_GUIDANCE).toContain('{ id: string, displayName: string, isRunning: true }[]') + expect(COMMON_GUIDANCE).toContain('{ id: string, displayName: string, path: string, isRunning: boolean }[]') expect(COMMON_GUIDANCE).toContain('bounds: { x: number, y: number, width: number, height: number }, isOnScreen: boolean, onCurrentSpace: boolean | null') }) diff --git a/packages/experimental/cua-windows/src/native-runtime.ts b/packages/experimental/cua-windows/src/native-runtime.ts index bf5da9aff3..0386d60f19 100644 --- a/packages/experimental/cua-windows/src/native-runtime.ts +++ b/packages/experimental/cua-windows/src/native-runtime.ts @@ -11,9 +11,9 @@ import { z } from 'zod' import { connectWindowsPipe, type WindowsConnection, type WindowsTransport } from './native-transport.ts' const Ready = z.object({ - type: z.literal('ready'), protocol: z.literal(1), runtimeKey: z.string(), instanceId: z.string().min(1), -}).strict() -const Started = Ready.extend({ endpoint: z.string().min(1), launcherId: z.string().min(1) }).strict() + type: z.literal('ready'), protocol: z.literal(1), runtimeKey: z.string().min(1), instanceId: z.string().min(1), +}) +const Started = Ready.extend({ endpoint: z.string().min(1), launcherId: z.string().min(1) }) // Private transport control frames have fixed encoding; operation replies pass through unchanged. const closedFrame = Buffer.from('{"type":"closed"}\n') type Owner = { subprocess: Pick } @@ -238,7 +238,7 @@ class WindowsChannel implements NativeChannel { } const response = await frame const accepted = Ready.parse(response.value) - if (accepted.runtimeKey !== ready.runtimeKey || accepted.instanceId !== ready.instanceId || accepted.pid !== ready.pid) + if (accepted.runtimeKey !== ready.runtimeKey || accepted.instanceId !== ready.instanceId) throw new NativeError('NATIVE_PROTOCOL', 'Windows pipe belongs to another helper instance') this.startup.signal.throwIfAborted() admitted = true diff --git a/packages/experimental/cua-windows/tests/native-runtime.spec.ts b/packages/experimental/cua-windows/tests/native-runtime.spec.ts index b3eb03caf2..5e526ab4d7 100644 --- a/packages/experimental/cua-windows/tests/native-runtime.spec.ts +++ b/packages/experimental/cua-windows/tests/native-runtime.spec.ts @@ -199,7 +199,12 @@ it.each(['wrong-runtime', 'wrong-instance', 'extra', 'malformed', 'oversized', ' }, ) -it.each(['wrong-instance', 'wrong-pid', 'extra', 'malformed', 'oversized'] as const)( +it.each(['wrong-pid', 'extra'] as const)('ignores unused %s handshake metadata', async (handshake) => { + const f = await fixture({ handshake }) + await expect(f.client().request('input', {}, new AbortController().signal)).resolves.toMatchObject({ connection: 1 }) +}) + +it.each(['wrong-instance', 'malformed', 'oversized'] as const)( 'rejects a %s Agent handshake before dispatch', async (handshake) => { const f = await fixture({ handshake }) await expect(f.client().request('input', {}, new AbortController().signal)).rejects.toThrow() diff --git a/packages/experimental/cua/src/access-types.ts b/packages/experimental/cua/src/access-types.ts index 0a587124d4..f37a5ea679 100644 --- a/packages/experimental/cua/src/access-types.ts +++ b/packages/experimental/cua/src/access-types.ts @@ -6,7 +6,6 @@ export type { CuaApplicationGrant, CuaApplicationId } from './application-types. export type CuaSystemPermission = 'accessibility' | 'screenRecording' /** Observed process; neither the helper nor its parent is assumed to be the TCC owner. */ export interface CuaPermissionProcess { - pid: number path?: string | undefined name?: string | undefined } diff --git a/packages/experimental/cua/src/access.ts b/packages/experimental/cua/src/access.ts index 535bfe84fb..507d628024 100644 --- a/packages/experimental/cua/src/access.ts +++ b/packages/experimental/cua/src/access.ts @@ -19,7 +19,7 @@ interface ControlOptions extends AccessOptions { permissionParameters: (method: 'requestPermission' | 'openPermissionSettings', permission: CuaSystemPermission, locale: string) => Record } type Control = (method: string, params: Record) => Promise -const permissionProcess = z.object({ pid: z.number().int().positive(), path: z.string().optional(), name: z.string().optional() }) +const permissionProcess = z.object({ path: z.string().optional(), name: z.string().optional() }) const systemPermissions = z.discriminatedUnion('platform', [z.object({ platform: z.literal('darwin'), accessibility: z.boolean(), screenRecording: z.boolean(), helper: permissionProcess, parent: permissionProcess, launchApplication: z.object({ name: z.string().min(1), path: z.string().min(1), icon: ApplicationIcon.optional() }).optional(), diff --git a/packages/experimental/cua/src/api.ts b/packages/experimental/cua/src/api.ts index 22039c6591..f41a4f61e4 100644 --- a/packages/experimental/cua/src/api.ts +++ b/packages/experimental/cua/src/api.ts @@ -59,7 +59,7 @@ export function createCuaApi(dispatch: CuaDispatch, sink?: CuaObservationSink): }, async listApps(options) { const result = AppsResult.parse(await call('listApps', {})).map(app => ({ - id: app.bundleId || String(app.pid), displayName: app.name, isRunning: true as const, pid: app.pid, + id: app.id ?? (app.bundleId || app.name), displayName: app.name, isRunning: true as const, })) await emit(sink, result, options) return result diff --git a/packages/experimental/cua/src/guidance.ts b/packages/experimental/cua/src/guidance.ts index df935f6525..a28de6d0ca 100644 --- a/packages/experimental/cua/src/guidance.ts +++ b/packages/experimental/cua/src/guidance.ts @@ -8,10 +8,10 @@ Signatures show resolved return values after await. ActionResult = { dispatched: Setup and discovery: - cua.getCapabilities(options?: { emit?: boolean }) -> { platform: string, permissions: { accessibility: boolean, screenRecording: boolean }, appLevelAccessibility: boolean, keyboard: ('app' | 'window')[], sessionLocked: boolean | null, methods: string[], coordinateSpace: 'screenshot-pixels', browser: false } — inspect reported permissions, sessionLocked, methods, and keyboard scopes without requesting permissions. -- cua.listApps(options?: { emit?: boolean }) -> { id: string, displayName: string, isRunning: true, pid: number }[] — enumerate running applications. -- cua.findApps(query: string, options?: { emit?: boolean }) -> ({ id: string, displayName: string, path: string } & ({ isRunning: true, pid: number } | { isRunning: false }))[] — search installed applications, including stopped matches; only running matches carry pid. -- cua.getState(options?: { emit?: boolean }) -> { apps: { id: string, displayName: string, isRunning: true, pid: number }[], browsers: [] } — summarize running applications; this is not an accessibility observation. -- cua.getApp(selector: string) -> App — select an application by name, bundle ID, absolute path, or running PID string, obtain consent, launch in the background if needed, and read initial AX state silently; it does not activate the app. +- cua.listApps(options?: { emit?: boolean }) -> { id: string, displayName: string, isRunning: true }[] — enumerate running applications. +- cua.findApps(query: string, options?: { emit?: boolean }) -> { id: string, displayName: string, path: string, isRunning: boolean }[] — search installed applications, including stopped matches. +- cua.getState(options?: { emit?: boolean }) -> { apps: { id: string, displayName: string, isRunning: true }[], browsers: [] } — summarize running applications; this is not an accessibility observation. +- cua.getApp(selector: string) -> App — select an application by provider-issued discovery ID, name, bundle ID, or absolute path where supported, obtain consent, launch in the background if needed, and read initial AX state silently; it does not activate the app. - app.getWindows(options?: { emit?: boolean }) -> { windowId: number, appName: string, title: string, bounds: { x: number, y: number, width: number, height: number }, isOnScreen: boolean, onCurrentSpace: boolean | null }[] — enumerate windows with global native bounds; null onCurrentSpace means unknown Space membership. - app.getWindow(windowId: number) -> Window — select one window and read its initial AX state silently; do this before any window screenshot or coordinate input. - app.activate() -> ActionResult — request explicit foreground activation; use only when foreground access is required. diff --git a/packages/experimental/cua/src/protocol.ts b/packages/experimental/cua/src/protocol.ts index 538c95cfe6..ad54407c51 100644 --- a/packages/experimental/cua/src/protocol.ts +++ b/packages/experimental/cua/src/protocol.ts @@ -4,7 +4,6 @@ import { z } from 'zod' import type { CuaAppHandle, CuaSnapshotId } from './types.ts' const id = z.number().int().positive().max(2 ** 32 - 1) -const pid = z.number().int().positive().max(2 ** 31 - 1) const point = z.number().nonnegative() const relativePoint = z.number().int().min(0).max(999) const app = { appHandle: z.string().min(1) } @@ -101,11 +100,12 @@ export const AppResult = z.object({ appHandle: z.string().min(1).transform(value => value as CuaAppHandle), name: z.string(), bundleId: z.string().optional(), running: z.boolean(), }) -/** Running application records from the helper. */ -export const AppsResult = z.array(z.object({ pid, name: z.string(), bundleId: z.string().optional() })) -/** Installed application matches keep running and stopped records distinct. */ -export const FoundAppsResult = z.array(z.intersection(z.object({ id: z.string().min(1), displayName: z.string(), path: z.string().min(1) }), - z.discriminatedUnion('isRunning', [z.object({ isRunning: z.literal(true), pid }), z.object({ isRunning: z.literal(false) })]))) +/** Running application metadata used for selection; other native fields are ignored. */ +export const AppsResult = z.array(z.object({ id: z.string().min(1).optional(), name: z.string(), bundleId: z.string().optional() })) +/** Installed application matches and their current running state. */ +export const FoundAppsResult = z.array(z.object({ + id: z.string().min(1), displayName: z.string(), path: z.string().min(1), isRunning: z.boolean(), +})) /** Current windows and their global native bounds. */ export const WindowsResult = z.array(z.object({ windowId: id, appName: z.string(), title: z.string(), bounds, diff --git a/packages/experimental/cua/src/types.ts b/packages/experimental/cua/src/types.ts index c059a546f2..f35c839abf 100644 --- a/packages/experimental/cua/src/types.ts +++ b/packages/experimental/cua/src/types.ts @@ -51,8 +51,8 @@ export type CuaStartupCapabilities = Pick< 'platform' | 'methods' | 'appLevelAccessibility' | 'keyboard' | 'browser' | 'coordinateSpace' > /** App discovery result accepted by getApp. */ -export type CuaAppInfo = Pick, 'id' | 'displayName' | 'isRunning' | 'pid'> -/** An installed application match; running matches include a process identifier. */ +export type CuaAppInfo = Pick & { isRunning: true } +/** An installed application match with its current running state. */ export type CuaFoundAppInfo = z.output[number] /** Window bounds in the provider's global native units. Local operations use an origin of [0,0]. */ export type CuaBounds = CuaWindowInfo['bounds'] @@ -273,7 +273,7 @@ export interface CuaApi { getState(options?: CuaObservationOptions): Promise<{ apps: CuaAppInfo[]; browsers: [] }> /** * Select an app, obtain consent, launch it in the background if necessary, and silently retain initial AX state. - * @param selector - Exact name, bundle ID, absolute application path or running PID string; ambiguous names reject. + * @param selector - Provider-issued identifier, exact name, bundle ID or absolute application path; ambiguous selectors reject. * @returns An application handle tied to this process lifetime; its initial tree read becomes the current snapshot. */ getApp(selector: string): Promise diff --git a/packages/experimental/cua/tests/access.spec.ts b/packages/experimental/cua/tests/access.spec.ts index ef6f6c203f..74dea0c738 100644 --- a/packages/experimental/cua/tests/access.spec.ts +++ b/packages/experimental/cua/tests/access.spec.ts @@ -398,7 +398,8 @@ it('preserves captured launch metadata separately from the current helper parent const launchApplication = { name: 'Visual Studio Code', path: '/Applications/Visual Studio Code.app', icon: 'data:image/png;base64,aWNvbg==' } control.request.mockResolvedValueOnce({ platform: 'darwin' as const, accessibility: false, screenRecording: false, helper: { pid: 9 }, parent: { pid: 1, path: '/sbin/launchd' }, launchApplication }) - expect(await f.ctx.cuaAccess.systemStatus()).toMatchObject({ parent: { pid: 1 }, launchApplication }) + expect(await f.ctx.cuaAccess.systemStatus()).toEqual({ platform: 'darwin', accessibility: false, screenRecording: false, + helper: {}, parent: { path: '/sbin/launchd' }, launchApplication }) }) diff --git a/packages/experimental/cua/tests/api.spec.ts b/packages/experimental/cua/tests/api.spec.ts index cbaa419951..707bfc7089 100644 --- a/packages/experimental/cua/tests/api.spec.ts +++ b/packages/experimental/cua/tests/api.spec.ts @@ -27,7 +27,7 @@ function fixture(withSink = true) { const dispatch = vi.fn(async ({ method, params }: CuaOperation): Promise => { switch (method) { case 'getCapabilities': return currentCapabilities - case 'listApps': return [selected, { pid: 18, name: 'Utility' }] + case 'listApps': return [selected, { id: 'utility-selector', pid: 4, name: 'Utility' }] case 'getApp': return selected case 'listWindows': return windows case 'mouseMove': return { ...delivered, hoverRoute: 'accessibility', systemPointerMoved: false } @@ -59,12 +59,12 @@ function screenshot(overrides: Record = {}): JsonValue { } describe('application discovery', () => { - it('reports permissions and discovers both bundle and PID selectors without activating an app', async () => { + it('reports permissions and discovers provider-issued selectors without activating an app', async () => { const f = fixture() expect(await f.api.getCapabilities()).toEqual(capabilities) expect(await f.api.getState()).toEqual({ apps: [ - { id: 'test.editor', displayName: 'Editor', isRunning: true, pid: 17 }, - { id: '18', displayName: 'Utility', isRunning: true, pid: 18 }, + { id: 'test.editor', displayName: 'Editor', isRunning: true }, + { id: 'utility-selector', displayName: 'Utility', isRunning: true }, ], browsers: [] }) expect(f.dispatch.mock.calls.map(([operation]) => operation.method)).toEqual(['getCapabilities', 'listApps']) const emitted = f.sink.text.mock.calls.map(([text]): unknown => JSON.parse(text)) @@ -72,6 +72,19 @@ describe('application discovery', () => { expect(f.sink.text).toHaveBeenCalledTimes(2) }) + it('passes a discovered selector unchanged to application selection', async () => { + const f = fixture() + const apps = await f.api.listApps({ emit: false }) + await f.api.getApp(apps[1]!.id) + expect(f.dispatch).toHaveBeenCalledWith({ method: 'getApp', params: { selector: 'utility-selector' } }) + }) + + it('uses the application name when discovery has no identifier', async () => { + const f = fixture() + f.dispatch.mockResolvedValueOnce([{ pid: 18, name: 'Utility' }]) + expect(await f.api.listApps({ emit: false })).toEqual([{ id: 'Utility', displayName: 'Utility', isRunning: true }]) + }) + it('returns observations without requiring an output sink', async () => { const f = fixture(false) expect(await f.api.getCapabilities({ emit: false })).toEqual(capabilities) @@ -94,9 +107,9 @@ describe('application discovery', () => { const f = fixture() const matches = [ { id: 'test.stopped', displayName: 'Stopped', path: '/Applications/Stopped.app', isRunning: false }, - { id: 'test.running', displayName: 'Running', path: '/Applications/Running.app', isRunning: true, pid: 17 }, + { id: 'test.running', displayName: 'Running', path: '/Applications/Running.app', isRunning: true }, ] - f.dispatch.mockResolvedValueOnce(matches) + f.dispatch.mockResolvedValueOnce([matches[0]!, { ...matches[1]!, pid: 17 }]) expect(await f.api.findApps('Editor')).toEqual(matches) expect(f.dispatch).toHaveBeenLastCalledWith({ method: 'findApps', params: { query: 'Editor' } }) expect(f.sink.text).toHaveBeenLastCalledWith(JSON.stringify(matches)) @@ -113,7 +126,7 @@ describe('application discovery', () => { const f = fixture() f.dispatch.mockResolvedValueOnce({ platform: 'macos' }) await expect(f.api.getCapabilities()).rejects.toThrow() - f.dispatch.mockResolvedValueOnce([{ pid: 0, name: 'Invalid' }]) + f.dispatch.mockResolvedValueOnce([{ id: '', name: 'Invalid' }]) await expect(f.api.listApps()).rejects.toThrow() f.dispatch.mockResolvedValueOnce({ ...selected, appHandle: '' }) await expect(f.api.getApp('Editor')).rejects.toThrow() diff --git a/packages/experimental/cua/tests/bridge.spec.ts b/packages/experimental/cua/tests/bridge.spec.ts index 14a36baaba..f9deb49f7f 100644 --- a/packages/experimental/cua/tests/bridge.spec.ts +++ b/packages/experimental/cua/tests/bridge.spec.ts @@ -16,7 +16,7 @@ const capabilities: CuaCapabilities = { keyboard: ['app'], sessionLocked: false, methods: ['getCapabilities', 'getApp', 'getState', 'screenshot'], coordinateSpace: 'screenshot-pixels', browser: false, } -const selected = { appHandle: 'app-17', pid: 17, name: 'Editor', running: true } +const selected = { appHandle: 'app-17', name: 'Editor', running: true } const bounds = { x: 0, y: 0, width: 640, height: 480 } const snapshot = { appHandle: 'app-17', windowId: null, snapshotId: 'snapshot-1', tree: '0 button', truncated: false, @@ -56,8 +56,8 @@ it('propagates a denied action without retrying it', async () => { }) it('supports callers that retain observations without a text callback', async () => { - const cua = connectCua(() => async () => [{ pid: 17, name: 'Editor' }]) - await expect(cua.listApps()).resolves.toEqual([{ id: '17', displayName: 'Editor', isRunning: true, pid: 17 }]) + const cua = connectCua(() => async () => [{ id: 'editor-selector', name: 'Editor' }]) + await expect(cua.listApps()).resolves.toEqual([{ id: 'editor-selector', displayName: 'Editor', isRunning: true }]) }) it.each([null, 'text only', { content: [{ type: 'text', text: '{}' }] }])('rejects an unusable tool result %j', async (result) => { diff --git a/packages/experimental/cua/tests/controller.client.spec.ts b/packages/experimental/cua/tests/controller.client.spec.ts index 81575d1eb8..31b402fdfd 100644 --- a/packages/experimental/cua/tests/controller.client.spec.ts +++ b/packages/experimental/cua/tests/controller.client.spec.ts @@ -7,7 +7,7 @@ import { expect, it, onTestFinished, vi } from 'vitest' import type { CuaApplicationId, CuaApplicationState, CuaSystemPermissionState } from '../src/access-types.ts' import { PermissionController } from '../src/client/controller.ts' -const value: CuaSystemPermissionState = { platform: 'darwin' as const, accessibility: true, screenRecording: false, helper: { pid: 9 }, parent: { pid: 8 } } +const value: CuaSystemPermissionState = { platform: 'darwin' as const, accessibility: true, screenRecording: false, helper: {}, parent: {} } const applications: CuaApplicationState = { allowedApps: [], blockedApps: [], persistentAvailable: true } type CuaRemote = Context['remote']['cuaAccess'] diff --git a/packages/experimental/cua/tests/mount.client.spec.ts b/packages/experimental/cua/tests/mount.client.spec.ts index dcbd253ae6..bd39c2623f 100644 --- a/packages/experimental/cua/tests/mount.client.spec.ts +++ b/packages/experimental/cua/tests/mount.client.spec.ts @@ -14,7 +14,7 @@ import type { ApplicationApprovalProps } from '../src/client/ApplicationApproval const contribution: TypertRemoteContribution = { package: '@deepseek-ai/dsh-cua', descriptors: [] } const value: CuaApplicationState & { system: CuaSystemPermissionState } = { - system: { platform: 'darwin' as const, accessibility: false, screenRecording: false, helper: { pid: 2 }, parent: { pid: 1 } }, + system: { platform: 'darwin' as const, accessibility: false, screenRecording: false, helper: {}, parent: {} }, allowedApps: [], blockedApps: [], persistentAvailable: true } function actionsOf(value: Record): asserts value is Record & PermissionFace { diff --git a/packages/experimental/cua/tests/panel.client.spec.tsx b/packages/experimental/cua/tests/panel.client.spec.tsx index 613f24fce3..c3b9d083fb 100644 --- a/packages/experimental/cua/tests/panel.client.spec.tsx +++ b/packages/experimental/cua/tests/panel.client.spec.tsx @@ -12,7 +12,7 @@ import { en, zh } from '../src/client/locales.ts' afterEach(() => { cleanup(); vi.useRealTimers() }) const value: CuaApplicationState & { system: Extract } = { system: { platform: 'darwin' as const, accessibility: false, screenRecording: true, - helper: { pid: 9, path: '/native/helper' }, parent: { pid: 8, path: '/host/node' } }, + helper: { path: '/native/helper' }, parent: { path: '/host/node' } }, allowedApps: [], blockedApps: [], persistentAvailable: true } function observe(value: CuaApplicationState & { system: CuaSystemPermissionState }) { @@ -232,7 +232,7 @@ it.each([en, zh])('shows four requirements with the target application beside ea const f = fixture() render() const application = { name: 'Visual Studio Code.app', path: '/Applications/Visual Studio Code.app', icon: 'data:image/png;base64,aWNvbg==' } - f.publish({ ...observe({ ...value, system: { ...value.system, parent: { pid: 1, path: '/sbin/launchd' }, launchApplication: application } }) }) + f.publish({ ...observe({ ...value, system: { ...value.system, parent: { path: '/sbin/launchd' }, launchApplication: application } }) }) const requirements = screen.getByRole('region', { name: dictionary.title }) expect(within(requirements).getAllByRole('group')).toHaveLength(4) expect(screen.getByRole('region', { name: dictionary.applicationsTitle })).toBeTruthy() @@ -440,7 +440,7 @@ it('retains a known read-only configuration and query failure throughout managem it.each([true, false, null] as const)('shows Windows desktop access for lock state %s without macOS permission actions', (sessionLocked) => { const f = fixture() f.publish({ ...observe(value), system: { value: { platform: 'windows', sessionLocked, captureAvailable: true, - elevated: false, helper: { pid: 9, path: 'C:\\helper.exe' } }, error: null, busy: false } }) + elevated: false, helper: { path: 'C:\\helper.exe' } }, error: null, busy: false } }) render() const desktop = screen.getByRole('group', { name: en.windowsDesktop }) const capture = screen.getByRole('group', { name: en.windowsCapture }) @@ -452,7 +452,7 @@ it.each([true, false, null] as const)('shows Windows desktop access for lock sta expect(screen.queryByRole('button', { name: en.granted })).toBeNull() expect(screen.queryByText('C:\\helper.exe')).toBeNull() f.publish({ system: { value: { platform: 'windows', sessionLocked: false, captureAvailable: false, - elevated: true, helper: { pid: 9 } }, error: null, busy: false } }) + elevated: true, helper: {} }, error: null, busy: false } }) expect(within(capture).getByText(en.unavailable)).toBeTruthy() expect(screen.getByText(en.elevated, { exact: false })).toBeTruthy() f.publish({ system: { ...f.state.getSnapshot().system, error: 'offline' } }) @@ -462,7 +462,7 @@ it.each([true, false, null] as const)('shows Windows desktop access for lock sta it.each([[true, true], [false, true], [false, false], [null, true]] as const)('offers Windows setup for lock=%s and capture=%s', (sessionLocked, captureAvailable) => { const f = fixture(), onDismiss = vi.fn() f.publish({ system: { value: { platform: 'windows', sessionLocked, captureAvailable, - elevated: false, helper: { pid: 9 } }, error: null, busy: false } }) + elevated: false, helper: {} }, error: null, busy: false } }) render() const needsSetup = sessionLocked !== false || !captureAvailable expect(screen.queryByRole('dialog') !== null).toBe(needsSetup) diff --git a/packages/extensions/tool-cordis/src/api-catalog.ts b/packages/extensions/tool-cordis/src/api-catalog.ts index 74a5703129..e182793ce2 100644 --- a/packages/extensions/tool-cordis/src/api-catalog.ts +++ b/packages/extensions/tool-cordis/src/api-catalog.ts @@ -6324,7 +6324,7 @@ export const TYPE_API: readonly TypeApiEntry[] = [ }, { name: 'CuaPermissionProcess', - declaration: 'export interface CuaPermissionProcess {\n pid: number;\n path?: string | undefined;\n name?: string | undefined;\n}', + declaration: 'export interface CuaPermissionProcess {\n path?: string | undefined;\n name?: string | undefined;\n}', }, { name: 'CuaSystemPermission', @@ -6332,7 +6332,7 @@ export const TYPE_API: readonly TypeApiEntry[] = [ }, { name: 'CuaSystemPermissionState', - declaration: 'export type CuaSystemPermissionState = {\n platform: \'darwin\';\n accessibility: boolean;\n screenRecording: boolean;\n helper: CuaPermissionProcess;\n parent: CuaPermissionProcess;\n launchApplication?: {\n name: string;\n path: string;\n icon?: string | undefined;\n } | undefined;\n} | {\n platform: \'win32\';\n sessionLocked: boolean | null;\n captureAvailable: boolean;\n elevated: boolean;\n helper: CuaPermissionProcess;\n};', + declaration: 'export type CuaSystemPermissionState = {\n platform: \'darwin\';\n accessibility: boolean;\n screenRecording: boolean;\n helper: CuaPermissionProcess;\n parent: CuaPermissionProcess;\n launchApplication?: {\n name: string;\n path: string;\n icon?: string | undefined;\n } | undefined;\n} | {\n platform: \'windows\';\n sessionLocked: boolean | null;\n captureAvailable: boolean;\n elevated: boolean;\n helper: CuaPermissionProcess;\n};', }, { name: 'DailyInput',