@momasiku/dsh-pilot 0.5.17 → 0.6.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/README.md +86 -13
- package/lib/index.js +190 -42
- package/lib/scripts/_dsh-action.ps1 +434 -425
- package/lib/scripts/_dsh-capture.ps1 +1 -1
- package/lib/scripts/_dsh-overlay.ps1 +301 -0
- package/lib/scripts/_dsh-uia.ps1 +1 -1
- package/lib/scripts/_dsh-win32.ps1 +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# pilot / _dsh-capture.ps1 - one capture, executed in whatever process called it.
|
|
1
|
+
# pilot / _dsh-capture.ps1 - one capture, executed in whatever process called it.
|
|
2
2
|
#
|
|
3
3
|
# Extracted from desktop-probe.ps1 so the same code serves two callers:
|
|
4
4
|
# * desktop-probe.ps1 - one frame per process (the fallback path);
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
|
|
2
|
+
# pilot / _dsh-overlay.ps1 - the visible part of a takeover.
|
|
3
|
+
#
|
|
4
|
+
# Ring around every monitor, a caption naming the operator, and a halo that follows
|
|
5
|
+
# the pointer so it is obvious the movement is not yours. Esc stamps the cancel token
|
|
6
|
+
# the host published.
|
|
7
|
+
#
|
|
8
|
+
# The halo is DRAWING, not the pointer itself: this process never calls SetCursorPos
|
|
9
|
+
# and never installs an input hook, because either would add exactly the input lag
|
|
10
|
+
# that makes a person's own mouse feel broken while an agent drives. Windows draws
|
|
11
|
+
# the real cursor above every window, so the ring and glow sit under it and the
|
|
12
|
+
# pointer reads as larger and lit without being replaced.
|
|
13
|
+
param(
|
|
14
|
+
[Parameter(Mandatory = $true)][string] $StateDir
|
|
15
|
+
)
|
|
16
|
+
$ErrorActionPreference = 'Stop'
|
|
17
|
+
|
|
18
|
+
Add-Type -AssemblyName PresentationFramework, PresentationCore, WindowsBase
|
|
19
|
+
Add-Type -TypeDefinition @"
|
|
20
|
+
using System;
|
|
21
|
+
using System.Runtime.InteropServices;
|
|
22
|
+
public class DshOv {
|
|
23
|
+
[StructLayout(LayoutKind.Sequential)] public struct POINT { public int X; public int Y; }
|
|
24
|
+
[DllImport("user32.dll")] public static extern bool GetCursorPos(out POINT p);
|
|
25
|
+
[DllImport("user32.dll")] public static extern int GetWindowLong(IntPtr h, int i);
|
|
26
|
+
[DllImport("user32.dll")] public static extern int SetWindowLong(IntPtr h, int i, int v);
|
|
27
|
+
[DllImport("user32.dll")] public static extern bool RegisterHotKey(IntPtr h, int id, uint mod, uint vk);
|
|
28
|
+
[DllImport("user32.dll")] public static extern bool UnregisterHotKey(IntPtr h, int id);
|
|
29
|
+
public const int GWL_EXSTYLE = -20;
|
|
30
|
+
public static void ClickThrough(IntPtr h) {
|
|
31
|
+
int ex = GetWindowLong(h, GWL_EXSTYLE);
|
|
32
|
+
SetWindowLong(h, GWL_EXSTYLE, ex | 0x20 | 0x80 | 0x08000000);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
"@
|
|
36
|
+
|
|
37
|
+
$showFile = Join-Path $StateDir 'show.txt'
|
|
38
|
+
$quitFile = Join-Path $StateDir 'quit.txt'
|
|
39
|
+
$hitFile = Join-Path $StateDir 'esc.txt'
|
|
40
|
+
$logFile = Join-Path $StateDir 'status.txt'
|
|
41
|
+
if (-not (Test-Path $StateDir)) { New-Item -ItemType Directory -Force -Path $StateDir | Out-Null }
|
|
42
|
+
function Log([string] $m) {
|
|
43
|
+
try { [System.IO.File]::AppendAllText($logFile, ((Get-Date).ToString('HH:mm:ss.fff') + ' ' + $m + [Environment]::NewLine)) } catch { }
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
$global:DshOvVsL = [System.Windows.SystemParameters]::VirtualScreenLeft
|
|
47
|
+
$global:DshOvVsT = [System.Windows.SystemParameters]::VirtualScreenTop
|
|
48
|
+
$vw = [System.Windows.SystemParameters]::VirtualScreenWidth
|
|
49
|
+
$vh = [System.Windows.SystemParameters]::VirtualScreenHeight
|
|
50
|
+
$unit = [Math]::Min($vw / 1920.0, $vh / 1080.0)
|
|
51
|
+
if ($unit -lt 0.75) { $unit = 0.75 }
|
|
52
|
+
|
|
53
|
+
$coreThickness = [Math]::Max(6, [Math]::Round(8 * $unit))
|
|
54
|
+
$glowThickness = [Math]::Max(18, [Math]::Round(36 * $unit))
|
|
55
|
+
$blurRadius = [Math]::Max(18, [Math]::Round(34 * $unit))
|
|
56
|
+
$radius = [Math]::Round(22 * $unit)
|
|
57
|
+
$fontSize = [Math]::Max(30, [Math]::Round(40 * $unit))
|
|
58
|
+
$spotD = [Math]::Round(120 * $unit)
|
|
59
|
+
$global:DshOvSpotD = $spotD
|
|
60
|
+
$haloD = [Math]::Round(58 * $unit)
|
|
61
|
+
|
|
62
|
+
function SB([int] $a, [int] $r, [int] $g, [int] $b) {
|
|
63
|
+
New-Object System.Windows.Media.SolidColorBrush ([System.Windows.Media.Color]::FromArgb($a, $r, $g, $b))
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
$window = New-Object System.Windows.Window
|
|
67
|
+
$window.WindowStyle = 'None'
|
|
68
|
+
$window.AllowsTransparency = $true
|
|
69
|
+
$window.Background = [System.Windows.Media.Brushes]::Transparent
|
|
70
|
+
$window.Topmost = $true
|
|
71
|
+
$window.ShowInTaskbar = $false
|
|
72
|
+
$window.ShowActivated = $false
|
|
73
|
+
$window.ResizeMode = 'NoResize'
|
|
74
|
+
$window.Left = $global:DshOvVsL
|
|
75
|
+
$window.Top = $global:DshOvVsT
|
|
76
|
+
$window.Width = $vw
|
|
77
|
+
$window.Height = $vh
|
|
78
|
+
|
|
79
|
+
$root = New-Object System.Windows.Controls.Grid
|
|
80
|
+
|
|
81
|
+
# ---- halo that follows the pointer ---------------------------------------
|
|
82
|
+
# Its own window, not a child of the ring window: a child Grid with runtime
|
|
83
|
+
# Margin never painted on this layered surface, while a window that is simply
|
|
84
|
+
# moved does. Moving a window is also cheaper than re-laying out a full-screen
|
|
85
|
+
# visual tree 30 times a second.
|
|
86
|
+
$haloWin = New-Object System.Windows.Window
|
|
87
|
+
$haloWin.WindowStyle = 'None'
|
|
88
|
+
$haloWin.AllowsTransparency = $true
|
|
89
|
+
$haloWin.Background = [System.Windows.Media.Brushes]::Transparent
|
|
90
|
+
$haloWin.Topmost = $true
|
|
91
|
+
$haloWin.ShowInTaskbar = $false
|
|
92
|
+
$haloWin.ShowActivated = $false
|
|
93
|
+
$haloWin.ResizeMode = 'NoResize'
|
|
94
|
+
$haloWin.Width = $spotD
|
|
95
|
+
$haloWin.Height = $spotD
|
|
96
|
+
$haloWin.Left = -10000
|
|
97
|
+
$haloWin.Top = -10000
|
|
98
|
+
|
|
99
|
+
$halo = New-Object System.Windows.Controls.Grid
|
|
100
|
+
$spot = New-Object System.Windows.Shapes.Ellipse
|
|
101
|
+
$spot.Width = $spotD
|
|
102
|
+
$spot.Height = $spotD
|
|
103
|
+
$spotFill = New-Object System.Windows.Media.RadialGradientBrush
|
|
104
|
+
$stop1 = New-Object System.Windows.Media.GradientStop ([System.Windows.Media.Color]::FromArgb(155, 70, 150, 255)), 0.0
|
|
105
|
+
$stop2 = New-Object System.Windows.Media.GradientStop ([System.Windows.Media.Color]::FromArgb(70, 70, 150, 255)), 0.55
|
|
106
|
+
$stop3 = New-Object System.Windows.Media.GradientStop ([System.Windows.Media.Color]::FromArgb(0, 70, 150, 255)), 1.0
|
|
107
|
+
$spotFill.GradientStops.Add($stop1) | Out-Null
|
|
108
|
+
$spotFill.GradientStops.Add($stop2) | Out-Null
|
|
109
|
+
$spotFill.GradientStops.Add($stop3) | Out-Null
|
|
110
|
+
$spot.Fill = $spotFill
|
|
111
|
+
$halo.Children.Add($spot) | Out-Null
|
|
112
|
+
|
|
113
|
+
$haloRing = New-Object System.Windows.Shapes.Ellipse
|
|
114
|
+
$haloRing.Width = $haloD
|
|
115
|
+
$haloRing.Height = $haloD
|
|
116
|
+
$haloRing.Stroke = SB 235 236 246 255
|
|
117
|
+
$haloRing.StrokeThickness = [Math]::Max(2, [Math]::Round(3 * $unit))
|
|
118
|
+
$haloRing.HorizontalAlignment = 'Center'
|
|
119
|
+
$haloRing.VerticalAlignment = 'Center'
|
|
120
|
+
$halo.Children.Add($haloRing) | Out-Null
|
|
121
|
+
|
|
122
|
+
$haloWin.Content = $halo
|
|
123
|
+
$haloWin.Add_SourceInitialized({
|
|
124
|
+
# This window sits exactly where the pointer is. Without WS_EX_TRANSPARENT it
|
|
125
|
+
# eats the very click it is drawn around.
|
|
126
|
+
$hh = (New-Object System.Windows.Interop.WindowInteropHelper($haloWin)).Handle
|
|
127
|
+
[DshOv]::ClickThrough($hh) | Out-Null
|
|
128
|
+
}.GetNewClosure())
|
|
129
|
+
$global:DshOvHaloWin = $haloWin
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
# ---- caption -------------------------------------------------------------
|
|
133
|
+
$sans = New-Object System.Windows.Media.FontFamily('Microsoft YaHei UI, Microsoft YaHei, Segoe UI Variable Display, Segoe UI')
|
|
134
|
+
$label = New-Object System.Windows.Controls.TextBlock
|
|
135
|
+
# Built from UTF-8 bytes on purpose: this file lost its BOM once and PowerShell
|
|
136
|
+
# 5.1 then read the literal as GBK, turning the caption into mojibake. Bytes cannot
|
|
137
|
+
# be mis-decoded.
|
|
138
|
+
$captionBytes = [byte[]]@(0x44,0x53,0x48,0x20,0xE6,0xAD,0xA3,0xE5,0x9C,0xA8,0xE6,0x93,0x8D,0xE4,0xBD,0x9C,0xE4,0xBD,0xA0,0xE7,0x9A,0x84,0xE7,0x94,0xB5,0xE8,0x84,0x91,0x20,0x20,0x20,0xE6,0x8C,0x89,0x20,0x45,0x73,0x63,0x20,0xE5,0x8F,0x96,0xE6,0xB6,0x88)
|
|
139
|
+
$label.Text = [System.Text.Encoding]::UTF8.GetString($captionBytes)
|
|
140
|
+
$label.FontSize = $fontSize
|
|
141
|
+
$label.FontFamily = $sans
|
|
142
|
+
$label.FontWeight = [System.Windows.FontWeights]::Bold
|
|
143
|
+
$label.Foreground = [System.Windows.Media.Brushes]::White
|
|
144
|
+
$label.Opacity = 0.9
|
|
145
|
+
$label.HorizontalAlignment = 'Center'
|
|
146
|
+
$label.VerticalAlignment = 'Top'
|
|
147
|
+
$label.Margin = [System.Windows.Thickness]::new(0, [Math]::Round(34 * $unit), 0, 0)
|
|
148
|
+
$capShadow = New-Object System.Windows.Media.Effects.DropShadowEffect
|
|
149
|
+
$capShadow.Color = [System.Windows.Media.Colors]::Black
|
|
150
|
+
$capShadow.BlurRadius = [Math]::Round(26 * $unit)
|
|
151
|
+
$capShadow.ShadowDepth = 3
|
|
152
|
+
$capShadow.Opacity = 0.9
|
|
153
|
+
$label.Effect = $capShadow
|
|
154
|
+
$root.Children.Add($label) | Out-Null
|
|
155
|
+
|
|
156
|
+
$window.Content = $root
|
|
157
|
+
|
|
158
|
+
$global:DshOvHwnd = [IntPtr]::Zero
|
|
159
|
+
$global:DshOvCancelTarget = ''
|
|
160
|
+
$global:DshOvStoppedFor = ''
|
|
161
|
+
$global:DshOvHotkeyOn = $false
|
|
162
|
+
|
|
163
|
+
function Enable-Hotkey {
|
|
164
|
+
if ($global:DshOvHotkeyOn -or $global:DshOvHwnd -eq [IntPtr]::Zero) { return }
|
|
165
|
+
$global:DshOvHotkeyOn = [DshOv]::RegisterHotKey($global:DshOvHwnd, 1, 0, 0x1B)
|
|
166
|
+
}
|
|
167
|
+
function Disable-Hotkey {
|
|
168
|
+
if (-not $global:DshOvHotkeyOn -or $global:DshOvHwnd -eq [IntPtr]::Zero) { return }
|
|
169
|
+
[DshOv]::UnregisterHotKey($global:DshOvHwnd, 1) | Out-Null
|
|
170
|
+
$global:DshOvHotkeyOn = $false
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function Stop-Takeover {
|
|
174
|
+
$global:DshOvStoppedFor = $global:DshOvCancelTarget
|
|
175
|
+
if ($global:DshOvCancelTarget -ne '') {
|
|
176
|
+
try { [System.IO.File]::WriteAllText($global:DshOvCancelTarget, 'stop', [System.Text.Encoding]::UTF8) } catch { }
|
|
177
|
+
}
|
|
178
|
+
try { [System.IO.File]::WriteAllText($hitFile, (Get-Date).ToString('o'), [System.Text.Encoding]::UTF8) } catch { }
|
|
179
|
+
if ($window.IsVisible) { $window.Hide(); Disable-Hotkey }
|
|
180
|
+
$global:DshOvCancelTarget = ''
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
$script:haloErrors = 0
|
|
184
|
+
function Update-Halo {
|
|
185
|
+
# No latching. A failed GetCursorPos (the desktop can be mid-switch between a
|
|
186
|
+
# locked and an active session) used to disable the halo for the rest of the
|
|
187
|
+
# process - which is exactly "it worked at first and then stopped".
|
|
188
|
+
try {
|
|
189
|
+
# The nested struct has to be named, not written as DshOv+POINT: unquoted,
|
|
190
|
+
# PowerShell reads the plus as arithmetic and the call throws on every tick.
|
|
191
|
+
$p = [DshOv+POINT]::new()
|
|
192
|
+
# A frozen position makes the halo verifiable without racing a human hand.
|
|
193
|
+
$freeze = Join-Path $StateDir 'freeze.txt'
|
|
194
|
+
$fx = $null
|
|
195
|
+
if (Test-Path -LiteralPath $freeze) {
|
|
196
|
+
try {
|
|
197
|
+
$parts = ([System.IO.File]::ReadAllText($freeze)).Trim() -split ','
|
|
198
|
+
if ($parts.Count -ge 2) { $fx = @([int] $parts[0], [int] $parts[1]) }
|
|
199
|
+
} catch { }
|
|
200
|
+
}
|
|
201
|
+
$ok = $false
|
|
202
|
+
if ($null -ne $fx) { $p.X = $fx[0]; $p.Y = $fx[1]; $ok = $true } else { $ok = [DshOv]::GetCursorPos([ref] $p) }
|
|
203
|
+
if ($ok) {
|
|
204
|
+
$h = $global:DshOvHaloWin
|
|
205
|
+
if ($null -eq $h) { if (-not $script:haloLogged) { $script:haloLogged = $true; Log 'halo missing' }; return }
|
|
206
|
+
$h.Left = $p.X - ($global:DshOvSpotD / 2)
|
|
207
|
+
$h.Top = $p.Y - ($global:DshOvSpotD / 2)
|
|
208
|
+
$script:haloMoves = [int] $script:haloMoves + 1
|
|
209
|
+
if ($script:haloMoves -le 3 -or ($script:haloMoves % 40) -eq 0) {
|
|
210
|
+
Log ("halo move " + $script:haloMoves + " -> " + $p.X + "," + $p.Y + " margin=" + $h.Margin.Left + "," + $h.Margin.Top)
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
} catch {
|
|
214
|
+
$script:haloErrors++
|
|
215
|
+
if ($script:haloErrors -le 3 -or ($script:haloErrors % 300) -eq 0) {
|
|
216
|
+
Log ("halo error " + $script:haloErrors + ": " + $_.Exception.Message)
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function Update-State {
|
|
222
|
+
$show = Test-Path -LiteralPath $showFile
|
|
223
|
+
if ($show) {
|
|
224
|
+
$raw = ''
|
|
225
|
+
try { $raw = [System.IO.File]::ReadAllText($showFile, [System.Text.Encoding]::UTF8).Trim() } catch { }
|
|
226
|
+
if ($raw -eq $global:DshOvStoppedFor) { $show = $false } else { $global:DshOvCancelTarget = $raw }
|
|
227
|
+
}
|
|
228
|
+
if ($show) {
|
|
229
|
+
if (-not $window.IsVisible) {
|
|
230
|
+
# The desktop can change size between shows (a reconnect, a display mode
|
|
231
|
+
# switch); re-fit rather than draw a 1080p ring on a 1600p desktop.
|
|
232
|
+
$w = [System.Windows.SystemParameters]::VirtualScreenWidth
|
|
233
|
+
$h = [System.Windows.SystemParameters]::VirtualScreenHeight
|
|
234
|
+
if ($window.Width -ne $w -or $window.Height -ne $h) {
|
|
235
|
+
$window.Left = [System.Windows.SystemParameters]::VirtualScreenLeft
|
|
236
|
+
$window.Top = [System.Windows.SystemParameters]::VirtualScreenTop
|
|
237
|
+
$window.Width = $w
|
|
238
|
+
$window.Height = $h
|
|
239
|
+
}
|
|
240
|
+
$window.Show(); Enable-Hotkey
|
|
241
|
+
if (-not $global:DshOvHaloWin.IsVisible) { $global:DshOvHaloWin.Show() }
|
|
242
|
+
Log ("shown " + $w + "x" + $h)
|
|
243
|
+
}
|
|
244
|
+
Update-Halo
|
|
245
|
+
} elseif ($window.IsVisible) {
|
|
246
|
+
$window.Hide()
|
|
247
|
+
if ($global:DshOvHaloWin.IsVisible) { $global:DshOvHaloWin.Hide() }
|
|
248
|
+
Disable-Hotkey
|
|
249
|
+
$global:DshOvCancelTarget = ''
|
|
250
|
+
}
|
|
251
|
+
if (Test-Path -LiteralPath $quitFile) { $window.Close() }
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
$window.Add_SourceInitialized({
|
|
255
|
+
$global:DshOvHwnd = (New-Object System.Windows.Interop.WindowInteropHelper($window)).Handle
|
|
256
|
+
[DshOv]::ClickThrough($global:DshOvHwnd) | Out-Null
|
|
257
|
+
$source = [System.Windows.Interop.HwndSource]::FromHwnd($global:DshOvHwnd)
|
|
258
|
+
$source.AddHook([System.Windows.Interop.HwndSourceHook]{
|
|
259
|
+
param($msgHwnd, $msg, $wParam, $lParam, [ref] $handled)
|
|
260
|
+
if ($msg -eq 0x0312 -and [int] $wParam -eq 1) { Stop-Takeover; $handled.Value = $true }
|
|
261
|
+
return [IntPtr]::Zero
|
|
262
|
+
})
|
|
263
|
+
}.GetNewClosure())
|
|
264
|
+
|
|
265
|
+
$haloWin.Add_Closed({ })
|
|
266
|
+
$window.Add_Closed({
|
|
267
|
+
if ($global:DshOvHaloWin.IsVisible) { $global:DshOvHaloWin.Close() }
|
|
268
|
+
if ($global:DshOvHwnd -ne [IntPtr]::Zero) { [DshOv]::UnregisterHotKey($global:DshOvHwnd, 1) | Out-Null }
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
# No parent watch: a host that dies leaves no trace to watch, and a false positive
|
|
272
|
+
# kills the ring the moment the launcher is a short-lived shell. An idle timeout
|
|
273
|
+
# bounds the leftover process without ever firing while it is in use.
|
|
274
|
+
$global:DshOvTicks = 0
|
|
275
|
+
$global:DshOvIdleTicks = 0
|
|
276
|
+
|
|
277
|
+
$timer = New-Object System.Windows.Threading.DispatcherTimer
|
|
278
|
+
$timer.Interval = [TimeSpan]::FromMilliseconds(33)
|
|
279
|
+
$timer.Add_Tick({
|
|
280
|
+
Update-State
|
|
281
|
+
$global:DshOvTicks++
|
|
282
|
+
if ($window.IsVisible) { $global:DshOvIdleTicks = 0 } else { $global:DshOvIdleTicks++ }
|
|
283
|
+
# 33 ms * 18000 = ~10 minutes hidden before the process gives the memory back.
|
|
284
|
+
if ($global:DshOvIdleTicks -gt 18000) { $window.Close() }
|
|
285
|
+
})
|
|
286
|
+
$timer.Start()
|
|
287
|
+
|
|
288
|
+
# Create the handle and strip activation BEFORE the first Show. Applying the
|
|
289
|
+
# extended style from SourceInitialized is too late: Windows has already offered
|
|
290
|
+
# the window the foreground by then, and a topmost window that takes focus breaks
|
|
291
|
+
# the very actions it is drawn for.
|
|
292
|
+
$pre = New-Object System.Windows.Interop.WindowInteropHelper($window)
|
|
293
|
+
$preHwnd = $pre.EnsureHandle()
|
|
294
|
+
[DshOv]::ClickThrough($preHwnd) | Out-Null
|
|
295
|
+
$preHalo = New-Object System.Windows.Interop.WindowInteropHelper($haloWin)
|
|
296
|
+
$preHaloHwnd = $preHalo.EnsureHandle()
|
|
297
|
+
[DshOv]::ClickThrough($preHaloHwnd) | Out-Null
|
|
298
|
+
|
|
299
|
+
$window.Show()
|
|
300
|
+
$window.Hide()
|
|
301
|
+
[System.Windows.Threading.Dispatcher]::Run()
|
package/lib/scripts/_dsh-uia.ps1
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# pilot / _dsh-uia.ps1 - read a window's UI Automation tree, and resolve a node by index.
|
|
1
|
+
# pilot / _dsh-uia.ps1 - read a window's UI Automation tree, and resolve a node by index.
|
|
2
2
|
#
|
|
3
3
|
# Why this exists: screen_view returns pixels. Finding a control in pixels costs the
|
|
4
4
|
# model a guess at coordinates plus another frame to confirm the guess. UI Automation
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# pilot / _dsh-win32.ps1 - the Win32 bridge and per-monitor DPI awareness, shared
|
|
1
|
+
# pilot / _dsh-win32.ps1 - the Win32 bridge and per-monitor DPI awareness, shared
|
|
2
2
|
# by the one-shot scripts and by the persistent worker.
|
|
3
3
|
#
|
|
4
4
|
# Every block is idempotent: a process that already has the type does not compile
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@momasiku/dsh-pilot",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Desktop vision and control for DeepSeek Harness - the whole Windows machine, any application, not browser automation: screen_view captures the live screen as an image the model can see, desktop_control drives the mouse, keyboard, and windows against the exact same pixel space; desktop_sequence runs a whole batch of actions in one call and looks once at the end.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "momasiku",
|