@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.
- package/LICENSE +21 -0
- package/README.i18n.yaml +6 -0
- package/README.md +307 -0
- package/README.zh.md +307 -0
- package/assets/computer-use-fixture.png +0 -0
- package/assets/cursor.png +0 -0
- package/cordis.patch.yml +13 -0
- package/docs/interaction-policy.i18n.yaml +4 -0
- package/docs/interaction-policy.md +140 -0
- package/docs/interaction-policy.zh.md +140 -0
- package/lib/approval-policy.js +12 -0
- package/lib/approval-policy.js.map +1 -0
- package/lib/artifacts.js +79 -0
- package/lib/artifacts.js.map +1 -0
- package/lib/backend.js +3 -0
- package/lib/backend.js.map +1 -0
- package/lib/client.js +349 -0
- package/lib/client.js.map +1 -0
- package/lib/config.js +120 -0
- package/lib/config.js.map +1 -0
- package/lib/confirmations.js +99 -0
- package/lib/confirmations.js.map +1 -0
- package/lib/diff.js +58 -0
- package/lib/diff.js.map +1 -0
- package/lib/errors.js +22 -0
- package/lib/errors.js.map +1 -0
- package/lib/exposure.js +231 -0
- package/lib/exposure.js.map +1 -0
- package/lib/index.js +56 -0
- package/lib/index.js.map +1 -0
- package/lib/leases.js +259 -0
- package/lib/leases.js.map +1 -0
- package/lib/providers/macos.js +148 -0
- package/lib/providers/macos.js.map +1 -0
- package/lib/providers/native-helper.js +356 -0
- package/lib/providers/native-helper.js.map +1 -0
- package/lib/service.js +480 -0
- package/lib/service.js.map +1 -0
- package/lib/skill.js +119 -0
- package/lib/skill.js.map +1 -0
- package/lib/target-resolver.js +180 -0
- package/lib/target-resolver.js.map +1 -0
- package/lib/tools.js +493 -0
- package/lib/tools.js.map +1 -0
- package/lib/types/approval-policy.d.ts +13 -0
- package/lib/types/approval-policy.d.ts.map +1 -0
- package/lib/types/artifacts.d.ts +10 -0
- package/lib/types/artifacts.d.ts.map +1 -0
- package/lib/types/backend.d.ts +94 -0
- package/lib/types/backend.d.ts.map +1 -0
- package/lib/types/client/index.d.ts +78 -0
- package/lib/types/client/index.d.ts.map +1 -0
- package/lib/types/config.d.ts +75 -0
- package/lib/types/config.d.ts.map +1 -0
- package/lib/types/confirmations.d.ts +23 -0
- package/lib/types/confirmations.d.ts.map +1 -0
- package/lib/types/diff.d.ts +5 -0
- package/lib/types/diff.d.ts.map +1 -0
- package/lib/types/errors.d.ts +15 -0
- package/lib/types/errors.d.ts.map +1 -0
- package/lib/types/exposure.d.ts +30 -0
- package/lib/types/exposure.d.ts.map +1 -0
- package/lib/types/index.d.ts +21 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/leases.d.ts +80 -0
- package/lib/types/leases.d.ts.map +1 -0
- package/lib/types/providers/macos.d.ts +15 -0
- package/lib/types/providers/macos.d.ts.map +1 -0
- package/lib/types/providers/native-helper.d.ts +36 -0
- package/lib/types/providers/native-helper.d.ts.map +1 -0
- package/lib/types/service.d.ts +52 -0
- package/lib/types/service.d.ts.map +1 -0
- package/lib/types/skill.d.ts +9 -0
- package/lib/types/skill.d.ts.map +1 -0
- package/lib/types/target-resolver.d.ts +38 -0
- package/lib/types/target-resolver.d.ts.map +1 -0
- package/lib/types/tools.d.ts +6 -0
- package/lib/types/tools.d.ts.map +1 -0
- package/lib/types/types.d.ts +246 -0
- package/lib/types/types.d.ts.map +1 -0
- package/lib/types/web.d.ts +32 -0
- package/lib/types/web.d.ts.map +1 -0
- package/lib/types.js +9 -0
- package/lib/types.js.map +1 -0
- package/lib/web.js +163 -0
- package/lib/web.js.map +1 -0
- package/native/macos/Sources/Fixture/main.swift +366 -0
- package/native/macos/Sources/Helper/CursorImage.swift +11 -0
- package/native/macos/Sources/Helper/CursorOverlay.swift +488 -0
- package/native/macos/Sources/Helper/TargetedPointer.swift +314 -0
- package/native/macos/Sources/Helper/main.swift +1140 -0
- package/native/macos/Sources/Monitor/main.swift +139 -0
- package/native/macos/bin/dsh-computer-use-helper +0 -0
- package/native/macos/manifest.json +14 -0
- package/package.json +128 -0
- package/scripts/build-client.mjs +24 -0
- package/scripts/build-native.mjs +158 -0
- package/scripts/check-native.mjs +92 -0
- package/scripts/model-e2e.mjs +291 -0
- package/scripts/session-transcript.mjs +117 -0
- package/scripts/validate.mjs +256 -0
- package/src/approval-policy.ts +16 -0
- package/src/artifacts.ts +93 -0
- package/src/backend.ts +103 -0
- package/src/client/index.tsx +539 -0
- package/src/config.ts +196 -0
- package/src/confirmations.ts +128 -0
- package/src/diff.ts +52 -0
- package/src/errors.ts +39 -0
- package/src/exposure.ts +236 -0
- package/src/index.ts +66 -0
- package/src/leases.ts +337 -0
- package/src/providers/macos.ts +185 -0
- package/src/providers/native-helper.ts +393 -0
- package/src/service.ts +583 -0
- package/src/skill.ts +123 -0
- package/src/target-resolver.ts +237 -0
- package/src/tools.ts +528 -0
- package/src/types.ts +299 -0
- package/src/web.ts +180 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import CoreGraphics
|
|
2
|
+
import Darwin
|
|
3
|
+
import Foundation
|
|
4
|
+
|
|
5
|
+
struct TargetedPointerError: Error {
|
|
6
|
+
let message: String
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
struct TargetedPointerTarget {
|
|
10
|
+
let pid: pid_t
|
|
11
|
+
let windowNumber: Int64
|
|
12
|
+
let windowFrame: CGRect
|
|
13
|
+
|
|
14
|
+
func localPoint(for screenPoint: CGPoint) -> CGPoint {
|
|
15
|
+
CGPoint(
|
|
16
|
+
x: screenPoint.x - windowFrame.origin.x,
|
|
17
|
+
y: screenPoint.y - windowFrame.origin.y
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private typealias PostToPidFunction = @convention(c) (pid_t, UnsafeMutableRawPointer?) -> Void
|
|
23
|
+
private typealias SetIntegerFieldFunction = @convention(c) (UnsafeMutableRawPointer?, UInt32, Int64) -> Void
|
|
24
|
+
private typealias SetWindowLocationFunction = @convention(c) (UnsafeMutableRawPointer?, Double, Double) -> Void
|
|
25
|
+
|
|
26
|
+
private final class SkyLightPointerBridge {
|
|
27
|
+
static let shared = SkyLightPointerBridge()
|
|
28
|
+
|
|
29
|
+
private let handle: UnsafeMutableRawPointer?
|
|
30
|
+
private let postToPid: PostToPidFunction?
|
|
31
|
+
private let setIntegerField: SetIntegerFieldFunction?
|
|
32
|
+
private let setWindowLocation: SetWindowLocationFunction?
|
|
33
|
+
|
|
34
|
+
private init() {
|
|
35
|
+
handle = dlopen(
|
|
36
|
+
"/System/Library/PrivateFrameworks/SkyLight.framework/SkyLight",
|
|
37
|
+
RTLD_LAZY | RTLD_GLOBAL
|
|
38
|
+
)
|
|
39
|
+
postToPid = Self.resolve(handle, "SLEventPostToPid", as: PostToPidFunction.self)
|
|
40
|
+
setIntegerField = Self.resolve(handle, "SLEventSetIntegerValueField", as: SetIntegerFieldFunction.self)
|
|
41
|
+
setWindowLocation = Self.resolve(handle, "CGEventSetWindowLocation", as: SetWindowLocationFunction.self)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
deinit {
|
|
45
|
+
if let handle { dlclose(handle) }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private static func resolve<T>(_ handle: UnsafeMutableRawPointer?, _ name: String, as type: T.Type) -> T? {
|
|
49
|
+
guard let handle, let symbol = dlsym(handle, name) else { return nil }
|
|
50
|
+
return unsafeBitCast(symbol, to: type)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
var isAvailable: Bool {
|
|
54
|
+
postToPid != nil && setIntegerField != nil && setWindowLocation != nil
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
func post(
|
|
58
|
+
_ event: CGEvent,
|
|
59
|
+
target: TargetedPointerTarget,
|
|
60
|
+
localPoint: CGPoint,
|
|
61
|
+
clickState: Int64,
|
|
62
|
+
buttonNumber: Int64,
|
|
63
|
+
subtype: Int64,
|
|
64
|
+
gesturePhase: Int64,
|
|
65
|
+
clickGroup: Int64
|
|
66
|
+
) throws {
|
|
67
|
+
guard let postToPid, let setIntegerField, let setWindowLocation else {
|
|
68
|
+
throw TargetedPointerError(message: "SkyLight target-process pointer routing is unavailable")
|
|
69
|
+
}
|
|
70
|
+
let pointer = Unmanaged.passUnretained(event).toOpaque()
|
|
71
|
+
setWindowLocation(pointer, localPoint.x, localPoint.y)
|
|
72
|
+
setIntegerField(pointer, 0, gesturePhase)
|
|
73
|
+
setIntegerField(pointer, 1, clickState)
|
|
74
|
+
setIntegerField(pointer, 3, buttonNumber)
|
|
75
|
+
setIntegerField(pointer, 7, subtype)
|
|
76
|
+
setIntegerField(pointer, 40, Int64(target.pid))
|
|
77
|
+
setIntegerField(pointer, 51, target.windowNumber)
|
|
78
|
+
setIntegerField(pointer, 58, clickGroup)
|
|
79
|
+
setIntegerField(pointer, 91, target.windowNumber)
|
|
80
|
+
setIntegerField(pointer, 92, target.windowNumber)
|
|
81
|
+
|
|
82
|
+
postToPid(target.pid, pointer)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private func targetedPointerSource() throws -> CGEventSource {
|
|
87
|
+
guard SkyLightPointerBridge.shared.isAvailable else {
|
|
88
|
+
throw TargetedPointerError(message: "SkyLight target-process pointer routing is unavailable")
|
|
89
|
+
}
|
|
90
|
+
guard let source = CGEventSource(stateID: .privateState) else {
|
|
91
|
+
throw TargetedPointerError(message: "CoreGraphics pointer event source is unavailable")
|
|
92
|
+
}
|
|
93
|
+
return source
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private func clickGroup() -> Int64 {
|
|
97
|
+
Int64(DispatchTime.now().uptimeNanoseconds & 0x7fff_ffff)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private func buttonNumber(_ button: CGMouseButton) -> Int64 {
|
|
101
|
+
switch button {
|
|
102
|
+
case .right: return 1
|
|
103
|
+
case .center: return 2
|
|
104
|
+
default: return 0
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private func pointerEvent(
|
|
109
|
+
source: CGEventSource,
|
|
110
|
+
type: CGEventType,
|
|
111
|
+
button: CGMouseButton
|
|
112
|
+
) throws -> CGEvent {
|
|
113
|
+
let cursorLocation = CGEvent(source: nil)?.location ?? .zero
|
|
114
|
+
guard let event = CGEvent(
|
|
115
|
+
mouseEventSource: source,
|
|
116
|
+
mouseType: type,
|
|
117
|
+
mouseCursorPosition: cursorLocation,
|
|
118
|
+
mouseButton: button
|
|
119
|
+
) else {
|
|
120
|
+
throw TargetedPointerError(message: "CoreGraphics could not create a pointer event")
|
|
121
|
+
}
|
|
122
|
+
return event
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
private func postPointerEvent(
|
|
126
|
+
_ event: CGEvent,
|
|
127
|
+
target: TargetedPointerTarget,
|
|
128
|
+
point: CGPoint,
|
|
129
|
+
clickState: Int64,
|
|
130
|
+
buttonNumber: Int64,
|
|
131
|
+
subtype: Int64,
|
|
132
|
+
gesturePhase: Int64,
|
|
133
|
+
clickGroup: Int64
|
|
134
|
+
) throws {
|
|
135
|
+
try SkyLightPointerBridge.shared.post(
|
|
136
|
+
event,
|
|
137
|
+
target: target,
|
|
138
|
+
localPoint: target.localPoint(for: point),
|
|
139
|
+
clickState: clickState,
|
|
140
|
+
buttonNumber: buttonNumber,
|
|
141
|
+
subtype: subtype,
|
|
142
|
+
gesturePhase: gesturePhase,
|
|
143
|
+
clickGroup: clickGroup
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
func targetedClick(
|
|
148
|
+
at point: CGPoint,
|
|
149
|
+
button: CGMouseButton,
|
|
150
|
+
count: Int,
|
|
151
|
+
target: TargetedPointerTarget
|
|
152
|
+
) throws {
|
|
153
|
+
let source = try targetedPointerSource()
|
|
154
|
+
let group = clickGroup()
|
|
155
|
+
let number = buttonNumber(button)
|
|
156
|
+
let moved = try pointerEvent(source: source, type: .mouseMoved, button: .left)
|
|
157
|
+
try postPointerEvent(
|
|
158
|
+
moved,
|
|
159
|
+
target: target,
|
|
160
|
+
point: point,
|
|
161
|
+
clickState: 0,
|
|
162
|
+
buttonNumber: 0,
|
|
163
|
+
subtype: 3,
|
|
164
|
+
gesturePhase: 2,
|
|
165
|
+
clickGroup: group
|
|
166
|
+
)
|
|
167
|
+
usleep(12_000)
|
|
168
|
+
|
|
169
|
+
let downType: CGEventType = button == .right ? .rightMouseDown : button == .center ? .otherMouseDown : .leftMouseDown
|
|
170
|
+
let upType: CGEventType = button == .right ? .rightMouseUp : button == .center ? .otherMouseUp : .leftMouseUp
|
|
171
|
+
for pair in 1...max(1, count) {
|
|
172
|
+
let down = try pointerEvent(source: source, type: downType, button: button)
|
|
173
|
+
down.setDoubleValueField(.mouseEventPressure, value: 1)
|
|
174
|
+
try postPointerEvent(
|
|
175
|
+
down,
|
|
176
|
+
target: target,
|
|
177
|
+
point: point,
|
|
178
|
+
clickState: Int64(pair),
|
|
179
|
+
buttonNumber: number,
|
|
180
|
+
subtype: 3,
|
|
181
|
+
gesturePhase: 3,
|
|
182
|
+
clickGroup: group
|
|
183
|
+
)
|
|
184
|
+
usleep(28_000)
|
|
185
|
+
|
|
186
|
+
let up = try pointerEvent(source: source, type: upType, button: button)
|
|
187
|
+
up.setDoubleValueField(.mouseEventPressure, value: 0)
|
|
188
|
+
try postPointerEvent(
|
|
189
|
+
up,
|
|
190
|
+
target: target,
|
|
191
|
+
point: point,
|
|
192
|
+
clickState: Int64(pair),
|
|
193
|
+
buttonNumber: number,
|
|
194
|
+
subtype: 3,
|
|
195
|
+
gesturePhase: 3,
|
|
196
|
+
clickGroup: group
|
|
197
|
+
)
|
|
198
|
+
if pair < count { usleep(80_000) }
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
func targetedScroll(
|
|
203
|
+
at point: CGPoint,
|
|
204
|
+
vertical: Int32,
|
|
205
|
+
horizontal: Int32,
|
|
206
|
+
target: TargetedPointerTarget
|
|
207
|
+
) throws {
|
|
208
|
+
let source = try targetedPointerSource()
|
|
209
|
+
let group = clickGroup()
|
|
210
|
+
let moved = try pointerEvent(source: source, type: .mouseMoved, button: .left)
|
|
211
|
+
try postPointerEvent(
|
|
212
|
+
moved,
|
|
213
|
+
target: target,
|
|
214
|
+
point: point,
|
|
215
|
+
clickState: 0,
|
|
216
|
+
buttonNumber: 0,
|
|
217
|
+
subtype: 0,
|
|
218
|
+
gesturePhase: 2,
|
|
219
|
+
clickGroup: group
|
|
220
|
+
)
|
|
221
|
+
usleep(12_000)
|
|
222
|
+
|
|
223
|
+
guard let event = CGEvent(
|
|
224
|
+
scrollWheelEvent2Source: source,
|
|
225
|
+
units: .line,
|
|
226
|
+
wheelCount: 2,
|
|
227
|
+
wheel1: vertical,
|
|
228
|
+
wheel2: horizontal,
|
|
229
|
+
wheel3: 0
|
|
230
|
+
) else {
|
|
231
|
+
throw TargetedPointerError(message: "CoreGraphics could not create a scroll event")
|
|
232
|
+
}
|
|
233
|
+
event.location = CGEvent(source: nil)?.location ?? .zero
|
|
234
|
+
try postPointerEvent(
|
|
235
|
+
event,
|
|
236
|
+
target: target,
|
|
237
|
+
point: point,
|
|
238
|
+
clickState: 0,
|
|
239
|
+
buttonNumber: 0,
|
|
240
|
+
subtype: 0,
|
|
241
|
+
gesturePhase: 2,
|
|
242
|
+
clickGroup: group
|
|
243
|
+
)
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
func targetedDrag(
|
|
247
|
+
from: CGPoint,
|
|
248
|
+
to: CGPoint,
|
|
249
|
+
target: TargetedPointerTarget
|
|
250
|
+
) throws {
|
|
251
|
+
let source = try targetedPointerSource()
|
|
252
|
+
let group = clickGroup()
|
|
253
|
+
let moved = try pointerEvent(source: source, type: .mouseMoved, button: .left)
|
|
254
|
+
try postPointerEvent(
|
|
255
|
+
moved,
|
|
256
|
+
target: target,
|
|
257
|
+
point: from,
|
|
258
|
+
clickState: 0,
|
|
259
|
+
buttonNumber: 0,
|
|
260
|
+
subtype: 0,
|
|
261
|
+
gesturePhase: 2,
|
|
262
|
+
clickGroup: group
|
|
263
|
+
)
|
|
264
|
+
usleep(12_000)
|
|
265
|
+
|
|
266
|
+
let down = try pointerEvent(source: source, type: .leftMouseDown, button: .left)
|
|
267
|
+
down.setDoubleValueField(.mouseEventPressure, value: 1)
|
|
268
|
+
try postPointerEvent(
|
|
269
|
+
down,
|
|
270
|
+
target: target,
|
|
271
|
+
point: from,
|
|
272
|
+
clickState: 1,
|
|
273
|
+
buttonNumber: 0,
|
|
274
|
+
subtype: 0,
|
|
275
|
+
gesturePhase: 3,
|
|
276
|
+
clickGroup: group
|
|
277
|
+
)
|
|
278
|
+
usleep(16_000)
|
|
279
|
+
|
|
280
|
+
for step in 1...12 {
|
|
281
|
+
let fraction = CGFloat(step) / 12
|
|
282
|
+
let point = CGPoint(
|
|
283
|
+
x: from.x + (to.x - from.x) * fraction,
|
|
284
|
+
y: from.y + (to.y - from.y) * fraction
|
|
285
|
+
)
|
|
286
|
+
let dragged = try pointerEvent(source: source, type: .leftMouseDragged, button: .left)
|
|
287
|
+
dragged.setDoubleValueField(.mouseEventPressure, value: 1)
|
|
288
|
+
try postPointerEvent(
|
|
289
|
+
dragged,
|
|
290
|
+
target: target,
|
|
291
|
+
point: point,
|
|
292
|
+
clickState: 1,
|
|
293
|
+
buttonNumber: 0,
|
|
294
|
+
subtype: 0,
|
|
295
|
+
gesturePhase: 3,
|
|
296
|
+
clickGroup: group
|
|
297
|
+
)
|
|
298
|
+
usleep(12_000)
|
|
299
|
+
}
|
|
300
|
+
usleep(50_000)
|
|
301
|
+
|
|
302
|
+
let up = try pointerEvent(source: source, type: .leftMouseUp, button: .left)
|
|
303
|
+
up.setDoubleValueField(.mouseEventPressure, value: 0)
|
|
304
|
+
try postPointerEvent(
|
|
305
|
+
up,
|
|
306
|
+
target: target,
|
|
307
|
+
point: to,
|
|
308
|
+
clickState: 1,
|
|
309
|
+
buttonNumber: 0,
|
|
310
|
+
subtype: 0,
|
|
311
|
+
gesturePhase: 3,
|
|
312
|
+
clickGroup: group
|
|
313
|
+
)
|
|
314
|
+
}
|