ft-scout 8.0.1 → 8.0.3

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.
@@ -0,0 +1,248 @@
1
+ param(
2
+ [string]$OutPath,
3
+ [switch]$InfoOnly
4
+ )
5
+
6
+ $source = @"
7
+ using System;
8
+ using System.Drawing;
9
+ using System.Drawing.Imaging;
10
+ using System.Runtime.InteropServices;
11
+ using System.Text;
12
+ using System.Threading;
13
+ using System.Collections.Generic;
14
+
15
+ public class WinCaptureResult {
16
+ public bool success;
17
+ public string savedPath;
18
+ public int width;
19
+ public int height;
20
+ public int cursorX;
21
+ public int cursorY;
22
+ public string activeWindow;
23
+ public string[] visibleWindows;
24
+ public string error;
25
+ }
26
+
27
+ public class WinCaptureHelper {
28
+ [DllImport("user32.dll", SetLastError = true)]
29
+ public static extern IntPtr OpenInputDesktop(uint dwFlags, bool fInherit, uint dwDesiredAccess);
30
+
31
+ [DllImport("user32.dll", SetLastError = true)]
32
+ public static extern IntPtr OpenDesktop(string lpszDesktop, uint dwFlags, bool fInherit, uint dwDesiredAccess);
33
+
34
+ [DllImport("user32.dll", SetLastError = true)]
35
+ public static extern bool SetThreadDesktop(IntPtr hDesktop);
36
+
37
+ [DllImport("user32.dll", SetLastError = true)]
38
+ public static extern bool CloseDesktop(IntPtr hDesktop);
39
+
40
+ [DllImport("user32.dll")]
41
+ public static extern IntPtr GetDC(IntPtr hWnd);
42
+
43
+ [DllImport("user32.dll")]
44
+ public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
45
+
46
+ [DllImport("gdi32.dll")]
47
+ public static extern IntPtr CreateCompatibleDC(IntPtr hdc);
48
+
49
+ [DllImport("gdi32.dll")]
50
+ public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);
51
+
52
+ [DllImport("gdi32.dll")]
53
+ public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
54
+
55
+ [DllImport("gdi32.dll")]
56
+ public static extern bool DeleteDC(IntPtr hdc);
57
+
58
+ [DllImport("gdi32.dll")]
59
+ public static extern bool DeleteObject(IntPtr hObject);
60
+
61
+ [DllImport("gdi32.dll")]
62
+ public static extern bool BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop);
63
+
64
+ [DllImport("user32.dll")]
65
+ public static extern int GetSystemMetrics(int nIndex);
66
+
67
+ public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
68
+
69
+ [DllImport("user32.dll")]
70
+ public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
71
+
72
+ [DllImport("user32.dll", CharSet = CharSet.Auto)]
73
+ public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
74
+
75
+ [DllImport("user32.dll")]
76
+ public static extern bool IsWindowVisible(IntPtr hWnd);
77
+
78
+ [DllImport("user32.dll")]
79
+ public static extern IntPtr GetForegroundWindow();
80
+
81
+ [StructLayout(LayoutKind.Sequential)]
82
+ public struct POINT {
83
+ public int X;
84
+ public int Y;
85
+ }
86
+
87
+ [DllImport("user32.dll")]
88
+ public static extern bool GetCursorPos(out POINT lpPoint);
89
+
90
+ const uint DESKTOP_ACCESS = 0x01FF | 0x00020000;
91
+ const int SM_CXSCREEN = 0;
92
+ const int SM_CYSCREEN = 1;
93
+ const int SRCCOPY = 0x00CC0020;
94
+ const int CAPTUREBLT = 0x40000000;
95
+
96
+ public static WinCaptureResult GetInfo() {
97
+ var res = new WinCaptureResult();
98
+ res.success = true;
99
+ res.error = "";
100
+ var visibleWindows = new List<string>();
101
+
102
+ Thread worker = new Thread(() => {
103
+ IntPtr hDesk = OpenInputDesktop(0, false, DESKTOP_ACCESS);
104
+ if (hDesk == IntPtr.Zero) {
105
+ hDesk = OpenDesktop("Default", 0, false, DESKTOP_ACCESS);
106
+ }
107
+ if (hDesk != IntPtr.Zero) {
108
+ SetThreadDesktop(hDesk);
109
+ }
110
+
111
+ res.width = GetSystemMetrics(SM_CXSCREEN);
112
+ res.height = GetSystemMetrics(SM_CYSCREEN);
113
+ if (res.width <= 0) res.width = 1920;
114
+ if (res.height <= 0) res.height = 1080;
115
+
116
+ POINT pt;
117
+ if (GetCursorPos(out pt)) {
118
+ res.cursorX = pt.X;
119
+ res.cursorY = pt.Y;
120
+ }
121
+
122
+ IntPtr fg = GetForegroundWindow();
123
+ if (fg != IntPtr.Zero) {
124
+ var sbFg = new StringBuilder(256);
125
+ GetWindowText(fg, sbFg, 256);
126
+ res.activeWindow = sbFg.ToString().Trim();
127
+ } else {
128
+ res.activeWindow = "";
129
+ }
130
+
131
+ EnumWindows((hWnd, lParam) => {
132
+ if (IsWindowVisible(hWnd)) {
133
+ var title = new StringBuilder(256);
134
+ GetWindowText(hWnd, title, 256);
135
+ string t = title.ToString().Trim();
136
+ if (t.Length > 0 && !visibleWindows.Contains(t) && t != "Program Manager" && t != "Windows Input Experience") {
137
+ visibleWindows.Add(t);
138
+ }
139
+ }
140
+ return true;
141
+ }, IntPtr.Zero);
142
+
143
+ if (hDesk != IntPtr.Zero) {
144
+ CloseDesktop(hDesk);
145
+ }
146
+ });
147
+
148
+ worker.SetApartmentState(ApartmentState.STA);
149
+ worker.Start();
150
+ worker.Join();
151
+
152
+ res.visibleWindows = visibleWindows.ToArray();
153
+ return res;
154
+ }
155
+
156
+ public static WinCaptureResult Capture(string filePath) {
157
+ var res = new WinCaptureResult();
158
+ res.savedPath = filePath;
159
+ res.error = "";
160
+ var visibleWindows = new List<string>();
161
+
162
+ Thread worker = new Thread(() => {
163
+ IntPtr hDesk = OpenInputDesktop(0, false, DESKTOP_ACCESS);
164
+ if (hDesk == IntPtr.Zero) {
165
+ hDesk = OpenDesktop("Default", 0, false, DESKTOP_ACCESS);
166
+ }
167
+ if (hDesk != IntPtr.Zero) {
168
+ SetThreadDesktop(hDesk);
169
+ }
170
+
171
+ res.width = GetSystemMetrics(SM_CXSCREEN);
172
+ res.height = GetSystemMetrics(SM_CYSCREEN);
173
+ if (res.width <= 0) res.width = 1920;
174
+ if (res.height <= 0) res.height = 1080;
175
+
176
+ POINT pt;
177
+ if (GetCursorPos(out pt)) {
178
+ res.cursorX = pt.X;
179
+ res.cursorY = pt.Y;
180
+ }
181
+
182
+ IntPtr fg = GetForegroundWindow();
183
+ if (fg != IntPtr.Zero) {
184
+ var sbFg = new StringBuilder(256);
185
+ GetWindowText(fg, sbFg, 256);
186
+ res.activeWindow = sbFg.ToString().Trim();
187
+ } else {
188
+ res.activeWindow = "";
189
+ }
190
+
191
+ EnumWindows((hWnd, lParam) => {
192
+ if (IsWindowVisible(hWnd)) {
193
+ var title = new StringBuilder(256);
194
+ GetWindowText(hWnd, title, 256);
195
+ string t = title.ToString().Trim();
196
+ if (t.Length > 0 && !visibleWindows.Contains(t) && t != "Program Manager" && t != "Windows Input Experience") {
197
+ visibleWindows.Add(t);
198
+ }
199
+ }
200
+ return true;
201
+ }, IntPtr.Zero);
202
+
203
+ try {
204
+ IntPtr hdcSrc = GetDC(IntPtr.Zero);
205
+ IntPtr hdcDest = CreateCompatibleDC(hdcSrc);
206
+ IntPtr hBitmap = CreateCompatibleBitmap(hdcSrc, res.width, res.height);
207
+ IntPtr hOld = SelectObject(hdcDest, hBitmap);
208
+ bool bltOk = BitBlt(hdcDest, 0, 0, res.width, res.height, hdcSrc, 0, 0, SRCCOPY | CAPTUREBLT);
209
+
210
+ SelectObject(hdcDest, hOld);
211
+ DeleteDC(hdcDest);
212
+ ReleaseDC(IntPtr.Zero, hdcSrc);
213
+
214
+ if (bltOk) {
215
+ using (Bitmap bmp = Bitmap.FromHbitmap(hBitmap)) {
216
+ bmp.Save(filePath, ImageFormat.Png);
217
+ }
218
+ res.success = true;
219
+ } else {
220
+ res.error = "BitBlt failed";
221
+ }
222
+ DeleteObject(hBitmap);
223
+ } catch (Exception ex) {
224
+ res.error = ex.Message;
225
+ }
226
+
227
+ if (hDesk != IntPtr.Zero) {
228
+ CloseDesktop(hDesk);
229
+ }
230
+ });
231
+
232
+ worker.SetApartmentState(ApartmentState.STA);
233
+ worker.Start();
234
+ worker.Join();
235
+
236
+ res.visibleWindows = visibleWindows.ToArray();
237
+ return res;
238
+ }
239
+ }
240
+ "@
241
+
242
+ Add-Type -TypeDefinition $source -ReferencedAssemblies System.Drawing, System.Windows.Forms
243
+
244
+ if ($InfoOnly) {
245
+ [WinCaptureHelper]::GetInfo() | ConvertTo-Json -Compress
246
+ } else {
247
+ [WinCaptureHelper]::Capture($OutPath) | ConvertTo-Json -Compress
248
+ }
package/bin/src/index.js CHANGED
@@ -32,13 +32,13 @@ program
32
32
  .name('scout')
33
33
  .alias('ft')
34
34
  .description('FrontTerrain — The Onboarding Co-Pilot for New Codebases')
35
- .version('8.0.1');
35
+ .version('8.0.3');
36
36
  // Header UI on execution with FrontTerrain proprietary logo & version auto-checker
37
37
  program.hook('preAction', async (_thisCommand, actionCommand) => {
38
- intro(renderBranding('8.0.1'));
38
+ intro(renderBranding('8.0.3'));
39
39
  const cmdName = actionCommand ? actionCommand.name() : '';
40
40
  if (cmdName !== 'upgrade') {
41
- await checkForUpdates('8.0.1');
41
+ await checkForUpdates('8.0.3');
42
42
  }
43
43
  // Auth Guard: enforce authentication for all commands except login, signup, upgrade, help, dashboard, auth, status
44
44
  const EXEMPT_COMMANDS = ['login', 'signin', 'signup', 'register', 'upgrade', 'help', 'dashboard', 'web-ui', 'gui', 'auth', 'status', 'quota', 'usage', 'credits'];
@@ -233,7 +233,7 @@ program
233
233
  .command('upgrade')
234
234
  .description('Check for updates and auto-upgrade Scout to the latest version')
235
235
  .action(async () => {
236
- await checkForUpdates('8.0.1', true);
236
+ await checkForUpdates('8.0.3', true);
237
237
  outro(chalk.cyan('Upgrade check complete.'));
238
238
  });
239
239
  program
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- export function renderBranding(version = '8.0.1') {
2
+ export function renderBranding(version = '8.0.3') {
3
3
  const logo = chalk.cyan.bold(' ███████╗████████╗') + ' ' + chalk.cyan.bold('███████╗ ██████╗ ██████╗ ██╗ ██╗████████╗') + '\n' +
4
4
  chalk.cyan.bold(' ██╔════╝╚══██╔══╝') + ' ' + chalk.cyan.bold('██╔════╝ ██╔════╝██╔═══██╗ ██║ ██║╚══██╔══╝') + '\n' +
5
5
  chalk.cyan.bold(' █████╗ ██║ ') + ' ' + chalk.cyan.bold(' ███████╗ ██║ ██║ ██║ ██║ ██║ ██║ ') + '\n' +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ft-scout",
3
- "version": "8.0.1",
3
+ "version": "8.0.3",
4
4
  "type": "module",
5
5
  "description": "FrontTerrain — The Onboarding Co-Pilot for New Codebases",
6
6
  "main": "index.js",
@@ -34,7 +34,7 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@clack/prompts": "^1.7.0",
37
- "@types/nodemailer": "^8.0.1",
37
+ "@types/nodemailer": "^8.0.2",
38
38
  "chalk": "^6.0.0",
39
39
  "commander": "^13.1.0",
40
40
  "dotenv": "^17.4.2",
package/web/app.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /* ==========================================================================
2
- FrontTerrain Scout — Multi-Page Application Engine v8.0.1
2
+ FrontTerrain Scout — Multi-Page Application Engine v8.0.3
3
3
  ========================================================================== */
4
4
 
5
5
  const FIREBASE_CONFIG = {
@@ -452,7 +452,7 @@ function initTerminalSimulator() {
452
452
  `;
453
453
  } else if (lower.includes('status')) {
454
454
  response.innerHTML = `
455
- <span class="term-green">✔ Scout CLI Engine: v8.0.1 Online</span><br>
455
+ <span class="term-green">✔ Scout CLI Engine: v8.0.3 Online</span><br>
456
456
  ↳ User: <strong>${escapeHtml(state.user ? state.user.name : 'Guest Session')}</strong><br>
457
457
  ↳ Active Subscription: <strong>${escapeHtml(TIER_DETAILS[state.currentTier].name)}</strong><br>
458
458
  ↳ Credit Quota: <strong>${state.byokEnabled ? 'BYOK Mode (Unlimited)' : `${state.creditsUsed} / ${state.creditsTotal} Credits Used`}</strong><br>
package/web/styles.css CHANGED
@@ -1,5 +1,5 @@
1
1
  /* ==========================================================================
2
- FrontTerrain Scout — Design System & Visual Engine v8.0.1
2
+ FrontTerrain Scout — Design System & Visual Engine v8.0.3
3
3
  Inspired by HappyRobot, Linear.app & Vercel aesthetics
4
4
  ========================================================================== */
5
5