@anionex/dsh-computer-use 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/LICENSE +21 -0
  2. package/README.i18n.yaml +6 -0
  3. package/README.md +307 -0
  4. package/README.zh.md +307 -0
  5. package/assets/computer-use-fixture.png +0 -0
  6. package/assets/cursor.png +0 -0
  7. package/cordis.patch.yml +13 -0
  8. package/docs/interaction-policy.i18n.yaml +4 -0
  9. package/docs/interaction-policy.md +140 -0
  10. package/docs/interaction-policy.zh.md +140 -0
  11. package/lib/approval-policy.js +12 -0
  12. package/lib/approval-policy.js.map +1 -0
  13. package/lib/artifacts.js +79 -0
  14. package/lib/artifacts.js.map +1 -0
  15. package/lib/backend.js +3 -0
  16. package/lib/backend.js.map +1 -0
  17. package/lib/client.js +349 -0
  18. package/lib/client.js.map +1 -0
  19. package/lib/config.js +120 -0
  20. package/lib/config.js.map +1 -0
  21. package/lib/confirmations.js +99 -0
  22. package/lib/confirmations.js.map +1 -0
  23. package/lib/diff.js +58 -0
  24. package/lib/diff.js.map +1 -0
  25. package/lib/errors.js +22 -0
  26. package/lib/errors.js.map +1 -0
  27. package/lib/exposure.js +231 -0
  28. package/lib/exposure.js.map +1 -0
  29. package/lib/index.js +56 -0
  30. package/lib/index.js.map +1 -0
  31. package/lib/leases.js +259 -0
  32. package/lib/leases.js.map +1 -0
  33. package/lib/providers/macos.js +148 -0
  34. package/lib/providers/macos.js.map +1 -0
  35. package/lib/providers/native-helper.js +356 -0
  36. package/lib/providers/native-helper.js.map +1 -0
  37. package/lib/service.js +480 -0
  38. package/lib/service.js.map +1 -0
  39. package/lib/skill.js +119 -0
  40. package/lib/skill.js.map +1 -0
  41. package/lib/target-resolver.js +180 -0
  42. package/lib/target-resolver.js.map +1 -0
  43. package/lib/tools.js +493 -0
  44. package/lib/tools.js.map +1 -0
  45. package/lib/types/approval-policy.d.ts +13 -0
  46. package/lib/types/approval-policy.d.ts.map +1 -0
  47. package/lib/types/artifacts.d.ts +10 -0
  48. package/lib/types/artifacts.d.ts.map +1 -0
  49. package/lib/types/backend.d.ts +94 -0
  50. package/lib/types/backend.d.ts.map +1 -0
  51. package/lib/types/client/index.d.ts +78 -0
  52. package/lib/types/client/index.d.ts.map +1 -0
  53. package/lib/types/config.d.ts +75 -0
  54. package/lib/types/config.d.ts.map +1 -0
  55. package/lib/types/confirmations.d.ts +23 -0
  56. package/lib/types/confirmations.d.ts.map +1 -0
  57. package/lib/types/diff.d.ts +5 -0
  58. package/lib/types/diff.d.ts.map +1 -0
  59. package/lib/types/errors.d.ts +15 -0
  60. package/lib/types/errors.d.ts.map +1 -0
  61. package/lib/types/exposure.d.ts +30 -0
  62. package/lib/types/exposure.d.ts.map +1 -0
  63. package/lib/types/index.d.ts +21 -0
  64. package/lib/types/index.d.ts.map +1 -0
  65. package/lib/types/leases.d.ts +80 -0
  66. package/lib/types/leases.d.ts.map +1 -0
  67. package/lib/types/providers/macos.d.ts +15 -0
  68. package/lib/types/providers/macos.d.ts.map +1 -0
  69. package/lib/types/providers/native-helper.d.ts +36 -0
  70. package/lib/types/providers/native-helper.d.ts.map +1 -0
  71. package/lib/types/service.d.ts +52 -0
  72. package/lib/types/service.d.ts.map +1 -0
  73. package/lib/types/skill.d.ts +9 -0
  74. package/lib/types/skill.d.ts.map +1 -0
  75. package/lib/types/target-resolver.d.ts +38 -0
  76. package/lib/types/target-resolver.d.ts.map +1 -0
  77. package/lib/types/tools.d.ts +6 -0
  78. package/lib/types/tools.d.ts.map +1 -0
  79. package/lib/types/types.d.ts +246 -0
  80. package/lib/types/types.d.ts.map +1 -0
  81. package/lib/types/web.d.ts +32 -0
  82. package/lib/types/web.d.ts.map +1 -0
  83. package/lib/types.js +9 -0
  84. package/lib/types.js.map +1 -0
  85. package/lib/web.js +163 -0
  86. package/lib/web.js.map +1 -0
  87. package/native/macos/Sources/Fixture/main.swift +366 -0
  88. package/native/macos/Sources/Helper/CursorImage.swift +11 -0
  89. package/native/macos/Sources/Helper/CursorOverlay.swift +488 -0
  90. package/native/macos/Sources/Helper/TargetedPointer.swift +314 -0
  91. package/native/macos/Sources/Helper/main.swift +1140 -0
  92. package/native/macos/Sources/Monitor/main.swift +139 -0
  93. package/native/macos/bin/dsh-computer-use-helper +0 -0
  94. package/native/macos/manifest.json +14 -0
  95. package/package.json +128 -0
  96. package/scripts/build-client.mjs +24 -0
  97. package/scripts/build-native.mjs +158 -0
  98. package/scripts/check-native.mjs +92 -0
  99. package/scripts/model-e2e.mjs +291 -0
  100. package/scripts/session-transcript.mjs +117 -0
  101. package/scripts/validate.mjs +256 -0
  102. package/src/approval-policy.ts +16 -0
  103. package/src/artifacts.ts +93 -0
  104. package/src/backend.ts +103 -0
  105. package/src/client/index.tsx +539 -0
  106. package/src/config.ts +196 -0
  107. package/src/confirmations.ts +128 -0
  108. package/src/diff.ts +52 -0
  109. package/src/errors.ts +39 -0
  110. package/src/exposure.ts +236 -0
  111. package/src/index.ts +66 -0
  112. package/src/leases.ts +337 -0
  113. package/src/providers/macos.ts +185 -0
  114. package/src/providers/native-helper.ts +393 -0
  115. package/src/service.ts +583 -0
  116. package/src/skill.ts +123 -0
  117. package/src/target-resolver.ts +237 -0
  118. package/src/tools.ts +528 -0
  119. package/src/types.ts +299 -0
  120. package/src/web.ts +180 -0
Binary file
@@ -0,0 +1,13 @@
1
+ # One aggregate row initializes the macOS Service provider before publishing
2
+ # the model-facing Skill and Agent-scoped Tools.
3
+ - insert:
4
+ - id: computer-use
5
+ name: '@anionex/dsh-computer-use'
6
+ config:
7
+ observationTtlMs: 0
8
+ interaction:
9
+ focusPolicy: preserve
10
+ keyboardPolicy: activate
11
+ pointerInputPolicy: targeted
12
+ cursorVisualization: visible
13
+ cursorAutoHideMs: 0
@@ -0,0 +1,4 @@
1
+ # Bilingual-pair consistency record. Both languages carry equal authority.
2
+ # Recompute these git blob hashes after confirming the two documents say the same thing.
3
+ interaction-policy.md: 6f2e9620b76a5e523f037fbd5abb8604b61c7a49
4
+ interaction-policy.zh.md: 7f00e6c0ea6d9e10687a11276f2ca2e7575e3503
@@ -0,0 +1,140 @@
1
+ # Foreground-safe input policy
2
+
3
+ ## Requirement
4
+
5
+ DSH Computer Use must let an Agent operate a native macOS application while the user continues working elsewhere. The default pointer path must not move the system cursor, post pointer events to the global HID stream, or activate the target application merely to make a pointer action work. Keyboard input is the one deliberate exception: the Bundle enables `keyboardPolicy: activate` so typing works reliably by bringing the target app to the foreground first, matching Codex Computer Use behavior. Pointer actions may show a separate Agent cursor, but that overlay must never become an input source or a window manager participant.
6
+
7
+ The default Bundle configuration is:
8
+
9
+ ```yaml
10
+ interaction:
11
+ focusPolicy: preserve
12
+ keyboardPolicy: activate
13
+ pointerInputPolicy: targeted
14
+ cursorVisualization: visible
15
+ cursorMotionMs: 180
16
+ cursorAutoHideMs: 0
17
+ ```
18
+
19
+ `preserve` means pointer actions do not request foreground activation. `keyboardPolicy: activate` (the Bundle default) requests foreground activation before `type-text` keyboard fallback and `press-key`; `keyboardPolicy: preserve` keeps typing routed to the selected pid without activation and is reliable only for applications that accept background keyboard events. `targeted` means mouse, drag, and wheel events may be sent only to the exact observed process and window. `visible` enables the separate Agent cursor, whose motion and auto-hide timing are also host-owned. The model cannot change any interaction policy through Tool arguments.
20
+
21
+ This is an input-routing property, not a consequence of Accessibility permission alone. Accessibility grants semantic UI access; foreground preservation comes from choosing semantic Accessibility operations first and using process/window-targeted fallback instead of the system cursor.
22
+
23
+ ## Overall design
24
+
25
+ The action path has five ordered layers:
26
+
27
+ 1. The DSH Service binds the request to one unexpired observation, exact bundle id, pid, window, and element target handle, compatibility index, window-relative point, or screen-global point.
28
+ 2. For a handle action, the Service obtains fresh Accessibility state and resolves the target through the original locator, one unique provider-native identifier, or one unique semantic role/name/actions/ancestor match. Application, process, and selected-window identity remain exact; ambiguity and low confidence fail closed.
29
+ 3. The native helper observes the resolved target again and rejects any race that changed its locator, properties, process, or window before input.
30
+ 4. The helper prefers `AXPress`, Accessibility value assignment, selected-text assignment, or an action advertised by the element. When a `click` target advertises `AXPress` but macOS rejects the press, the helper retries `AXPress` on the element's pressable descendants within a bounded depth before considering the element-frame or coordinate pointer route.
31
+ 5. When semantic input is unavailable, keyboard events are posted to the selected pid and pointer events are posted to the selected pid and window. No pointer fallback uses a global event tap.
32
+
33
+ Pointer delivery uses the observed window when it contains the point; otherwise it resolves the topmost on-screen window of the selected app that contains the screen point and posts through `SLEventPostToPid` with the pid/window fields and window-local coordinates. This is the same target-process shape Codex Computer Use uses (`SynthesizedEvent.send(to: pid)` with `CGWindow.window(at:)`), so `coordinateSpace: screen` supports arbitrary-coordinate clicks without a global HID event stream. Unavailable SkyLight symbols or a point outside every window of the selected app fails closed.
34
+
35
+ Visual feedback uses a 28x28 `NSPanel` owned by a dedicated, persistent cursor process. The panel is borderless, nonactivating, click-through, and excluded from normal window cycling; it is not made visible on every Space. It draws the embedded transparent whole-image cursor (`assets/cursor.png`, Cursor arrow plus DeepSeek whale) with its top-left corner at the target point. Before input it animates to the same screen-global target point using an ease-out motion, briefly compresses the image for click, and keeps it pressed through a drag. By default it stays at the target point until the bound window changes or a hide command; set `cursorAutoHideMs` to a finite value for inactivity auto-hide. The overlay never posts input and never changes the system cursor position.
36
+
37
+ Policy is enforced twice on the supported DSH Tool path. The Service rejects a known pointer or foreground requirement before obtaining a control lease or consuming a sensitive-action confirmation. The helper validates the same resolved policy immediately before input, including fallback decisions that can only be made at runtime. The helper also requires an isolated process group plus three standard pipe or Unix-socket transports whose peer endpoints belong to its direct parent process; ordinary shell redirection fails closed before any command is parsed. This transport check is defense in depth, not authentication against arbitrary code running as the same macOS user: a deliberately constructed detached parent can reproduce the topology, especially under `danger-full-access`. The registered Tool path remains the only supported route because it applies leases, confirmations, and host policy before invoking the helper.
38
+
39
+ Every action result reports the route actually used:
40
+
41
+ ```ts
42
+ activation: 'not-requested' | 'already-frontmost' | 'activated'
43
+ pointerInput: boolean
44
+ pointerRouting: 'none' | 'target-process'
45
+ resolution?: {
46
+ mode: 'exact-locator' | 'native-identifier' | 'semantic-rebind'
47
+ confidence: number
48
+ candidateCount: number
49
+ targetChanged: boolean
50
+ }
51
+ ```
52
+
53
+ These fields do not claim that a target application can never change focus as its own side effect. They report only what the helper requested and emitted.
54
+
55
+ ## Action matrix
56
+
57
+ | Action path | Default activation | Pointer route | Default result |
58
+ |---|---|---|---|
59
+ | `click` through `AXPress` | None | None | Allowed |
60
+ | `set-value` through Accessibility | None | None | Allowed |
61
+ | non-foreground `perform-action` advertised by the element | None | None | Allowed |
62
+ | `AXRaise` | Denied | None | Requires explicit `focusPolicy: activate`, then re-observation/revalidation |
63
+ | `type-text` through selected-text assignment | None | None | Allowed when the focused element accepts it |
64
+ | `type-text` keyboard fallback | None with `keyboardPolicy: preserve`; `activated` with `keyboardPolicy: activate` | Target pid | Allowed; activation makes it reliable |
65
+ | `press-key` | None with `keyboardPolicy: preserve`; `activated` with `keyboardPolicy: activate` | Target pid | Allowed; activation makes it reliable |
66
+ | coordinate click or element-frame fallback | None | Target pid + window | Allowed when `pointerInputPolicy: targeted` |
67
+ | scroll | None | Target pid + window | Allowed when `pointerInputPolicy: targeted` |
68
+ | drag | None | Target pid + window | Allowed when `pointerInputPolicy: targeted` |
69
+
70
+ `pointerInputPolicy: deny` disables coordinate click/fallback, scroll, and drag while leaving semantic Accessibility and process-targeted keyboard paths available. `coordinateSpace: window` (default) resolves coordinates inside the observed window frame; `coordinateSpace: screen` accepts Quartz screen-global points.
71
+
72
+ ## Critical decisions
73
+
74
+ ### Host policy is not a Tool argument
75
+
76
+ The deployment owns `focusPolicy`, `keyboardPolicy`, and `pointerInputPolicy`. `allowCoordinateFallback` says only that `computer_click` may try the host-authorized pointer route after `AXPress` is unavailable. It cannot enable pointer delivery or foreground activation. `computer_perform_action` also treats `AXRaise` as foreground-affecting and rejects it under `preserve`.
77
+
78
+ ### Accessibility remains the primary route
79
+
80
+ Semantic Accessibility operations are more stable than pixels and need no cursor emulation. They also work against many background applications. The helper revalidates the exact target before invoking them and reports `activation: not-requested`, `pointerInput: false`, and `pointerRouting: none`.
81
+
82
+ ### Stable handles rebind only with independent identity evidence
83
+
84
+ The public `targetHandle` is opaque and observation-local; it does not expose an `AXUIElement`, locator, or `AXIdentifier`. The Service stores the normalized descriptor in Agent-owned memory and re-observes immediately before a handle action. Exact locator identity is preferred. Rebinding is opt-in through `allowRebind` and requires either one provider-native identifier whose stable semantics still match or one semantic candidate with the same role, normalized accessible name, advertised actions, and stable ancestor fingerprint. The resolver preserves the exact bundle id, pid, and selected-window identity. A truncated tree cannot authorize rebinding. Duplicate candidates return `COMPUTER_TARGET_AMBIGUOUS`; missing or insufficient evidence returns `COMPUTER_TARGET_LOW_CONFIDENCE`.
85
+
86
+ Sensitive confirmation is bound to the exact handle action. Any native-identifier or semantic fallback marks the target changed, invalidates the prior token, and returns `COMPUTER_TARGET_REBIND_REQUIRES_CONFIRMATION` before input. Coordinates and screenshot-derived boxes cannot become handles, identity evidence, or authorization for a sensitive target. The caller must select the current handle and obtain a new one-use confirmation. Provider-native visual hit-testing remains a separate follow-up because the current visual workflow cannot independently validate a screenshot coordinate.
87
+
88
+ ### The default pointer route is virtual and target-specific
89
+
90
+ The helper never moves the system cursor and then tries to restore it. That design would still interrupt the user, race with real input, and risk delivering an event to the wrong application.
91
+
92
+ Instead, pointer fallback creates an event at the target screen point, binds it to the exact pid and `CGWindowID` (the observed window when it contains the point, otherwise the topmost app window under the point), supplies the window-local point expected by AppKit, and sends it through the per-process SkyLight route. Click, scroll, and drag share this route. The committed helper contains no `CGWarpMouseCursorPosition`, global `CGEventPost`, or `.post(tap: .cghidEventTap)` path.
93
+
94
+ ### Cursor visualization is presentation-only
95
+
96
+ The visible Agent cursor is deliberately not the input source. It is a separate process with a strict JSON-lines protocol and a startup-ready handshake. Every show, press, and release is bound to the observed pid, `CGWindowID`, and expected frame; a closed, moved, resized, minimized, or off-screen window hides the overlay. Because presentation is separate from routing, disabling the cursor cannot change action semantics and overlay failure cannot redirect or globally emit input.
97
+
98
+ ### Activation is an explicit compatibility mode
99
+
100
+ Some applications accept input only while active. A deployment may set `focusPolicy: activate` (all actions) or `keyboardPolicy: activate` (keyboard actions only), accepting that the target application can take the foreground. Before emitting input, the helper activates the exact process and observes it again. Element and window targets are revalidated; for keyboard actions the refreshed focused element is the target, because activation may move focus to the app's default control. Any element/window mismatch fails with `COMPUTER_STALE_OBSERVATION` instead of acting on the pre-activation target.
101
+
102
+ With `focusPolicy: preserve` and `keyboardPolicy: preserve`, the helper never performs this activation step.
103
+
104
+ ### Pointer delivery fails closed
105
+
106
+ Target-process pointer delivery resolves the window from the point itself: the observed window is used when its frame contains the point; otherwise the helper takes the topmost on-screen window of the selected app whose frame contains the point. Observation still captures `AXWindowNumber` when available and falls back to a unique frame/title match, but coordinate actions no longer require that match. A point outside every on-screen window of the selected app fails closed instead of falling back to the global cursor.
107
+
108
+ ### Private SPI is isolated and optional at runtime
109
+
110
+ The per-process pointer route uses dynamically resolved SkyLight symbols. This keeps the failure explicit on an unsupported macOS build: semantic Accessibility and process-targeted keyboard input remain available, while pointer fallback returns `COMPUTER_ACTION_BLOCKED`. The helper never silently changes to global pointer injection.
111
+
112
+ ## Verified evidence
113
+
114
+ The release evidence covers both implementation and observed behavior:
115
+
116
+ - source and binary checks reject system-cursor warp symbols, the exact global `CGEventPost` symbol, and unknown dynamically resolved native symbols;
117
+ - overlay checks require a nonactivating panel, click-through hit testing, prohibited application activation policy, and no cursor-warp primitive;
118
+ - the overlay runtime rejects missing or malformed target identity, oversized or invalid JSON-lines commands, unsupported timing, and direct helpers that do not own a managed parent transport;
119
+ - a real overlay process must emit its ready frame before commands, reuse one process across commands, and stop cleanly on disposal;
120
+ - a native monitor requires the overlay to be the only 28x28 window owned by its process, not become frontmost, and produce no global pointer events from that process pid;
121
+ - the helper must contain `SLEventPostToPid` and `CGEventSetWindowLocation`;
122
+ - a coordinate click without an observed window id resolves the app window under the Quartz screen point and still reports `pointerRouting: target-process`;
123
+ - `keyboardPolicy: activate` makes a background fixture become active and receive the key event, and the fixture transcript records the activation;
124
+ - the fixture is started through `open -g` with `--background`, so LaunchServices does not request foreground activation;
125
+ - the fixture records every `applicationDidBecomeActive` callback and the default path must not increase `activationCount`;
126
+ - an independent native monitor samples cursor position and the frontmost pid every millisecond throughout click, scroll, and drag; every sample must remain unchanged;
127
+ - background `AXPress`, Accessibility value/action, selected-text input, and pid-targeted key input change the fixture without activating it;
128
+ - the native fixture inserts a harmless sibling and recreates a uniquely identified checkbox, proving the raw locator becomes stale while `AXIdentifier` resolution still finds exactly one target;
129
+ - target-process click and scroll are each observed exactly once; drag has exactly one down/up gesture; the target remains non-frontmost;
130
+ - `pointerInputPolicy: deny` rejects click fallback, scroll, and drag before any target pointer event is delivered;
131
+ - clean Profile and real-model validation require the model-visible action result and fixture transcript to agree.
132
+
133
+ ## Known limitations
134
+
135
+ - Target-process pointer delivery is less universal than semantic Accessibility. Custom canvases, games, hardened input surfaces, or future macOS changes may reject it.
136
+ - The clicked point must fall inside an on-screen window of the selected app; minimized, fully hidden, or windowless targets fail closed.
137
+ - `focusPolicy: activate` and `keyboardPolicy: activate` are intentionally disruptive and exist only as operator-selected compatibility modes.
138
+ - A target application may change its own activation or focus as a side effect of an accepted action; the helper does not claim control over application-internal behavior.
139
+ - The Agent cursor is scoped to one active Space and the exact observed window. `cursorAutoHideMs: 0` keeps it visible until the bound window changes, a new hide command arrives, or the helper is disposed.
140
+ - Stable handles currently use exact locators, provider-native identifiers, and strict semantic identity. Semantic-spatial rebinding and provider-native visual hit-testing remain follow-up work; a vision-derived coordinate alone is never a verified target.
@@ -0,0 +1,140 @@
1
+ # 前台安全输入策略
2
+
3
+ ## 需求
4
+
5
+ DSH Computer Use 应让 Agent 操作原生 macOS 应用时,用户仍能在其他应用中继续工作。默认指针路径不能移动系统光标、向全局 HID 事件流投递指针事件,也不能只为完成指针动作就激活目标应用。键盘输入是唯一刻意例外:Bundle 默认启用 `keyboardPolicy: activate`,通过先把目标应用带到前台来让输入可靠工作,这与 Codex Computer Use 的行为一致。指针动作可以显示独立 Agent 光标,但 overlay 绝不能成为输入源或窗口管理器参与者。
6
+
7
+ Bundle 默认配置为:
8
+
9
+ ```yaml
10
+ interaction:
11
+ focusPolicy: preserve
12
+ keyboardPolicy: activate
13
+ pointerInputPolicy: targeted
14
+ cursorVisualization: visible
15
+ cursorMotionMs: 180
16
+ cursorAutoHideMs: 1400
17
+ ```
18
+
19
+ `preserve` 表示指针动作不请求前台激活。`keyboardPolicy: activate`(Bundle 默认)会在 `type-text` 键盘 fallback 与 `press-key` 前请求前台激活;`keyboardPolicy: preserve` 仍把键盘事件定向投递给选定 pid 而不激活,只有接受后台键盘事件的应用才可靠。`targeted` 表示鼠标、拖拽和滚轮事件只能投递给准确的已观察进程与窗口。`visible` 开启独立 Agent 光标,其移动与自动隐藏时长同样归宿主所有。模型不能通过 Tool 参数修改任何交互策略。
20
+
21
+ 这是一项输入路由属性,并不是只要拿到 Accessibility 权限就自然成立。Accessibility 授予语义化 UI 访问能力;真正避免抢前台的是优先使用语义化 Accessibility 操作,并用进程/窗口定向 fallback 代替系统光标。
22
+
23
+ ## 总体设计
24
+
25
+ 动作路径按以下五层执行:
26
+
27
+ 1. DSH Service 把请求绑定到一个未过期 observation、准确 bundle id、pid、窗口,以及 element target handle、兼容 index、窗口相对坐标或屏幕全局坐标。
28
+ 2. 对 handle 动作,Service 会获取新鲜 Accessibility 状态,并通过原 locator、唯一 provider-native identifier,或唯一 semantic role/name/actions/ancestor match 解析目标。应用、进程与选定窗口身份始终保持准确;歧义和低置信度都会 fail closed。
29
+ 3. Native helper 会再次观察已解析目标,并拒绝输入前发生的 locator、属性、进程或窗口竞态变化。
30
+ 4. Helper 优先使用 `AXPress`、Accessibility value 赋值、selected-text 赋值,或元素声明的 action。当 `click` 目标声明了 `AXPress` 但 macOS 拒绝执行时,helper 会在有界深度内重试该元素可点击子节点的 `AXPress`,之后才考虑元素 frame 或坐标指针路由。
31
+ 5. 语义输入不可用时,键盘事件定向投递到选定 pid;指针事件定向投递到选定 pid 和窗口。任何指针 fallback 都不使用全局 event tap。
32
+
33
+ 指针投递在点位于已观察窗口内时直接使用该窗口;否则解析选定应用在该屏幕点下最上层的屏幕内窗口,再通过 `SLEventPostToPid` 投递并附带 pid/window 字段与窗口本地坐标。这与 Codex Computer Use 的 target-process 形态一致(`SynthesizedEvent.send(to: pid)` 配合 `CGWindow.window(at:)`),因此 `coordinateSpace: screen` 无需全局 HID 事件流即可支持任意坐标点击。SkyLight symbol 不可用,或该点不在选定应用的任何屏幕内窗口中时都会 fail closed。
34
+
35
+ 视觉反馈由专用、常驻的光标进程创建 28x28 `NSPanel`。该 panel 无边框、不激活应用、点击穿透,并且不会进入普通窗口切换列表;它不会在全部 Space 上显示。它绘制嵌入的透明整图光标(`assets/cursor.png`,Cursor 箭头加 DeepSeek 鲸鱼),图片左上角对准目标点。输入前它会以 ease-out 动画移动到相同的屏幕全局目标点,click 时短暂压缩图片,drag 期间保持按压状态。默认它会停留在目标点,直到绑定窗口变化或收到 hide 命令;设置 `cursorAutoHideMs` 为有限值可以开启空闲自动隐藏。这个 overlay 不发出输入,也不会改变系统光标位置。
36
+
37
+ 受支持的 DSH Tool 路径会执行两层策略检查。Service 会在申请 control lease 或消费敏感动作 confirmation 之前拒绝已知需要指针或前台权限的动作;helper 会在真正发出输入前再次校验同一份已解析策略,包括只能在运行时确定的 fallback。Helper 还要求独立进程组,以及三条标准 pipe 或 Unix socket 传输的对端都属于它的直接父进程;普通 shell 重定向会在解析命令前 fail closed。这个传输检查只属于纵深防御,不会认证同一 macOS 用户下运行的任意代码:专门构造的 detached 父进程仍能复现这类拓扑,尤其是在 `danger-full-access` 下。注册 Tool 路径仍是唯一受支持的调用方式,因为它会在调用 helper 前执行 lease、confirmation 与宿主策略。
38
+
39
+ 每个动作结果都会报告实际使用的路由:
40
+
41
+ ```ts
42
+ activation: 'not-requested' | 'already-frontmost' | 'activated'
43
+ pointerInput: boolean
44
+ pointerRouting: 'none' | 'target-process'
45
+ resolution?: {
46
+ mode: 'exact-locator' | 'native-identifier' | 'semantic-rebind'
47
+ confidence: number
48
+ candidateCount: number
49
+ targetChanged: boolean
50
+ }
51
+ ```
52
+
53
+ 这些字段不会声称目标应用绝不可能因自身副作用改变焦点,只报告 helper 实际请求和发出的行为。
54
+
55
+ ## 动作矩阵
56
+
57
+ | 动作路径 | 默认激活行为 | 指针路由 | 默认结果 |
58
+ |---|---|---|---|
59
+ | 通过 `AXPress` 的 `click` | 不激活 | 无 | 允许 |
60
+ | 通过 Accessibility 的 `set-value` | 不激活 | 无 | 允许 |
61
+ | 元素声明且不影响前台的 `perform-action` | 不激活 | 无 | 允许 |
62
+ | `AXRaise` | 拒绝 | 无 | 需要显式 `focusPolicy: activate`,随后重新观察/校验 |
63
+ | 通过 selected-text 赋值的 `type-text` | 不激活 | 无 | 当前 focused element 接受时允许 |
64
+ | `type-text` 键盘 fallback | `keyboardPolicy: preserve` 不激活;`keyboardPolicy: activate` 激活 | 目标 pid | 允许;激活后更可靠 |
65
+ | `press-key` | `keyboardPolicy: preserve` 不激活;`keyboardPolicy: activate` 激活 | 目标 pid | 允许;激活后更可靠 |
66
+ | 坐标点击或元素 frame fallback | 不激活 | 目标 pid + window | `pointerInputPolicy: targeted` 时允许 |
67
+ | 滚动 | 不激活 | 目标 pid + window | `pointerInputPolicy: targeted` 时允许 |
68
+ | 拖拽 | 不激活 | 目标 pid + window | `pointerInputPolicy: targeted` 时允许 |
69
+
70
+ `pointerInputPolicy: deny` 会禁用坐标点击/fallback、滚动和拖拽,但保留语义化 Accessibility 与进程定向键盘路径。`coordinateSpace: window`(默认)在已观察窗口 frame 内解释坐标;`coordinateSpace: screen` 接受 Quartz 屏幕全局坐标。
71
+
72
+ ## 关键决策
73
+
74
+ ### 宿主策略不是 Tool 参数
75
+
76
+ `focusPolicy`、`keyboardPolicy` 与 `pointerInputPolicy` 归部署方所有。`allowCoordinateFallback` 只表示 `computer_click` 在 `AXPress` 不可用后可以尝试宿主已授权的指针路由,不能自行开启指针投递或前台激活。`computer_perform_action` 也会把 `AXRaise` 视为影响前台的动作,并在 `preserve` 下拒绝。
77
+
78
+ ### Accessibility 始终是主路径
79
+
80
+ 语义化 Accessibility 操作比像素坐标更稳定,不需要模拟光标,并且能在许多后台应用上工作。Helper 会先重新校验准确目标,再调用这些操作,并返回 `activation: not-requested`、`pointerInput: false` 和 `pointerRouting: none`。
81
+
82
+ ### Stable handle 只在独立身份依据充分时 rebind
83
+
84
+ 公开的 `targetHandle` 是 opaque 且 observation-local 的;它不暴露 `AXUIElement`、locator 或 `AXIdentifier`。Service 把 normalized descriptor 保存在 Agent 自有内存中,并在 handle 动作前立即重新观察。系统优先使用准确 locator 身份。Rebind 必须通过 `allowRebind` 显式启用,并且只能依赖稳定语义仍一致的唯一 provider-native identifier,或 role、normalized accessible name、已声明 action 与稳定 ancestor fingerprint 全部一致的唯一 semantic candidate。Resolver 保留准确 bundle id、pid 与选定窗口身份。Truncated tree 不能授权 rebind。重复 candidate 返回 `COMPUTER_TARGET_AMBIGUOUS`;证据缺失或不足返回 `COMPUTER_TARGET_LOW_CONFIDENCE`。
85
+
86
+ 敏感 confirmation 绑定准确 handle action。任何 native-identifier 或 semantic fallback 都会把目标标记为 changed,在输入前使旧 token 失效,并返回 `COMPUTER_TARGET_REBIND_REQUIRES_CONFIRMATION`。坐标与截图-derived box 不能变成 handle、身份依据或敏感目标授权。调用方必须选择当前 handle,并获取新的单次 confirmation。Provider-native visual hit-test 被明确拆为后续能力,因为当前视觉流程无法独立校验截图坐标。
87
+
88
+ ### 默认指针路由是虚拟且目标定向的
89
+
90
+ Helper 不会先移动系统光标再尝试恢复。那种设计仍会打断用户、与真实输入竞争,还可能把事件送错应用。
91
+
92
+ 指针 fallback 会在目标屏幕点创建事件,将其绑定到准确 pid 和 `CGWindowID`(点位于已观察窗口内时使用该窗口,否则使用该点下选定应用的最上层窗口),填入 AppKit 需要的窗口本地坐标,再通过 SkyLight 的进程定向路由发出。点击、滚动与拖拽共用这条路径。提交的 helper 不包含 `CGWarpMouseCursorPosition`、全局 `CGEventPost` 或 `.post(tap: .cghidEventTap)` 路径。
93
+
94
+ ### 光标可视化只负责展示
95
+
96
+ 可见 Agent 光标有意不作为输入源。它是独立进程,使用严格 JSON-lines 协议和启动就绪握手。每次 show、press 与 release 都绑定已观察的 pid、`CGWindowID` 和预期 frame;目标窗口关闭、移动、缩放、最小化或离开屏幕时,overlay 会隐藏。由于展示与输入路由彼此独立,关闭光标不会改变动作语义,overlay 失败也不能改道或全局发出输入。
97
+
98
+ ### 激活是显式兼容模式
99
+
100
+ 少数应用只有在 active 状态下才接受输入。部署方可以设置 `focusPolicy: activate`(全部动作)或 `keyboardPolicy: activate`(仅键盘动作),并明确接受目标应用可能抢到前台。Helper 会先激活准确进程并再次观察;元素与窗口目标会被重新校验,键盘动作则以刷新后的 focused element 为目标,因为激活可能把焦点移到应用默认控件。任何元素/窗口不匹配都会返回 `COMPUTER_STALE_OBSERVATION`,而不是继续操作激活前的目标。
101
+
102
+ `focusPolicy: preserve` 且 `keyboardPolicy: preserve` 时,helper 不会执行这个激活步骤。
103
+
104
+ ### 指针投递必须 fail closed
105
+
106
+ 目标进程指针投递直接从点解析窗口:点位于已观察窗口 frame 内时使用该窗口;否则取选定应用在屏幕内且 frame 包含该点的最上层窗口。observation 仍会在可用时捕获 `AXWindowNumber`,并回退到唯一 frame/title 匹配,但坐标动作不再依赖该匹配。点不在选定应用任何屏幕内窗口时 fail closed,而不是退回全局光标。
107
+
108
+ ### Private SPI 被隔离并允许运行时缺失
109
+
110
+ 进程定向指针路由使用动态解析的 SkyLight symbol。这样在不支持的 macOS 版本上会明确失败:语义化 Accessibility 与进程定向键盘输入仍可用,指针 fallback 返回 `COMPUTER_ACTION_BLOCKED`。Helper 不会静默切换成全局指针注入。
111
+
112
+ ## 已验证证据
113
+
114
+ 发布证据同时覆盖实现与真实行为:
115
+
116
+ - 源码与 binary 检查会拒绝系统光标 warp symbol、准确的全局 `CGEventPost` symbol,以及未知的动态解析 native symbol;
117
+ - overlay 检查要求 nonactivating panel、点击穿透、prohibited 应用激活策略,并拒绝任何 cursor warp primitive;
118
+ - overlay runtime 会拒绝缺失或格式错误的目标身份、超长或非法 JSON-lines 命令、不支持的时长,以及不拥有托管父进程传输的直接 helper 调用;
119
+ - 真实 overlay 进程必须在执行命令前输出 ready frame,多条命令复用同一进程,并在释放时干净退出;
120
+ - native monitor 要求 overlay 是该进程拥有的唯一 28x28 窗口、不会成为前台,且该进程 pid 不产生任何全局 pointer event;
121
+ - helper 必须包含 `SLEventPostToPid` 与 `CGEventSetWindowLocation`;
122
+ - 不携带已观察窗口 id 的坐标点击会按 Quartz 屏幕点解析应用窗口,结果仍报告 `pointerRouting: target-process`;
123
+ - `keyboardPolicy: activate` 会让后台 fixture 变为前台并收到按键事件,fixture transcript 记录这次激活;
124
+ - fixture 通过 `open -g` 与 `--background` 启动,LaunchServices 不会请求前台激活;
125
+ - fixture 记录每次 `applicationDidBecomeActive` 回调,默认路径不得增加 `activationCount`;
126
+ - 独立 native monitor 会在 click、scroll 与 drag 整个动作期间每毫秒采样系统光标和前台 pid,所有采样都必须保持不变;
127
+ - 后台 `AXPress`、Accessibility value/action、selected-text 输入与 pid 定向按键都能修改 fixture 且不激活它;
128
+ - native fixture 会插入无害 sibling 并重建一个带唯一 identifier 的 checkbox,证明原始 locator 已 stale,而 `AXIdentifier` resolution 仍只找到一个目标;
129
+ - 目标进程 click 与 scroll 各只被观察到一次;drag 只产生一组 down/up gesture;目标始终不是前台应用;
130
+ - `pointerInputPolicy: deny` 会在任何目标指针事件发出前拒绝 click fallback、scroll 与 drag;
131
+ - 干净 Profile 与真实模型验证要求模型可见动作结果和 fixture transcript 相互一致。
132
+
133
+ ## 已知限制
134
+
135
+ - 目标进程指针投递不如语义化 Accessibility 普适。自定义 canvas、游戏、强化输入 surface 或未来 macOS 变化可能拒绝该路由。
136
+ - 点击点必须落在选定应用的某个屏幕内窗口里;最小化、完全隐藏或无窗口目标会 fail closed。
137
+ - `focusPolicy: activate` 与 `keyboardPolicy: activate` 会有意打断前台工作,只作为操作方显式选择的兼容模式。
138
+ - 目标应用可能因接受动作而自行改变 activation 或 focus;helper 不承诺控制应用内部副作用。
139
+ - Agent 光标只属于当前 Space 和准确已观察窗口。`cursorAutoHideMs: 0` 会让它持续显示,直到绑定窗口变化、收到新的 hide 命令或 helper 被释放。
140
+ - Stable handle 当前只使用准确 locator、provider-native identifier 与严格 semantic identity。Semantic-spatial rebind 和 provider-native visual hit-test 留作后续;仅凭 vision 得到的坐标永远不是已验证目标。
@@ -0,0 +1,12 @@
1
+ /** Shared DSH approval-policy read for Computer Use permission paths. */
2
+ /**
3
+ * The session's effective DSH approval policy: a logged override, else the
4
+ * approval plugin's configured default.
5
+ * @param ctx - context with the approval service injected.
6
+ * @param agent - the agent whose session policy applies.
7
+ * @returns `'never'` when every approval ask would auto-reject without a prompt.
8
+ */
9
+ export function approvalPolicy(ctx, agent) {
10
+ return ctx.approval.overrideOf(agent.session) ?? ctx.approval.config.policy ?? 'ask';
11
+ }
12
+ //# sourceMappingURL=approval-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval-policy.js","sourceRoot":"","sources":["../src/approval-policy.ts"],"names":[],"mappings":"AAAA,yEAAyE;AAMzE;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,GAAY,EAAE,KAAY;IACvD,OAAO,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,IAAI,KAAK,CAAA;AACtF,CAAC"}
@@ -0,0 +1,79 @@
1
+ /** Workspace-fenced screenshot artifact allocation and validation. */
2
+ import { randomUUID } from 'node:crypto';
3
+ import { lstat, mkdir, realpath, stat } from 'node:fs/promises';
4
+ import { basename, isAbsolute, relative, resolve, sep } from 'node:path';
5
+ import { ComputerUseError } from "./errors.js";
6
+ /** Screenshot description that hands visual analysis to the sibling Vision Toolkit. */
7
+ export const COMPUTER_SCREENSHOT_DESCRIPTION = [
8
+ 'Current macOS application window observation.',
9
+ 'For OCR, visual grounding, or pixel inspection, load the vision-tools Skill and pass this exact path to vision_glance, vision_ground, vision_detect, or vision_crop;',
10
+ 'do not recreate OCR with bash, tesseract, or an ad hoc script.',
11
+ ].join(' ');
12
+ function isWithin(root, candidate) {
13
+ const rel = relative(root, candidate);
14
+ return rel === '' || (!rel.startsWith(`..${sep}`) && rel !== '..' && !isAbsolute(rel));
15
+ }
16
+ async function rejectSymlinkComponents(root, target) {
17
+ const rel = relative(root, target);
18
+ let current = root;
19
+ for (const part of rel.split(sep).filter(Boolean)) {
20
+ current = resolve(current, part);
21
+ try {
22
+ const info = await lstat(current);
23
+ if (info.isSymbolicLink()) {
24
+ throw new ComputerUseError('COMPUTER_PROVIDER_FAILURE', `artifact path component must not be a symbolic link: ${part}`);
25
+ }
26
+ }
27
+ catch (error) {
28
+ if (error instanceof ComputerUseError)
29
+ throw error;
30
+ const code = error.code;
31
+ if (code !== 'ENOENT')
32
+ throw error;
33
+ }
34
+ }
35
+ }
36
+ /** Allocate a unique managed PNG path inside the current Session workspace. */
37
+ export async function allocateScreenshotPath(workspace, artifactRoot, sessionId) {
38
+ const realWorkspace = await realpath(workspace);
39
+ const directory = resolve(realWorkspace, artifactRoot, String(sessionId));
40
+ if (!isWithin(realWorkspace, directory)) {
41
+ throw new ComputerUseError('COMPUTER_PROVIDER_FAILURE', 'artifactRoot escapes the Session workspace');
42
+ }
43
+ await rejectSymlinkComponents(realWorkspace, directory);
44
+ await mkdir(directory, { recursive: true, mode: 0o700 });
45
+ const realDirectory = await realpath(directory);
46
+ if (!isWithin(realWorkspace, realDirectory)) {
47
+ throw new ComputerUseError('COMPUTER_PROVIDER_FAILURE', 'artifact directory escaped the Session workspace');
48
+ }
49
+ return resolve(realDirectory, `observation-${randomUUID()}.png`);
50
+ }
51
+ /** Validate a committed screenshot and return its stable model/client descriptor. */
52
+ export async function describeScreenshot(path, width, height, maxBytes, sourceTool) {
53
+ const link = await lstat(path).catch((error) => {
54
+ throw new ComputerUseError('COMPUTER_PROVIDER_FAILURE', 'the screenshot artifact was not created', { cause: error });
55
+ });
56
+ if (link.isSymbolicLink() || !link.isFile()) {
57
+ throw new ComputerUseError('COMPUTER_PROVIDER_FAILURE', 'the screenshot artifact must be a regular non-symbolic-link file');
58
+ }
59
+ const info = await stat(path);
60
+ if (info.size > maxBytes) {
61
+ throw new ComputerUseError('COMPUTER_PROVIDER_FAILURE', `screenshot exceeds maxScreenshotBytes (${info.size} > ${maxBytes})`);
62
+ }
63
+ if (!Number.isInteger(width) || width <= 0 || !Number.isInteger(height) || height <= 0) {
64
+ throw new ComputerUseError('COMPUTER_PROVIDER_FAILURE', 'provider returned invalid screenshot dimensions');
65
+ }
66
+ return {
67
+ path,
68
+ filename: basename(path),
69
+ mimeType: 'image/png',
70
+ kind: 'image',
71
+ description: COMPUTER_SCREENSHOT_DESCRIPTION,
72
+ sourceTool,
73
+ previewIntent: 'image',
74
+ bytes: info.size,
75
+ width,
76
+ height,
77
+ };
78
+ }
79
+ //# sourceMappingURL=artifacts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../src/artifacts.ts"],"names":[],"mappings":"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"}
package/lib/backend.js ADDED
@@ -0,0 +1,3 @@
1
+ /** Provider-facing backend protocol kept below the public Computer Use Service. */
2
+ export {};
3
+ //# sourceMappingURL=backend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.js","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AAAA,mFAAmF"}