pikakit 3.9.125 → 3.9.126

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/bin/cli.mjs CHANGED
@@ -1,29 +1,30 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * PikaKit CLI - Main Entry Point
4
- * Routes to install wizard or kit commands
5
- * Using .mjs extension for Windows npx compatibility
6
- */
7
-
8
- const args = process.argv.slice(2);
9
- const firstArg = args[0] || '';
10
-
11
- // List of commands that should go to kit.mjs (not installer)
12
- const kitCommands = [
13
- 'uninstall', 'remove', 'rm',
14
- 'update',
15
- 'init', 'list', 'ls',
16
- 'lock', 'cache',
17
- 'verify', 'doctor', 'validate', 'check', 'analyze',
18
- 'info', 'show',
19
- 'help', '--help', '-h',
20
- '--version', '-V'
21
- ];
22
-
23
- if (kitCommands.includes(firstArg)) {
24
- // Route to kit commands
25
- import('./kit.mjs');
26
- } else {
27
- // Default: installation wizard (no args or org/repo syntax)
28
- import('./install.mjs');
29
- }
2
+ /**
3
+ * PikaKit CLI - Main Entry Point
4
+ * Routes to install wizard or kit commands
5
+ * Using .mjs extension for Windows npx compatibility
6
+ */
7
+
8
+ const args = process.argv.slice(2);
9
+ const firstArg = args[0] || '';
10
+
11
+ // List of commands that should go to kit.mjs (not installer)
12
+ const kitCommands = [
13
+ 'uninstall', 'remove', 'rm',
14
+ 'update',
15
+ 'init', 'list', 'ls',
16
+ 'lock', 'cache',
17
+ 'verify', 'doctor', 'validate', 'check', 'analyze',
18
+ 'cdp', 'devtools',
19
+ 'info', 'show',
20
+ 'help', '--help', '-h',
21
+ '--version', '-V'
22
+ ];
23
+
24
+ if (kitCommands.includes(firstArg)) {
25
+ // Route to kit commands
26
+ import('./kit.mjs');
27
+ } else {
28
+ // Default: installation wizard (no args or org/repo syntax)
29
+ import('./install.mjs');
30
+ }
package/bin/kit.mjs CHANGED
@@ -27,6 +27,9 @@ const COMMANDS = {
27
27
  // Metrics & Observability
28
28
  metrics: { module: "./lib/commands/metrics.js", hasParam: true, aliases: ["stats"] },
29
29
 
30
+ // Tools
31
+ cdp: { module: "./lib/commands/cdp.js", aliases: ["devtools"] },
32
+
30
33
  // Info
31
34
  info: { module: "./lib/commands/info.js", hasParam: true, aliases: ["show"] },
32
35
  help: { module: "./lib/commands/help.js", aliases: ["--help", "-h"] }
@@ -0,0 +1,391 @@
1
+ /**
2
+ * @fileoverview CDP command - Setup Chrome DevTools Protocol for Antigravity
3
+ *
4
+ * Automates the entire CDP setup process:
5
+ * 1. Detects Antigravity installation path
6
+ * 2. Kills ghost processes holding the CDP port
7
+ * 3. Creates/patches desktop shortcut with --remote-debugging-port flag
8
+ * 4. Launches Antigravity with CDP enabled
9
+ * 5. Verifies CDP is active
10
+ */
11
+
12
+ import { execSync, spawn } from "child_process";
13
+ import fs from "fs";
14
+ import path from "path";
15
+ import os from "os";
16
+ import { step, stepLine, S, c, spinner, confirm, isCancel, cancel, select } from "../ui.js";
17
+
18
+ /** Default CDP port */
19
+ const DEFAULT_PORT = 9000;
20
+
21
+ /** Common Antigravity installation paths */
22
+ const ANTIGRAVITY_PATHS = [
23
+ path.join(os.homedir(), "AppData", "Local", "Programs", "Antigravity", "Antigravity.exe"),
24
+ path.join("C:", "Program Files", "Antigravity", "Antigravity.exe"),
25
+ path.join("C:", "Program Files (x86)", "Antigravity", "Antigravity.exe"),
26
+ ];
27
+
28
+ /** Desktop shortcut path */
29
+ const DESKTOP_SHORTCUT = path.join(os.homedir(), "Desktop", "Antigravity.lnk");
30
+
31
+ /**
32
+ * Find Antigravity executable
33
+ * @returns {string|null}
34
+ */
35
+ function findAntigravity() {
36
+ // Check common paths
37
+ for (const p of ANTIGRAVITY_PATHS) {
38
+ if (fs.existsSync(p)) return p;
39
+ }
40
+
41
+ // Try to find from running processes (Windows)
42
+ if (process.platform === "win32") {
43
+ try {
44
+ const result = execSync(
45
+ 'powershell -Command "Get-CimInstance Win32_Process | Where-Object { $_.Name -like \'*Antigravity*\' -and $_.CommandLine -notlike \'*--type=*\' } | Select-Object -First 1 -ExpandProperty ExecutablePath"',
46
+ { encoding: "utf-8", timeout: 10000 }
47
+ ).trim();
48
+ if (result && fs.existsSync(result)) return result;
49
+ } catch { /* not running */ }
50
+ }
51
+
52
+ return null;
53
+ }
54
+
55
+ /**
56
+ * Check if a port is in use
57
+ * @param {number} port
58
+ * @returns {{ inUse: boolean, pid: number|null }}
59
+ */
60
+ function checkPort(port) {
61
+ if (process.platform !== "win32") {
62
+ return { inUse: false, pid: null };
63
+ }
64
+
65
+ try {
66
+ const result = execSync(
67
+ `netstat -ano | findstr ":${port}" | findstr "LISTENING"`,
68
+ { encoding: "utf-8", timeout: 5000 }
69
+ ).trim();
70
+
71
+ if (result) {
72
+ const parts = result.split(/\s+/);
73
+ const pid = parseInt(parts[parts.length - 1], 10);
74
+ return { inUse: true, pid: isNaN(pid) ? null : pid };
75
+ }
76
+ } catch { /* port not in use */ }
77
+
78
+ return { inUse: false, pid: null };
79
+ }
80
+
81
+ /**
82
+ * Kill a process by PID
83
+ * @param {number} pid
84
+ * @returns {boolean}
85
+ */
86
+ function killProcess(pid) {
87
+ try {
88
+ execSync(`taskkill /F /PID ${pid}`, { timeout: 5000 });
89
+ return true;
90
+ } catch { return false; }
91
+ }
92
+
93
+ /**
94
+ * Kill all Antigravity processes
95
+ * @returns {number} Number of processes killed
96
+ */
97
+ function killAllAntigravity() {
98
+ try {
99
+ const result = execSync(
100
+ 'powershell -Command "(Get-Process -Name Antigravity -ErrorAction SilentlyContinue).Count"',
101
+ { encoding: "utf-8", timeout: 5000 }
102
+ ).trim();
103
+
104
+ const count = parseInt(result, 10) || 0;
105
+
106
+ if (count > 0) {
107
+ execSync(
108
+ 'powershell -Command "Stop-Process -Name Antigravity -Force -ErrorAction SilentlyContinue"',
109
+ { timeout: 10000 }
110
+ );
111
+ }
112
+
113
+ return count;
114
+ } catch {
115
+ return 0;
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Check if desktop shortcut already has CDP flag
121
+ * @param {string} shortcutPath
122
+ * @returns {{ exists: boolean, hasCDP: boolean, port: number|null, targetPath: string|null }}
123
+ */
124
+ function checkShortcut(shortcutPath) {
125
+ if (!fs.existsSync(shortcutPath)) {
126
+ return { exists: false, hasCDP: false, port: null, targetPath: null };
127
+ }
128
+
129
+ try {
130
+ const result = execSync(
131
+ `powershell -Command "$ws = New-Object -COM WScript.Shell; $s = $ws.CreateShortcut('${shortcutPath.replace(/'/g, "''")}'); Write-Output $s.Arguments; Write-Output '---SEPARATOR---'; Write-Output $s.TargetPath"`,
132
+ { encoding: "utf-8", timeout: 5000 }
133
+ ).trim();
134
+
135
+ const [args, , targetPath] = result.split("---SEPARATOR---");
136
+ const match = (args || "").match(/--remote-debugging-port=(\d+)/);
137
+
138
+ return {
139
+ exists: true,
140
+ hasCDP: !!match,
141
+ port: match ? parseInt(match[1], 10) : null,
142
+ targetPath: (targetPath || "").trim()
143
+ };
144
+ } catch {
145
+ return { exists: true, hasCDP: false, port: null, targetPath: null };
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Patch desktop shortcut to include CDP flag
151
+ * @param {string} shortcutPath
152
+ * @param {string} exePath
153
+ * @param {number} port
154
+ * @returns {boolean}
155
+ */
156
+ function patchShortcut(shortcutPath, exePath, port) {
157
+ try {
158
+ const escapedShortcut = shortcutPath.replace(/'/g, "''");
159
+ const escapedExe = exePath.replace(/'/g, "''");
160
+ const startIn = path.dirname(exePath).replace(/'/g, "''");
161
+
162
+ const script = `$ws = New-Object -COM WScript.Shell;$s = $ws.CreateShortcut('${escapedShortcut}');$s.TargetPath = '${escapedExe}';$s.Arguments = '--remote-debugging-port=${port}';$s.WorkingDirectory = '${startIn}';$s.Save()`;
163
+
164
+ execSync(`powershell -Command "${script.replace(/"/g, '\\"')}"`, { timeout: 10000 });
165
+ return true;
166
+ } catch {
167
+ return false;
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Create a new desktop shortcut with CDP flag
173
+ * @param {string} exePath
174
+ * @param {number} port
175
+ * @returns {boolean}
176
+ */
177
+ function createShortcut(exePath, port) {
178
+ return patchShortcut(DESKTOP_SHORTCUT, exePath, port);
179
+ }
180
+
181
+ /**
182
+ * Launch Antigravity with CDP flag
183
+ * @param {string} exePath
184
+ * @param {number} port
185
+ */
186
+ function launchAntigravity(exePath, port) {
187
+ const child = spawn(exePath, [`--remote-debugging-port=${port}`], {
188
+ detached: true,
189
+ stdio: "ignore"
190
+ });
191
+ child.unref();
192
+ }
193
+
194
+ /**
195
+ * Wait for CDP to become available
196
+ * @param {number} port
197
+ * @param {number} timeoutMs
198
+ * @returns {Promise<boolean>}
199
+ */
200
+ async function waitForCDP(port, timeoutMs = 15000) {
201
+ const start = Date.now();
202
+
203
+ while (Date.now() - start < timeoutMs) {
204
+ try {
205
+ const result = execSync(
206
+ `powershell -Command "try { $r = Invoke-WebRequest -Uri 'http://127.0.0.1:${port}/json/version' -UseBasicParsing -TimeoutSec 2; Write-Output 'OK' } catch { Write-Output 'FAIL' }"`,
207
+ { encoding: "utf-8", timeout: 5000 }
208
+ ).trim();
209
+
210
+ if (result === "OK") return true;
211
+ } catch { /* retry */ }
212
+
213
+ // Wait 1 second before retry
214
+ await new Promise(r => setTimeout(r, 1000));
215
+ }
216
+
217
+ return false;
218
+ }
219
+
220
+ /**
221
+ * Main CDP setup command
222
+ */
223
+ export async function run() {
224
+ stepLine();
225
+ step(c.bold("CDP Setup — Chrome DevTools Protocol"), S.diamondFilled, "cyan");
226
+ stepLine();
227
+
228
+ // --- Step 1: Detect Antigravity ---
229
+ step("Detecting Antigravity installation...", S.diamond, "cyan");
230
+
231
+ const exePath = findAntigravity();
232
+
233
+ if (!exePath) {
234
+ step(c.red("Antigravity not found!"), S.cross, "red");
235
+ step(c.dim("Install Antigravity first, then run this command again."), S.branch, "gray");
236
+ return;
237
+ }
238
+
239
+ step(`Found: ${c.green(exePath)}`, S.check, "green");
240
+
241
+ // --- Step 2 & 3: Find available port ---
242
+ let port = DEFAULT_PORT;
243
+ let isPortAvailable = false;
244
+ const MAX_PORT = 9003;
245
+
246
+ stepLine();
247
+ step("Scanning for available CDP port (9000-9003)...", S.diamond, "cyan");
248
+
249
+ for (let p = DEFAULT_PORT; p <= MAX_PORT; p++) {
250
+ const portStatus = checkPort(p);
251
+
252
+ if (!portStatus.inUse) {
253
+ port = p;
254
+ isPortAvailable = true;
255
+ step(c.green(`Port ${port} is available`), S.check, "green");
256
+ break;
257
+ }
258
+
259
+ step(c.yellow(`Port ${p} is occupied by PID ${portStatus.pid}`), S.diamond, "yellow");
260
+
261
+ // Check if it's an Antigravity process
262
+ let isAntigravity = false;
263
+ if (portStatus.pid) {
264
+ try {
265
+ const name = execSync(
266
+ `powershell -Command "(Get-Process -Id ${portStatus.pid} -ErrorAction SilentlyContinue).ProcessName"`,
267
+ { encoding: "utf-8", timeout: 5000 }
268
+ ).trim();
269
+ isAntigravity = name.toLowerCase().includes("antigravity");
270
+ } catch { /* process may have ended */ }
271
+ }
272
+
273
+ if (isAntigravity) {
274
+ step("Port is held by a running Antigravity instance", S.diamond, "yellow");
275
+ step(c.dim("We will restart it safely to avoid abruptly killing your terminal."), S.branch, "gray");
276
+ port = p;
277
+ isPortAvailable = true;
278
+ break;
279
+ } else {
280
+ step("Port is held by another process or ghost process. Attempting to free...", S.diamond, "yellow");
281
+
282
+ if (portStatus.pid) killProcess(portStatus.pid);
283
+
284
+ // Wait for port to be freed
285
+ await new Promise(r => setTimeout(r, 2000));
286
+
287
+ const recheck = checkPort(p);
288
+ if (!recheck.inUse) {
289
+ port = p;
290
+ isPortAvailable = true;
291
+ step(c.green(`Port ${port} freed successfully`), S.check, "green");
292
+ break;
293
+ } else {
294
+ step(c.dim(`Could not free port ${p}. Trying next port...`), S.branch, "gray");
295
+ }
296
+ }
297
+ }
298
+
299
+ if (!isPortAvailable) {
300
+ step(c.red(`Could not find any available port between 9000-9003.`), S.cross, "red");
301
+ step(c.dim(`Please try restarting your computer.`), S.branch, "gray");
302
+ return;
303
+ }
304
+
305
+ // --- Step 4: Setup shortcut ---
306
+ stepLine();
307
+ step("Setting up Desktop shortcut...", S.diamond, "cyan");
308
+
309
+ const shortcutInfo = checkShortcut(DESKTOP_SHORTCUT);
310
+
311
+ if (shortcutInfo.exists && shortcutInfo.hasCDP && shortcutInfo.port === port) {
312
+ step(c.green("Shortcut already configured with CDP"), S.check, "green");
313
+ } else if (shortcutInfo.exists) {
314
+ // Patch existing shortcut
315
+ const patched = patchShortcut(DESKTOP_SHORTCUT, exePath, port);
316
+ if (patched) {
317
+ step(c.green(`Shortcut updated with --remote-debugging-port=${port}`), S.check, "green");
318
+ } else {
319
+ step(c.yellow("Could not update shortcut (run as Admin?)"), S.diamond, "yellow");
320
+ }
321
+ } else {
322
+ // Create new shortcut
323
+ const created = createShortcut(exePath, port);
324
+ if (created) {
325
+ step(c.green(`Shortcut created on Desktop with CDP enabled`), S.check, "green");
326
+ } else {
327
+ step(c.yellow("Could not create shortcut"), S.diamond, "yellow");
328
+ }
329
+ }
330
+
331
+ // --- Step 5: Ask to launch ---
332
+ stepLine();
333
+
334
+ const shouldLaunch = await confirm({
335
+ message: "Restart Antigravity to enable CDP now? (Will close current window)",
336
+ initialValue: true
337
+ });
338
+
339
+ if (isCancel(shouldLaunch) || !shouldLaunch) {
340
+ stepLine();
341
+ step(c.green("CDP setup complete!"), S.check, "green");
342
+ step(c.dim("Please close and re-launch Antigravity from the Desktop shortcut to use CDP."), S.branch, "gray");
343
+ stepLine();
344
+ return;
345
+ }
346
+
347
+ // --- Step 6: Launch & verify ---
348
+ step(c.cyan("Preparing to restart Antigravity..."), S.diamond, "cyan");
349
+
350
+ // Write a self-deleting .bat file that handles the restart sequence.
351
+ // This is more reliable than spawning a detached child process because:
352
+ // 1. The .bat file persists on disk even when the parent (Antigravity) dies
353
+ // 2. cmd.exe /c start launches it in a truly independent process
354
+ // 3. The bat file cleans itself up after execution
355
+ const batPath = path.join(os.tmpdir(), `pikakit-cdp-restart-${Date.now()}.bat`);
356
+ const batContent = [
357
+ "@echo off",
358
+ "timeout /t 3 /nobreak >nul",
359
+ "taskkill /IM Antigravity.exe /F >nul 2>&1",
360
+ "timeout /t 2 /nobreak >nul",
361
+ `start "" "${exePath}" --remote-debugging-port=${port}`,
362
+ `del "%~f0"`
363
+ ].join("\r\n");
364
+
365
+ fs.writeFileSync(batPath, batContent, "utf-8");
366
+
367
+ // Launch the bat file in a fully detached, hidden window via wscript
368
+ // This ensures it runs even after our process and Antigravity are killed
369
+ const vbsPath = path.join(os.tmpdir(), `pikakit-cdp-launcher-${Date.now()}.vbs`);
370
+ const vbsContent = `CreateObject("Wscript.Shell").Run """${batPath}""", 0, False`;
371
+ fs.writeFileSync(vbsPath, vbsContent, "utf-8");
372
+
373
+ const child = spawn("wscript.exe", [vbsPath], {
374
+ detached: true,
375
+ stdio: "ignore"
376
+ });
377
+ child.unref();
378
+
379
+ // --- Summary ---
380
+ stepLine();
381
+ step(c.bold(c.green("✓ CDP Setup Complete - Restarting System")), S.diamondFilled, "green");
382
+ stepLine();
383
+
384
+ console.log(`${c.gray(S.branch)} ${c.dim("Status:")} The editor will close automatically in 2 seconds...`);
385
+ console.log(`${c.gray(S.branch)} ${c.dim("Action:")} It will restart with CDP turned ${c.green("ON")}.`);
386
+ stepLine();
387
+
388
+ // We do not wait for CDP because we are about to be killed
389
+ process.exit(0);
390
+ stepLine();
391
+ }
@@ -91,6 +91,11 @@ async function showCommands() {
91
91
  step(c.cyan("lock") + c.dim(" Generate skill-lock.json"));
92
92
  stepLine();
93
93
 
94
+ // Tools
95
+ step(c.bold(c.blue("Tools")));
96
+ step(c.cyan("cdp") + c.dim(" Setup CDP (Chrome DevTools Protocol)"));
97
+ stepLine();
98
+
94
99
  // Developer Commands
95
100
  step(c.bold(c.magenta("Developer Commands")));
96
101
  step(c.cyan("validate [skill]") + c.dim(" Validate against spec"));
@@ -199,6 +204,11 @@ function showQuickStart() {
199
204
  step(" " + c.cyan("npx pikakit doctor"));
200
205
  stepLine();
201
206
 
202
- step(c.bold("5. Use in your AI"));
207
+ step(c.bold("5. Enable CDP (Browser Control)"));
208
+ step(" " + c.cyan("npx pikakit cdp"));
209
+ step(" " + c.dim("→ Auto-setup CDP for Antigravity (kills ghost processes, patches shortcut)"));
210
+ stepLine();
211
+
212
+ step(c.bold("6. Use in your AI"));
203
213
  step(" " + c.dim("Skills are now available in .agent/skills/"));
204
214
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pikakit",
3
- "version": "3.9.125",
3
+ "version": "3.9.126",
4
4
  "description": "PikaKit FAANG-Grade AI Operating System — Install 51 skills, 18 workflows.",
5
5
  "license": "Proprietary",
6
6
  "author": "pikakit <pikakit@gmail.com>",
@@ -36,7 +36,7 @@ The extension is installed automatically during skill installation.
36
36
  cd packages/pikakit-extension
37
37
  npm install && npm run compile
38
38
  npx @vscode/vsce package --allow-missing-repository
39
- code --install-extension pikakit-engine-3.9.125.vsix
39
+ code --install-extension pikakit-engine-3.9.126.vsix
40
40
  ```
41
41
 
42
42
  ### Local Development
@@ -121,4 +121,4 @@ Autopilot includes dangerous command blocking for:
121
121
 
122
122
  ---
123
123
 
124
- ⚡ PikaKit Engine v3.9.125
124
+ ⚡ PikaKit Engine v3.9.126