@devness/useai-cli 0.4.20 → 0.4.21

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 (2) hide show
  1. package/dist/index.js +58 -33
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4589,7 +4589,7 @@ function buildNodePath() {
4589
4589
 
4590
4590
  // ../shared/dist/daemon/ensure.js
4591
4591
  import { existsSync as existsSync5, readFileSync as readFileSync2, unlinkSync } from "fs";
4592
- import { spawn } from "child_process";
4592
+ import { execSync as execSync2, spawn } from "child_process";
4593
4593
  function readPidFile() {
4594
4594
  if (!existsSync5(DAEMON_PID_FILE))
4595
4595
  return null;
@@ -4627,33 +4627,55 @@ async function fetchDaemonHealth(port) {
4627
4627
  return null;
4628
4628
  }
4629
4629
  }
4630
- async function killDaemon() {
4631
- const pid = readPidFile();
4632
- if (!pid)
4633
- return;
4634
- if (!isProcessRunning(pid.pid)) {
4635
- try {
4636
- unlinkSync(DAEMON_PID_FILE);
4637
- } catch {
4638
- }
4639
- return;
4630
+ function findPidsByPort(port) {
4631
+ try {
4632
+ const output = execSync2(`lsof -ti :${port}`, { encoding: "utf-8", timeout: 3e3 });
4633
+ return output.trim().split("\n").map((s) => parseInt(s, 10)).filter((n) => !isNaN(n) && n > 0);
4634
+ } catch {
4635
+ return [];
4640
4636
  }
4637
+ }
4638
+ async function killPid(pid) {
4639
+ if (!isProcessRunning(pid))
4640
+ return;
4641
4641
  try {
4642
- process.kill(pid.pid, "SIGTERM");
4642
+ process.kill(pid, "SIGTERM");
4643
4643
  } catch {
4644
4644
  return;
4645
4645
  }
4646
4646
  const start = Date.now();
4647
4647
  while (Date.now() - start < 5e3) {
4648
- if (!isProcessRunning(pid.pid)) {
4648
+ if (!isProcessRunning(pid))
4649
4649
  return;
4650
- }
4651
4650
  await new Promise((r) => setTimeout(r, 200));
4652
4651
  }
4653
4652
  try {
4654
- process.kill(pid.pid, "SIGKILL");
4653
+ process.kill(pid, "SIGKILL");
4655
4654
  } catch {
4656
4655
  }
4656
+ }
4657
+ async function killDaemon() {
4658
+ const pidData = readPidFile();
4659
+ const port = pidData?.port ?? DAEMON_PORT;
4660
+ if (pidData && isProcessRunning(pidData.pid)) {
4661
+ await killPid(pidData.pid);
4662
+ try {
4663
+ if (existsSync5(DAEMON_PID_FILE))
4664
+ unlinkSync(DAEMON_PID_FILE);
4665
+ } catch {
4666
+ }
4667
+ return;
4668
+ }
4669
+ if (pidData) {
4670
+ try {
4671
+ unlinkSync(DAEMON_PID_FILE);
4672
+ } catch {
4673
+ }
4674
+ }
4675
+ const pids = findPidsByPort(port);
4676
+ if (pids.length > 0) {
4677
+ await Promise.all(pids.map((p) => killPid(p)));
4678
+ }
4657
4679
  try {
4658
4680
  if (existsSync5(DAEMON_PID_FILE))
4659
4681
  unlinkSync(DAEMON_PID_FILE);
@@ -4700,7 +4722,7 @@ async function ensureDaemon() {
4700
4722
 
4701
4723
  // ../shared/dist/daemon/autostart.js
4702
4724
  import { existsSync as existsSync6, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, unlinkSync as unlinkSync2 } from "fs";
4703
- import { execSync as execSync2 } from "child_process";
4725
+ import { execSync as execSync3 } from "child_process";
4704
4726
  import { dirname } from "path";
4705
4727
  function detectPlatform() {
4706
4728
  switch (process.platform) {
@@ -4758,14 +4780,14 @@ function installMacos() {
4758
4780
  mkdirSync2(dirname(LAUNCHD_PLIST_PATH), { recursive: true });
4759
4781
  writeFileSync2(LAUNCHD_PLIST_PATH, buildPlist(npxPath, nodePath));
4760
4782
  try {
4761
- execSync2(`launchctl unload "${LAUNCHD_PLIST_PATH}" 2>/dev/null`, { stdio: "ignore" });
4783
+ execSync3(`launchctl unload "${LAUNCHD_PLIST_PATH}" 2>/dev/null`, { stdio: "ignore" });
4762
4784
  } catch {
4763
4785
  }
4764
- execSync2(`launchctl load "${LAUNCHD_PLIST_PATH}"`, { stdio: "ignore" });
4786
+ execSync3(`launchctl load "${LAUNCHD_PLIST_PATH}"`, { stdio: "ignore" });
4765
4787
  }
4766
4788
  function removeMacos() {
4767
4789
  try {
4768
- execSync2(`launchctl unload "${LAUNCHD_PLIST_PATH}" 2>/dev/null`, { stdio: "ignore" });
4790
+ execSync3(`launchctl unload "${LAUNCHD_PLIST_PATH}" 2>/dev/null`, { stdio: "ignore" });
4769
4791
  } catch {
4770
4792
  }
4771
4793
  try {
@@ -4798,12 +4820,12 @@ function installLinux() {
4798
4820
  const nodePath = buildNodePath();
4799
4821
  mkdirSync2(dirname(SYSTEMD_SERVICE_PATH), { recursive: true });
4800
4822
  writeFileSync2(SYSTEMD_SERVICE_PATH, buildSystemdUnit(npxPath, nodePath));
4801
- execSync2("systemctl --user daemon-reload", { stdio: "ignore" });
4802
- execSync2("systemctl --user enable --now useai-daemon.service", { stdio: "ignore" });
4823
+ execSync3("systemctl --user daemon-reload", { stdio: "ignore" });
4824
+ execSync3("systemctl --user enable --now useai-daemon.service", { stdio: "ignore" });
4803
4825
  }
4804
4826
  function removeLinux() {
4805
4827
  try {
4806
- execSync2("systemctl --user disable --now useai-daemon.service", { stdio: "ignore" });
4828
+ execSync3("systemctl --user disable --now useai-daemon.service", { stdio: "ignore" });
4807
4829
  } catch {
4808
4830
  }
4809
4831
  try {
@@ -4812,7 +4834,7 @@ function removeLinux() {
4812
4834
  } catch {
4813
4835
  }
4814
4836
  try {
4815
- execSync2("systemctl --user daemon-reload", { stdio: "ignore" });
4837
+ execSync3("systemctl --user daemon-reload", { stdio: "ignore" });
4816
4838
  } catch {
4817
4839
  }
4818
4840
  }
@@ -5058,7 +5080,7 @@ function removeClaudeCodeHooks() {
5058
5080
  }
5059
5081
 
5060
5082
  // src/services/tools.ts
5061
- import { execSync as execSync3 } from "child_process";
5083
+ import { execSync as execSync4 } from "child_process";
5062
5084
  import { existsSync as existsSync8, readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, unlinkSync as unlinkSync4 } from "fs";
5063
5085
  import { dirname as dirname2, join as join4 } from "path";
5064
5086
  import { homedir as homedir4 } from "os";
@@ -5095,7 +5117,7 @@ function installVscodeHttp(configPath) {
5095
5117
  }
5096
5118
  function hasBinary(name) {
5097
5119
  try {
5098
- execSync3(`which ${name}`, { stdio: "ignore" });
5120
+ execSync4(`which ${name}`, { stdio: "ignore" });
5099
5121
  return true;
5100
5122
  } catch {
5101
5123
  return false;
@@ -5904,20 +5926,23 @@ var startCommand = new Command8("start").description("Start the UseAI daemon").o
5904
5926
  console.log(chalk7.dim(` Try: useai daemon start --foreground`));
5905
5927
  }
5906
5928
  });
5907
- var stopCommand = new Command8("stop").description("Stop the UseAI daemon").action(async () => {
5929
+ var stopCommand = new Command8("stop").description("Stop the UseAI daemon").option("-p, --port <port>", "Port to stop daemon on", String(DAEMON_PORT)).action(async (opts) => {
5930
+ const port = parseInt(opts.port, 10);
5908
5931
  const pid = readPidFile();
5909
- if (!pid) {
5910
- console.log(chalk7.dim(" Daemon is not running (no PID file found)"));
5932
+ if (pid && isProcessRunning(pid.pid)) {
5933
+ console.log(chalk7.dim(` Stopping daemon (PID ${pid.pid})...`));
5934
+ await killDaemon();
5935
+ console.log(chalk7.green(` \u2713 Daemon stopped`));
5911
5936
  return;
5912
5937
  }
5913
- if (!isProcessRunning(pid.pid)) {
5914
- console.log(chalk7.dim(" Daemon is not running (stale PID file)"));
5938
+ const pids = findPidsByPort(port);
5939
+ if (pids.length > 0) {
5940
+ console.log(chalk7.dim(` Stopping daemon on port ${port} (PIDs: ${pids.join(", ")})...`));
5915
5941
  await killDaemon();
5942
+ console.log(chalk7.green(` \u2713 Daemon stopped`));
5916
5943
  return;
5917
5944
  }
5918
- console.log(chalk7.dim(` Stopping daemon (PID ${pid.pid})...`));
5919
- await killDaemon();
5920
- console.log(chalk7.green(` \u2713 Daemon stopped`));
5945
+ console.log(chalk7.dim(" Daemon is not running"));
5921
5946
  });
5922
5947
  var statusCommand2 = new Command8("status").description("Show daemon status").action(async () => {
5923
5948
  const pid = readPidFile();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devness/useai-cli",
3
- "version": "0.4.20",
3
+ "version": "0.4.21",
4
4
  "description": "CLI tool for useai.dev — stats, sync, publish your AI development workflow",
5
5
  "author": "nabeelkausari",
6
6
  "license": "MIT",