@anionex/dsh-computer-use 0.2.1 → 0.3.1
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/README.md +13 -7
- package/README.zh.md +13 -7
- package/cordis.patch.yml +3 -0
- package/docs/interaction-policy.md +6 -4
- package/docs/interaction-policy.zh.md +7 -5
- package/lib/client.js +31 -11
- package/lib/client.js.map +1 -1
- package/lib/config.js +13 -3
- package/lib/config.js.map +1 -1
- package/lib/providers/macos.js +79 -14
- package/lib/providers/macos.js.map +1 -1
- package/lib/providers/native-helper.js +240 -17
- package/lib/providers/native-helper.js.map +1 -1
- package/lib/providers/unsupported.js +6 -0
- package/lib/providers/unsupported.js.map +1 -1
- package/lib/service.js +74 -32
- package/lib/service.js.map +1 -1
- package/lib/types/backend.d.ts +18 -3
- package/lib/types/backend.d.ts.map +1 -1
- package/lib/types/client/index.d.ts +7 -2
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/config.d.ts +7 -1
- package/lib/types/config.d.ts.map +1 -1
- package/lib/types/providers/macos.d.ts +8 -2
- package/lib/types/providers/macos.d.ts.map +1 -1
- package/lib/types/providers/native-helper.d.ts +9 -1
- package/lib/types/providers/native-helper.d.ts.map +1 -1
- package/lib/types/providers/unsupported.d.ts +6 -2
- package/lib/types/providers/unsupported.d.ts.map +1 -1
- package/lib/types/service.d.ts.map +1 -1
- package/native/macos/Sources/Fixture/main.swift +46 -0
- package/native/macos/Sources/Helper/CursorMotion.swift +67 -0
- package/native/macos/Sources/Helper/CursorOverlay.swift +334 -60
- package/native/macos/Sources/Helper/TargetedPointer.swift +23 -10
- package/native/macos/Sources/Helper/main.swift +80 -5
- package/native/macos/Sources/Monitor/main.swift +15 -1
- package/native/macos/bin/dsh-computer-use-helper +0 -0
- package/native/macos/manifest.json +3 -3
- package/package.json +16 -18
- package/scripts/build-client.mjs +0 -0
- package/scripts/build-native.mjs +0 -0
- package/scripts/model-e2e.mjs +0 -0
- package/scripts/validate.mjs +0 -0
- package/src/backend.ts +18 -3
- package/src/client/index.tsx +50 -13
- package/src/config.ts +20 -4
- package/src/providers/macos.ts +102 -14
- package/src/providers/native-helper.ts +234 -17
- package/src/providers/unsupported.ts +11 -1
- package/src/service.ts +100 -37
|
@@ -70,6 +70,9 @@ private final class FixtureDelegate: NSObject, NSApplicationDelegate {
|
|
|
70
70
|
private var insertedHarmlessSibling = false
|
|
71
71
|
private var keyMonitor: Any?
|
|
72
72
|
private var reorderTimer: Timer?
|
|
73
|
+
private var activationTimer: Timer?
|
|
74
|
+
private var activationReleaseTimer: Timer?
|
|
75
|
+
private var activationHoldUntil: Date?
|
|
73
76
|
private var pointerClickCount = 0
|
|
74
77
|
private var pointerScrollCount = 0
|
|
75
78
|
private var pointerDragCount = 0
|
|
@@ -80,6 +83,9 @@ private final class FixtureDelegate: NSObject, NSApplicationDelegate {
|
|
|
80
83
|
private var activationCount = 0
|
|
81
84
|
private let transcriptPath: String?
|
|
82
85
|
private let reorderTriggerPath: String?
|
|
86
|
+
private let activationTriggerPath: String?
|
|
87
|
+
private let activationReleaseTriggerPath: String?
|
|
88
|
+
private let activationOnly: Bool
|
|
83
89
|
private let launchInBackground: Bool
|
|
84
90
|
|
|
85
91
|
override init() {
|
|
@@ -94,6 +100,17 @@ private final class FixtureDelegate: NSObject, NSApplicationDelegate {
|
|
|
94
100
|
} else {
|
|
95
101
|
reorderTriggerPath = nil
|
|
96
102
|
}
|
|
103
|
+
if let index = arguments.firstIndex(of: "--activation-trigger"), arguments.indices.contains(index + 1) {
|
|
104
|
+
activationTriggerPath = arguments[index + 1]
|
|
105
|
+
} else {
|
|
106
|
+
activationTriggerPath = nil
|
|
107
|
+
}
|
|
108
|
+
if let index = arguments.firstIndex(of: "--activation-release-trigger"), arguments.indices.contains(index + 1) {
|
|
109
|
+
activationReleaseTriggerPath = arguments[index + 1]
|
|
110
|
+
} else {
|
|
111
|
+
activationReleaseTriggerPath = nil
|
|
112
|
+
}
|
|
113
|
+
activationOnly = arguments.contains("--activation-only")
|
|
97
114
|
launchInBackground = arguments.contains("--background")
|
|
98
115
|
super.init()
|
|
99
116
|
}
|
|
@@ -113,6 +130,9 @@ private final class FixtureDelegate: NSObject, NSApplicationDelegate {
|
|
|
113
130
|
window.makeKeyAndOrderFront(nil)
|
|
114
131
|
}
|
|
115
132
|
writeTranscript(event: "ready")
|
|
133
|
+
if activationOnly {
|
|
134
|
+
activationHoldUntil = Date().addingTimeInterval(5)
|
|
135
|
+
}
|
|
116
136
|
if let reorderTriggerPath {
|
|
117
137
|
reorderTimer = Timer.scheduledTimer(withTimeInterval: 0.05, repeats: true) { [weak self] timer in
|
|
118
138
|
guard FileManager.default.fileExists(atPath: reorderTriggerPath) else { return }
|
|
@@ -120,6 +140,30 @@ private final class FixtureDelegate: NSObject, NSApplicationDelegate {
|
|
|
120
140
|
self?.insertHarmlessSibling()
|
|
121
141
|
}
|
|
122
142
|
}
|
|
143
|
+
if activationTriggerPath != nil || activationOnly {
|
|
144
|
+
activationTimer = Timer.scheduledTimer(withTimeInterval: 0.05, repeats: true) { [weak self] _ in
|
|
145
|
+
guard let self else { return }
|
|
146
|
+
if let activationTriggerPath,
|
|
147
|
+
FileManager.default.fileExists(atPath: activationTriggerPath) {
|
|
148
|
+
try? FileManager.default.removeItem(atPath: activationTriggerPath)
|
|
149
|
+
self.activationHoldUntil = Date().addingTimeInterval(5)
|
|
150
|
+
}
|
|
151
|
+
guard let holdUntil = self.activationHoldUntil else { return }
|
|
152
|
+
guard Date() < holdUntil else {
|
|
153
|
+
self.activationHoldUntil = nil
|
|
154
|
+
return
|
|
155
|
+
}
|
|
156
|
+
NSApplication.shared.activate(ignoringOtherApps: true)
|
|
157
|
+
self.window.makeKeyAndOrderFront(nil)
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if let activationReleaseTriggerPath {
|
|
161
|
+
activationReleaseTimer = Timer.scheduledTimer(withTimeInterval: 0.05, repeats: true) { [weak self] _ in
|
|
162
|
+
guard FileManager.default.fileExists(atPath: activationReleaseTriggerPath) else { return }
|
|
163
|
+
try? FileManager.default.removeItem(atPath: activationReleaseTriggerPath)
|
|
164
|
+
self?.activationHoldUntil = nil
|
|
165
|
+
}
|
|
166
|
+
}
|
|
123
167
|
}
|
|
124
168
|
|
|
125
169
|
func applicationDidBecomeActive(_ notification: Notification) {
|
|
@@ -130,6 +174,8 @@ private final class FixtureDelegate: NSObject, NSApplicationDelegate {
|
|
|
130
174
|
func applicationWillTerminate(_ notification: Notification) {
|
|
131
175
|
if let keyMonitor { NSEvent.removeMonitor(keyMonitor) }
|
|
132
176
|
reorderTimer?.invalidate()
|
|
177
|
+
activationTimer?.invalidate()
|
|
178
|
+
activationReleaseTimer?.invalidate()
|
|
133
179
|
}
|
|
134
180
|
|
|
135
181
|
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import CoreGraphics
|
|
2
|
+
import Foundation
|
|
3
|
+
|
|
4
|
+
private func rawCursorMotionDuration(distance: Double, speed: Double, acceleration: Double) -> Double {
|
|
5
|
+
let accelerationDistance = speed * speed / acceleration
|
|
6
|
+
if distance <= accelerationDistance {
|
|
7
|
+
return 2 * sqrt(distance / acceleration)
|
|
8
|
+
}
|
|
9
|
+
return 2 * speed / acceleration + (distance - accelerationDistance) / speed
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
func cursorMotionDuration(distance: Double, speed: Double, acceleration: Double) -> Double {
|
|
13
|
+
min(2, max(0.048, rawCursorMotionDuration(distance: distance, speed: speed, acceleration: acceleration)))
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
func cursorMotionFraction(
|
|
17
|
+
progress: Double,
|
|
18
|
+
distance: Double,
|
|
19
|
+
speed: Double,
|
|
20
|
+
acceleration: Double
|
|
21
|
+
) -> Double {
|
|
22
|
+
guard distance > 0 else { return 1 }
|
|
23
|
+
let rawDuration = rawCursorMotionDuration(distance: distance, speed: speed, acceleration: acceleration)
|
|
24
|
+
let elapsed = min(1, max(0, progress)) * rawDuration
|
|
25
|
+
let accelerationTime = min(speed / acceleration, rawDuration / 2)
|
|
26
|
+
let peakSpeed = acceleration * accelerationTime
|
|
27
|
+
let cruiseTime = max(0, rawDuration - 2 * accelerationTime)
|
|
28
|
+
let accelerationDistance = 0.5 * acceleration * accelerationTime * accelerationTime
|
|
29
|
+
let traveled: Double
|
|
30
|
+
if elapsed <= accelerationTime {
|
|
31
|
+
traveled = 0.5 * acceleration * elapsed * elapsed
|
|
32
|
+
} else if elapsed <= accelerationTime + cruiseTime {
|
|
33
|
+
traveled = accelerationDistance + peakSpeed * (elapsed - accelerationTime)
|
|
34
|
+
} else {
|
|
35
|
+
let remaining = rawDuration - elapsed
|
|
36
|
+
traveled = distance - 0.5 * acceleration * remaining * remaining
|
|
37
|
+
}
|
|
38
|
+
return min(1, max(0, traveled / distance))
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
func cursorMotionPoint(from origin: CGPoint, to target: CGPoint, fraction: Double) -> CGPoint {
|
|
42
|
+
let distance = hypot(target.x - origin.x, target.y - origin.y)
|
|
43
|
+
guard distance > 0 else { return target }
|
|
44
|
+
let delta = CGPoint(x: target.x - origin.x, y: target.y - origin.y)
|
|
45
|
+
let directionSign: CGFloat = Int(abs(origin.x + origin.y + target.x + target.y)) % 2 == 0 ? 1 : -1
|
|
46
|
+
let bend = min(18, distance * 0.06) * directionSign
|
|
47
|
+
let normal = CGPoint(x: -delta.y / distance, y: delta.x / distance)
|
|
48
|
+
let control1 = CGPoint(
|
|
49
|
+
x: origin.x + delta.x * 0.32 + normal.x * bend,
|
|
50
|
+
y: origin.y + delta.y * 0.32 + normal.y * bend
|
|
51
|
+
)
|
|
52
|
+
let control2 = CGPoint(
|
|
53
|
+
x: origin.x + delta.x * 0.72 + normal.x * bend * 0.45,
|
|
54
|
+
y: origin.y + delta.y * 0.72 + normal.y * bend * 0.45
|
|
55
|
+
)
|
|
56
|
+
let inverse = 1 - fraction
|
|
57
|
+
return CGPoint(
|
|
58
|
+
x: inverse * inverse * inverse * origin.x
|
|
59
|
+
+ 3 * inverse * inverse * fraction * control1.x
|
|
60
|
+
+ 3 * inverse * fraction * fraction * control2.x
|
|
61
|
+
+ fraction * fraction * fraction * target.x,
|
|
62
|
+
y: inverse * inverse * inverse * origin.y
|
|
63
|
+
+ 3 * inverse * inverse * fraction * control1.y
|
|
64
|
+
+ 3 * inverse * fraction * fraction * control2.y
|
|
65
|
+
+ fraction * fraction * fraction * target.y
|
|
66
|
+
)
|
|
67
|
+
}
|