mindweave 3.2.2 → 3.2.4
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/dist/cli/App.js +37 -7
- package/dist/cli/App.js.map +1 -1
- package/dist/cli/agentLines.js +196 -0
- package/dist/cli/agentLines.js.map +1 -0
- package/dist/cli/approvalText.js +31 -0
- package/dist/cli/approvalText.js.map +1 -0
- package/dist/cli/components/BlockView.js +1 -1
- package/dist/cli/components/BlockView.js.map +1 -1
- package/dist/cli/components/SubagentView.js +43 -74
- package/dist/cli/components/SubagentView.js.map +1 -1
- package/dist/cli/components/WorkGroup.js +1 -1
- package/dist/cli/components/WorkGroup.js.map +1 -1
- package/dist/cli/help.js +3 -1
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/transcript.js +13 -3
- package/dist/cli/transcript.js.map +1 -1
- package/dist/core/turnRunner.js +2 -2
- package/dist/core/turnRunner.js.map +1 -1
- package/dist/dynamo/engine.js +28 -4
- package/dist/dynamo/engine.js.map +1 -1
- package/dist/dynamo/guard.js +6 -0
- package/dist/dynamo/guard.js.map +1 -1
- package/dist/dynamo/marathon.js +22 -4
- package/dist/dynamo/marathon.js.map +1 -1
- package/dist/memory/compaction.js +60 -6
- package/dist/memory/compaction.js.map +1 -1
- package/dist/memory/session.js +2 -0
- package/dist/memory/session.js.map +1 -1
- package/dist/tools/childReport.js +44 -0
- package/dist/tools/childReport.js.map +1 -0
- package/dist/tools/guard.js +9 -2
- package/dist/tools/guard.js.map +1 -1
- package/dist/tools/registry.js +1 -1
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/runCommand.js +92 -56
- package/dist/tools/runCommand.js.map +1 -1
- package/dist/tools/screenshot.js +28 -9
- package/dist/tools/screenshot.js.map +1 -1
- package/dist/tools/screenshotWin.js +258 -175
- package/dist/tools/screenshotWin.js.map +1 -1
- package/dist/tools/subagent.js +73 -31
- package/dist/tools/subagent.js.map +1 -1
- package/dist/tools/subagentOutcome.js +27 -0
- package/dist/tools/subagentOutcome.js.map +1 -0
- package/dist/tools/treeGuard.js +164 -0
- package/dist/tools/treeGuard.js.map +1 -0
- package/dist/tools/ui.js +32 -1
- package/dist/tools/ui.js.map +1 -1
- package/dist/tools/uiHide.js +19 -6
- package/dist/tools/uiHide.js.map +1 -1
- package/dist/tools/verifierCommands.js +188 -0
- package/dist/tools/verifierCommands.js.map +1 -0
- package/dist/tools/verifierRun.js +88 -0
- package/dist/tools/verifierRun.js.map +1 -0
- package/dist/tools/verifierTools.js +19 -0
- package/dist/tools/verifierTools.js.map +1 -0
- package/dist/tools/verifyReport.js +79 -9
- package/dist/tools/verifyReport.js.map +1 -1
- package/package.json +3 -3
|
@@ -42,176 +42,221 @@ import { tmpdir } from "node:os";
|
|
|
42
42
|
import { join } from "node:path";
|
|
43
43
|
import { DESK_CS, HIDDEN_MARK, hiddenDesktopName, windowArgs } from "./hiddenDesktop.js";
|
|
44
44
|
const PS_TIMEOUT_MS = 20_000;
|
|
45
|
-
const SCRIPT = String.raw `
|
|
46
|
-
param([string]$Mode = "list", [string]$Handle = "", [string]$Out = "", [string]$Desktop = "", [string]$Hidden = "")
|
|
47
|
-
$ErrorActionPreference = "Stop"
|
|
48
|
-
Add-Type -AssemblyName System.Drawing
|
|
49
|
-
|
|
50
|
-
Add-Type -ReferencedAssemblies System.Drawing -TypeDefinition @"
|
|
51
|
-
using System;
|
|
52
|
-
using System.Collections.Generic;
|
|
53
|
-
using System.Drawing;
|
|
54
|
-
using System.Drawing.Imaging;
|
|
55
|
-
using System.Runtime.InteropServices;
|
|
56
|
-
using System.Text;
|
|
57
|
-
|
|
58
|
-
public static class MwCapture {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
[DllImport("user32.dll"
|
|
64
|
-
[DllImport("user32.dll"
|
|
65
|
-
[DllImport("user32.dll")] static extern bool
|
|
66
|
-
[DllImport("user32.dll")] static extern
|
|
67
|
-
[DllImport("user32.dll")] static extern
|
|
68
|
-
[DllImport("user32.dll")]
|
|
69
|
-
[DllImport("user32.dll")] static extern
|
|
70
|
-
[DllImport("user32.dll")] static extern
|
|
71
|
-
[DllImport("
|
|
72
|
-
[DllImport("
|
|
73
|
-
|
|
74
|
-
[
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
static
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
static
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
45
|
+
const SCRIPT = String.raw `
|
|
46
|
+
param([string]$Mode = "list", [string]$Handle = "", [string]$Out = "", [string]$Desktop = "", [string]$Hidden = "", [int]$Owner = 0)
|
|
47
|
+
$ErrorActionPreference = "Stop"
|
|
48
|
+
Add-Type -AssemblyName System.Drawing
|
|
49
|
+
|
|
50
|
+
Add-Type -ReferencedAssemblies System.Drawing -TypeDefinition @"
|
|
51
|
+
using System;
|
|
52
|
+
using System.Collections.Generic;
|
|
53
|
+
using System.Drawing;
|
|
54
|
+
using System.Drawing.Imaging;
|
|
55
|
+
using System.Runtime.InteropServices;
|
|
56
|
+
using System.Text;
|
|
57
|
+
|
|
58
|
+
public static class MwCapture {
|
|
59
|
+
// The processes this one runs inside (the terminal, its console host, the app hosting it).
|
|
60
|
+
// Their windows are marked "host" in the list, so the caller can tell them from the app under test.
|
|
61
|
+
public static HashSet<uint> HostPids = new HashSet<uint>();
|
|
62
|
+
delegate bool EnumProc(IntPtr hWnd, IntPtr lParam);
|
|
63
|
+
[DllImport("user32.dll")] static extern bool EnumWindows(EnumProc cb, IntPtr l);
|
|
64
|
+
[DllImport("user32.dll")] static extern bool IsWindowVisible(IntPtr h);
|
|
65
|
+
[DllImport("user32.dll")] static extern bool IsIconic(IntPtr h);
|
|
66
|
+
[DllImport("user32.dll", CharSet = CharSet.Unicode)] static extern int GetWindowTextLength(IntPtr h);
|
|
67
|
+
[DllImport("user32.dll", CharSet = CharSet.Unicode)] static extern int GetWindowText(IntPtr h, StringBuilder s, int n);
|
|
68
|
+
[DllImport("user32.dll")] static extern bool PrintWindow(IntPtr h, IntPtr hdc, uint flags);
|
|
69
|
+
[DllImport("user32.dll")] static extern bool SetProcessDPIAware();
|
|
70
|
+
[DllImport("user32.dll")] static extern bool GetWindowRect(IntPtr h, out RECT r);
|
|
71
|
+
[DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow();
|
|
72
|
+
[DllImport("user32.dll")] static extern uint GetWindowThreadProcessId(IntPtr h, out uint pid);
|
|
73
|
+
[DllImport("user32.dll")] static extern int GetWindowLong(IntPtr h, int index);
|
|
74
|
+
[DllImport("dwmapi.dll")] static extern int DwmGetWindowAttribute(IntPtr h, int attr, out RECT r, int size);
|
|
75
|
+
[DllImport("dwmapi.dll", EntryPoint = "DwmGetWindowAttribute")] static extern int DwmGetIntAttribute(IntPtr h, int attr, out int v, int size);
|
|
76
|
+
|
|
77
|
+
[StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left, Top, Right, Bottom; }
|
|
78
|
+
|
|
79
|
+
public static void Dpi() { SetProcessDPIAware(); }
|
|
80
|
+
|
|
81
|
+
[DllImport("kernel32.dll")] static extern IntPtr GetConsoleWindow();
|
|
82
|
+
[DllImport("user32.dll")] static extern IntPtr GetAncestor(IntPtr h, uint flags);
|
|
83
|
+
|
|
84
|
+
// The window the console this process is attached to is drawn in. In Windows Terminal the console
|
|
85
|
+
// window is a hidden stand-in owned by the real top-level window, so the owner is what is returned.
|
|
86
|
+
// Empty when there is no console (the desktop app, a service).
|
|
87
|
+
public static string HostWindow() {
|
|
88
|
+
IntPtr c = GetConsoleWindow();
|
|
89
|
+
if (c == IntPtr.Zero) return "";
|
|
90
|
+
IntPtr root = GetAncestor(c, 3 /* GA_ROOTOWNER */);
|
|
91
|
+
return (root == IntPtr.Zero ? c : root).ToInt64().ToString();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// A DWM-cloaked window passes IsWindowVisible but is not actually on screen — the
|
|
95
|
+
// invisible UWP and host windows that would otherwise flood the list. Any failure to
|
|
96
|
+
// read the attribute is treated as not-cloaked, so a window is never dropped on error.
|
|
97
|
+
static bool Cloaked(IntPtr h) {
|
|
98
|
+
int v;
|
|
99
|
+
return DwmGetIntAttribute(h, 14 /* DWMWA_CLOAKED */, out v, sizeof(int)) == 0 && v != 0;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// The Shell's own "is this an Alt-Tab window" test: a tool window is a palette or
|
|
103
|
+
// tray surface and is never what "the app" means, unless it also asks for the taskbar.
|
|
104
|
+
static bool AltTabWorthy(IntPtr h) {
|
|
105
|
+
int ex = GetWindowLong(h, -20 /* GWL_EXSTYLE */);
|
|
106
|
+
bool tool = (ex & 0x00000080) != 0; // WS_EX_TOOLWINDOW
|
|
107
|
+
bool app = (ex & 0x00040000) != 0; // WS_EX_APPWINDOW
|
|
108
|
+
return !tool || app;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// The window's process name, for a window that has no title of its own. Wrapped
|
|
112
|
+
// because the process can exit between the enum and the lookup.
|
|
113
|
+
static string ProcName(IntPtr h) {
|
|
114
|
+
try {
|
|
115
|
+
uint pid;
|
|
116
|
+
GetWindowThreadProcessId(h, out pid);
|
|
117
|
+
if (pid == 0) return "";
|
|
118
|
+
using (var p = System.Diagnostics.Process.GetProcessById((int)pid)) return p.ProcessName;
|
|
119
|
+
} catch { return ""; }
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// DWMWA_EXTENDED_FRAME_BOUNDS. GetWindowRect includes an invisible border on
|
|
123
|
+
// Windows 10+, so it is the fallback rather than the first choice.
|
|
124
|
+
static bool Bounds(IntPtr h, out RECT r) {
|
|
125
|
+
if (DwmGetWindowAttribute(h, 9, out r, Marshal.SizeOf(typeof(RECT))) == 0
|
|
126
|
+
&& r.Right > r.Left && r.Bottom > r.Top) return true;
|
|
127
|
+
return GetWindowRect(h, out r);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// The hidden desktop's windows are marked, so a capture is sent back there.
|
|
131
|
+
public static string ListOn(string desk) {
|
|
132
|
+
return MwDesk.On(desk, () => string.Join("\n", List("${HIDDEN_MARK}").ToArray()));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
public static List<string> List(string mark) {
|
|
136
|
+
var found = new List<string>();
|
|
137
|
+
IntPtr fg = GetForegroundWindow();
|
|
138
|
+
EnumWindows(delegate(IntPtr h, IntPtr l) {
|
|
139
|
+
if (!IsWindowVisible(h) || IsIconic(h)) return true;
|
|
140
|
+
if (Cloaked(h) || !AltTabWorthy(h)) return true;
|
|
141
|
+
RECT r;
|
|
142
|
+
if (!Bounds(h, out r)) return true;
|
|
143
|
+
// Tool windows and tray hosts are real but never what anyone means.
|
|
144
|
+
if (r.Right - r.Left < 120 || r.Bottom - r.Top < 120) return true;
|
|
145
|
+
int len = GetWindowTextLength(h);
|
|
146
|
+
string title = "";
|
|
147
|
+
if (len > 0) {
|
|
148
|
+
var sb = new StringBuilder(len + 1);
|
|
149
|
+
GetWindowText(h, sb, sb.Capacity);
|
|
150
|
+
title = sb.ToString().Trim();
|
|
151
|
+
}
|
|
152
|
+
// An empty title is NOT a reason to drop the window. A custom title bar
|
|
153
|
+
// (Tauri or Electron with decorations off) leaves the OS title blank, as does
|
|
154
|
+
// an app whose web content has not set document.title yet — and dropping it
|
|
155
|
+
// makes a window the user is plainly looking at impossible to capture, by name
|
|
156
|
+
// OR as the foreground. Label it by its process so it stays nameable.
|
|
157
|
+
if (title.Length == 0) {
|
|
158
|
+
string pn = ProcName(h);
|
|
159
|
+
title = pn.Length > 0 ? pn : "(untitled window)";
|
|
160
|
+
}
|
|
161
|
+
// The leading marker is how the caller knows which window the user is
|
|
162
|
+
// actually looking at, so it can name it when asking permission.
|
|
163
|
+
uint wpid; GetWindowThreadProcessId(h, out wpid);
|
|
164
|
+
string hostCol = mark.Length == 0 && HostPids.Contains(wpid) ? "\thost" : "";
|
|
165
|
+
found.Add((h == fg && mark.Length == 0 ? "*" : "-") + mark + h.ToInt64().ToString() + "\t" + title + hostCol);
|
|
166
|
+
return true;
|
|
167
|
+
}, IntPtr.Zero);
|
|
168
|
+
return found;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
public static string CaptureOn(string desk, IntPtr h, string path) {
|
|
172
|
+
return MwDesk.On(desk, () => Capture(h, path, string.IsNullOrEmpty(desk)));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// screen: whether a blank PrintWindow may fall back to copying the screen. Never for a
|
|
176
|
+
// window on the hidden desktop: the screen is the USER's, and that window is not on it.
|
|
177
|
+
public static string Capture(IntPtr h, string path, bool screen) {
|
|
178
|
+
RECT r;
|
|
179
|
+
if (!Bounds(h, out r)) return "ERR could not measure the window";
|
|
180
|
+
int w = r.Right - r.Left, ht = r.Bottom - r.Top;
|
|
181
|
+
if (w <= 0 || ht <= 0) return "ERR the window has no visible area";
|
|
182
|
+
using (var bmp = new Bitmap(w, ht)) {
|
|
183
|
+
bool drew = false;
|
|
184
|
+
using (var g = Graphics.FromImage(bmp)) {
|
|
185
|
+
IntPtr hdc = g.GetHdc();
|
|
186
|
+
drew = PrintWindow(h, hdc, 2); // PW_RENDERFULLCONTENT
|
|
187
|
+
g.ReleaseHdc(hdc);
|
|
188
|
+
}
|
|
189
|
+
if (!drew || Blank(bmp)) {
|
|
190
|
+
if (!screen) return "ERR the window drew nothing to capture";
|
|
191
|
+
using (var g = Graphics.FromImage(bmp)) {
|
|
192
|
+
g.CopyFromScreen(r.Left, r.Top, 0, 0, new Size(w, ht));
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
bmp.Save(path, ImageFormat.Png);
|
|
196
|
+
return "OK " + w + " " + ht;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// PrintWindow can report success and draw nothing. Sampling three corners of a
|
|
201
|
+
// fully transparent bitmap is enough to tell that apart from a real capture.
|
|
202
|
+
static bool Blank(Bitmap b) {
|
|
203
|
+
if (b.Width < 4 || b.Height < 4) return false;
|
|
204
|
+
return b.GetPixel(1, 1).A == 0
|
|
205
|
+
&& b.GetPixel(b.Width / 2, b.Height / 2).A == 0
|
|
206
|
+
&& b.GetPixel(b.Width - 2, b.Height - 2).A == 0;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
${DESK_CS}
|
|
210
|
+
"@
|
|
211
|
+
|
|
212
|
+
# Before any measurement, or every rectangle is in the wrong coordinate space.
|
|
213
|
+
[MwCapture]::Dpi() | Out-Null
|
|
214
|
+
|
|
215
|
+
if ($Mode -eq "host") {
|
|
216
|
+
Write-Output ([MwCapture]::HostWindow())
|
|
217
|
+
exit 0
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if ($Mode -eq "list") {
|
|
221
|
+
# Which windows are the one this process runs in: walk up from it, stopping at the shell that
|
|
222
|
+
# started the whole session (the desktop, services), and take each console host that belongs to
|
|
223
|
+
# one of those on the way. Every process passed may own the window.
|
|
224
|
+
if ($Owner -gt 0) {
|
|
225
|
+
$procs = Get-CimInstance Win32_Process -Property ProcessId, ParentProcessId, Name
|
|
226
|
+
$parent = @{}
|
|
227
|
+
$name = @{}
|
|
228
|
+
foreach ($p in $procs) { $parent[[int]$p.ProcessId] = [int]$p.ParentProcessId; $name[[int]$p.ProcessId] = ([string]$p.Name).ToLower() }
|
|
229
|
+
$stop = @("explorer.exe", "services.exe", "wininit.exe", "winlogon.exe", "csrss.exe", "svchost.exe", "system")
|
|
230
|
+
$seen = @{}
|
|
231
|
+
$at = $Owner
|
|
232
|
+
while ($at -gt 0 -and -not $seen.ContainsKey($at)) {
|
|
233
|
+
$seen[$at] = $true
|
|
234
|
+
if ($stop -contains $name[$at]) { break }
|
|
235
|
+
[void][MwCapture]::HostPids.Add([uint32]$at)
|
|
236
|
+
$at = $parent[$at]
|
|
237
|
+
}
|
|
238
|
+
foreach ($p in $procs) {
|
|
239
|
+
$n = ([string]$p.Name).ToLower()
|
|
240
|
+
if (($n -eq "conhost.exe" -or $n -eq "openconsole.exe") -and [MwCapture]::HostPids.Contains([uint32]$p.ParentProcessId)) { [void][MwCapture]::HostPids.Add([uint32]$p.ProcessId) }
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
[MwCapture]::List("") | ForEach-Object { Write-Output $_ }
|
|
244
|
+
# The windows of apps started for testing, which are never on the screen.
|
|
245
|
+
if ($Hidden -and [MwDesk]::Exists($Hidden)) { Write-Output ([MwCapture]::ListOn($Hidden)) }
|
|
246
|
+
exit 0
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if ($Mode -eq "capture") {
|
|
250
|
+
$h = if ($Handle -eq "foreground") { [MwCapture]::GetForegroundWindow() } else { [IntPtr][Int64]$Handle }
|
|
251
|
+
if ($h -eq [IntPtr]::Zero) { Write-Output "ERR no such window"; exit 1 }
|
|
252
|
+
$r = [MwCapture]::CaptureOn($Desktop, $h, $Out)
|
|
253
|
+
Write-Output $r
|
|
254
|
+
if ($r.StartsWith("ERR")) { exit 1 }
|
|
255
|
+
exit 0
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
Write-Output "ERR unknown mode"
|
|
259
|
+
exit 1
|
|
215
260
|
`;
|
|
216
261
|
let scriptPath = null;
|
|
217
262
|
/** Write the capture script to a temp file once per process. */
|
|
@@ -225,10 +270,12 @@ async function ensureScript() {
|
|
|
225
270
|
return path;
|
|
226
271
|
}
|
|
227
272
|
/** Run the script in one of its two modes. Rejects with the script's own message. */
|
|
228
|
-
async function runScript(args, signal) {
|
|
273
|
+
async function runScript(args, signal, shareConsole = false) {
|
|
229
274
|
const script = await ensureScript();
|
|
230
275
|
return await new Promise((resolve, reject) => {
|
|
231
|
-
const child = spawn("powershell.exe", ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-File", script, ...args],
|
|
276
|
+
const child = spawn("powershell.exe", ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-File", script, ...args],
|
|
277
|
+
// Hidden, with a console of its own, unless it must see THIS process's console (see hostWindowHandle).
|
|
278
|
+
shareConsole ? { stdio: ["ignore", "pipe", "pipe"] } : { windowsHide: true });
|
|
232
279
|
let out = "";
|
|
233
280
|
let err = "";
|
|
234
281
|
const timer = setTimeout(() => {
|
|
@@ -269,11 +316,14 @@ export function parseWindowList(stdout) {
|
|
|
269
316
|
if (tab <= 0)
|
|
270
317
|
continue;
|
|
271
318
|
const marked = line.slice(0, tab).trim();
|
|
272
|
-
|
|
319
|
+
// A third column, "host", marks the window this process runs in.
|
|
320
|
+
const rest = line.slice(tab + 1).split("\t");
|
|
321
|
+
const host = rest.length > 1 && rest[rest.length - 1].trim() === "host";
|
|
322
|
+
const title = (host ? rest.slice(0, -1) : rest).join("\t").trim();
|
|
273
323
|
const match = new RegExp(`^([*-])(${HIDDEN_MARK}?\\d+)$`).exec(marked);
|
|
274
324
|
if (!match || !title)
|
|
275
325
|
continue;
|
|
276
|
-
windows.push({ handle: match[2], title, foreground: match[1] === "*" });
|
|
326
|
+
windows.push({ handle: match[2], title, foreground: match[1] === "*", ...(host ? { host: true } : {}) });
|
|
277
327
|
}
|
|
278
328
|
return windows;
|
|
279
329
|
}
|
|
@@ -283,7 +333,40 @@ export function parseWindowList(stdout) {
|
|
|
283
333
|
* title (a custom title bar) kept and labelled by its process rather than dropped.
|
|
284
334
|
*/
|
|
285
335
|
export async function listWindows(signal) {
|
|
286
|
-
|
|
336
|
+
const [raw, host] = await Promise.all([
|
|
337
|
+
runScript(["-Mode", "list", "-Hidden", hiddenDesktopName(), "-Owner", String(process.pid)], signal),
|
|
338
|
+
hostWindowHandle(signal),
|
|
339
|
+
]);
|
|
340
|
+
const windows = parseWindowList(raw);
|
|
341
|
+
// The terminal's own window: found from the console this process is attached to, which the list cannot see
|
|
342
|
+
// (Windows Terminal is not a parent of the shell, only the owner of its window).
|
|
343
|
+
if (host)
|
|
344
|
+
for (const w of windows)
|
|
345
|
+
if (w.handle === host)
|
|
346
|
+
w.host = true;
|
|
347
|
+
return windows;
|
|
348
|
+
}
|
|
349
|
+
let hostHandleCache;
|
|
350
|
+
/**
|
|
351
|
+
* The window of the terminal this process is typed into, as a handle, or null when it has none (the desktop
|
|
352
|
+
* app) or it cannot be told. Asked once and kept: it does not change while the process runs. The question
|
|
353
|
+
* is put by a child that shares this console rather than making one of its own, since a console is what
|
|
354
|
+
* names the window, and that is only done when this process has a terminal at all, so a program with none
|
|
355
|
+
* is never made to open a window.
|
|
356
|
+
*/
|
|
357
|
+
export async function hostWindowHandle(signal) {
|
|
358
|
+
if (hostHandleCache !== undefined)
|
|
359
|
+
return hostHandleCache;
|
|
360
|
+
if (!process.stdout.isTTY && !process.stdin.isTTY)
|
|
361
|
+
return (hostHandleCache = null);
|
|
362
|
+
try {
|
|
363
|
+
const out = (await runScript(["-Mode", "host"], signal, true)).trim().split(/\s+/).pop() ?? "";
|
|
364
|
+
hostHandleCache = /^\d+$/.test(out) ? out : null;
|
|
365
|
+
}
|
|
366
|
+
catch {
|
|
367
|
+
hostHandleCache = null;
|
|
368
|
+
}
|
|
369
|
+
return hostHandleCache;
|
|
287
370
|
}
|
|
288
371
|
/** Capture one window to `outPath`. `handle` may be the literal "foreground". */
|
|
289
372
|
export async function captureWindow(handle, outPath, signal) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screenshotWin.js","sourceRoot":"","sources":["../../src/tools/screenshotWin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"screenshotWin.js","sourceRoot":"","sources":["../../src/tools/screenshotWin.ts"],"names":[],"mappings":"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"}
|