|
1 | 1 | import { spawnSync } from "node:child_process"; |
| 2 | +import path from "node:path"; |
2 | 3 | import { formatCliCommand } from "../cli/command-format.js"; |
3 | 4 | import type { OpenClawConfig } from "../config/types.openclaw.js"; |
4 | 5 | import { note } from "../terminal/note.js"; |
@@ -15,8 +16,24 @@ type ProcessController = {
|
15 | 16 | kill: (pid: number, signal: ProcessSignal | 0) => boolean; |
16 | 17 | }; |
17 | 18 | |
18 | | -const LOCAL_TUI_CMD_RE = |
19 | | -/(?:^|\s)(?:openclaw-tui|openclaw\s+tui|openclaw\s+chat|openclaw\s+terminal)(?:\s|$)/; |
| 19 | +const LOCAL_TUI_SUBCOMMANDS = new Set(["chat", "terminal", "tui"]); |
| 20 | + |
| 21 | +function tokenizeCommandLine(command: string): string[] { |
| 22 | +return command.trim().split(/\s+/u).filter(Boolean); |
| 23 | +} |
| 24 | + |
| 25 | +function normalizeExecutableName(value: string | undefined): string { |
| 26 | +return path.basename(value ?? "").replace(/\.exe$/iu, ""); |
| 27 | +} |
| 28 | + |
| 29 | +function isLocalTuiCommand(command: string): boolean { |
| 30 | +const argv = tokenizeCommandLine(command); |
| 31 | +const executable = normalizeExecutableName(argv[0]); |
| 32 | +if (executable === "openclaw-tui") { |
| 33 | +return true; |
| 34 | +} |
| 35 | +return executable === "openclaw" && LOCAL_TUI_SUBCOMMANDS.has(argv[1] ?? ""); |
| 36 | +} |
20 | 37 | |
21 | 38 | function parsePsPidLine(line: string): LocalTuiProcess | null { |
22 | 39 | const match = line.match(/^\s*(\d+)\s+(.+)$/); |
@@ -28,7 +45,7 @@ function parsePsPidLine(line: string): LocalTuiProcess | null {
|
28 | 45 | return null; |
29 | 46 | } |
30 | 47 | const command = match[2]?.trim() ?? ""; |
31 | | -if (!LOCAL_TUI_CMD_RE.test(command)) { |
| 48 | +if (!isLocalTuiCommand(command)) { |
32 | 49 | return null; |
33 | 50 | } |
34 | 51 | return { pid, command }; |
|