@rehpic/vcli 0.1.0-beta.54.1 → 0.1.0-beta.56.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 CHANGED
@@ -2094,12 +2094,34 @@ function killExistingMenuBar() {
2094
2094
  }
2095
2095
  }
2096
2096
  }
2097
+ function getRunningMenuBarPid() {
2098
+ if (!existsSync2(MENUBAR_PID_FILE)) {
2099
+ return null;
2100
+ }
2101
+ try {
2102
+ const pid = Number(readFileSync2(MENUBAR_PID_FILE, "utf-8").trim());
2103
+ if (Number.isFinite(pid) && pid > 0 && isKnownMenuBarProcess(pid)) {
2104
+ process.kill(pid, 0);
2105
+ return pid;
2106
+ }
2107
+ } catch {
2108
+ }
2109
+ try {
2110
+ unlinkSync(MENUBAR_PID_FILE);
2111
+ } catch {
2112
+ }
2113
+ return null;
2114
+ }
2097
2115
  async function launchMenuBar() {
2098
2116
  if (platform() !== "darwin") return;
2099
2117
  removeLegacyMenuBarLaunchAgent();
2100
2118
  const executable = findMenuBarExecutable();
2101
2119
  const cliInvocation = getCurrentCliInvocation();
2102
2120
  if (!executable || !cliInvocation) return;
2121
+ const existingPid = getRunningMenuBarPid();
2122
+ if (existingPid) {
2123
+ return;
2124
+ }
2103
2125
  killExistingMenuBar();
2104
2126
  try {
2105
2127
  const { spawn: spawnChild } = await import("child_process");
@@ -2420,6 +2442,65 @@ function requireOrg(runtime, explicit) {
2420
2442
  }
2421
2443
  return orgSlug;
2422
2444
  }
2445
+ function readJsonFile(path3, fallback) {
2446
+ try {
2447
+ return JSON.parse(readFileSync3(path3, "utf8"));
2448
+ } catch {
2449
+ return fallback;
2450
+ }
2451
+ }
2452
+ function hostForAppUrl(appUrl) {
2453
+ if (!appUrl) {
2454
+ return void 0;
2455
+ }
2456
+ try {
2457
+ const url = new URL(appUrl);
2458
+ return url.port ? `${url.hostname}:${url.port}` : url.hostname;
2459
+ } catch {
2460
+ return void 0;
2461
+ }
2462
+ }
2463
+ function decodeSessionClaims(session) {
2464
+ const jwt = session?.cookies?.["__Secure-better-auth.convex_jwt"];
2465
+ if (!jwt) {
2466
+ return {};
2467
+ }
2468
+ const parts = jwt.split(".");
2469
+ if (parts.length < 2) {
2470
+ return {};
2471
+ }
2472
+ let payload = parts[1].replace(/-/g, "+").replace(/_/g, "/");
2473
+ while (payload.length % 4 !== 0) {
2474
+ payload += "=";
2475
+ }
2476
+ try {
2477
+ const decoded = JSON.parse(
2478
+ Buffer.from(payload, "base64").toString("utf8")
2479
+ );
2480
+ return {
2481
+ email: decoded.email,
2482
+ userId: decoded.sub ?? decoded.userId
2483
+ };
2484
+ } catch {
2485
+ return {};
2486
+ }
2487
+ }
2488
+ function buildMenuSessionInfo(session) {
2489
+ const claims = decodeSessionClaims(session);
2490
+ return {
2491
+ orgSlug: session?.activeOrgSlug ?? "oss-lab",
2492
+ appUrl: session?.appUrl,
2493
+ appDomain: hostForAppUrl(session?.appUrl),
2494
+ email: claims.email,
2495
+ userId: claims.userId
2496
+ };
2497
+ }
2498
+ function parseAgentProvider(value) {
2499
+ if (value === "codex" || value === "claude_code" || value === "vector_cli") {
2500
+ return value;
2501
+ }
2502
+ throw new Error("provider must be one of: codex, claude_code, vector_cli");
2503
+ }
2423
2504
  async function getClient(command) {
2424
2505
  const runtime = await getRuntime(command);
2425
2506
  const session = requireSession(runtime);
@@ -4245,6 +4326,76 @@ serviceCommand.command("status").description("Show bridge service status").actio
4245
4326
  console.log(` Status: ${statusLabel}`);
4246
4327
  console.log(` Config: ${VECTOR_HOME}/bridge.json`);
4247
4328
  });
4329
+ serviceCommand.command("menu-state").description("Return JSON state for the macOS tray").action(async (_options, command) => {
4330
+ const status = getBridgeStatus();
4331
+ const globalOptions = command.optsWithGlobals();
4332
+ const profile = globalOptions.profile ?? "default";
4333
+ const session = await readSession(profile);
4334
+ const liveActivities = readJsonFile(
4335
+ join3(VECTOR_HOME, "live-activities.json"),
4336
+ []
4337
+ );
4338
+ let processes = [];
4339
+ try {
4340
+ const runtime = await getRuntime(command);
4341
+ if (runtime.session && status.config?.deviceId) {
4342
+ const client = await createConvexClient(
4343
+ runtime.session,
4344
+ runtime.appUrl,
4345
+ runtime.convexUrl
4346
+ );
4347
+ const devices = await runQuery(
4348
+ client,
4349
+ api.agentBridge.queries.listProcessesForAttach,
4350
+ {}
4351
+ );
4352
+ const currentDevice = devices.find(
4353
+ (entry) => entry.device._id === status.config?.deviceId
4354
+ );
4355
+ processes = currentDevice?.processes ?? [];
4356
+ }
4357
+ } catch {
4358
+ processes = [];
4359
+ }
4360
+ printOutput(
4361
+ {
4362
+ configured: status.configured,
4363
+ running: status.running,
4364
+ starting: status.starting,
4365
+ pid: status.pid,
4366
+ config: status.config,
4367
+ sessionInfo: buildMenuSessionInfo(session),
4368
+ liveActivities,
4369
+ processes
4370
+ },
4371
+ Boolean(globalOptions.json)
4372
+ );
4373
+ });
4374
+ serviceCommand.command("search-issues <query>").description("Search issues for tray attach actions").option("--limit <n>").action(async (query, options, command) => {
4375
+ const { client, runtime } = await getClient(command);
4376
+ const orgSlug = requireOrg(runtime);
4377
+ const result = await runQuery(client, api.search.queries.searchEntities, {
4378
+ orgSlug,
4379
+ query,
4380
+ limit: optionalNumber(options.limit, "limit") ?? 8
4381
+ });
4382
+ printOutput(result.issues ?? [], runtime.json);
4383
+ });
4384
+ serviceCommand.command("attach-process").description("Attach a detected local process to an issue").requiredOption("--issue-id <id>").requiredOption("--device-id <id>").requiredOption("--process-id <id>").requiredOption("--provider <provider>").option("--title <title>").action(async (options, command) => {
4385
+ const { client, runtime } = await getClient(command);
4386
+ const liveActivityId = await runMutation(
4387
+ client,
4388
+ api.agentBridge.mutations.attachLiveActivity,
4389
+ {
4390
+ issueId: options.issueId,
4391
+ deviceId: options.deviceId,
4392
+ processId: options.processId,
4393
+ provider: parseAgentProvider(options.provider),
4394
+ title: options.title?.trim() || void 0
4395
+ }
4396
+ );
4397
+ printOutput({ ok: true, liveActivityId }, runtime.json);
4398
+ });
4248
4399
  serviceCommand.command("install").description("Install the bridge as a system service (macOS LaunchAgent)").action(async (_options, command) => {
4249
4400
  if (osPlatform() !== "darwin") {
4250
4401
  console.error("Service install is currently macOS only (LaunchAgent).");