@meyverick/omnicode 0.1.0 → 0.1.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meyverick/omnicode",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Cross-platform command-line entrypoint for OpenCode through OmniRoute",
5
5
  "type": "module",
6
6
  "bin": {
@@ -2,9 +2,8 @@ import { spawn } from "node:child_process";
2
2
  import { closeSync, existsSync, mkdirSync, openSync, readFileSync, writeFileSync, unlinkSync } from "node:fs";
3
3
  import { join } from "node:path";
4
4
 
5
- import { commandExists, getDataDir, isProcessRunning, isPidAlive } from "../installer/lib.js";
5
+ import { commandExists, getDataDir, isPidAlive, isProcessRunningAsync } from "../installer/lib.js";
6
6
 
7
- const isWindows = process.platform === "win32";
8
7
  const MAX_OMNI_WAIT = 30;
9
8
  const OMNI_CHECK_DELAY = 1000;
10
9
 
@@ -53,13 +52,13 @@ async function initTools(dataDir) {
53
52
  ]);
54
53
  }
55
54
 
56
- function startOmniroute(dataDir, logFile, pidFile) {
57
- if (isProcessRunning("omniroute")) {
55
+ async function startOmniroute(dataDir, logFile, pidFile) {
56
+ if (await isProcessRunningAsync("omniroute")) {
58
57
  console.log("[omnicode] omniroute already running");
59
58
  return null;
60
59
  }
61
60
 
62
- if (existsSync(pidFile) || existsSync(pidFile)) {
61
+ if (existsSync(pidFile)) {
63
62
  let pid = null;
64
63
  try {
65
64
  pid = parseInt(readFileSync(pidFile, "utf8").trim(), 10);
@@ -95,7 +94,7 @@ async function waitForOmniroute(pid, logFile) {
95
94
  process.exit(1);
96
95
  }
97
96
 
98
- if (isProcessRunning("omniroute")) {
97
+ if (await isProcessRunningAsync("omniroute")) {
99
98
  console.log(`[omnicode] omniroute started (pid: ${pid})`);
100
99
  return;
101
100
  }
@@ -105,8 +104,8 @@ async function waitForOmniroute(pid, logFile) {
105
104
  process.exit(1);
106
105
  }
107
106
 
108
- function stopOmnirouteIfIdle(pidFile) {
109
- if (isProcessRunning("opencode")) {
107
+ async function stopOmnirouteIfIdle(pidFile) {
108
+ if (await isProcessRunningAsync("opencode")) {
110
109
  return;
111
110
  }
112
111
 
@@ -124,7 +123,7 @@ function stopOmnirouteIfIdle(pidFile) {
124
123
  }
125
124
  for (let i = 0; i < 10; i++) {
126
125
  if (!isPidAlive(pid)) break;
127
- try { process.kill(pid, 0); } catch { break; }
126
+ await sleep(100);
128
127
  }
129
128
  }
130
129
  try { unlinkSync(pidFile); } catch {}
@@ -138,16 +137,25 @@ export async function runRuntime(mode) {
138
137
  const logFile = join(dataDir, "omniroute.log");
139
138
  const pidFile = join(dataDir, "omniroute.pid");
140
139
 
141
- if (!isWindows) {
140
+ if (process.platform !== "win32") {
142
141
  process.umask(0o077);
143
142
  }
144
143
 
145
- const cleanup = () => stopOmnirouteIfIdle(pidFile);
146
- process.on("exit", cleanup);
147
- process.on("SIGINT", () => { cleanup(); process.exit(0); });
148
- process.on("SIGTERM", () => { cleanup(); process.exit(0); });
144
+ const cleanup = async () => { await stopOmnirouteIfIdle(pidFile); };
145
+ process.on("exit", () => {
146
+ try {
147
+ if (!existsSync(pidFile)) return;
148
+ const pid = parseInt(readFileSync(pidFile, "utf8").trim(), 10);
149
+ if (pid && isPidAlive(pid)) {
150
+ process.kill(-pid, "SIGTERM");
151
+ }
152
+ unlinkSync(pidFile);
153
+ } catch {}
154
+ });
155
+ process.on("SIGINT", async () => { await cleanup(); process.exit(0); });
156
+ process.on("SIGTERM", async () => { await cleanup(); process.exit(0); });
149
157
 
150
- const pid = startOmniroute(dataDir, logFile, pidFile);
158
+ const pid = await startOmniroute(dataDir, logFile, pidFile);
151
159
 
152
160
  await Promise.all([
153
161
  pid !== null ? waitForOmniroute(pid, logFile) : Promise.resolve(),
@@ -1,8 +1,10 @@
1
- import { execFileSync } from "node:child_process";
1
+ import { execFileSync, execFile } from "node:child_process";
2
+ import { promisify } from "node:util";
2
3
  import { existsSync } from "node:fs";
3
4
  import { join } from "node:path";
4
5
  import os from "node:os";
5
6
 
7
+ const execFileAsync = promisify(execFile);
6
8
  const isWindows = process.platform === "win32";
7
9
 
8
10
  export function commandExists(command) {
@@ -35,6 +37,27 @@ export function isProcessRunning(name) {
35
37
  }
36
38
  }
37
39
 
40
+ export async function isProcessRunningAsync(name) {
41
+ try {
42
+ if (isWindows) {
43
+ const extensions = [".exe", ".cmd", ".bat"];
44
+ for (const ext of extensions) {
45
+ try {
46
+ const { stdout } = await execFileAsync("tasklist", ["/FI", `IMAGENAME eq ${name}${ext}`, "/NH"], {
47
+ encoding: "utf8",
48
+ });
49
+ if (stdout.includes(`${name}${ext}`)) return true;
50
+ } catch {}
51
+ }
52
+ return false;
53
+ }
54
+ await execFileAsync("pgrep", ["-f", name]);
55
+ return true;
56
+ } catch {
57
+ return false;
58
+ }
59
+ }
60
+
38
61
  export function isPidAlive(pid) {
39
62
  try {
40
63
  process.kill(pid, 0);