@diegopetrucci/pi-extensions 0.1.74 → 0.1.78

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.
Files changed (108) hide show
  1. package/LICENSE +2 -0
  2. package/README.md +17 -12
  3. package/extensions/agent-workflow-audit/README.md +1 -1
  4. package/extensions/agent-workflow-audit/index.ts +1631 -1009
  5. package/extensions/agent-workflow-audit/package.json +1 -1
  6. package/extensions/annotate-git-diff/README.md +3 -1
  7. package/extensions/annotate-git-diff/clipboard.ts +109 -100
  8. package/extensions/annotate-git-diff/git.ts +846 -768
  9. package/extensions/annotate-git-diff/glimpseui.d.ts +87 -78
  10. package/extensions/annotate-git-diff/index.ts +712 -671
  11. package/extensions/annotate-git-diff/package.json +1 -1
  12. package/extensions/annotate-git-diff/prompt.ts +45 -45
  13. package/extensions/annotate-git-diff/quiet-glimpse.ts +161 -155
  14. package/extensions/annotate-git-diff/review-server.ts +337 -311
  15. package/extensions/annotate-git-diff/types.ts +132 -132
  16. package/extensions/annotate-git-diff/ui.ts +27 -27
  17. package/extensions/annotate-git-diff/watch.ts +74 -74
  18. package/extensions/annotate-git-diff/web/app.js +1947 -1884
  19. package/extensions/annotate-git-diff/web/index.html +5 -6
  20. package/extensions/annotate-last-message/README.md +1 -1
  21. package/extensions/annotate-last-message/glimpseui.d.ts +87 -78
  22. package/extensions/annotate-last-message/index.ts +210 -206
  23. package/extensions/annotate-last-message/package.json +1 -1
  24. package/extensions/annotate-last-message/prompt.ts +87 -66
  25. package/extensions/annotate-last-message/quiet-glimpse.ts +161 -155
  26. package/extensions/annotate-last-message/session.ts +94 -89
  27. package/extensions/annotate-last-message/theme.ts +199 -193
  28. package/extensions/annotate-last-message/types.ts +23 -23
  29. package/extensions/annotate-last-message/ui.ts +27 -25
  30. package/extensions/annotate-last-message/web/app.js +4 -7
  31. package/extensions/annotate-last-message/web/index.html +3 -3
  32. package/extensions/annotate-last-message/web/md-renderer.js +1 -1
  33. package/extensions/brrr/README.md +1 -1
  34. package/extensions/brrr/index.ts +213 -191
  35. package/extensions/brrr/package.json +1 -1
  36. package/extensions/claude-fast/README.md +5 -79
  37. package/extensions/claude-fast/index.ts +31 -289
  38. package/extensions/claude-fast/package.json +2 -3
  39. package/extensions/code-reviewer/README.md +6 -6
  40. package/extensions/code-reviewer/index.ts +1825 -1373
  41. package/extensions/code-reviewer/package.json +1 -1
  42. package/extensions/confirm-destructive/README.md +1 -1
  43. package/extensions/confirm-destructive/index.ts +50 -52
  44. package/extensions/confirm-destructive/package.json +1 -1
  45. package/extensions/context-cap/README.md +9 -9
  46. package/extensions/context-cap/index.ts +313 -305
  47. package/extensions/context-cap/package.json +2 -2
  48. package/extensions/context-inspector/index.ts +1211 -1064
  49. package/extensions/context-inspector/package.json +1 -1
  50. package/extensions/contrarian/README.md +4 -3
  51. package/extensions/contrarian/index.ts +1863 -1737
  52. package/extensions/contrarian/package.json +1 -1
  53. package/extensions/dirty-repo-guard/index.ts +37 -41
  54. package/extensions/dirty-repo-guard/package.json +1 -1
  55. package/extensions/dynamic-context-pruning/README.md +11 -43
  56. package/extensions/dynamic-context-pruning/index.ts +2131 -2105
  57. package/extensions/dynamic-context-pruning/package.json +1 -1
  58. package/extensions/fast/README.md +52 -14
  59. package/extensions/fast/index.ts +513 -317
  60. package/extensions/fast/package.json +1 -1
  61. package/extensions/git-footer/README.md +1 -1
  62. package/extensions/git-footer/index.ts +458 -411
  63. package/extensions/git-footer/package.json +2 -3
  64. package/extensions/gnosis/index.ts +180 -130
  65. package/extensions/gnosis/package.json +1 -1
  66. package/extensions/inline-bash/index.ts +87 -103
  67. package/extensions/inline-bash/package.json +1 -1
  68. package/extensions/librarian/README.md +1 -1
  69. package/extensions/librarian/index.ts +1877 -1419
  70. package/extensions/librarian/package.json +1 -1
  71. package/extensions/minimal-footer/README.md +5 -5
  72. package/extensions/minimal-footer/index.ts +987 -1012
  73. package/extensions/minimal-footer/minimal-footer.example.json +1 -1
  74. package/extensions/minimal-footer/openai-usage.ts +195 -190
  75. package/extensions/minimal-footer/package.json +1 -1
  76. package/extensions/notify/index.ts +222 -230
  77. package/extensions/notify/package.json +1 -1
  78. package/extensions/openai-fast/README.md +5 -73
  79. package/extensions/openai-fast/index.ts +32 -272
  80. package/extensions/openai-fast/package.json +2 -3
  81. package/extensions/oracle/README.md +4 -3
  82. package/extensions/oracle/index.ts +1740 -1627
  83. package/extensions/oracle/package.json +1 -1
  84. package/extensions/permission-gate/README.md +3 -0
  85. package/extensions/permission-gate/index.ts +785 -612
  86. package/extensions/permission-gate/package.json +1 -1
  87. package/extensions/permission-gate/powershell-safety.ts +840 -793
  88. package/extensions/project-mcp-json/.pi-fleet-tested-version +1 -0
  89. package/extensions/project-mcp-json/README.md +199 -0
  90. package/extensions/project-mcp-json/config.ts +564 -0
  91. package/extensions/project-mcp-json/index.ts +119 -0
  92. package/extensions/project-mcp-json/package.json +38 -0
  93. package/extensions/quiet-tools/.pi-fleet-tested-version +1 -1
  94. package/extensions/quiet-tools/README.md +30 -19
  95. package/extensions/quiet-tools/index.ts +376 -291
  96. package/extensions/quiet-tools/package.json +2 -2
  97. package/extensions/review/README.md +2 -2
  98. package/extensions/review/index.ts +1745 -1872
  99. package/extensions/review/package.json +1 -1
  100. package/extensions/todo/index.ts +280 -280
  101. package/extensions/todo/package.json +1 -1
  102. package/extensions/triage-comments/README.md +6 -4
  103. package/extensions/triage-comments/index.ts +2620 -1888
  104. package/extensions/triage-comments/package.json +1 -1
  105. package/package.json +9 -6
  106. package/assets/social-preview.png +0 -0
  107. package/extensions/claude-fast/claude-fast.example.json +0 -4
  108. package/extensions/openai-fast/openai-fast.example.json +0 -4
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diegopetrucci/pi-annotate-git-diff",
3
- "version": "0.1.12",
3
+ "version": "0.1.14",
4
4
  "description": "A standalone pi extension that adds /annotate-git-diff, a native Glimpse UI for annotating git diffs and sending explicit feedback directly to the agent; close recovery keeps unsent drafts in the editor.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -1,66 +1,66 @@
1
1
  import type { DiffReviewComment, ReviewFile, ReviewSubmitPayload } from "./types.js";
2
2
 
3
3
  function formatScopeLabel(comment: DiffReviewComment): string {
4
- switch (comment.scope) {
5
- case "branch":
6
- return "branch diff";
7
- case "commits":
8
- return comment.commitKind === "working-tree"
9
- ? "working tree changes"
10
- : comment.commitShort
11
- ? `commit ${comment.commitShort}`
12
- : "commit";
13
- default:
14
- return "all files";
15
- }
4
+ switch (comment.scope) {
5
+ case "branch":
6
+ return "branch diff";
7
+ case "commits":
8
+ return comment.commitKind === "working-tree"
9
+ ? "working tree changes"
10
+ : comment.commitShort
11
+ ? `commit ${comment.commitShort}`
12
+ : "commit";
13
+ default:
14
+ return "all files";
15
+ }
16
16
  }
17
17
 
18
18
  function getCommentFilePath(file: ReviewFile | undefined): string {
19
- if (file == null) return "(unknown file)";
20
- return file.gitDiff?.displayPath ?? file.path;
19
+ if (file == null) return "(unknown file)";
20
+ return file.gitDiff?.displayPath ?? file.path;
21
21
  }
22
22
 
23
23
  function formatLocation(comment: DiffReviewComment, file: ReviewFile | undefined): string {
24
- const filePath = getCommentFilePath(file);
25
- const scopePrefix = `[${formatScopeLabel(comment)}] `;
24
+ const filePath = getCommentFilePath(file);
25
+ const scopePrefix = `[${formatScopeLabel(comment)}] `;
26
26
 
27
- if (comment.side === "file" || comment.startLine == null) {
28
- return `${scopePrefix}${filePath}`;
29
- }
27
+ if (comment.side === "file" || comment.startLine == null) {
28
+ return `${scopePrefix}${filePath}`;
29
+ }
30
30
 
31
- const range =
32
- comment.endLine != null && comment.endLine !== comment.startLine
33
- ? `${comment.startLine}-${comment.endLine}`
34
- : `${comment.startLine}`;
31
+ const range =
32
+ comment.endLine != null && comment.endLine !== comment.startLine
33
+ ? `${comment.startLine}-${comment.endLine}`
34
+ : `${comment.startLine}`;
35
35
 
36
- if (comment.scope === "all") {
37
- return `${scopePrefix}${filePath}:${range}`;
38
- }
36
+ if (comment.scope === "all") {
37
+ return `${scopePrefix}${filePath}:${range}`;
38
+ }
39
39
 
40
- const suffix = comment.side === "original" ? " (old)" : " (new)";
41
- return `${scopePrefix}${filePath}:${range}${suffix}`;
40
+ const suffix = comment.side === "original" ? " (old)" : " (new)";
41
+ return `${scopePrefix}${filePath}:${range}${suffix}`;
42
42
  }
43
43
 
44
44
  export function composeReviewPrompt(files: ReviewFile[], payload: ReviewSubmitPayload): string {
45
- const fileMap = new Map(files.map((file) => [file.id, file]));
46
- const comments = payload.comments.filter((comment) => comment.body.trim().length > 0);
47
- const lines: string[] = [];
45
+ const fileMap = new Map(files.map((file) => [file.id, file]));
46
+ const comments = payload.comments.filter((comment) => comment.body.trim().length > 0);
47
+ const lines: string[] = [];
48
48
 
49
- lines.push("Please address the following feedback");
50
- lines.push("");
49
+ lines.push("Please address the following feedback");
50
+ lines.push("");
51
51
 
52
- const overallComment = payload.overallComment.trim();
53
- if (overallComment.length > 0) {
54
- lines.push(overallComment);
55
- lines.push("");
56
- }
52
+ const overallComment = payload.overallComment.trim();
53
+ if (overallComment.length > 0) {
54
+ lines.push(overallComment);
55
+ lines.push("");
56
+ }
57
57
 
58
- comments.forEach((comment, index) => {
59
- const file = fileMap.get(comment.fileId);
60
- lines.push(`${index + 1}. ${formatLocation(comment, file)}`);
61
- lines.push(` ${comment.body.trim()}`);
62
- lines.push("");
63
- });
58
+ comments.forEach((comment, index) => {
59
+ const file = fileMap.get(comment.fileId);
60
+ lines.push(`${index + 1}. ${formatLocation(comment, file)}`);
61
+ lines.push(` ${comment.body.trim()}`);
62
+ lines.push("");
63
+ });
64
64
 
65
- return lines.join("\n").trim();
65
+ return lines.join("\n").trim();
66
66
  }
@@ -7,173 +7,179 @@ import { createInterface } from "node:readline";
7
7
  import type { GlimpseOpenOptions } from "glimpseui";
8
8
 
9
9
  interface NativeHostInfo {
10
- path: string;
11
- extraArgs?: string[];
12
- buildHint?: string;
10
+ path: string;
11
+ extraArgs?: string[];
12
+ buildHint?: string;
13
13
  }
14
14
 
15
15
  interface GlimpseProtocolMessage {
16
- type?: string;
17
- data?: unknown;
18
- screen?: unknown;
19
- screens?: unknown;
20
- appearance?: unknown;
21
- cursor?: unknown;
22
- cursorTip?: unknown;
16
+ type?: string;
17
+ data?: unknown;
18
+ screen?: unknown;
19
+ screens?: unknown;
20
+ appearance?: unknown;
21
+ cursor?: unknown;
22
+ cursorTip?: unknown;
23
23
  }
24
24
 
25
25
  export interface QuietGlimpseWindow {
26
- readonly closed: boolean;
27
- readonly failure: Error | null;
28
- on(event: "message", listener: (data: unknown) => void): this;
29
- on(event: "closed", listener: () => void): this;
30
- on(event: "error", listener: (error: Error) => void): this;
31
- removeListener(event: "message", listener: (data: unknown) => void): this;
32
- removeListener(event: "closed", listener: () => void): this;
33
- removeListener(event: "error", listener: (error: Error) => void): this;
34
- send(js: string): void;
35
- close(): void;
26
+ readonly closed: boolean;
27
+ readonly failure: Error | null;
28
+ on(event: "message", listener: (data: unknown) => void): this;
29
+ on(event: "closed", listener: () => void): this;
30
+ on(event: "error", listener: (error: Error) => void): this;
31
+ removeListener(event: "message", listener: (data: unknown) => void): this;
32
+ removeListener(event: "closed", listener: () => void): this;
33
+ removeListener(event: "error", listener: (error: Error) => void): this;
34
+ send(js: string): void;
35
+ close(): void;
36
36
  }
37
37
 
38
38
  class QuietGlimpseWindowImpl extends EventEmitter implements QuietGlimpseWindow {
39
- #proc: ChildProcessWithoutNullStreams;
40
- #closed = false;
41
- #pendingHTML: string | null;
42
- #stderr = "";
43
- #failure: Error | null = null;
44
-
45
- constructor(proc: ChildProcessWithoutNullStreams, initialHTML: string) {
46
- super();
47
- this.#proc = proc;
48
- this.#pendingHTML = initialHTML;
49
- // EventEmitter treats an unobserved `error` as fatal. Keep a permanent
50
- // fallback while callers attach and detach their lifecycle listeners.
51
- this.on("error", () => {});
52
-
53
- proc.stdin.on("error", () => {});
54
- proc.stderr.on("data", (chunk) => {
55
- this.#stderr += chunk.toString();
56
- });
57
-
58
- const rl = createInterface({ input: proc.stdout, crlfDelay: Infinity });
59
- rl.on("line", (line) => {
60
- let parsed: unknown;
61
- try {
62
- parsed = JSON.parse(line);
63
- } catch {
64
- this.#reportError(new Error(`Malformed glimpse protocol line: ${line}`));
65
- return;
66
- }
67
- if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return;
68
- const message = parsed as GlimpseProtocolMessage;
69
-
70
- switch (message.type) {
71
- case "ready":
72
- if (this.#pendingHTML != null) {
73
- this.setHTML(this.#pendingHTML);
74
- this.#pendingHTML = null;
75
- }
76
- break;
77
- case "message":
78
- this.emit("message", message.data);
79
- break;
80
- case "closed":
81
- this.#markClosed();
82
- break;
83
- default:
84
- break;
85
- }
86
- });
87
-
88
- proc.on("error", (error) => this.#reportError(error));
89
- proc.on("exit", (code, signal) => {
90
- const stderr = this.#stderr.trim();
91
- const failed = signal != null || (code != null && code !== 0);
92
- if (!this.#closed && failed) {
93
- const message = stderr || `Glimpse process exited abnormally (code: ${code}, signal: ${signal}).`;
94
- this.#reportError(new Error(message));
95
- }
96
- this.#markClosed();
97
- });
98
- // Spawn failures can emit `error` and then `close` without `exit`.
99
- proc.on("close", () => this.#markClosed());
100
- }
101
-
102
- send(js: string): void {
103
- this.#write({ type: "eval", js });
104
- }
105
-
106
- close(): void {
107
- this.#write({ type: "close" });
108
- }
109
-
110
- get closed(): boolean {
111
- return this.#closed;
112
- }
113
-
114
- get failure(): Error | null {
115
- return this.#failure;
116
- }
117
-
118
- #reportError(error: Error): void {
119
- this.#failure ??= error;
120
- this.emit("error", error);
121
- }
122
-
123
- #markClosed(): void {
124
- if (this.#closed) return;
125
- this.#closed = true;
126
- this.emit("closed");
127
- }
128
-
129
- #write(obj: Record<string, unknown>): void {
130
- if (this.#closed) return;
131
- this.#proc.stdin.write(`${JSON.stringify(obj)}\n`);
132
- }
133
-
134
- setHTML(html: string): void {
135
- this.#write({ type: "html", html: Buffer.from(html).toString("base64") });
136
- }
39
+ #proc: ChildProcessWithoutNullStreams;
40
+ #closed = false;
41
+ #pendingHTML: string | null;
42
+ #stderr = "";
43
+ #failure: Error | null = null;
44
+
45
+ constructor(proc: ChildProcessWithoutNullStreams, initialHTML: string) {
46
+ super();
47
+ this.#proc = proc;
48
+ this.#pendingHTML = initialHTML;
49
+ // EventEmitter treats an unobserved `error` as fatal. Keep a permanent
50
+ // fallback while callers attach and detach their lifecycle listeners.
51
+ this.on("error", () => {});
52
+
53
+ proc.stdin.on("error", () => {});
54
+ proc.stderr.on("data", (chunk) => {
55
+ this.#stderr += chunk.toString();
56
+ });
57
+
58
+ const rl = createInterface({ input: proc.stdout, crlfDelay: Infinity });
59
+ rl.on("line", (line) => {
60
+ let parsed: unknown;
61
+ try {
62
+ parsed = JSON.parse(line);
63
+ } catch {
64
+ this.#reportError(new Error(`Malformed glimpse protocol line: ${line}`));
65
+ return;
66
+ }
67
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return;
68
+ const message = parsed as GlimpseProtocolMessage;
69
+
70
+ switch (message.type) {
71
+ case "ready":
72
+ if (this.#pendingHTML != null) {
73
+ this.setHTML(this.#pendingHTML);
74
+ this.#pendingHTML = null;
75
+ }
76
+ break;
77
+ case "message":
78
+ this.emit("message", message.data);
79
+ break;
80
+ case "closed":
81
+ this.#markClosed();
82
+ break;
83
+ default:
84
+ break;
85
+ }
86
+ });
87
+
88
+ proc.on("error", (error) => this.#reportError(error));
89
+ proc.on("exit", (code, signal) => {
90
+ const stderr = this.#stderr.trim();
91
+ const failed = signal != null || (code != null && code !== 0);
92
+ if (!this.#closed && failed) {
93
+ const message =
94
+ stderr || `Glimpse process exited abnormally (code: ${code}, signal: ${signal}).`;
95
+ this.#reportError(new Error(message));
96
+ }
97
+ this.#markClosed();
98
+ });
99
+ // Spawn failures can emit `error` and then `close` without `exit`.
100
+ proc.on("close", () => this.#markClosed());
101
+ }
102
+
103
+ send(js: string): void {
104
+ this.#write({ type: "eval", js });
105
+ }
106
+
107
+ close(): void {
108
+ this.#write({ type: "close" });
109
+ }
110
+
111
+ get closed(): boolean {
112
+ return this.#closed;
113
+ }
114
+
115
+ get failure(): Error | null {
116
+ return this.#failure;
117
+ }
118
+
119
+ #reportError(error: Error): void {
120
+ this.#failure ??= error;
121
+ this.emit("error", error);
122
+ }
123
+
124
+ #markClosed(): void {
125
+ if (this.#closed) return;
126
+ this.#closed = true;
127
+ this.emit("closed");
128
+ }
129
+
130
+ #write(obj: Record<string, unknown>): void {
131
+ if (this.#closed) return;
132
+ this.#proc.stdin.write(`${JSON.stringify(obj)}\n`);
133
+ }
134
+
135
+ setHTML(html: string): void {
136
+ this.#write({ type: "html", html: Buffer.from(html).toString("base64") });
137
+ }
137
138
  }
138
139
 
139
140
  async function getNativeHostInfo(): Promise<NativeHostInfo> {
140
- const glimpseModule = (await import("glimpseui")) as unknown as { getNativeHostInfo: () => NativeHostInfo };
141
- return glimpseModule.getNativeHostInfo();
141
+ const glimpseModule = (await import("glimpseui")) as unknown as {
142
+ getNativeHostInfo: () => NativeHostInfo;
143
+ };
144
+ return glimpseModule.getNativeHostInfo();
142
145
  }
143
146
 
144
- export async function openQuietGlimpse(html: string, options: GlimpseOpenOptions = {}): Promise<QuietGlimpseWindow> {
145
- const host = await getNativeHostInfo();
146
- if (!existsSync(host.path)) {
147
- const hint = host.buildHint ? ` ${host.buildHint}` : "";
148
- throw new Error(`Glimpse host not found at '${host.path}'.${hint}`);
149
- }
150
- const args: string[] = [];
151
-
152
- if (options.width != null) args.push("--width", String(options.width));
153
- if (options.height != null) args.push("--height", String(options.height));
154
- if (options.title != null) args.push("--title", options.title);
155
- if (options.frameless) args.push("--frameless");
156
- if (options.floating) args.push("--floating");
157
- if (options.transparent) args.push("--transparent");
158
- if (options.clickThrough) args.push("--click-through");
159
- if (options.hidden) args.push("--hidden");
160
- if (options.autoClose) args.push("--auto-close");
161
- if (options.x != null) args.push(`--x=${options.x}`);
162
- if (options.y != null) args.push(`--y=${options.y}`);
163
- if (options.cursorOffset?.x != null) args.push(`--cursor-offset-x=${options.cursorOffset.x}`);
164
- if (options.cursorOffset?.y != null) args.push(`--cursor-offset-y=${options.cursorOffset.y}`);
165
- if (options.cursorAnchor != null) args.push("--cursor-anchor", options.cursorAnchor);
166
- if (options.followMode != null) args.push("--follow-mode", options.followMode);
167
- if (options.followCursor) args.push("--follow-cursor");
168
-
169
- const proc = spawn(host.path, [...(host.extraArgs ?? []), ...args], {
170
- stdio: ["pipe", "pipe", "pipe"],
171
- windowsHide: process.platform === "win32",
172
- env: {
173
- ...process.env,
174
- OS_ACTIVITY_MODE: process.env.OS_ACTIVITY_MODE ?? "disable",
175
- },
176
- });
177
-
178
- return new QuietGlimpseWindowImpl(proc, html);
147
+ export async function openQuietGlimpse(
148
+ html: string,
149
+ options: GlimpseOpenOptions = {},
150
+ ): Promise<QuietGlimpseWindow> {
151
+ const host = await getNativeHostInfo();
152
+ if (!existsSync(host.path)) {
153
+ const hint = host.buildHint ? ` ${host.buildHint}` : "";
154
+ throw new Error(`Glimpse host not found at '${host.path}'.${hint}`);
155
+ }
156
+ const args: string[] = [];
157
+
158
+ if (options.width != null) args.push("--width", String(options.width));
159
+ if (options.height != null) args.push("--height", String(options.height));
160
+ if (options.title != null) args.push("--title", options.title);
161
+ if (options.frameless) args.push("--frameless");
162
+ if (options.floating) args.push("--floating");
163
+ if (options.transparent) args.push("--transparent");
164
+ if (options.clickThrough) args.push("--click-through");
165
+ if (options.hidden) args.push("--hidden");
166
+ if (options.autoClose) args.push("--auto-close");
167
+ if (options.x != null) args.push(`--x=${options.x}`);
168
+ if (options.y != null) args.push(`--y=${options.y}`);
169
+ if (options.cursorOffset?.x != null) args.push(`--cursor-offset-x=${options.cursorOffset.x}`);
170
+ if (options.cursorOffset?.y != null) args.push(`--cursor-offset-y=${options.cursorOffset.y}`);
171
+ if (options.cursorAnchor != null) args.push("--cursor-anchor", options.cursorAnchor);
172
+ if (options.followMode != null) args.push("--follow-mode", options.followMode);
173
+ if (options.followCursor) args.push("--follow-cursor");
174
+
175
+ const proc = spawn(host.path, [...(host.extraArgs ?? []), ...args], {
176
+ stdio: ["pipe", "pipe", "pipe"],
177
+ windowsHide: process.platform === "win32",
178
+ env: {
179
+ ...process.env,
180
+ OS_ACTIVITY_MODE: process.env.OS_ACTIVITY_MODE ?? "disable",
181
+ },
182
+ });
183
+
184
+ return new QuietGlimpseWindowImpl(proc, html);
179
185
  }