@kwonye/mcpx 0.1.87 → 0.1.88

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.
@@ -2,11 +2,11 @@ import {
2
2
  loadConfig,
3
3
  loadMergedConfig,
4
4
  saveConfig
5
- } from "./cli-bq7zsrv6.js";
5
+ } from "./cli-btx8jwra.js";
6
6
  import {
7
7
  SecretsManager,
8
8
  ensureGatewayToken
9
- } from "./cli-dvj5waat.js";
9
+ } from "./cli-qfvawh8e.js";
10
10
  import {
11
11
  ensureDir,
12
12
  ensureParentDir,
@@ -290,6 +290,7 @@ function mapRegistryToSpec(_name, option, resolvedValues) {
290
290
  }
291
291
 
292
292
  // src/adapters/claude.ts
293
+ import fs2 from "node:fs";
293
294
  import path2 from "node:path";
294
295
  import { z } from "zod";
295
296
 
@@ -352,6 +353,9 @@ function errorResult(clientId, configPath, message) {
352
353
  message
353
354
  };
354
355
  }
356
+ function managedGatewayEntryName(serverName) {
357
+ return `${serverName} (mcpx)`;
358
+ }
355
359
  function isManagedGatewayProjection(entryName) {
356
360
  return entryName.endsWith(" (mcpx)");
357
361
  }
@@ -419,6 +423,22 @@ function syncMcpExcludedArray(raw, managedNames, managedEntries) {
419
423
  }
420
424
 
421
425
  // src/adapters/claude.ts
426
+ function normalizeProjectKey(p) {
427
+ try {
428
+ return fs2.realpathSync(path2.resolve(p));
429
+ } catch {
430
+ return path2.resolve(p);
431
+ }
432
+ }
433
+ function syncProjectDisabledArray(project, managedNames, disabledForThisProject) {
434
+ const existingNonManaged = (project.disabledMcpServers ?? []).filter((name) => !managedNames.includes(name));
435
+ const combined = [...existingNonManaged, ...disabledForThisProject];
436
+ if (combined.length > 0) {
437
+ project.disabledMcpServers = combined;
438
+ } else {
439
+ delete project.disabledMcpServers;
440
+ }
441
+ }
422
442
  var stringMapSchema = z.record(z.string(), z.string());
423
443
  var claudeEntrySchema = z.object({
424
444
  type: z.string().optional(),
@@ -531,12 +551,26 @@ class ClaudeAdapter {
531
551
  }
532
552
  raw.mcpServers = topLevelServers;
533
553
  syncDisabledMcpServersArray(raw, managedNames, options.managedEntries);
554
+ const scopeByNormalizedPath = new Map;
555
+ for (const scope of options.projectScopes ?? []) {
556
+ scopeByNormalizedPath.set(normalizeProjectKey(scope.path), scope.disabledServerNames);
557
+ }
534
558
  const projects = raw.projects ?? {};
535
559
  for (const projectPath of Object.keys(projects)) {
536
560
  const project = projects[projectPath] ?? {};
537
- syncDisabledMcpServersArray(project, managedNames, options.managedEntries);
561
+ const disabledForThis = scopeByNormalizedPath.get(normalizeProjectKey(projectPath)) ?? [];
562
+ syncProjectDisabledArray(project, managedNames, disabledForThis);
538
563
  projects[projectPath] = project;
539
564
  }
565
+ for (const scope of options.projectScopes ?? []) {
566
+ if (scope.disabledServerNames.length === 0)
567
+ continue;
568
+ const normalizedKey = normalizeProjectKey(scope.path);
569
+ const alreadyExists = Object.keys(projects).some((p) => normalizeProjectKey(p) === normalizedKey);
570
+ if (!alreadyExists) {
571
+ projects[scope.path] = { disabledMcpServers: [...scope.disabledServerNames] };
572
+ }
573
+ }
540
574
  raw.projects = projects;
541
575
  writeJsonAtomic(configPath, raw);
542
576
  setManagedEntries(options.managedIndex, this.id, configPath, Object.fromEntries(Object.entries(serverEntries).map(([name, entry]) => [name, JSON.stringify(entry)])));
@@ -680,7 +714,7 @@ class ClaudeDesktopAdapter {
680
714
 
681
715
  // src/adapters/codex.ts
682
716
  import path4 from "node:path";
683
- import fs2 from "node:fs";
717
+ import fs3 from "node:fs";
684
718
  import { parse, stringify } from "@iarna/toml";
685
719
  import { z as z3 } from "zod";
686
720
  var stringMapSchema3 = z3.preprocess((value) => {
@@ -711,10 +745,10 @@ class CodexAdapter {
711
745
  scanForImports(_config, managedIndex) {
712
746
  const configPath = this.detectConfigPath();
713
747
  const result = emptyImportScan(this.id, configPath ?? undefined);
714
- if (!configPath || !fs2.existsSync(configPath)) {
748
+ if (!configPath || !fs3.existsSync(configPath)) {
715
749
  return result;
716
750
  }
717
- const existing = fs2.readFileSync(configPath, "utf8");
751
+ const existing = fs3.readFileSync(configPath, "utf8");
718
752
  const doc = existing.trim().length > 0 ? parse(existing) : {};
719
753
  const mcpServers = doc.mcp_servers ?? {};
720
754
  for (const [name, rawEntry] of Object.entries(mcpServers)) {
@@ -769,7 +803,7 @@ class CodexAdapter {
769
803
  return errorResult(this.id, undefined, "Unable to resolve Codex config.toml path.");
770
804
  }
771
805
  try {
772
- const existing = fs2.existsSync(configPath) ? fs2.readFileSync(configPath, "utf8") : "";
806
+ const existing = fs3.existsSync(configPath) ? fs3.readFileSync(configPath, "utf8") : "";
773
807
  const doc = existing.trim().length > 0 ? parse(existing) : {};
774
808
  const mcpServers = doc.mcp_servers ?? {};
775
809
  removeSourceEntries(mcpServers, options.sourceEntriesToRemove);
@@ -790,10 +824,10 @@ class CodexAdapter {
790
824
  mcpServers[name] = entry;
791
825
  }
792
826
  doc.mcp_servers = mcpServers;
793
- fs2.mkdirSync(path4.dirname(configPath), { recursive: true });
827
+ fs3.mkdirSync(path4.dirname(configPath), { recursive: true });
794
828
  const tmpPath = `${configPath}.tmp-${process.pid}-${Date.now()}`;
795
- fs2.writeFileSync(tmpPath, stringify(doc), { mode: 384 });
796
- fs2.renameSync(tmpPath, configPath);
829
+ fs3.writeFileSync(tmpPath, stringify(doc), { mode: 384 });
830
+ fs3.renameSync(tmpPath, configPath);
797
831
  setManagedEntries(options.managedIndex, this.id, configPath, Object.fromEntries(Object.entries(serverEntries).map(([name, entry]) => [name, JSON.stringify(entry)])));
798
832
  return okResult(this.id, configPath);
799
833
  } catch (error) {
@@ -933,7 +967,7 @@ class CursorAdapter {
933
967
 
934
968
  // src/adapters/cline.ts
935
969
  import path6 from "node:path";
936
- import fs3 from "node:fs";
970
+ import fs4 from "node:fs";
937
971
  import { z as z5 } from "zod";
938
972
  var stringMapSchema5 = z5.record(z5.string(), z5.string());
939
973
  var clineEntrySchema = z5.object({
@@ -970,7 +1004,7 @@ class ClineAdapter {
970
1004
  detectConfigPath() {
971
1005
  const candidates = getCandidatePaths();
972
1006
  for (const candidate of candidates) {
973
- if (fs3.existsSync(candidate)) {
1007
+ if (fs4.existsSync(candidate)) {
974
1008
  return candidate;
975
1009
  }
976
1010
  }
@@ -982,7 +1016,7 @@ class ClineAdapter {
982
1016
  scanForImports(_config, managedIndex) {
983
1017
  const configPath = this.detectConfigPath();
984
1018
  const result = emptyImportScan(this.id, configPath ?? undefined);
985
- if (!configPath || !fs3.existsSync(configPath)) {
1019
+ if (!configPath || !fs4.existsSync(configPath)) {
986
1020
  return result;
987
1021
  }
988
1022
  const raw = readJsonFile(configPath, {});
@@ -1040,7 +1074,7 @@ class ClineAdapter {
1040
1074
  if (!configPath) {
1041
1075
  return errorResult(this.id, undefined, "Unable to resolve Cline MCP config path.");
1042
1076
  }
1043
- if (!fs3.existsSync(configPath)) {
1077
+ if (!fs4.existsSync(configPath)) {
1044
1078
  return okResult(this.id, configPath, "Cline config not found; skipping sync.");
1045
1079
  }
1046
1080
  try {
@@ -1080,7 +1114,7 @@ class ClineAdapter {
1080
1114
  }
1081
1115
 
1082
1116
  // src/adapters/kiro.ts
1083
- import fs4 from "node:fs";
1117
+ import fs5 from "node:fs";
1084
1118
  import path7 from "node:path";
1085
1119
  import { z as z6 } from "zod";
1086
1120
  var stringMapSchema6 = z6.record(z6.string(), z6.string());
@@ -1198,22 +1232,22 @@ class KiroAdapter {
1198
1232
  }
1199
1233
  syncSkills(skills) {
1200
1234
  const skillsDir = path7.join(homeDir(), ".kiro", "skills");
1201
- if (!fs4.existsSync(skillsDir)) {
1202
- fs4.mkdirSync(skillsDir, { recursive: true });
1235
+ if (!fs5.existsSync(skillsDir)) {
1236
+ fs5.mkdirSync(skillsDir, { recursive: true });
1203
1237
  }
1204
- const existingFiles = fs4.readdirSync(skillsDir);
1238
+ const existingFiles = fs5.readdirSync(skillsDir);
1205
1239
  const managedIds = new Set(skills.map((s) => s.id));
1206
1240
  for (const file of existingFiles) {
1207
1241
  if (file.endsWith(".md")) {
1208
1242
  const id = path7.basename(file, ".md");
1209
1243
  if (!managedIds.has(id)) {
1210
- fs4.unlinkSync(path7.join(skillsDir, file));
1244
+ fs5.unlinkSync(path7.join(skillsDir, file));
1211
1245
  }
1212
1246
  }
1213
1247
  }
1214
1248
  for (const skill of skills) {
1215
1249
  const targetPath = path7.join(skillsDir, `${skill.id}.md`);
1216
- fs4.writeFileSync(targetPath, skill.content, "utf-8");
1250
+ fs5.writeFileSync(targetPath, skill.content, "utf-8");
1217
1251
  }
1218
1252
  }
1219
1253
  }
@@ -1468,7 +1502,7 @@ class VsCodeAdapter {
1468
1502
  }
1469
1503
 
1470
1504
  // src/adapters/qwen.ts
1471
- import fs5 from "node:fs";
1505
+ import fs6 from "node:fs";
1472
1506
  import path10 from "node:path";
1473
1507
  import { z as z9 } from "zod";
1474
1508
  var stringMapSchema9 = z9.record(z9.string(), z9.string());
@@ -1583,22 +1617,22 @@ class QwenAdapter {
1583
1617
  }
1584
1618
  syncSkills(skills) {
1585
1619
  const skillsDir = path10.join(homeDir(), ".qwen", "skills");
1586
- if (!fs5.existsSync(skillsDir)) {
1587
- fs5.mkdirSync(skillsDir, { recursive: true });
1620
+ if (!fs6.existsSync(skillsDir)) {
1621
+ fs6.mkdirSync(skillsDir, { recursive: true });
1588
1622
  }
1589
- const existingFiles = fs5.readdirSync(skillsDir);
1623
+ const existingFiles = fs6.readdirSync(skillsDir);
1590
1624
  const managedIds = new Set(skills.map((s) => s.id));
1591
1625
  for (const file of existingFiles) {
1592
1626
  if (file.endsWith(".md")) {
1593
1627
  const id = path10.basename(file, ".md");
1594
1628
  if (!managedIds.has(id)) {
1595
- fs5.unlinkSync(path10.join(skillsDir, file));
1629
+ fs6.unlinkSync(path10.join(skillsDir, file));
1596
1630
  }
1597
1631
  }
1598
1632
  }
1599
1633
  for (const skill of skills) {
1600
1634
  const targetPath = path10.join(skillsDir, `${skill.id}.md`);
1601
- fs5.writeFileSync(targetPath, skill.content, "utf-8");
1635
+ fs6.writeFileSync(targetPath, skill.content, "utf-8");
1602
1636
  }
1603
1637
  }
1604
1638
  }
@@ -1643,6 +1677,13 @@ function saveManagedIndex(index, filePath = getManagedIndexPath()) {
1643
1677
  function getGatewayUrl(config) {
1644
1678
  return `http://127.0.0.1:${config.gateway.port}/mcp`;
1645
1679
  }
1680
+ function buildProjectScopes(config) {
1681
+ const globallyEnabled = new Set(Object.entries(config.servers).filter(([, spec]) => isServerEnabled(spec)).map(([name]) => name));
1682
+ return Object.values(config.projects ?? {}).map((project) => {
1683
+ const disabledServerNames = (project.disabledServers ?? []).filter((name) => globallyEnabled.has(name)).map((name) => managedGatewayEntryName(name));
1684
+ return { path: project.path, disabledServerNames };
1685
+ });
1686
+ }
1646
1687
  function buildManagedEntries(config, gatewayUrl, localToken) {
1647
1688
  const entries = Object.entries(config.servers);
1648
1689
  return entries.map(([name, spec]) => ({
@@ -1752,7 +1793,8 @@ function syncAllClients(config, secrets, targetClients) {
1752
1793
  managedEntries,
1753
1794
  managedIndex,
1754
1795
  managedIndexPath,
1755
- sourceEntriesToRemove: Array.from(sourceEntriesToRemove.get(adapter.id) ?? [])
1796
+ sourceEntriesToRemove: Array.from(sourceEntriesToRemove.get(adapter.id) ?? []),
1797
+ projectScopes: buildProjectScopes(config)
1756
1798
  });
1757
1799
  results.push(result);
1758
1800
  }
@@ -1887,11 +1929,11 @@ function maybePrefixBearer(target, value, raw = false) {
1887
1929
  // src/core/spawn-env.ts
1888
1930
  import os from "node:os";
1889
1931
  import path11 from "node:path";
1890
- import fs6 from "node:fs";
1932
+ import fs7 from "node:fs";
1891
1933
  function existingNvmCurrentBin() {
1892
1934
  const nvmDir = process.env.NVM_DIR ?? path11.join(os.homedir(), ".nvm");
1893
1935
  const current = path11.join(nvmDir, "current", "bin");
1894
- return fs6.existsSync(current) ? current : null;
1936
+ return fs7.existsSync(current) ? current : null;
1895
1937
  }
1896
1938
  function buildEnrichedPath(current = process.env.PATH ?? "") {
1897
1939
  const candidates = [
@@ -2211,7 +2253,7 @@ async function getOAuthAccessToken(serverName, spec, secrets, options = {}) {
2211
2253
  var APP_VERSION = "0.1.3";
2212
2254
 
2213
2255
  // src/core/update.ts
2214
- import fs7 from "node:fs";
2256
+ import fs8 from "node:fs";
2215
2257
  import path12 from "node:path";
2216
2258
  import { execFileSync as execFileSync2 } from "node:child_process";
2217
2259
  function compareVersions(a, b) {
@@ -2251,17 +2293,17 @@ async function checkForUpdates() {
2251
2293
  }
2252
2294
  function getStagedUpdate() {
2253
2295
  const stagedPath = getStagedVersionPath();
2254
- if (!fs7.existsSync(stagedPath)) {
2296
+ if (!fs8.existsSync(stagedPath)) {
2255
2297
  return null;
2256
2298
  }
2257
2299
  try {
2258
- const raw = fs7.readFileSync(stagedPath, "utf8");
2300
+ const raw = fs8.readFileSync(stagedPath, "utf8");
2259
2301
  const info = JSON.parse(raw);
2260
2302
  if (!info.version || !info.cliPath) {
2261
2303
  return null;
2262
2304
  }
2263
2305
  const absoluteCliPath = path12.isAbsolute(info.cliPath) ? info.cliPath : path12.join(getUpdatesDir(), info.cliPath);
2264
- if (!fs7.existsSync(absoluteCliPath)) {
2306
+ if (!fs8.existsSync(absoluteCliPath)) {
2265
2307
  return null;
2266
2308
  }
2267
2309
  return {
@@ -2280,15 +2322,15 @@ function stageUpdate(version, cliPath) {
2280
2322
  cliPath: path12.isAbsolute(cliPath) ? path12.relative(updatesDir, cliPath) : cliPath,
2281
2323
  stagedAt: new Date().toISOString()
2282
2324
  };
2283
- fs7.writeFileSync(getStagedVersionPath(), JSON.stringify(stagedInfo, null, 2), "utf8");
2325
+ fs8.writeFileSync(getStagedVersionPath(), JSON.stringify(stagedInfo, null, 2), "utf8");
2284
2326
  }
2285
2327
  function shouldUseStagedCli(stagedVersion, currentVersion) {
2286
2328
  return compareVersions(stagedVersion, currentVersion) > 0;
2287
2329
  }
2288
2330
  function clearStagedUpdate() {
2289
2331
  const stagedPath = getStagedVersionPath();
2290
- if (fs7.existsSync(stagedPath)) {
2291
- fs7.unlinkSync(stagedPath);
2332
+ if (fs8.existsSync(stagedPath)) {
2333
+ fs8.unlinkSync(stagedPath);
2292
2334
  }
2293
2335
  }
2294
2336
  function getStagedCliPath() {
@@ -2297,10 +2339,10 @@ function getStagedCliPath() {
2297
2339
  }
2298
2340
  function removeOldVersions(keepCount = 2) {
2299
2341
  const updatesDir = getUpdatesDir();
2300
- if (!fs7.existsSync(updatesDir)) {
2342
+ if (!fs8.existsSync(updatesDir)) {
2301
2343
  return;
2302
2344
  }
2303
- const entries = fs7.readdirSync(updatesDir, { withFileTypes: true });
2345
+ const entries = fs8.readdirSync(updatesDir, { withFileTypes: true });
2304
2346
  const versionDirs = entries.filter((entry) => entry.isDirectory() && entry.name.startsWith("v")).map((entry) => entry.name).sort((a, b) => compareVersions(b.slice(1), a.slice(1)));
2305
2347
  if (versionDirs.length <= keepCount) {
2306
2348
  return;
@@ -2308,20 +2350,20 @@ function removeOldVersions(keepCount = 2) {
2308
2350
  for (const oldVersion of versionDirs.slice(keepCount)) {
2309
2351
  const oldPath = path12.join(updatesDir, oldVersion);
2310
2352
  try {
2311
- fs7.rmSync(oldPath, { recursive: true, force: true });
2353
+ fs8.rmSync(oldPath, { recursive: true, force: true });
2312
2354
  } catch {}
2313
2355
  }
2314
2356
  }
2315
2357
 
2316
2358
  // src/core/update-manager.ts
2317
- import fs8 from "node:fs";
2359
+ import fs9 from "node:fs";
2318
2360
  import path13 from "node:path";
2319
2361
  import { execSync, spawn } from "node:child_process";
2320
2362
  function acquireLock() {
2321
2363
  const lockPath = getUpdateLockPath();
2322
2364
  try {
2323
2365
  ensureDir(path13.dirname(lockPath));
2324
- fs8.writeFileSync(lockPath, `${process.pid}
2366
+ fs9.writeFileSync(lockPath, `${process.pid}
2325
2367
  `, { flag: "wx" });
2326
2368
  return true;
2327
2369
  } catch {
@@ -2331,25 +2373,25 @@ function acquireLock() {
2331
2373
  function releaseLock() {
2332
2374
  const lockPath = getUpdateLockPath();
2333
2375
  try {
2334
- fs8.unlinkSync(lockPath);
2376
+ fs9.unlinkSync(lockPath);
2335
2377
  } catch {}
2336
2378
  }
2337
2379
  function isUpdateInProgress() {
2338
2380
  const lockPath = getUpdateLockPath();
2339
- if (!fs8.existsSync(lockPath)) {
2381
+ if (!fs9.existsSync(lockPath)) {
2340
2382
  return false;
2341
2383
  }
2342
2384
  try {
2343
- const raw = fs8.readFileSync(lockPath, "utf8").trim();
2385
+ const raw = fs9.readFileSync(lockPath, "utf8").trim();
2344
2386
  const pid = Number(raw);
2345
2387
  if (!Number.isFinite(pid) || pid <= 0) {
2346
- fs8.unlinkSync(lockPath);
2388
+ fs9.unlinkSync(lockPath);
2347
2389
  return false;
2348
2390
  }
2349
2391
  process.kill(pid, 0);
2350
2392
  return true;
2351
2393
  } catch {
2352
- fs8.unlinkSync(lockPath);
2394
+ fs9.unlinkSync(lockPath);
2353
2395
  return false;
2354
2396
  }
2355
2397
  }
@@ -2361,7 +2403,7 @@ async function downloadAndStageUpdate() {
2361
2403
  const targetVersion = updateStatus.latestVersion;
2362
2404
  const updatesDir = getUpdatesDir();
2363
2405
  const versionDir = path13.join(updatesDir, `v${targetVersion}`);
2364
- if (fs8.existsSync(versionDir)) {
2406
+ if (fs9.existsSync(versionDir)) {
2365
2407
  const existingStaged = getStagedUpdate();
2366
2408
  if (existingStaged?.version === targetVersion) {
2367
2409
  return { success: false, error: `Version ${targetVersion} already staged` };
@@ -2374,7 +2416,7 @@ async function downloadAndStageUpdate() {
2374
2416
  stdio: ["pipe", "pipe", "pipe"]
2375
2417
  });
2376
2418
  const tarballPath = path13.join(versionDir, `kwonye-mcpx-${targetVersion}.tgz`);
2377
- if (!fs8.existsSync(tarballPath)) {
2419
+ if (!fs9.existsSync(tarballPath)) {
2378
2420
  throw new Error("Downloaded tarball not found");
2379
2421
  }
2380
2422
  execSync(`tar -xzf ${tarballPath} --strip-components=1`, {
@@ -2386,7 +2428,7 @@ async function downloadAndStageUpdate() {
2386
2428
  stdio: ["pipe", "pipe", "pipe"]
2387
2429
  });
2388
2430
  const cliPath = path13.join(versionDir, "dist", "cli.js");
2389
- if (!fs8.existsSync(cliPath)) {
2431
+ if (!fs9.existsSync(cliPath)) {
2390
2432
  throw new Error("CLI entry point not found in downloaded package");
2391
2433
  }
2392
2434
  stageUpdate(targetVersion, cliPath);
@@ -2394,7 +2436,7 @@ async function downloadAndStageUpdate() {
2394
2436
  return { success: true, version: targetVersion };
2395
2437
  } catch (error) {
2396
2438
  try {
2397
- fs8.rmSync(versionDir, { recursive: true, force: true });
2439
+ fs9.rmSync(versionDir, { recursive: true, force: true });
2398
2440
  } catch {}
2399
2441
  return {
2400
2442
  success: false,
@@ -2472,7 +2514,7 @@ function performRollback() {
2472
2514
  }
2473
2515
 
2474
2516
  // src/core/daemon.ts
2475
- import fs9 from "node:fs";
2517
+ import fs10 from "node:fs";
2476
2518
  import net from "node:net";
2477
2519
  import { spawn as spawn2 } from "node:child_process";
2478
2520
 
@@ -3416,10 +3458,10 @@ function createGatewayServer(options) {
3416
3458
 
3417
3459
  // src/core/daemon.ts
3418
3460
  function readPidFromFile(pidPath = getPidPath()) {
3419
- if (!fs9.existsSync(pidPath)) {
3461
+ if (!fs10.existsSync(pidPath)) {
3420
3462
  return null;
3421
3463
  }
3422
- const raw = fs9.readFileSync(pidPath, "utf8").trim();
3464
+ const raw = fs10.readFileSync(pidPath, "utf8").trim();
3423
3465
  if (!raw) {
3424
3466
  return null;
3425
3467
  }
@@ -3521,7 +3563,7 @@ async function startDaemon(config, cliPath, secrets) {
3521
3563
  };
3522
3564
  }
3523
3565
  try {
3524
- fs9.unlinkSync(getPidPath());
3566
+ fs10.unlinkSync(getPidPath());
3525
3567
  } catch {}
3526
3568
  }
3527
3569
  const port = await resolveGatewayPort(config);
@@ -3530,7 +3572,7 @@ async function startDaemon(config, cliPath, secrets) {
3530
3572
  const logPath = getLogPath();
3531
3573
  ensureParentDir(pidPath);
3532
3574
  ensureParentDir(logPath);
3533
- const logFd = fs9.openSync(logPath, "a", 384);
3575
+ const logFd = fs10.openSync(logPath, "a", 384);
3534
3576
  const child = spawn2(process.execPath, [cliPath, "daemon", "run", "--port", String(port)], {
3535
3577
  detached: true,
3536
3578
  stdio: ["ignore", logFd, logFd],
@@ -3540,7 +3582,7 @@ async function startDaemon(config, cliPath, secrets) {
3540
3582
  }
3541
3583
  });
3542
3584
  child.unref();
3543
- fs9.writeFileSync(pidPath, `${child.pid}
3585
+ fs10.writeFileSync(pidPath, `${child.pid}
3544
3586
  `, { mode: 384 });
3545
3587
  startBackgroundUpdateCheck();
3546
3588
  await waitForGatewayReady(port, token);
@@ -3564,7 +3606,7 @@ function stopDaemon() {
3564
3606
  process.kill(pid, "SIGTERM");
3565
3607
  } catch {}
3566
3608
  try {
3567
- fs9.unlinkSync(pidPath);
3609
+ fs10.unlinkSync(pidPath);
3568
3610
  } catch {}
3569
3611
  return {
3570
3612
  stopped: true,
@@ -3577,10 +3619,10 @@ async function restartDaemon(config, cliPath, secrets) {
3577
3619
  }
3578
3620
  function readDaemonLogs(maxLines = 200) {
3579
3621
  const logPath = getLogPath();
3580
- if (!fs9.existsSync(logPath)) {
3622
+ if (!fs10.existsSync(logPath)) {
3581
3623
  return "";
3582
3624
  }
3583
- const lines = fs9.readFileSync(logPath, "utf8").split(`
3625
+ const lines = fs10.readFileSync(logPath, "utf8").split(`
3584
3626
  `);
3585
3627
  return lines.slice(Math.max(lines.length - maxLines, 0)).join(`
3586
3628
  `);
@@ -3697,11 +3739,11 @@ async function buildStatusReport(config, managedIndex, daemon = getDaemonStatus(
3697
3739
  tokenCount
3698
3740
  };
3699
3741
  if (serverEntry.enabled && tokenCount) {
3700
- const matchingProject = projectEntries.find((p) => name.startsWith(`${p.name}.`));
3701
- if (matchingProject) {
3702
- totalProjectTokens[matchingProject.path] = (totalProjectTokens[matchingProject.path] ?? 0) + tokenCount.total;
3703
- } else {
3704
- totalGlobalTokens += tokenCount.total;
3742
+ totalGlobalTokens += tokenCount.total;
3743
+ for (const projectEntry of projectEntries) {
3744
+ if (!(projectEntry.disabledServers ?? []).includes(name)) {
3745
+ totalProjectTokens[projectEntry.path] = (totalProjectTokens[projectEntry.path] ?? 0) + tokenCount.total;
3746
+ }
3705
3747
  }
3706
3748
  }
3707
3749
  return serverEntry;