Files
claude-code-haha/native/cu-helper/README.md
T
2026-09-14 17:01:56 +08:00

157 lines
8.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Native Computer Use compatibility
The compatibility reference is the installed **official** Codex Computer Use
plugin, its shipped JavaScript client, and its native service. Third-party
replicas are historical references, not specifications for current Codex.
`docs/internals/computer-use-codex-impl-blueprint.md` describes the verified
contracts and the boundaries of our implementation.
## Reference inspected on 2026-09-09
- Plugin: `openai-bundled/unified-computer-use/26.901.51231`.
- Native service: `SkyComputerUseService` **26.831.1000926**, SHA-256
`25e9141499b94c396f39afbdb7b19ed8f49e45dc8c61be61028ceab8f3807ce6`.
- The app ships `@oai/cua` and `@oai/sky` under
`Contents/Resources/cua_node/lib/node_modules/`. Its native client sends
length-prefixed JSON-RPC over a persistent local pipe. The browser provider is
separate from the native app provider.
- The public Codex CLI/App Server repository supplies MCP integration, not the
native service's mouse-event implementation. Missing static CGEvent imports
do not prove an AX-only implementation: the service also resolves functions
indirectly.
These observations apply to this build. Recheck the actual caller and callee
when changing versions; a nearby symbol or a third-party constant is insufficient
evidence for a timing or event contract.
## Native browser Apps and the separate browser provider
The native App route permits Chrome and other browsers on macOS. The earlier
TypeScript and `AppTargetPolicy` browser-category rejection blocked this route
despite it being the route used by the official native App client. Both dispatch
layers now permit native browser targets while preserving other denials,
authorization, signatures, and process/window-identity checks. Windows browser
categories and tiers remain unchanged. This permission is for native App
control; it does not implement the browser service's Tab, DOM, or Playwright API.
In the user-designated Townscaper success trace, 21 JS calls include one browser
inventory and a `getTab` attempt that times out after 30.0355 seconds. The next
binding is `cua.getApp("com.google.Chrome")`. All 57 later input actions are
native: 47 drags, 3 clicks, 3 scrolls, 3 key presses, and 1 paste. The trace
returns 18 screenshot blocks. Six cells containing loops perform 41 drags;
39 occur inside loop bodies and two are palette selections outside them.
Those six cells take 19.9703 seconds including their final observations. There
are no successful Tab/DOM/Playwright construction calls. Browser provider setup
is outside this native compatibility scope.
## Coordinate drag contract
The native coordinate click controller calls `ApplicationUIElement.sendClick`
with an optional drag destination and `delay: nil`. The specialized
`SynthesizedEvent.click` implementation emits:
| Event | Location | Click count | Event number |
| --- | --- | --- | --- |
| Mouse down | origin | 1 | gesture number |
| Mouse dragged | origin | 0 | motion number |
| Mouse dragged | midpoint | 0 | motion number |
| Mouse dragged | destination | 0 | motion number |
| Mouse up | destination | 1 | gesture number |
Zero-distance drags retain all five events. Do not replace them with clicks or
drop the initial dragged event. The three motion events share a number distinct
from the down/up pair. The origin window stays bound for the complete gesture.
In the inspected arm64 service, the specialized function is at `0x100723c60`,
the midpoint calculation is at `0x100723d34`, and the five NSEvent constructions
are at `0x100723dd8`, `0x100723fbc`, `0x100724160`, `0x100724300`, and
`0x1007244a8`. The coordinate caller at `0x10007c8dc` supplies a nil delay to
`sendClick` at `0x1006e22d8`. Both the direct and virtual-cursor sender branches
skip their optional sleep for this call. Actor transitions are not evidence for
a guaranteed yield or a substitute fixed delay.
`AXAction.dragEvents` and `MouseDragEventTests` encode this event contract using
the production event builder. `MouseEventBurstDelivery` retains target/window
validation, cancellation checks, and release of a held button at the last
posted point. Removing artificial waits must not remove those checks.
## Batches and observations
The official native app API supports persistent JavaScript bindings and loops.
It recommends batching known actions and observing the resulting state in the
same call. In the inspected coordinate controller, only `returnSkyshot: true`
enters the UI-settle/capture branch (notification delay 250ms); false invalidates
state and returns. The full observation time is not a fixed 250ms promise.
Only `js`/`js_reset` are advertised to models on macOS, avoiding duplicate
per-action schemas. These entry points provide an isolated persistent worker.
Variables, App bindings, top-level await, loops, calculations, and intermediate
observations survive across ordinary cells. Native App methods pass JSON messages
through the existing host semantic-tool dispatch and target checks. Binding an
App uses the approved path returned by initial observation; it does not cache a
PID as authority. The first visible App selection or inventory includes concise
API guidance; selecting an App initially displays AX text only.
The official facade's `getAXState`, `getScreenshot`, and
`getAXStateAndScreenshot` all call `get_app_state`. Our facade mirrors that
boundary: output selection and `emit:false` do not optimize away native AX
traversal or screenshot work. Actions do not add implicit observations. Copied
`gN:id` handles remain opaque; integer aliases are mapped only from returned AX
rows and track native diffs/generations. Image-only observations clear integer
aliases; a full AX observation is required to rebuild them.
Each JS cell permits 256 native calls, 256 KiB of source, 128 emitted content
blocks and 16 MiB of emitted data. The wall timeout defaults to 30 seconds and
is capped at 60 seconds. Ordinary script errors preserve bindings; timeout,
cancellation, or explicit reset discards them. Already-dispatched actions may
have run and are never automatically replayed. Imports, Node, filesystem and
networking are not exposed. Runtime, compiler, and worker boundaries live under
`src/utils/computerUse/`; `src/vendor/computer-use-mcp/replApi.ts` owns the native
method facade and observation output.
The existing `sequence` still executes validated JSON actions serially against
one proven process and observes once. It stops after failure/cancellation and
reports completed steps. Its limits remain 256 steps and a cooperative 60-second
deadline; an in-flight native command must settle before the runner returns.
Standalone semantic tools retain direct-call compatibility, but they and
`sequence` are not advertised by default. Windows retains its pixel tool face.
The ordinary Swift test suite uses event factories and injected receivers to
check input construction and routing without launching fixture apps, opening
windows, or driving the macOS desktop. The former native receiver integration
suite was removed because it interacted with the developer's desktop whenever
Accessibility and Screen Recording permissions were already available.
These tests do not prove delivery to a real receiving app.
The identity diagnostic added to `Injection.validateAuthorizedTarget` is
DEBUG-only and records the exact target/current values used by strict comparison.
`ProcessValidationObservationTests` verifies that this observer does not alter
the comparison or allow missing identity evidence. Controlled repeated runs
passed 15 rounds, comprising 45 disposable Apps, 180 complete drags, and 1,095
actual validation samples (1,080 during drag delivery). Each process retained
one complete identity, including identical launch-time Double bits. Twelve
gestures and a final observation took 1.178–1.405 seconds in those fixture runs.
This is fixture throughput, not model task performance.
Two earlier anomalies, `stale_process` and a timeout lacking phase records,
were not reproduced. Their causes remain unknown. The investigation added
diagnostics, not launch-time tolerances, retries, a relaxed comparison, or a
different fixture bundle ID.
## Compatibility limits
Matching these contracts does not establish complete Codex compatibility or
Townscaper/Blender task success. The persistent JS native App facade is present,
but browser-tab/DOM providers and the official runtime's general Node facilities
are not. Tests that run the actual sandboxed worker with simulated native tools
establish persistence, isolation and output behavior. Real receiving-app gesture
delivery requires a separate manual check. These tests do not prove parity
across real model tasks.
Focus acquisition, AX fallbacks, key synthesis, coordinate transforms, capture,
and gesture delivery must each be verified at their actual boundary. Do not
remove focus or interference checks merely because they cost time. Compare
action counts, observations, model round trips, per-action tool time and
receiver-visible outcomes separately; tool-time improvements alone do not
predict end-to-end model task performance.