@brierb/brier-cli 0.0.4 → 0.0.5
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/dist/config.js +43 -6
- package/dist/index.js +0 -0
- package/dist/runtimes.js +10 -4
- package/dist/tunnel/TunnelClient.js +1 -0
- package/package.json +1 -1
- package/types/runtimes.d.ts +2 -0
- package/types/types.d.ts +3 -0
package/dist/config.js
CHANGED
|
@@ -1,11 +1,23 @@
|
|
|
1
|
-
import { hostname as getHostname, type as osType, arch, platform } from 'node:os';
|
|
1
|
+
import { hostname as getHostname, type as osType, arch, platform, homedir } from 'node:os';
|
|
2
2
|
import { execSync } from 'node:child_process';
|
|
3
|
-
import {
|
|
3
|
+
import { accessSync, constants, readFileSync } from 'node:fs';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
5
6
|
import { RUNTIME_REGISTRY } from './runtimes.js';
|
|
6
7
|
export const BRIER_DIR = join(homedir(), '.brier');
|
|
7
8
|
export const PID_FILE = join(BRIER_DIR, 'daemon.pid');
|
|
8
9
|
export const LOG_FILE = join(BRIER_DIR, 'daemon.log');
|
|
10
|
+
/** CLI 自身版本(读取 dist 同级的 package.json)。 */
|
|
11
|
+
const readCliVersion = () => {
|
|
12
|
+
try {
|
|
13
|
+
const pkgPath = fileURLToPath(new URL('../package.json', import.meta.url));
|
|
14
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
|
|
15
|
+
return pkg.version ?? 'unknown';
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return 'unknown';
|
|
19
|
+
}
|
|
20
|
+
};
|
|
9
21
|
export const loadConfig = (options) => {
|
|
10
22
|
const serverUrl = options.serverUrl ?? process.env.BRIER_SERVER_URL;
|
|
11
23
|
const token = options.token ?? process.env.BRIER_TOKEN;
|
|
@@ -21,6 +33,7 @@ export const loadConfig = (options) => {
|
|
|
21
33
|
hostname: getHostname(),
|
|
22
34
|
os: `${osType()} ${platform()} ${arch()}`,
|
|
23
35
|
runtimes: detectRuntimes(),
|
|
36
|
+
version: readCliVersion(),
|
|
24
37
|
};
|
|
25
38
|
};
|
|
26
39
|
export const toWsUrl = (serverUrl) => {
|
|
@@ -29,16 +42,40 @@ export const toWsUrl = (serverUrl) => {
|
|
|
29
42
|
.replace(/^http:\/\//, 'ws://')
|
|
30
43
|
.replace(/\/$/, '') + '/tunnel');
|
|
31
44
|
};
|
|
45
|
+
// macOS 自带磁盘分区工具 gpt(8) 位于 /usr/sbin/gpt,会与 OpenAI 的 gpt CLI 同名,
|
|
46
|
+
// macOS 自带磁盘分区工具 gpt(8) 位于 /usr/sbin/gpt,会与 OpenAI CLI 同名;
|
|
47
|
+
// 命中 /sbin、/usr/sbin 视为「未安装」,避免误报。
|
|
48
|
+
const SYSTEM_SBIN_RE = /^\/(usr\/)?sbin\//;
|
|
49
|
+
// shell 内建命令(如 continue、cd、type)会被 `command -v` 返回为无路径的裸名,
|
|
50
|
+
// 不是真实可执行文件,需排除。
|
|
51
|
+
const isRealExecutablePath = (hit) => Boolean(hit) && hit.includes('/') && !SYSTEM_SBIN_RE.test(hit);
|
|
52
|
+
const isExecutable = (file) => {
|
|
53
|
+
try {
|
|
54
|
+
accessSync(file, constants.X_OK);
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const expandHome = (p) => (p.startsWith('~/') ? join(homedir(), p.slice(2)) : p);
|
|
32
62
|
const detectRuntimes = () => {
|
|
33
63
|
const runtimes = [];
|
|
34
|
-
for (const { name, command } of RUNTIME_REGISTRY) {
|
|
64
|
+
for (const { name, command, fallbacks } of RUNTIME_REGISTRY) {
|
|
65
|
+
let found = false;
|
|
35
66
|
try {
|
|
36
|
-
execSync(`command -v ${command}`, { stdio: 'pipe' });
|
|
37
|
-
|
|
67
|
+
const hit = execSync(`command -v ${command}`, { stdio: 'pipe' }).toString().trim();
|
|
68
|
+
found = isRealExecutablePath(hit);
|
|
38
69
|
}
|
|
39
70
|
catch {
|
|
40
|
-
//
|
|
71
|
+
// 不在 PATH
|
|
41
72
|
}
|
|
73
|
+
if (!found) {
|
|
74
|
+
const candidates = fallbacks ?? [`~/.local/bin/${command}`];
|
|
75
|
+
found = candidates.some((p) => isExecutable(expandHome(p)));
|
|
76
|
+
}
|
|
77
|
+
if (found)
|
|
78
|
+
runtimes.push(name);
|
|
42
79
|
}
|
|
43
80
|
return runtimes;
|
|
44
81
|
};
|
package/dist/index.js
CHANGED
|
File without changes
|
package/dist/runtimes.js
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
export const RUNTIME_REGISTRY = [
|
|
2
|
-
{ name: 'Claude Code', command: 'claude' },
|
|
2
|
+
{ name: 'Claude Code', command: 'claude', fallbacks: ['~/.claude/bin/claude'] },
|
|
3
3
|
{ name: 'Codex CLI', command: 'codex' },
|
|
4
|
-
{ name: '
|
|
4
|
+
{ name: 'OpenAI CLI', command: 'openai' },
|
|
5
5
|
{ name: 'Gemini CLI', command: 'gemini' },
|
|
6
6
|
{ name: 'Cursor CLI', command: 'cursor' },
|
|
7
|
-
{
|
|
8
|
-
|
|
7
|
+
{
|
|
8
|
+
name: 'OpenCode',
|
|
9
|
+
command: 'opencode',
|
|
10
|
+
fallbacks: ['~/.opencode/bin/opencode', '~/.local/bin/opencode'],
|
|
11
|
+
},
|
|
12
|
+
{ name: 'Aider', command: 'aider', fallbacks: ['~/.local/bin/aider'] },
|
|
13
|
+
{ name: 'Goose', command: 'goose', fallbacks: ['~/.local/bin/goose'] },
|
|
14
|
+
{ name: 'Cody', command: 'cody', fallbacks: ['~/.local/bin/cody'] },
|
|
9
15
|
];
|
|
10
16
|
export const RUNTIME_COMMANDS = Object.fromEntries(RUNTIME_REGISTRY.map((r) => [r.name, r.command]));
|
package/package.json
CHANGED
package/types/runtimes.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export interface RuntimeEntry {
|
|
2
2
|
name: string;
|
|
3
3
|
command: string;
|
|
4
|
+
/** 命令不在 PATH 时的兜底可执行文件(~ 开头表示用户主目录),存在即视为已安装 */
|
|
5
|
+
fallbacks?: readonly string[];
|
|
4
6
|
}
|
|
5
7
|
export declare const RUNTIME_REGISTRY: readonly RuntimeEntry[];
|
|
6
8
|
export declare const RUNTIME_COMMANDS: Record<string, string>;
|
package/types/types.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export type ClientMessage = {
|
|
|
7
7
|
hostname: string;
|
|
8
8
|
os: string;
|
|
9
9
|
runtimes: string[];
|
|
10
|
+
version?: string;
|
|
10
11
|
} | {
|
|
11
12
|
type: 'heartbeat';
|
|
12
13
|
timestamp: number;
|
|
@@ -64,6 +65,8 @@ export interface DaemonConfig {
|
|
|
64
65
|
hostname: string;
|
|
65
66
|
os: string;
|
|
66
67
|
runtimes: string[];
|
|
68
|
+
/** CLI 自身版本(package.json),Auth 时上报给服务端展示。 */
|
|
69
|
+
version: string;
|
|
67
70
|
}
|
|
68
71
|
export interface PidFileData {
|
|
69
72
|
pid: number;
|