@rehpic/vcli 0.1.0-beta.50.1 → 0.1.0-beta.51.1
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/index.js +97 -284
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9,248 +9,6 @@ var __export = (target, all) => {
|
|
|
9
9
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
// src/menubar.ts
|
|
13
|
-
var menubar_exports = {};
|
|
14
|
-
__export(menubar_exports, {
|
|
15
|
-
startMenuBar: () => startMenuBar
|
|
16
|
-
});
|
|
17
|
-
import SysTrayModule from "systray2";
|
|
18
|
-
import { existsSync, readFileSync } from "fs";
|
|
19
|
-
import { homedir as homedir2 } from "os";
|
|
20
|
-
import { join } from "path";
|
|
21
|
-
import { execSync } from "child_process";
|
|
22
|
-
function loadIconBase64() {
|
|
23
|
-
const iconPath = join(CONFIG_DIR, "assets", "vector-menubar.png");
|
|
24
|
-
if (existsSync(iconPath)) {
|
|
25
|
-
return readFileSync(iconPath).toString("base64");
|
|
26
|
-
}
|
|
27
|
-
return "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==";
|
|
28
|
-
}
|
|
29
|
-
function loadConfig() {
|
|
30
|
-
try {
|
|
31
|
-
return JSON.parse(readFileSync(BRIDGE_CONFIG_FILE, "utf-8"));
|
|
32
|
-
} catch {
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
function loadActivities() {
|
|
37
|
-
try {
|
|
38
|
-
return JSON.parse(readFileSync(LIVE_ACTIVITIES_FILE, "utf-8"));
|
|
39
|
-
} catch {
|
|
40
|
-
return [];
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
function isBridgeRunning() {
|
|
44
|
-
try {
|
|
45
|
-
const pid = Number(readFileSync(PID_FILE, "utf-8").trim());
|
|
46
|
-
process.kill(pid, 0);
|
|
47
|
-
return { running: true, pid };
|
|
48
|
-
} catch {
|
|
49
|
-
return { running: false };
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
function getSessionInfo() {
|
|
53
|
-
try {
|
|
54
|
-
const session = JSON.parse(
|
|
55
|
-
readFileSync(join(CONFIG_DIR, "cli-default.json"), "utf-8")
|
|
56
|
-
);
|
|
57
|
-
return {
|
|
58
|
-
orgSlug: session.activeOrgSlug ?? "oss-lab",
|
|
59
|
-
appUrl: session.appUrl
|
|
60
|
-
};
|
|
61
|
-
} catch {
|
|
62
|
-
return { orgSlug: "oss-lab" };
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
function getOrgSlug() {
|
|
66
|
-
try {
|
|
67
|
-
const session = JSON.parse(
|
|
68
|
-
readFileSync(join(CONFIG_DIR, "cli-default.json"), "utf-8")
|
|
69
|
-
);
|
|
70
|
-
return session.activeOrgSlug ?? "oss-lab";
|
|
71
|
-
} catch {
|
|
72
|
-
return "oss-lab";
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
function providerLabel(provider) {
|
|
76
|
-
if (provider === "claude_code") return "Claude";
|
|
77
|
-
if (provider === "codex") return "Codex";
|
|
78
|
-
return provider;
|
|
79
|
-
}
|
|
80
|
-
function buildMenu() {
|
|
81
|
-
const config = loadConfig();
|
|
82
|
-
const { running, pid } = isBridgeRunning();
|
|
83
|
-
const activities = loadActivities();
|
|
84
|
-
const items = [];
|
|
85
|
-
const actions = /* @__PURE__ */ new Map();
|
|
86
|
-
let idx = 0;
|
|
87
|
-
if (running && config) {
|
|
88
|
-
items.push({
|
|
89
|
-
title: `Vector Bridge \u2014 Running (PID ${pid})`,
|
|
90
|
-
enabled: false
|
|
91
|
-
});
|
|
92
|
-
idx++;
|
|
93
|
-
items.push({ title: ` ${config.displayName}`, enabled: false });
|
|
94
|
-
idx++;
|
|
95
|
-
} else if (config) {
|
|
96
|
-
items.push({ title: "Vector Bridge \u2014 Offline", enabled: false });
|
|
97
|
-
idx++;
|
|
98
|
-
} else {
|
|
99
|
-
items.push({ title: "Vector Bridge \u2014 Not Configured", enabled: false });
|
|
100
|
-
idx++;
|
|
101
|
-
items.push({
|
|
102
|
-
title: " Run: vcli service start",
|
|
103
|
-
enabled: false
|
|
104
|
-
});
|
|
105
|
-
idx++;
|
|
106
|
-
}
|
|
107
|
-
items.push({ title: "---", enabled: false });
|
|
108
|
-
idx++;
|
|
109
|
-
if (activities.length > 0) {
|
|
110
|
-
items.push({ title: "Active Sessions", enabled: false });
|
|
111
|
-
idx++;
|
|
112
|
-
const orgSlug = getOrgSlug();
|
|
113
|
-
for (const a of activities) {
|
|
114
|
-
const label = `${a.issueKey} \u2014 ${a.title ?? a.issueTitle} (${providerLabel(a.provider)})`;
|
|
115
|
-
items.push({ title: label, tooltip: a.latestSummary });
|
|
116
|
-
const issueKey = a.issueKey;
|
|
117
|
-
actions.set(idx, () => {
|
|
118
|
-
const url = `http://localhost:3000/${orgSlug}/issues/${issueKey}`;
|
|
119
|
-
try {
|
|
120
|
-
execSync(`open "${url}"`, { stdio: "ignore" });
|
|
121
|
-
} catch {
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
idx++;
|
|
125
|
-
}
|
|
126
|
-
items.push({ title: "---", enabled: false });
|
|
127
|
-
idx++;
|
|
128
|
-
}
|
|
129
|
-
if (running) {
|
|
130
|
-
items.push({ title: "Stop Bridge" });
|
|
131
|
-
actions.set(idx, () => {
|
|
132
|
-
try {
|
|
133
|
-
if (pid) process.kill(pid, "SIGTERM");
|
|
134
|
-
} catch {
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
idx++;
|
|
138
|
-
items.push({ title: "Restart Bridge" });
|
|
139
|
-
actions.set(idx, () => {
|
|
140
|
-
try {
|
|
141
|
-
if (pid) process.kill(pid, "SIGTERM");
|
|
142
|
-
setTimeout(() => {
|
|
143
|
-
execSync("vcli service start", { stdio: "ignore" });
|
|
144
|
-
}, 2e3);
|
|
145
|
-
} catch {
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
idx++;
|
|
149
|
-
} else if (config) {
|
|
150
|
-
items.push({ title: "Start Bridge" });
|
|
151
|
-
actions.set(idx, () => {
|
|
152
|
-
try {
|
|
153
|
-
execSync("vcli service start", { stdio: "ignore" });
|
|
154
|
-
} catch {
|
|
155
|
-
}
|
|
156
|
-
});
|
|
157
|
-
idx++;
|
|
158
|
-
}
|
|
159
|
-
items.push({ title: "---", enabled: false });
|
|
160
|
-
idx++;
|
|
161
|
-
if (config) {
|
|
162
|
-
const { orgSlug, appUrl } = getSessionInfo();
|
|
163
|
-
items.push({
|
|
164
|
-
title: `Account: ${config.userId.slice(0, 12)}...`,
|
|
165
|
-
enabled: false
|
|
166
|
-
});
|
|
167
|
-
idx++;
|
|
168
|
-
if (orgSlug) {
|
|
169
|
-
items.push({ title: `Org: ${orgSlug}`, enabled: false });
|
|
170
|
-
idx++;
|
|
171
|
-
}
|
|
172
|
-
items.push({ title: "---", enabled: false });
|
|
173
|
-
idx++;
|
|
174
|
-
}
|
|
175
|
-
items.push({ title: "Open Vector" });
|
|
176
|
-
actions.set(idx, () => {
|
|
177
|
-
const { appUrl } = getSessionInfo();
|
|
178
|
-
const url = appUrl ?? "http://localhost:3000";
|
|
179
|
-
try {
|
|
180
|
-
execSync(`open "${url}"`, { stdio: "ignore" });
|
|
181
|
-
} catch {
|
|
182
|
-
}
|
|
183
|
-
});
|
|
184
|
-
idx++;
|
|
185
|
-
items.push({ title: "Quit Vector" });
|
|
186
|
-
actions.set(idx, () => {
|
|
187
|
-
try {
|
|
188
|
-
const { pid: bridgePid } = isBridgeRunning();
|
|
189
|
-
if (bridgePid) process.kill(bridgePid, "SIGTERM");
|
|
190
|
-
} catch {
|
|
191
|
-
}
|
|
192
|
-
process.exit(0);
|
|
193
|
-
});
|
|
194
|
-
idx++;
|
|
195
|
-
return { items, actions };
|
|
196
|
-
}
|
|
197
|
-
async function startMenuBar() {
|
|
198
|
-
try {
|
|
199
|
-
const { fileURLToPath: fileURLToPath3 } = await import("url");
|
|
200
|
-
const { dirname: dirname2, join: pjoin } = await import("path");
|
|
201
|
-
const { chmodSync } = await import("fs");
|
|
202
|
-
const systrayIndex = fileURLToPath3(import.meta.resolve("systray2"));
|
|
203
|
-
const binName = process.platform === "darwin" ? "tray_darwin_release" : process.platform === "win32" ? "tray_windows_release.exe" : "tray_linux_release";
|
|
204
|
-
const trayBin = pjoin(dirname2(systrayIndex), "traybin", binName);
|
|
205
|
-
chmodSync(trayBin, 493);
|
|
206
|
-
} catch {
|
|
207
|
-
}
|
|
208
|
-
const icon = loadIconBase64();
|
|
209
|
-
const { items, actions } = buildMenu();
|
|
210
|
-
const systray = new SysTray({
|
|
211
|
-
menu: {
|
|
212
|
-
icon,
|
|
213
|
-
title: "",
|
|
214
|
-
tooltip: "Vector Bridge",
|
|
215
|
-
items: items.map((item) => ({
|
|
216
|
-
title: item.title,
|
|
217
|
-
tooltip: item.tooltip ?? "",
|
|
218
|
-
checked: item.checked ?? false,
|
|
219
|
-
enabled: item.enabled ?? true,
|
|
220
|
-
hidden: false
|
|
221
|
-
}))
|
|
222
|
-
},
|
|
223
|
-
debug: false,
|
|
224
|
-
copyDir: false
|
|
225
|
-
});
|
|
226
|
-
void systray.onClick((action) => {
|
|
227
|
-
const handler = actions.get(action.seq_id);
|
|
228
|
-
if (handler) handler();
|
|
229
|
-
});
|
|
230
|
-
setInterval(() => {
|
|
231
|
-
const { items: newItems, actions: newActions } = buildMenu();
|
|
232
|
-
void newItems;
|
|
233
|
-
void newActions;
|
|
234
|
-
}, 15e3);
|
|
235
|
-
}
|
|
236
|
-
var SysTray, CONFIG_DIR, BRIDGE_CONFIG_FILE, PID_FILE, LIVE_ACTIVITIES_FILE;
|
|
237
|
-
var init_menubar = __esm({
|
|
238
|
-
"src/menubar.ts"() {
|
|
239
|
-
"use strict";
|
|
240
|
-
SysTray = typeof SysTrayModule.default === "function" ? SysTrayModule.default : SysTrayModule;
|
|
241
|
-
CONFIG_DIR = join(homedir2(), ".vector");
|
|
242
|
-
BRIDGE_CONFIG_FILE = join(CONFIG_DIR, "bridge.json");
|
|
243
|
-
PID_FILE = join(CONFIG_DIR, "bridge.pid");
|
|
244
|
-
LIVE_ACTIVITIES_FILE = join(CONFIG_DIR, "live-activities.json");
|
|
245
|
-
if (process.argv[1]?.endsWith("menubar.ts") || process.argv[1]?.endsWith("menubar.js")) {
|
|
246
|
-
startMenuBar().catch((e) => {
|
|
247
|
-
console.error("Menu bar error:", e);
|
|
248
|
-
process.exit(1);
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
});
|
|
253
|
-
|
|
254
12
|
// ../../node_modules/.pnpm/is-docker@3.0.0/node_modules/is-docker/index.js
|
|
255
13
|
import fs from "fs";
|
|
256
14
|
function hasDockerEnv() {
|
|
@@ -978,9 +736,9 @@ var init_open = __esm({
|
|
|
978
736
|
});
|
|
979
737
|
|
|
980
738
|
// src/index.ts
|
|
981
|
-
import { readFileSync as
|
|
739
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
982
740
|
import { readFile as readFile2 } from "fs/promises";
|
|
983
|
-
import { dirname, extname, join as
|
|
741
|
+
import { dirname, extname, join as join2 } from "path";
|
|
984
742
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
985
743
|
import { config as loadEnv } from "dotenv";
|
|
986
744
|
import { Command } from "commander";
|
|
@@ -1338,38 +1096,38 @@ function createEmptySession() {
|
|
|
1338
1096
|
|
|
1339
1097
|
// src/bridge-service.ts
|
|
1340
1098
|
import { ConvexHttpClient as ConvexHttpClient2 } from "convex/browser";
|
|
1341
|
-
import { execSync
|
|
1099
|
+
import { execSync } from "child_process";
|
|
1342
1100
|
import {
|
|
1343
|
-
existsSync
|
|
1101
|
+
existsSync,
|
|
1344
1102
|
mkdirSync,
|
|
1345
|
-
readFileSync
|
|
1103
|
+
readFileSync,
|
|
1346
1104
|
writeFileSync,
|
|
1347
1105
|
unlinkSync
|
|
1348
1106
|
} from "fs";
|
|
1349
|
-
import { homedir as
|
|
1350
|
-
import { join
|
|
1107
|
+
import { homedir as homedir2, hostname, platform } from "os";
|
|
1108
|
+
import { join } from "path";
|
|
1351
1109
|
import { randomUUID } from "crypto";
|
|
1352
|
-
var
|
|
1353
|
-
var
|
|
1354
|
-
var
|
|
1355
|
-
var LIVE_ACTIVITIES_CACHE =
|
|
1356
|
-
var LAUNCHAGENT_DIR =
|
|
1357
|
-
var LAUNCHAGENT_PLIST =
|
|
1110
|
+
var CONFIG_DIR = join(homedir2(), ".vector");
|
|
1111
|
+
var BRIDGE_CONFIG_FILE = join(CONFIG_DIR, "bridge.json");
|
|
1112
|
+
var PID_FILE = join(CONFIG_DIR, "bridge.pid");
|
|
1113
|
+
var LIVE_ACTIVITIES_CACHE = join(CONFIG_DIR, "live-activities.json");
|
|
1114
|
+
var LAUNCHAGENT_DIR = join(homedir2(), "Library", "LaunchAgents");
|
|
1115
|
+
var LAUNCHAGENT_PLIST = join(LAUNCHAGENT_DIR, "com.vector.bridge.plist");
|
|
1358
1116
|
var LAUNCHAGENT_LABEL = "com.vector.bridge";
|
|
1359
1117
|
var HEARTBEAT_INTERVAL_MS = 3e4;
|
|
1360
1118
|
var COMMAND_POLL_INTERVAL_MS = 5e3;
|
|
1361
1119
|
var PROCESS_DISCOVERY_INTERVAL_MS = 6e4;
|
|
1362
1120
|
function loadBridgeConfig() {
|
|
1363
|
-
if (!
|
|
1121
|
+
if (!existsSync(BRIDGE_CONFIG_FILE)) return null;
|
|
1364
1122
|
try {
|
|
1365
|
-
return JSON.parse(
|
|
1123
|
+
return JSON.parse(readFileSync(BRIDGE_CONFIG_FILE, "utf-8"));
|
|
1366
1124
|
} catch {
|
|
1367
1125
|
return null;
|
|
1368
1126
|
}
|
|
1369
1127
|
}
|
|
1370
1128
|
function saveBridgeConfig(config) {
|
|
1371
|
-
if (!
|
|
1372
|
-
writeFileSync(
|
|
1129
|
+
if (!existsSync(CONFIG_DIR)) mkdirSync(CONFIG_DIR, { recursive: true });
|
|
1130
|
+
writeFileSync(BRIDGE_CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
1373
1131
|
}
|
|
1374
1132
|
function discoverLocalProcesses() {
|
|
1375
1133
|
const processes = [];
|
|
@@ -1384,7 +1142,7 @@ function discoverLocalProcesses() {
|
|
|
1384
1142
|
];
|
|
1385
1143
|
for (const { grep, provider, label, prefix } of patterns) {
|
|
1386
1144
|
try {
|
|
1387
|
-
const ps =
|
|
1145
|
+
const ps = execSync(
|
|
1388
1146
|
`ps aux | grep -E '${grep}' | grep -v vector-bridge | grep -v grep`,
|
|
1389
1147
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
1390
1148
|
);
|
|
@@ -1393,7 +1151,7 @@ function discoverLocalProcesses() {
|
|
|
1393
1151
|
if (!pid) continue;
|
|
1394
1152
|
let cwd;
|
|
1395
1153
|
try {
|
|
1396
|
-
cwd =
|
|
1154
|
+
cwd = execSync(
|
|
1397
1155
|
`lsof -p ${pid} 2>/dev/null | grep cwd | awk '{print $NF}'`,
|
|
1398
1156
|
{ encoding: "utf-8", timeout: 3e3 }
|
|
1399
1157
|
).trim() || void 0;
|
|
@@ -1419,12 +1177,12 @@ function discoverLocalProcesses() {
|
|
|
1419
1177
|
}
|
|
1420
1178
|
function getGitInfo(cwd) {
|
|
1421
1179
|
try {
|
|
1422
|
-
const branch =
|
|
1180
|
+
const branch = execSync("git rev-parse --abbrev-ref HEAD", {
|
|
1423
1181
|
encoding: "utf-8",
|
|
1424
1182
|
cwd,
|
|
1425
1183
|
timeout: 3e3
|
|
1426
1184
|
}).trim();
|
|
1427
|
-
const repoRoot =
|
|
1185
|
+
const repoRoot = execSync("git rev-parse --show-toplevel", {
|
|
1428
1186
|
encoding: "utf-8",
|
|
1429
1187
|
cwd,
|
|
1430
1188
|
timeout: 3e3
|
|
@@ -1537,8 +1295,8 @@ var BridgeService = class {
|
|
|
1537
1295
|
console.log(` Convex: ${this.config.convexUrl}`);
|
|
1538
1296
|
console.log(` PID: ${process.pid}`);
|
|
1539
1297
|
console.log("");
|
|
1540
|
-
if (!
|
|
1541
|
-
writeFileSync(
|
|
1298
|
+
if (!existsSync(CONFIG_DIR)) mkdirSync(CONFIG_DIR, { recursive: true });
|
|
1299
|
+
writeFileSync(PID_FILE, String(process.pid));
|
|
1542
1300
|
await this.heartbeat();
|
|
1543
1301
|
await this.reportProcesses();
|
|
1544
1302
|
await this.refreshLiveActivities();
|
|
@@ -1572,7 +1330,7 @@ var BridgeService = class {
|
|
|
1572
1330
|
[${ts()}] Shutting down...`);
|
|
1573
1331
|
for (const t of this.timers) clearInterval(t);
|
|
1574
1332
|
try {
|
|
1575
|
-
unlinkSync(
|
|
1333
|
+
unlinkSync(PID_FILE);
|
|
1576
1334
|
} catch {
|
|
1577
1335
|
}
|
|
1578
1336
|
process.exit(0);
|
|
@@ -1635,9 +1393,9 @@ function installLaunchAgent(vcliPath) {
|
|
|
1635
1393
|
<key>KeepAlive</key>
|
|
1636
1394
|
<true/>
|
|
1637
1395
|
<key>StandardOutPath</key>
|
|
1638
|
-
<string>${
|
|
1396
|
+
<string>${CONFIG_DIR}/bridge.log</string>
|
|
1639
1397
|
<key>StandardErrorPath</key>
|
|
1640
|
-
<string>${
|
|
1398
|
+
<string>${CONFIG_DIR}/bridge.err.log</string>
|
|
1641
1399
|
<key>EnvironmentVariables</key>
|
|
1642
1400
|
<dict>
|
|
1643
1401
|
<key>PATH</key>
|
|
@@ -1646,11 +1404,11 @@ function installLaunchAgent(vcliPath) {
|
|
|
1646
1404
|
</dict>
|
|
1647
1405
|
</plist>`;
|
|
1648
1406
|
const menuBarCandidates = [
|
|
1649
|
-
|
|
1407
|
+
join(CONFIG_DIR, "VectorMenuBar"),
|
|
1650
1408
|
"/usr/local/bin/VectorMenuBar",
|
|
1651
|
-
|
|
1409
|
+
join(homedir2(), ".local", "bin", "VectorMenuBar")
|
|
1652
1410
|
];
|
|
1653
|
-
const menuBarBinary = menuBarCandidates.find((p) =>
|
|
1411
|
+
const menuBarBinary = menuBarCandidates.find((p) => existsSync(p));
|
|
1654
1412
|
if (menuBarBinary) {
|
|
1655
1413
|
const menuBarPlist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
1656
1414
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
@@ -1668,15 +1426,15 @@ function installLaunchAgent(vcliPath) {
|
|
|
1668
1426
|
<false/>
|
|
1669
1427
|
</dict>
|
|
1670
1428
|
</plist>`;
|
|
1671
|
-
const menuBarPlistPath =
|
|
1429
|
+
const menuBarPlistPath = join(LAUNCHAGENT_DIR, "com.vector.menubar.plist");
|
|
1672
1430
|
writeFileSync(menuBarPlistPath, menuBarPlist);
|
|
1673
1431
|
try {
|
|
1674
|
-
|
|
1432
|
+
execSync(`launchctl load ${menuBarPlistPath}`, { stdio: "pipe" });
|
|
1675
1433
|
console.log("Menu bar helper installed.");
|
|
1676
1434
|
} catch {
|
|
1677
1435
|
}
|
|
1678
1436
|
}
|
|
1679
|
-
if (!
|
|
1437
|
+
if (!existsSync(LAUNCHAGENT_DIR)) {
|
|
1680
1438
|
mkdirSync(LAUNCHAGENT_DIR, { recursive: true });
|
|
1681
1439
|
}
|
|
1682
1440
|
writeFileSync(LAUNCHAGENT_PLIST, plist);
|
|
@@ -1684,7 +1442,7 @@ function installLaunchAgent(vcliPath) {
|
|
|
1684
1442
|
}
|
|
1685
1443
|
function loadLaunchAgent() {
|
|
1686
1444
|
try {
|
|
1687
|
-
|
|
1445
|
+
execSync(`launchctl load ${LAUNCHAGENT_PLIST}`, { stdio: "inherit" });
|
|
1688
1446
|
console.log(
|
|
1689
1447
|
"LaunchAgent loaded. Bridge will start automatically on login."
|
|
1690
1448
|
);
|
|
@@ -1694,7 +1452,7 @@ function loadLaunchAgent() {
|
|
|
1694
1452
|
}
|
|
1695
1453
|
function unloadLaunchAgent() {
|
|
1696
1454
|
try {
|
|
1697
|
-
|
|
1455
|
+
execSync(`launchctl unload ${LAUNCHAGENT_PLIST}`, { stdio: "inherit" });
|
|
1698
1456
|
console.log("LaunchAgent unloaded.");
|
|
1699
1457
|
} catch {
|
|
1700
1458
|
console.error("Failed to unload LaunchAgent (may not be loaded)");
|
|
@@ -1708,10 +1466,65 @@ function uninstallLaunchAgent() {
|
|
|
1708
1466
|
} catch {
|
|
1709
1467
|
}
|
|
1710
1468
|
}
|
|
1469
|
+
var MENUBAR_BINARY = join(CONFIG_DIR, "VectorMenuBar");
|
|
1470
|
+
var MENUBAR_SWIFT_URL = "https://raw.githubusercontent.com/xrehpicx/vector/main/cli/macos/VectorMenuBar.swift";
|
|
1471
|
+
async function ensureMenuBarBinary() {
|
|
1472
|
+
if (platform() !== "darwin") return null;
|
|
1473
|
+
if (existsSync(MENUBAR_BINARY)) return MENUBAR_BINARY;
|
|
1474
|
+
try {
|
|
1475
|
+
execSync("which swiftc", { stdio: "pipe" });
|
|
1476
|
+
} catch {
|
|
1477
|
+
return null;
|
|
1478
|
+
}
|
|
1479
|
+
const localSource = join(
|
|
1480
|
+
process.cwd(),
|
|
1481
|
+
"cli",
|
|
1482
|
+
"macos",
|
|
1483
|
+
"VectorMenuBar.swift"
|
|
1484
|
+
);
|
|
1485
|
+
let swiftSource;
|
|
1486
|
+
if (existsSync(localSource)) {
|
|
1487
|
+
swiftSource = localSource;
|
|
1488
|
+
} else {
|
|
1489
|
+
const downloadPath = join(CONFIG_DIR, "VectorMenuBar.swift");
|
|
1490
|
+
try {
|
|
1491
|
+
execSync(`curl -fsSL "${MENUBAR_SWIFT_URL}" -o "${downloadPath}"`, {
|
|
1492
|
+
stdio: "pipe",
|
|
1493
|
+
timeout: 15e3
|
|
1494
|
+
});
|
|
1495
|
+
swiftSource = downloadPath;
|
|
1496
|
+
} catch {
|
|
1497
|
+
return null;
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
try {
|
|
1501
|
+
execSync(
|
|
1502
|
+
`swiftc -o "${MENUBAR_BINARY}" "${swiftSource}" -framework AppKit`,
|
|
1503
|
+
{ stdio: "pipe", timeout: 3e4 }
|
|
1504
|
+
);
|
|
1505
|
+
const assetsSource = join(swiftSource, "..", "assets");
|
|
1506
|
+
const assetsDest = join(CONFIG_DIR, "assets");
|
|
1507
|
+
if (existsSync(assetsSource)) {
|
|
1508
|
+
mkdirSync(assetsDest, { recursive: true });
|
|
1509
|
+
for (const f of ["vector-menubar.png", "vector-menubar@2x.png"]) {
|
|
1510
|
+
const src = join(assetsSource, f);
|
|
1511
|
+
if (existsSync(src))
|
|
1512
|
+
writeFileSync(join(assetsDest, f), readFileSync(src));
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
return MENUBAR_BINARY;
|
|
1516
|
+
} catch {
|
|
1517
|
+
return null;
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1711
1520
|
async function launchMenuBar() {
|
|
1521
|
+
if (platform() !== "darwin") return;
|
|
1522
|
+
const binary = await ensureMenuBarBinary();
|
|
1523
|
+
if (!binary) return;
|
|
1712
1524
|
try {
|
|
1713
|
-
const {
|
|
1714
|
-
|
|
1525
|
+
const { spawn: spawnChild } = await import("child_process");
|
|
1526
|
+
const child = spawnChild(binary, [], { detached: true, stdio: "ignore" });
|
|
1527
|
+
child.unref();
|
|
1715
1528
|
console.log("Menu bar started.");
|
|
1716
1529
|
} catch {
|
|
1717
1530
|
}
|
|
@@ -1722,8 +1535,8 @@ function getBridgeStatus() {
|
|
|
1722
1535
|
let running = false;
|
|
1723
1536
|
let starting = false;
|
|
1724
1537
|
let pid;
|
|
1725
|
-
if (
|
|
1726
|
-
const pidStr =
|
|
1538
|
+
if (existsSync(PID_FILE)) {
|
|
1539
|
+
const pidStr = readFileSync(PID_FILE, "utf-8").trim();
|
|
1727
1540
|
pid = Number(pidStr);
|
|
1728
1541
|
try {
|
|
1729
1542
|
process.kill(pid, 0);
|
|
@@ -1734,7 +1547,7 @@ function getBridgeStatus() {
|
|
|
1734
1547
|
}
|
|
1735
1548
|
if (!running && platform() === "darwin") {
|
|
1736
1549
|
try {
|
|
1737
|
-
const result =
|
|
1550
|
+
const result = execSync(
|
|
1738
1551
|
`launchctl list ${LAUNCHAGENT_LABEL} 2>/dev/null`,
|
|
1739
1552
|
{ encoding: "utf-8", timeout: 3e3 }
|
|
1740
1553
|
);
|
|
@@ -1747,8 +1560,8 @@ function getBridgeStatus() {
|
|
|
1747
1560
|
return { configured: true, running, starting, pid, config };
|
|
1748
1561
|
}
|
|
1749
1562
|
function stopBridge() {
|
|
1750
|
-
if (!
|
|
1751
|
-
const pid = Number(
|
|
1563
|
+
if (!existsSync(PID_FILE)) return false;
|
|
1564
|
+
const pid = Number(readFileSync(PID_FILE, "utf-8").trim());
|
|
1752
1565
|
try {
|
|
1753
1566
|
process.kill(pid, "SIGTERM");
|
|
1754
1567
|
return true;
|
|
@@ -2204,7 +2017,7 @@ var program = new Command();
|
|
|
2204
2017
|
function readPackageVersionSync() {
|
|
2205
2018
|
try {
|
|
2206
2019
|
const dir = import.meta.dirname ?? dirname(fileURLToPath2(import.meta.url));
|
|
2207
|
-
const raw =
|
|
2020
|
+
const raw = readFileSync2(join2(dir, "..", "package.json"), "utf8");
|
|
2208
2021
|
return JSON.parse(raw).version ?? "unknown";
|
|
2209
2022
|
} catch {
|
|
2210
2023
|
return "unknown";
|