aisnitch 0.2.21 → 0.2.23

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/index.js CHANGED
@@ -1,4 +1,739 @@
1
1
  #!/usr/bin/env node
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __esm = (fn, res) => function __init() {
5
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
6
+ };
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+
12
+ // node_modules/.pnpm/is-docker@3.0.0/node_modules/is-docker/index.js
13
+ import fs from "fs";
14
+ function hasDockerEnv() {
15
+ try {
16
+ fs.statSync("/.dockerenv");
17
+ return true;
18
+ } catch {
19
+ return false;
20
+ }
21
+ }
22
+ function hasDockerCGroup() {
23
+ try {
24
+ return fs.readFileSync("/proc/self/cgroup", "utf8").includes("docker");
25
+ } catch {
26
+ return false;
27
+ }
28
+ }
29
+ function isDocker() {
30
+ if (isDockerCached === void 0) {
31
+ isDockerCached = hasDockerEnv() || hasDockerCGroup();
32
+ }
33
+ return isDockerCached;
34
+ }
35
+ var isDockerCached;
36
+ var init_is_docker = __esm({
37
+ "node_modules/.pnpm/is-docker@3.0.0/node_modules/is-docker/index.js"() {
38
+ "use strict";
39
+ }
40
+ });
41
+
42
+ // node_modules/.pnpm/is-inside-container@1.0.0/node_modules/is-inside-container/index.js
43
+ import fs2 from "fs";
44
+ function isInsideContainer() {
45
+ if (cachedResult === void 0) {
46
+ cachedResult = hasContainerEnv() || isDocker();
47
+ }
48
+ return cachedResult;
49
+ }
50
+ var cachedResult, hasContainerEnv;
51
+ var init_is_inside_container = __esm({
52
+ "node_modules/.pnpm/is-inside-container@1.0.0/node_modules/is-inside-container/index.js"() {
53
+ "use strict";
54
+ init_is_docker();
55
+ hasContainerEnv = () => {
56
+ try {
57
+ fs2.statSync("/run/.containerenv");
58
+ return true;
59
+ } catch {
60
+ return false;
61
+ }
62
+ };
63
+ }
64
+ });
65
+
66
+ // node_modules/.pnpm/is-wsl@3.1.1/node_modules/is-wsl/index.js
67
+ import process2 from "process";
68
+ import os from "os";
69
+ import fs3 from "fs";
70
+ var isWsl, is_wsl_default;
71
+ var init_is_wsl = __esm({
72
+ "node_modules/.pnpm/is-wsl@3.1.1/node_modules/is-wsl/index.js"() {
73
+ "use strict";
74
+ init_is_inside_container();
75
+ isWsl = () => {
76
+ if (process2.platform !== "linux") {
77
+ return false;
78
+ }
79
+ if (os.release().toLowerCase().includes("microsoft")) {
80
+ if (isInsideContainer()) {
81
+ return false;
82
+ }
83
+ return true;
84
+ }
85
+ try {
86
+ if (fs3.readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft")) {
87
+ return !isInsideContainer();
88
+ }
89
+ } catch {
90
+ }
91
+ if (fs3.existsSync("/proc/sys/fs/binfmt_misc/WSLInterop") || fs3.existsSync("/run/WSL")) {
92
+ return !isInsideContainer();
93
+ }
94
+ return false;
95
+ };
96
+ is_wsl_default = process2.env.__IS_WSL_TEST__ ? isWsl : isWsl();
97
+ }
98
+ });
99
+
100
+ // node_modules/.pnpm/powershell-utils@0.1.0/node_modules/powershell-utils/index.js
101
+ import process3 from "process";
102
+ import { Buffer as Buffer2 } from "buffer";
103
+ import { promisify as promisify15 } from "util";
104
+ import childProcess from "child_process";
105
+ import fs4, { constants as fsConstants } from "fs/promises";
106
+ var execFile15, powerShellPath, executePowerShell;
107
+ var init_powershell_utils = __esm({
108
+ "node_modules/.pnpm/powershell-utils@0.1.0/node_modules/powershell-utils/index.js"() {
109
+ "use strict";
110
+ execFile15 = promisify15(childProcess.execFile);
111
+ powerShellPath = () => `${process3.env.SYSTEMROOT || process3.env.windir || String.raw`C:\Windows`}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`;
112
+ executePowerShell = async (command, options = {}) => {
113
+ const {
114
+ powerShellPath: psPath,
115
+ ...execFileOptions
116
+ } = options;
117
+ const encodedCommand = executePowerShell.encodeCommand(command);
118
+ return execFile15(
119
+ psPath ?? powerShellPath(),
120
+ [
121
+ ...executePowerShell.argumentsPrefix,
122
+ encodedCommand
123
+ ],
124
+ {
125
+ encoding: "utf8",
126
+ ...execFileOptions
127
+ }
128
+ );
129
+ };
130
+ executePowerShell.argumentsPrefix = [
131
+ "-NoProfile",
132
+ "-NonInteractive",
133
+ "-ExecutionPolicy",
134
+ "Bypass",
135
+ "-EncodedCommand"
136
+ ];
137
+ executePowerShell.encodeCommand = (command) => Buffer2.from(command, "utf16le").toString("base64");
138
+ executePowerShell.escapeArgument = (value) => `'${String(value).replaceAll("'", "''")}'`;
139
+ }
140
+ });
141
+
142
+ // node_modules/.pnpm/wsl-utils@0.3.1/node_modules/wsl-utils/utilities.js
143
+ function parseMountPointFromConfig(content) {
144
+ for (const line of content.split("\n")) {
145
+ if (/^\s*#/.test(line)) {
146
+ continue;
147
+ }
148
+ const match = /^\s*root\s*=\s*(?<mountPoint>"[^"]*"|'[^']*'|[^#]*)/.exec(line);
149
+ if (!match) {
150
+ continue;
151
+ }
152
+ return match.groups.mountPoint.trim().replaceAll(/^["']|["']$/g, "");
153
+ }
154
+ }
155
+ var init_utilities = __esm({
156
+ "node_modules/.pnpm/wsl-utils@0.3.1/node_modules/wsl-utils/utilities.js"() {
157
+ "use strict";
158
+ }
159
+ });
160
+
161
+ // node_modules/.pnpm/wsl-utils@0.3.1/node_modules/wsl-utils/index.js
162
+ import { promisify as promisify16 } from "util";
163
+ import childProcess2 from "child_process";
164
+ import fs5, { constants as fsConstants2 } from "fs/promises";
165
+ var execFile16, wslDrivesMountPoint, powerShellPathFromWsl, powerShellPath2, canAccessPowerShellPromise, canAccessPowerShell, wslDefaultBrowser, convertWslPathToWindows;
166
+ var init_wsl_utils = __esm({
167
+ "node_modules/.pnpm/wsl-utils@0.3.1/node_modules/wsl-utils/index.js"() {
168
+ "use strict";
169
+ init_is_wsl();
170
+ init_powershell_utils();
171
+ init_utilities();
172
+ init_is_wsl();
173
+ execFile16 = promisify16(childProcess2.execFile);
174
+ wslDrivesMountPoint = /* @__PURE__ */ (() => {
175
+ const defaultMountPoint = "/mnt/";
176
+ let mountPoint;
177
+ return async function() {
178
+ if (mountPoint) {
179
+ return mountPoint;
180
+ }
181
+ const configFilePath = "/etc/wsl.conf";
182
+ let isConfigFileExists = false;
183
+ try {
184
+ await fs5.access(configFilePath, fsConstants2.F_OK);
185
+ isConfigFileExists = true;
186
+ } catch {
187
+ }
188
+ if (!isConfigFileExists) {
189
+ return defaultMountPoint;
190
+ }
191
+ const configContent = await fs5.readFile(configFilePath, { encoding: "utf8" });
192
+ const parsedMountPoint = parseMountPointFromConfig(configContent);
193
+ if (parsedMountPoint === void 0) {
194
+ return defaultMountPoint;
195
+ }
196
+ mountPoint = parsedMountPoint;
197
+ mountPoint = mountPoint.endsWith("/") ? mountPoint : `${mountPoint}/`;
198
+ return mountPoint;
199
+ };
200
+ })();
201
+ powerShellPathFromWsl = async () => {
202
+ const mountPoint = await wslDrivesMountPoint();
203
+ return `${mountPoint}c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe`;
204
+ };
205
+ powerShellPath2 = is_wsl_default ? powerShellPathFromWsl : powerShellPath;
206
+ canAccessPowerShell = async () => {
207
+ canAccessPowerShellPromise ??= (async () => {
208
+ try {
209
+ const psPath = await powerShellPath2();
210
+ await fs5.access(psPath, fsConstants2.X_OK);
211
+ return true;
212
+ } catch {
213
+ return false;
214
+ }
215
+ })();
216
+ return canAccessPowerShellPromise;
217
+ };
218
+ wslDefaultBrowser = async () => {
219
+ const psPath = await powerShellPath2();
220
+ const command = String.raw`(Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice").ProgId`;
221
+ const { stdout } = await executePowerShell(command, { powerShellPath: psPath });
222
+ return stdout.trim();
223
+ };
224
+ convertWslPathToWindows = async (path2) => {
225
+ if (/^[a-z]+:\/\//i.test(path2)) {
226
+ return path2;
227
+ }
228
+ try {
229
+ const { stdout } = await execFile16("wslpath", ["-aw", path2], { encoding: "utf8" });
230
+ return stdout.trim();
231
+ } catch {
232
+ return path2;
233
+ }
234
+ };
235
+ }
236
+ });
237
+
238
+ // node_modules/.pnpm/define-lazy-prop@3.0.0/node_modules/define-lazy-prop/index.js
239
+ function defineLazyProperty(object, propertyName, valueGetter) {
240
+ const define = (value) => Object.defineProperty(object, propertyName, { value, enumerable: true, writable: true });
241
+ Object.defineProperty(object, propertyName, {
242
+ configurable: true,
243
+ enumerable: true,
244
+ get() {
245
+ const result = valueGetter();
246
+ define(result);
247
+ return result;
248
+ },
249
+ set(value) {
250
+ define(value);
251
+ }
252
+ });
253
+ return object;
254
+ }
255
+ var init_define_lazy_prop = __esm({
256
+ "node_modules/.pnpm/define-lazy-prop@3.0.0/node_modules/define-lazy-prop/index.js"() {
257
+ "use strict";
258
+ }
259
+ });
260
+
261
+ // node_modules/.pnpm/default-browser-id@5.0.1/node_modules/default-browser-id/index.js
262
+ import { promisify as promisify17 } from "util";
263
+ import process4 from "process";
264
+ import { execFile as execFile17 } from "child_process";
265
+ async function defaultBrowserId() {
266
+ if (process4.platform !== "darwin") {
267
+ throw new Error("macOS only");
268
+ }
269
+ const { stdout } = await execFileAsync2("defaults", ["read", "com.apple.LaunchServices/com.apple.launchservices.secure", "LSHandlers"]);
270
+ const match = /LSHandlerRoleAll = "(?!-)(?<id>[^"]+?)";\s+?LSHandlerURLScheme = (?:http|https);/.exec(stdout);
271
+ const browserId = match?.groups.id ?? "com.apple.Safari";
272
+ if (browserId === "com.apple.safari") {
273
+ return "com.apple.Safari";
274
+ }
275
+ return browserId;
276
+ }
277
+ var execFileAsync2;
278
+ var init_default_browser_id = __esm({
279
+ "node_modules/.pnpm/default-browser-id@5.0.1/node_modules/default-browser-id/index.js"() {
280
+ "use strict";
281
+ execFileAsync2 = promisify17(execFile17);
282
+ }
283
+ });
284
+
285
+ // node_modules/.pnpm/run-applescript@7.1.0/node_modules/run-applescript/index.js
286
+ import process5 from "process";
287
+ import { promisify as promisify18 } from "util";
288
+ import { execFile as execFile18, execFileSync } from "child_process";
289
+ async function runAppleScript(script, { humanReadableOutput = true, signal } = {}) {
290
+ if (process5.platform !== "darwin") {
291
+ throw new Error("macOS only");
292
+ }
293
+ const outputArguments = humanReadableOutput ? [] : ["-ss"];
294
+ const execOptions = {};
295
+ if (signal) {
296
+ execOptions.signal = signal;
297
+ }
298
+ const { stdout } = await execFileAsync3("osascript", ["-e", script, outputArguments], execOptions);
299
+ return stdout.trim();
300
+ }
301
+ var execFileAsync3;
302
+ var init_run_applescript = __esm({
303
+ "node_modules/.pnpm/run-applescript@7.1.0/node_modules/run-applescript/index.js"() {
304
+ "use strict";
305
+ execFileAsync3 = promisify18(execFile18);
306
+ }
307
+ });
308
+
309
+ // node_modules/.pnpm/bundle-name@4.1.0/node_modules/bundle-name/index.js
310
+ async function bundleName(bundleId) {
311
+ return runAppleScript(`tell application "Finder" to set app_path to application file id "${bundleId}" as string
312
+ tell application "System Events" to get value of property list item "CFBundleName" of property list file (app_path & ":Contents:Info.plist")`);
313
+ }
314
+ var init_bundle_name = __esm({
315
+ "node_modules/.pnpm/bundle-name@4.1.0/node_modules/bundle-name/index.js"() {
316
+ "use strict";
317
+ init_run_applescript();
318
+ }
319
+ });
320
+
321
+ // node_modules/.pnpm/default-browser@5.5.0/node_modules/default-browser/windows.js
322
+ import { promisify as promisify19 } from "util";
323
+ import { execFile as execFile19 } from "child_process";
324
+ async function defaultBrowser(_execFileAsync = execFileAsync4) {
325
+ const { stdout } = await _execFileAsync("reg", [
326
+ "QUERY",
327
+ " HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice",
328
+ "/v",
329
+ "ProgId"
330
+ ]);
331
+ const match = /ProgId\s*REG_SZ\s*(?<id>\S+)/.exec(stdout);
332
+ if (!match) {
333
+ throw new UnknownBrowserError(`Cannot find Windows browser in stdout: ${JSON.stringify(stdout)}`);
334
+ }
335
+ const { id } = match.groups;
336
+ const dotIndex = id.lastIndexOf(".");
337
+ const hyphenIndex = id.lastIndexOf("-");
338
+ const baseIdByDot = dotIndex === -1 ? void 0 : id.slice(0, dotIndex);
339
+ const baseIdByHyphen = hyphenIndex === -1 ? void 0 : id.slice(0, hyphenIndex);
340
+ return windowsBrowserProgIds[id] ?? windowsBrowserProgIds[baseIdByDot] ?? windowsBrowserProgIds[baseIdByHyphen] ?? { name: id, id };
341
+ }
342
+ var execFileAsync4, windowsBrowserProgIds, _windowsBrowserProgIdMap, UnknownBrowserError;
343
+ var init_windows = __esm({
344
+ "node_modules/.pnpm/default-browser@5.5.0/node_modules/default-browser/windows.js"() {
345
+ "use strict";
346
+ execFileAsync4 = promisify19(execFile19);
347
+ windowsBrowserProgIds = {
348
+ MSEdgeHTM: { name: "Edge", id: "com.microsoft.edge" },
349
+ // The missing `L` is correct.
350
+ MSEdgeBHTML: { name: "Edge Beta", id: "com.microsoft.edge.beta" },
351
+ MSEdgeDHTML: { name: "Edge Dev", id: "com.microsoft.edge.dev" },
352
+ AppXq0fevzme2pys62n3e0fbqa7peapykr8v: { name: "Edge", id: "com.microsoft.edge.old" },
353
+ ChromeHTML: { name: "Chrome", id: "com.google.chrome" },
354
+ ChromeBHTML: { name: "Chrome Beta", id: "com.google.chrome.beta" },
355
+ ChromeDHTML: { name: "Chrome Dev", id: "com.google.chrome.dev" },
356
+ ChromiumHTM: { name: "Chromium", id: "org.chromium.Chromium" },
357
+ BraveHTML: { name: "Brave", id: "com.brave.Browser" },
358
+ BraveBHTML: { name: "Brave Beta", id: "com.brave.Browser.beta" },
359
+ BraveDHTML: { name: "Brave Dev", id: "com.brave.Browser.dev" },
360
+ BraveSSHTM: { name: "Brave Nightly", id: "com.brave.Browser.nightly" },
361
+ FirefoxURL: { name: "Firefox", id: "org.mozilla.firefox" },
362
+ OperaStable: { name: "Opera", id: "com.operasoftware.Opera" },
363
+ VivaldiHTM: { name: "Vivaldi", id: "com.vivaldi.Vivaldi" },
364
+ "IE.HTTP": { name: "Internet Explorer", id: "com.microsoft.ie" }
365
+ };
366
+ _windowsBrowserProgIdMap = new Map(Object.entries(windowsBrowserProgIds));
367
+ UnknownBrowserError = class extends Error {
368
+ };
369
+ }
370
+ });
371
+
372
+ // node_modules/.pnpm/default-browser@5.5.0/node_modules/default-browser/index.js
373
+ import { promisify as promisify20 } from "util";
374
+ import process6 from "process";
375
+ import { execFile as execFile20 } from "child_process";
376
+ async function defaultBrowser2() {
377
+ if (process6.platform === "darwin") {
378
+ const id = await defaultBrowserId();
379
+ const name = await bundleName(id);
380
+ return { name, id };
381
+ }
382
+ if (process6.platform === "linux") {
383
+ const { stdout } = await execFileAsync5("xdg-mime", ["query", "default", "x-scheme-handler/http"]);
384
+ const id = stdout.trim();
385
+ const name = titleize(id.replace(/.desktop$/, "").replace("-", " "));
386
+ return { name, id };
387
+ }
388
+ if (process6.platform === "win32") {
389
+ return defaultBrowser();
390
+ }
391
+ throw new Error("Only macOS, Linux, and Windows are supported");
392
+ }
393
+ var execFileAsync5, titleize;
394
+ var init_default_browser = __esm({
395
+ "node_modules/.pnpm/default-browser@5.5.0/node_modules/default-browser/index.js"() {
396
+ "use strict";
397
+ init_default_browser_id();
398
+ init_bundle_name();
399
+ init_windows();
400
+ init_windows();
401
+ execFileAsync5 = promisify20(execFile20);
402
+ titleize = (string) => string.toLowerCase().replaceAll(/(?:^|\s|-)\S/g, (x) => x.toUpperCase());
403
+ }
404
+ });
405
+
406
+ // node_modules/.pnpm/is-in-ssh@1.0.0/node_modules/is-in-ssh/index.js
407
+ import process7 from "process";
408
+ var isInSsh, is_in_ssh_default;
409
+ var init_is_in_ssh = __esm({
410
+ "node_modules/.pnpm/is-in-ssh@1.0.0/node_modules/is-in-ssh/index.js"() {
411
+ "use strict";
412
+ isInSsh = Boolean(process7.env.SSH_CONNECTION || process7.env.SSH_CLIENT || process7.env.SSH_TTY);
413
+ is_in_ssh_default = isInSsh;
414
+ }
415
+ });
416
+
417
+ // node_modules/.pnpm/open@11.0.0/node_modules/open/index.js
418
+ var open_exports = {};
419
+ __export(open_exports, {
420
+ apps: () => apps,
421
+ default: () => open_default,
422
+ openApp: () => openApp
423
+ });
424
+ import process8 from "process";
425
+ import path from "path";
426
+ import { fileURLToPath } from "url";
427
+ import childProcess3 from "child_process";
428
+ import fs6, { constants as fsConstants3 } from "fs/promises";
429
+ function detectArchBinary(binary) {
430
+ if (typeof binary === "string" || Array.isArray(binary)) {
431
+ return binary;
432
+ }
433
+ const { [arch]: archBinary } = binary;
434
+ if (!archBinary) {
435
+ throw new Error(`${arch} is not supported`);
436
+ }
437
+ return archBinary;
438
+ }
439
+ function detectPlatformBinary({ [platform]: platformBinary }, { wsl } = {}) {
440
+ if (wsl && is_wsl_default) {
441
+ return detectArchBinary(wsl);
442
+ }
443
+ if (!platformBinary) {
444
+ throw new Error(`${platform} is not supported`);
445
+ }
446
+ return detectArchBinary(platformBinary);
447
+ }
448
+ var fallbackAttemptSymbol, __dirname, localXdgOpenPath, platform, arch, tryEachApp, baseOpen, open, openApp, apps, open_default;
449
+ var init_open = __esm({
450
+ "node_modules/.pnpm/open@11.0.0/node_modules/open/index.js"() {
451
+ "use strict";
452
+ init_wsl_utils();
453
+ init_powershell_utils();
454
+ init_define_lazy_prop();
455
+ init_default_browser();
456
+ init_is_inside_container();
457
+ init_is_in_ssh();
458
+ fallbackAttemptSymbol = /* @__PURE__ */ Symbol("fallbackAttempt");
459
+ __dirname = import.meta.url ? path.dirname(fileURLToPath(import.meta.url)) : "";
460
+ localXdgOpenPath = path.join(__dirname, "xdg-open");
461
+ ({ platform, arch } = process8);
462
+ tryEachApp = async (apps2, opener) => {
463
+ if (apps2.length === 0) {
464
+ return;
465
+ }
466
+ const errors = [];
467
+ for (const app of apps2) {
468
+ try {
469
+ return await opener(app);
470
+ } catch (error) {
471
+ errors.push(error);
472
+ }
473
+ }
474
+ throw new AggregateError(errors, "Failed to open in all supported apps");
475
+ };
476
+ baseOpen = async (options) => {
477
+ options = {
478
+ wait: false,
479
+ background: false,
480
+ newInstance: false,
481
+ allowNonzeroExitCode: false,
482
+ ...options
483
+ };
484
+ const isFallbackAttempt = options[fallbackAttemptSymbol] === true;
485
+ delete options[fallbackAttemptSymbol];
486
+ if (Array.isArray(options.app)) {
487
+ return tryEachApp(options.app, (singleApp) => baseOpen({
488
+ ...options,
489
+ app: singleApp,
490
+ [fallbackAttemptSymbol]: true
491
+ }));
492
+ }
493
+ let { name: app, arguments: appArguments = [] } = options.app ?? {};
494
+ appArguments = [...appArguments];
495
+ if (Array.isArray(app)) {
496
+ return tryEachApp(app, (appName) => baseOpen({
497
+ ...options,
498
+ app: {
499
+ name: appName,
500
+ arguments: appArguments
501
+ },
502
+ [fallbackAttemptSymbol]: true
503
+ }));
504
+ }
505
+ if (app === "browser" || app === "browserPrivate") {
506
+ const ids = {
507
+ "com.google.chrome": "chrome",
508
+ "google-chrome.desktop": "chrome",
509
+ "com.brave.browser": "brave",
510
+ "org.mozilla.firefox": "firefox",
511
+ "firefox.desktop": "firefox",
512
+ "com.microsoft.msedge": "edge",
513
+ "com.microsoft.edge": "edge",
514
+ "com.microsoft.edgemac": "edge",
515
+ "microsoft-edge.desktop": "edge",
516
+ "com.apple.safari": "safari"
517
+ };
518
+ const flags = {
519
+ chrome: "--incognito",
520
+ brave: "--incognito",
521
+ firefox: "--private-window",
522
+ edge: "--inPrivate"
523
+ // Safari doesn't support private mode via command line
524
+ };
525
+ let browser;
526
+ if (is_wsl_default) {
527
+ const progId = await wslDefaultBrowser();
528
+ const browserInfo = _windowsBrowserProgIdMap.get(progId);
529
+ browser = browserInfo ?? {};
530
+ } else {
531
+ browser = await defaultBrowser2();
532
+ }
533
+ if (browser.id in ids) {
534
+ const browserName = ids[browser.id.toLowerCase()];
535
+ if (app === "browserPrivate") {
536
+ if (browserName === "safari") {
537
+ throw new Error("Safari doesn't support opening in private mode via command line");
538
+ }
539
+ appArguments.push(flags[browserName]);
540
+ }
541
+ return baseOpen({
542
+ ...options,
543
+ app: {
544
+ name: apps[browserName],
545
+ arguments: appArguments
546
+ }
547
+ });
548
+ }
549
+ throw new Error(`${browser.name} is not supported as a default browser`);
550
+ }
551
+ let command;
552
+ const cliArguments = [];
553
+ const childProcessOptions = {};
554
+ let shouldUseWindowsInWsl = false;
555
+ if (is_wsl_default && !isInsideContainer() && !is_in_ssh_default && !app) {
556
+ shouldUseWindowsInWsl = await canAccessPowerShell();
557
+ }
558
+ if (platform === "darwin") {
559
+ command = "open";
560
+ if (options.wait) {
561
+ cliArguments.push("--wait-apps");
562
+ }
563
+ if (options.background) {
564
+ cliArguments.push("--background");
565
+ }
566
+ if (options.newInstance) {
567
+ cliArguments.push("--new");
568
+ }
569
+ if (app) {
570
+ cliArguments.push("-a", app);
571
+ }
572
+ } else if (platform === "win32" || shouldUseWindowsInWsl) {
573
+ command = await powerShellPath2();
574
+ cliArguments.push(...executePowerShell.argumentsPrefix);
575
+ if (!is_wsl_default) {
576
+ childProcessOptions.windowsVerbatimArguments = true;
577
+ }
578
+ if (is_wsl_default && options.target) {
579
+ options.target = await convertWslPathToWindows(options.target);
580
+ }
581
+ const encodedArguments = ["$ProgressPreference = 'SilentlyContinue';", "Start"];
582
+ if (options.wait) {
583
+ encodedArguments.push("-Wait");
584
+ }
585
+ if (app) {
586
+ encodedArguments.push(executePowerShell.escapeArgument(app));
587
+ if (options.target) {
588
+ appArguments.push(options.target);
589
+ }
590
+ } else if (options.target) {
591
+ encodedArguments.push(executePowerShell.escapeArgument(options.target));
592
+ }
593
+ if (appArguments.length > 0) {
594
+ appArguments = appArguments.map((argument) => executePowerShell.escapeArgument(argument));
595
+ encodedArguments.push("-ArgumentList", appArguments.join(","));
596
+ }
597
+ options.target = executePowerShell.encodeCommand(encodedArguments.join(" "));
598
+ if (!options.wait) {
599
+ childProcessOptions.stdio = "ignore";
600
+ }
601
+ } else {
602
+ if (app) {
603
+ command = app;
604
+ } else {
605
+ const isBundled = !__dirname || __dirname === "/";
606
+ let exeLocalXdgOpen = false;
607
+ try {
608
+ await fs6.access(localXdgOpenPath, fsConstants3.X_OK);
609
+ exeLocalXdgOpen = true;
610
+ } catch {
611
+ }
612
+ const useSystemXdgOpen = process8.versions.electron ?? (platform === "android" || isBundled || !exeLocalXdgOpen);
613
+ command = useSystemXdgOpen ? "xdg-open" : localXdgOpenPath;
614
+ }
615
+ if (appArguments.length > 0) {
616
+ cliArguments.push(...appArguments);
617
+ }
618
+ if (!options.wait) {
619
+ childProcessOptions.stdio = "ignore";
620
+ childProcessOptions.detached = true;
621
+ }
622
+ }
623
+ if (platform === "darwin" && appArguments.length > 0) {
624
+ cliArguments.push("--args", ...appArguments);
625
+ }
626
+ if (options.target) {
627
+ cliArguments.push(options.target);
628
+ }
629
+ const subprocess = childProcess3.spawn(command, cliArguments, childProcessOptions);
630
+ if (options.wait) {
631
+ return new Promise((resolve2, reject) => {
632
+ subprocess.once("error", reject);
633
+ subprocess.once("close", (exitCode) => {
634
+ if (!options.allowNonzeroExitCode && exitCode !== 0) {
635
+ reject(new Error(`Exited with code ${exitCode}`));
636
+ return;
637
+ }
638
+ resolve2(subprocess);
639
+ });
640
+ });
641
+ }
642
+ if (isFallbackAttempt) {
643
+ return new Promise((resolve2, reject) => {
644
+ subprocess.once("error", reject);
645
+ subprocess.once("spawn", () => {
646
+ subprocess.once("close", (exitCode) => {
647
+ subprocess.off("error", reject);
648
+ if (exitCode !== 0) {
649
+ reject(new Error(`Exited with code ${exitCode}`));
650
+ return;
651
+ }
652
+ subprocess.unref();
653
+ resolve2(subprocess);
654
+ });
655
+ });
656
+ });
657
+ }
658
+ subprocess.unref();
659
+ return new Promise((resolve2, reject) => {
660
+ subprocess.once("error", reject);
661
+ subprocess.once("spawn", () => {
662
+ subprocess.off("error", reject);
663
+ resolve2(subprocess);
664
+ });
665
+ });
666
+ };
667
+ open = (target, options) => {
668
+ if (typeof target !== "string") {
669
+ throw new TypeError("Expected a `target`");
670
+ }
671
+ return baseOpen({
672
+ ...options,
673
+ target
674
+ });
675
+ };
676
+ openApp = (name, options) => {
677
+ if (typeof name !== "string" && !Array.isArray(name)) {
678
+ throw new TypeError("Expected a valid `name`");
679
+ }
680
+ const { arguments: appArguments = [] } = options ?? {};
681
+ if (appArguments !== void 0 && appArguments !== null && !Array.isArray(appArguments)) {
682
+ throw new TypeError("Expected `appArguments` as Array type");
683
+ }
684
+ return baseOpen({
685
+ ...options,
686
+ app: {
687
+ name,
688
+ arguments: appArguments
689
+ }
690
+ });
691
+ };
692
+ apps = {
693
+ browser: "browser",
694
+ browserPrivate: "browserPrivate"
695
+ };
696
+ defineLazyProperty(apps, "chrome", () => detectPlatformBinary({
697
+ darwin: "google chrome",
698
+ win32: "chrome",
699
+ // `chromium-browser` is the older deb package name used by Ubuntu/Debian before snap.
700
+ linux: ["google-chrome", "google-chrome-stable", "chromium", "chromium-browser"]
701
+ }, {
702
+ wsl: {
703
+ ia32: "/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe",
704
+ x64: ["/mnt/c/Program Files/Google/Chrome/Application/chrome.exe", "/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe"]
705
+ }
706
+ }));
707
+ defineLazyProperty(apps, "brave", () => detectPlatformBinary({
708
+ darwin: "brave browser",
709
+ win32: "brave",
710
+ linux: ["brave-browser", "brave"]
711
+ }, {
712
+ wsl: {
713
+ ia32: "/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe",
714
+ x64: ["/mnt/c/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe", "/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe"]
715
+ }
716
+ }));
717
+ defineLazyProperty(apps, "firefox", () => detectPlatformBinary({
718
+ darwin: "firefox",
719
+ win32: String.raw`C:\Program Files\Mozilla Firefox\firefox.exe`,
720
+ linux: "firefox"
721
+ }, {
722
+ wsl: "/mnt/c/Program Files/Mozilla Firefox/firefox.exe"
723
+ }));
724
+ defineLazyProperty(apps, "edge", () => detectPlatformBinary({
725
+ darwin: "microsoft edge",
726
+ win32: "msedge",
727
+ linux: ["microsoft-edge", "microsoft-edge-dev"]
728
+ }, {
729
+ wsl: "/mnt/c/Program Files (x86)/Microsoft/Edge/Application/msedge.exe"
730
+ }));
731
+ defineLazyProperty(apps, "safari", () => detectPlatformBinary({
732
+ darwin: "Safari"
733
+ }));
734
+ open_default = open;
735
+ }
736
+ });
2
737
 
3
738
  // src/cli/index.ts
4
739
  import { CommanderError } from "commander";
@@ -8,7 +743,7 @@ import { Command, InvalidArgumentError } from "commander";
8
743
 
9
744
  // src/package-info.ts
10
745
  var AISNITCH_PACKAGE_NAME = "aisnitch";
11
- var AISNITCH_VERSION = "0.2.21";
746
+ var AISNITCH_VERSION = "0.2.23";
12
747
  var AISNITCH_DESCRIPTION = "Universal bridge for AI coding tool activity \u2014 capture, normalize, stream.";
13
748
 
14
749
  // src/core/events/schema.ts
@@ -117,6 +852,9 @@ var EventDataSchema = z.strictObject({
117
852
  activeFile: z.string().min(1).max(4096).optional(),
118
853
  model: z.string().min(1).max(200).optional(),
119
854
  tokensUsed: z.number().int().min(0).optional(),
855
+ inputTokens: z.number().int().min(0).optional(),
856
+ outputTokens: z.number().int().min(0).optional(),
857
+ cachedTokens: z.number().int().min(0).optional(),
120
858
  errorMessage: z.string().min(1).max(1e4).optional(),
121
859
  errorType: ErrorTypeSchema.optional(),
122
860
  raw: z.record(z.string(), z.unknown()).optional(),
@@ -936,8 +1674,8 @@ var ClaudeCodeSetup = class extends FileToolSetupBase {
936
1674
  return `${JSON.stringify(nextSettings, null, 2)}
937
1675
  `;
938
1676
  }
939
- getFileBackupPath(path) {
940
- return `${path}.bak`;
1677
+ getFileBackupPath(path2) {
1678
+ return `${path2}.bak`;
941
1679
  }
942
1680
  };
943
1681
  var OpenCodeSetup = class extends FileToolSetupBase {
@@ -1177,8 +1915,8 @@ var CopilotCLISetup = class {
1177
1915
  return `${JSON.stringify(nextConfig, null, 2)}
1178
1916
  `;
1179
1917
  }
1180
- getBackupPath(path) {
1181
- return `${path}.bak`;
1918
+ getBackupPath(path2) {
1919
+ return `${path2}.bak`;
1182
1920
  }
1183
1921
  };
1184
1922
  var OpenClawSetup = class {
@@ -1303,8 +2041,8 @@ var OpenClawSetup = class {
1303
2041
  return `${JSON.stringify(nextConfig, null, 2)}
1304
2042
  `;
1305
2043
  }
1306
- getBackupPath(path) {
1307
- return `${path}.bak`;
2044
+ getBackupPath(path2) {
2045
+ return `${path2}.bak`;
1308
2046
  }
1309
2047
  };
1310
2048
  async function createToolSetup(toolName, options = {}, dependencies = {}) {
@@ -2347,17 +3085,17 @@ async function isBinaryAvailable(binaryName) {
2347
3085
  return false;
2348
3086
  }
2349
3087
  }
2350
- async function fileExists(path) {
3088
+ async function fileExists(path2) {
2351
3089
  try {
2352
- await access(path, constants.F_OK);
3090
+ await access(path2, constants.F_OK);
2353
3091
  return true;
2354
3092
  } catch {
2355
3093
  return false;
2356
3094
  }
2357
3095
  }
2358
- async function readOptionalFile(path) {
3096
+ async function readOptionalFile(path2) {
2359
3097
  try {
2360
- return await readFile2(path, "utf8");
3098
+ return await readFile2(path2, "utf8");
2361
3099
  } catch (error) {
2362
3100
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
2363
3101
  return null;
@@ -2368,14 +3106,14 @@ async function readOptionalFile(path) {
2368
3106
  function shellEscapeSingle(value) {
2369
3107
  return `'${value.replaceAll("'", `'"'"'`)}'`;
2370
3108
  }
2371
- async function restoreBackupOrRemove(path) {
2372
- const backupPath = `${path}.bak`;
3109
+ async function restoreBackupOrRemove(path2) {
3110
+ const backupPath = `${path2}.bak`;
2373
3111
  if (await fileExists(backupPath)) {
2374
- await copyFile(backupPath, path);
3112
+ await copyFile(backupPath, path2);
2375
3113
  await rm(backupPath, { force: true });
2376
3114
  return;
2377
3115
  }
2378
- await rm(path, { force: true });
3116
+ await rm(path2, { force: true });
2379
3117
  }
2380
3118
  function buildAiderNotificationCommand(options) {
2381
3119
  const cliArgs = [process.execPath, resolveCurrentCliEntryPath(), "aider-notify"];
@@ -2449,7 +3187,7 @@ import { mkdtemp, readFile as readFile15, rename, rm as rm4, writeFile as writeF
2449
3187
  import { createConnection as createConnection3 } from "net";
2450
3188
  import { tmpdir } from "os";
2451
3189
  import { basename as basename12, join as join18 } from "path";
2452
- import { promisify as promisify15 } from "util";
3190
+ import { promisify as promisify21 } from "util";
2453
3191
 
2454
3192
  // src/adapters/generic-pty.ts
2455
3193
  import { basename as basename3 } from "path";
@@ -5749,7 +6487,7 @@ function extractClaudeTranscriptObservations(payload, transcriptPath) {
5749
6487
  });
5750
6488
  const contentParts = extractClaudeContentParts(payload);
5751
6489
  const model = getString(payload, "model") ?? getString(getRecord(payload.message), "model");
5752
- const tokensUsed = extractTokenUsage(payload);
6490
+ const tokens = extractTokenUsageDetailed(payload);
5753
6491
  const rawPayload = payload;
5754
6492
  const sharedContext = {
5755
6493
  // 📖 Pass process.env so terminal detection works from transcript path too
@@ -5762,7 +6500,10 @@ function extractClaudeTranscriptObservations(payload, transcriptPath) {
5762
6500
  const sharedData = {
5763
6501
  model,
5764
6502
  raw: rawPayload,
5765
- tokensUsed
6503
+ tokensUsed: tokens.total,
6504
+ inputTokens: tokens.input,
6505
+ outputTokens: tokens.output,
6506
+ cachedTokens: tokens.cached
5766
6507
  };
5767
6508
  const observations = [];
5768
6509
  if (contentParts.some((part) => part.type === "thinking")) {
@@ -5820,23 +6561,28 @@ function extractClaudeContentParts(payload) {
5820
6561
  }
5821
6562
  return content.filter(isRecord2);
5822
6563
  }
5823
- function extractTokenUsage(payload) {
6564
+ function extractTokenUsageDetailed(payload) {
5824
6565
  const tokens = getNumber(payload, "tokens");
5825
6566
  if (tokens !== void 0) {
5826
- return tokens;
6567
+ return { total: tokens };
5827
6568
  }
5828
6569
  const usage = getRecord(payload.usage);
5829
6570
  if (!usage) {
5830
- return void 0;
6571
+ return {};
5831
6572
  }
5832
6573
  const totalTokens = getNumber(usage, "total_tokens");
5833
6574
  if (totalTokens !== void 0) {
5834
- return totalTokens;
6575
+ return {
6576
+ total: totalTokens,
6577
+ input: getNumber(usage, "input_tokens"),
6578
+ output: getNumber(usage, "output_tokens"),
6579
+ cached: getNumber(usage, "cached_tokens")
6580
+ };
5835
6581
  }
5836
6582
  const inputTokens = getNumber(usage, "input_tokens") ?? 0;
5837
6583
  const outputTokens = getNumber(usage, "output_tokens") ?? 0;
5838
6584
  const usageSum = inputTokens + outputTokens;
5839
- return usageSum > 0 ? usageSum : void 0;
6585
+ return usageSum > 0 ? { total: usageSum, input: inputTokens, output: outputTokens } : {};
5840
6586
  }
5841
6587
  function extractClaudeToolInput(payload) {
5842
6588
  const toolInput = getRecord(payload.tool_input) ?? getRecord(payload.toolInput);
@@ -10940,7 +11686,17 @@ var OpenCodeAdapter = class extends BaseAdapter {
10940
11686
  project: extractOpenCodeProject(payload),
10941
11687
  raw: payload,
10942
11688
  toolInput: extractOpenCodeToolInput(payload),
10943
- toolName: extractOpenCodeToolName(payload)
11689
+ toolName: extractOpenCodeToolName(payload),
11690
+ // 📖 Extract token usage from payload (with input/output/cached breakdown)
11691
+ ...(() => {
11692
+ const tokens = extractOpenCodeTokens(payload);
11693
+ return {
11694
+ tokensUsed: tokens.total,
11695
+ inputTokens: tokens.inputTokens,
11696
+ outputTokens: tokens.outputTokens,
11697
+ cachedTokens: tokens.cachedTokens
11698
+ };
11699
+ })()
10944
11700
  };
10945
11701
  switch (eventType) {
10946
11702
  case "session.created": {
@@ -10969,9 +11725,21 @@ var OpenCodeAdapter = class extends BaseAdapter {
10969
11725
  await this.emitStateChange("agent.compact", sharedData, context);
10970
11726
  return;
10971
11727
  }
11728
+ case "thinking": {
11729
+ const thinkingContent = extractOpenCodeThinkingContent(payload);
11730
+ await this.emitStateChange("agent.thinking", {
11731
+ ...sharedData,
11732
+ thinkingContent
11733
+ }, context);
11734
+ return;
11735
+ }
10972
11736
  case "message.updated":
10973
11737
  case "message.part.updated": {
10974
- await this.emitStateChange("agent.streaming", sharedData, context);
11738
+ const messageContent = extractOpenCodeMessageContent(payload);
11739
+ await this.emitStateChange("agent.streaming", {
11740
+ ...sharedData,
11741
+ messageContent
11742
+ }, context);
10975
11743
  return;
10976
11744
  }
10977
11745
  case "permission.asked": {
@@ -11190,6 +11958,67 @@ function extractOpenCodeToolResult(payload) {
11190
11958
  }
11191
11959
  return void 0;
11192
11960
  }
11961
+ function extractOpenCodeMessageContent(payload) {
11962
+ const directMessage = getString10(payload, "text") ?? getString10(payload, "message") ?? getString10(payload, "content") ?? getString10(payload, "output");
11963
+ if (directMessage) {
11964
+ return directMessage;
11965
+ }
11966
+ const part = getRecord9(payload.part) ?? getRecord9(getRecord9(payload.properties)?.part);
11967
+ if (part) {
11968
+ return getString10(part, "text") ?? getString10(part, "content");
11969
+ }
11970
+ const props = getRecord9(payload.properties);
11971
+ if (props) {
11972
+ const message = getRecord9(props.message) ?? getRecord9(props.info);
11973
+ if (message) {
11974
+ return getString10(message, "text") ?? getString10(message, "content");
11975
+ }
11976
+ return getString10(props, "text") ?? getString10(props, "message");
11977
+ }
11978
+ return void 0;
11979
+ }
11980
+ function extractOpenCodeThinkingContent(payload) {
11981
+ const directThinking = getString10(payload, "thinking") ?? getString10(payload, "thinkingContent") ?? getString10(payload, "reasoning") ?? getString10(payload, "thought");
11982
+ if (directThinking) {
11983
+ return directThinking;
11984
+ }
11985
+ const props = getRecord9(payload.properties);
11986
+ if (props) {
11987
+ return getString10(props, "thinking") ?? getString10(props, "reasoning") ?? getString10(props, "thought");
11988
+ }
11989
+ return void 0;
11990
+ }
11991
+ function extractOpenCodeTokens(payload) {
11992
+ const directTokens = getNumber8(payload, "tokensUsed") ?? getNumber8(payload, "tokens");
11993
+ if (directTokens !== void 0) {
11994
+ return { total: directTokens };
11995
+ }
11996
+ const props = getRecord9(payload.properties);
11997
+ if (props) {
11998
+ const info = getRecord9(props.info);
11999
+ if (info) {
12000
+ const tokens = getRecord9(info.tokens);
12001
+ if (tokens) {
12002
+ const inputTokens = getNumber8(tokens, "input") ?? 0;
12003
+ const outputTokens = getNumber8(tokens, "output") ?? 0;
12004
+ const reasoningTokens = getNumber8(tokens, "reasoning") ?? 0;
12005
+ const total = inputTokens + outputTokens + reasoningTokens;
12006
+ return total > 0 ? {
12007
+ total,
12008
+ inputTokens,
12009
+ outputTokens,
12010
+ // reasoning tokens are often billed as cached on some providers
12011
+ cachedTokens: reasoningTokens
12012
+ } : {};
12013
+ }
12014
+ }
12015
+ const fallbackTokens = getNumber8(props, "tokensUsed") ?? getNumber8(props, "tokens");
12016
+ if (fallbackTokens !== void 0) {
12017
+ return { total: fallbackTokens };
12018
+ }
12019
+ }
12020
+ return {};
12021
+ }
11193
12022
 
11194
12023
  // src/adapters/pi.ts
11195
12024
  import { execFile as execFile14 } from "child_process";
@@ -14692,9 +15521,9 @@ function flattenValue(lines, currentPath, value) {
14692
15521
  }
14693
15522
  lines.push(formatLoggerField(currentPath, value, inferValueKind(value)));
14694
15523
  }
14695
- function formatLoggerField(path, value, kind) {
15524
+ function formatLoggerField(path2, value, kind) {
14696
15525
  const renderedValue = typeof value === "string" ? JSON.stringify(value) : value === null ? "null" : typeof value === "undefined" ? "undefined" : JSON.stringify(value);
14697
- return `${colorize(path, TUI_THEME.warning)} ${colorize("=", TUI_THEME.muted)} ${colorize(
15526
+ return `${colorize(path2, TUI_THEME.warning)} ${colorize("=", TUI_THEME.muted)} ${colorize(
14698
15527
  renderedValue,
14699
15528
  getValueColor(kind)
14700
15529
  )}`;
@@ -14769,7 +15598,8 @@ function isRecord13(value) {
14769
15598
  }
14770
15599
 
14771
15600
  // src/cli/runtime.ts
14772
- var execFile15 = promisify15(execFileCallback14);
15601
+ var openPromise = Promise.resolve().then(() => (init_open(), open_exports));
15602
+ var execFile21 = promisify21(execFileCallback14);
14773
15603
  var DAEMON_READY_TIMEOUT_MS = 4e3;
14774
15604
  var DAEMON_READY_POLL_INTERVAL_MS = 100;
14775
15605
  var DAEMON_STOP_TIMEOUT_MS = 4e3;
@@ -14785,7 +15615,7 @@ function createCliRuntime(dependencies = {}) {
14785
15615
  spawn: spawnImplementation
14786
15616
  });
14787
15617
  const execFileImplementation = dependencies.execFile ?? (async (file, args) => {
14788
- return await execFile15(file, [...args], {
15618
+ return await execFile21(file, [...args], {
14789
15619
  encoding: "utf8"
14790
15620
  });
14791
15621
  });
@@ -15272,6 +16102,113 @@ function createCliRuntime(dependencies = {}) {
15272
16102
  }
15273
16103
  });
15274
16104
  }
16105
+ async function fullscreen(options) {
16106
+ const snapshot = await getStatusSnapshot(options);
16107
+ if (!snapshot.running && options.daemonMode) {
16108
+ output.stdout("Starting daemon...\n");
16109
+ await startDetachedDaemon(options);
16110
+ }
16111
+ if (!snapshot.running && !options.daemonMode) {
16112
+ throw new Error(
16113
+ "AISnitch daemon is not running. Start one with `aisnitch start --daemon` or use `aisnitch fs --daemon` to start and open the dashboard."
16114
+ );
16115
+ }
16116
+ for (let i = 0; i < 20; i++) {
16117
+ const health = await fetchHealth(snapshot.httpPort);
16118
+ if (health) break;
16119
+ await new Promise((resolve2) => setTimeout(resolve2, 200).unref());
16120
+ }
16121
+ const dashboardPort = options.dashboardPort ?? 5174;
16122
+ const dashboardUrl = `http://127.0.0.1:${dashboardPort}`;
16123
+ const distPath = join18(process.cwd(), "examples", "fullscreen-dashboard", "dist");
16124
+ output.stdout(`Starting dashboard server on port ${dashboardPort}...
16125
+ `);
16126
+ const viteProcess = spawnImplementation(process.execPath, [
16127
+ "-e",
16128
+ `
16129
+ import { createServer } from 'vite';
16130
+ import path from 'path';
16131
+
16132
+ const distPath = '${distPath}';
16133
+ const port = ${dashboardPort};
16134
+
16135
+ const server = await createServer({
16136
+ root: distPath,
16137
+ server: {
16138
+ port,
16139
+ strictPort: true,
16140
+ allowedHosts: true,
16141
+ },
16142
+ preview: {
16143
+ port,
16144
+ strictPort: true,
16145
+ },
16146
+ });
16147
+
16148
+ await server.listen();
16149
+ console.log('READY');
16150
+
16151
+ process.stdin.resume();
16152
+ `
16153
+ ], {
16154
+ cwd: distPath,
16155
+ stdio: ["pipe", "pipe", "pipe"]
16156
+ });
16157
+ let serverOutput = "";
16158
+ viteProcess.stdout?.on("data", (data) => {
16159
+ serverOutput += data.toString();
16160
+ });
16161
+ viteProcess.stderr?.on("data", (data) => {
16162
+ serverOutput += data.toString();
16163
+ });
16164
+ let serverReady = false;
16165
+ for (let i = 0; i < 100; i++) {
16166
+ await new Promise((resolve2) => setTimeout(resolve2, 100).unref());
16167
+ try {
16168
+ const response = await fetchImplementation(dashboardUrl);
16169
+ if (response.ok) {
16170
+ serverReady = true;
16171
+ break;
16172
+ }
16173
+ } catch {
16174
+ }
16175
+ if (!viteProcess.pid) break;
16176
+ }
16177
+ if (!serverReady) {
16178
+ output.stdout(`Server output: ${serverOutput}
16179
+ `);
16180
+ throw new Error("Failed to start dashboard server");
16181
+ }
16182
+ output.stdout(`Dashboard ready at ${dashboardUrl}
16183
+ `);
16184
+ if (!options.noBrowser) {
16185
+ output.stdout("Opening browser...\n");
16186
+ const openModule = await openPromise;
16187
+ await openModule.default(dashboardUrl);
16188
+ }
16189
+ output.stdout("Press Ctrl+C to stop\n");
16190
+ await new Promise((resolve2) => {
16191
+ const shutdown = () => {
16192
+ process.off("SIGINT", handleSigint);
16193
+ process.off("SIGTERM", handleSigterm);
16194
+ if (viteProcess.pid !== void 0) {
16195
+ try {
16196
+ process.kill(viteProcess.pid, "SIGTERM");
16197
+ } catch {
16198
+ }
16199
+ }
16200
+ resolve2();
16201
+ };
16202
+ const handleSigint = () => {
16203
+ shutdown();
16204
+ };
16205
+ const handleSigterm = () => {
16206
+ shutdown();
16207
+ };
16208
+ process.once("SIGINT", handleSigint);
16209
+ process.once("SIGTERM", handleSigterm);
16210
+ });
16211
+ }
15275
16212
  async function logger2(options) {
15276
16213
  const snapshot = await getStatusSnapshot(options);
15277
16214
  if (!snapshot.running) {
@@ -15563,6 +16500,7 @@ function createCliRuntime(dependencies = {}) {
15563
16500
  adapters,
15564
16501
  aiderNotify,
15565
16502
  attach,
16503
+ fullscreen,
15566
16504
  install,
15567
16505
  logger: logger2,
15568
16506
  mock,
@@ -15774,6 +16712,9 @@ Examples:
15774
16712
  aisnitch start --daemon
15775
16713
  aisnitch start --view full-data
15776
16714
  aisnitch start --mock
16715
+ aisnitch fs
16716
+ aisnitch fs --daemon
16717
+ aisnitch fs --dashboard-port 8080
15777
16718
  aisnitch status
15778
16719
  aisnitch attach
15779
16720
  aisnitch attach --view full-data
@@ -15797,6 +16738,7 @@ Examples:
15797
16738
  addAdaptersCommand(program, runtime);
15798
16739
  addSetupCommand(program, runtime);
15799
16740
  addAttachCommand(program, runtime);
16741
+ addFullscreenCommand(program, runtime);
15800
16742
  addLoggerCommand(program, runtime);
15801
16743
  addMockCommand(program, runtime);
15802
16744
  addWrapCommand(program, runtime);
@@ -15929,6 +16871,23 @@ function addAttachCommand(program, runtime) {
15929
16871
  await runtime.attach(options);
15930
16872
  });
15931
16873
  }
16874
+ function addFullscreenCommand(program, runtime) {
16875
+ addCommonOptions(
16876
+ program.command("fs").description("Open the fullscreen web dashboard in browser (starts daemon if needed with --daemon)").alias("fullscreen").option(
16877
+ "--daemon",
16878
+ "Start the daemon automatically if not running"
16879
+ ).option(
16880
+ "--dashboard-port <port>",
16881
+ "Port for the dashboard server (default: 5174)",
16882
+ wrapOptionParser(parsePortOption)
16883
+ ).option(
16884
+ "--no-browser",
16885
+ "Start server without opening browser"
16886
+ )
16887
+ ).action(async (options) => {
16888
+ await runtime.fullscreen(options);
16889
+ });
16890
+ }
15932
16891
  function addWrapCommand(program, runtime) {
15933
16892
  addCommonOptions(
15934
16893
  program.command("wrap").description("Run a command inside a PTY while AISnitch observes its terminal activity").allowUnknownOption(true).argument("<command>", "Command to wrap").argument("[args...]", "Arguments forwarded to the wrapped command").option("--cwd <path>", "Run the wrapped command from a specific working directory")