@buoy-gg/mcp 7.0.39 → 7.0.41

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.
@@ -904,7 +904,7 @@ async function waitForBroker(url, attempts = 20) {
904
904
  var delay = (ms) => new Promise((r) => setTimeout(r, ms));
905
905
 
906
906
  // src/version.ts
907
- var VERSION = "7.0.39" ? "7.0.39" : "0.0.0-dev";
907
+ var VERSION = "7.0.41" ? "7.0.41" : "0.0.0-dev";
908
908
  var PACKAGE_NAME = "@buoy-gg/mcp";
909
909
 
910
910
  // src/update/checkForUpdate.ts
@@ -1496,6 +1496,24 @@ function failuresFromIndex(index, batchId) {
1496
1496
  }
1497
1497
  return [...byCase.entries()].map(([index2, reason]) => ({ index: index2, reason }));
1498
1498
  }
1499
+ function expectedRunsFor(config) {
1500
+ const caseCount = config.cases.length + (config.discardWarmupCase === true ? 1 : 0);
1501
+ return caseCount * (config.runsPerCase ?? 1);
1502
+ }
1503
+ var SETTLE_WAIT_MS = 1e4;
1504
+ function isRunnerBusy(phase) {
1505
+ return !!phase && phase !== "idle" && phase !== "done" && phase !== "cancelled";
1506
+ }
1507
+ async function waitForRunnerSettled(sync, deviceId, log, maxMs = SETTLE_WAIT_MS) {
1508
+ const start = Date.now();
1509
+ while (Date.now() - start < maxMs) {
1510
+ const snap = await readPerfSnapshot(sync, deviceId).catch(() => null);
1511
+ if (snap && !isRunnerBusy(snap.live?.automation?.phase)) return true;
1512
+ await delay2(POLL_INTERVAL_MS);
1513
+ }
1514
+ log(`automation still busy after ${Math.round(maxMs / 1e3)}s`);
1515
+ return false;
1516
+ }
1499
1517
  async function waitForBatchByIndex(sync, deviceId, opts) {
1500
1518
  const { preBatchIds, expectedRuns, maxWaitMs, log } = opts;
1501
1519
  const start = Date.now();
@@ -1528,6 +1546,7 @@ async function waitForBatchByIndex(sync, deviceId, opts) {
1528
1546
  if (newId2) {
1529
1547
  const count = runCountFor(index, newId2);
1530
1548
  if (expectedRuns > 0 && count >= expectedRuns) {
1549
+ await waitForRunnerSettled(sync, deviceId, log);
1531
1550
  log(`batch ${newId2} complete (${count}/${expectedRuns} runs saved)`);
1532
1551
  return { batchId: newId2, failures: failuresFromIndex(index, newId2) };
1533
1552
  }
@@ -1582,7 +1601,12 @@ function registerPerfMonitorTools(server, sync) {
1582
1601
  const { config, warnings } = buildAutomationConfig(args, base);
1583
1602
  const estimateMs = estimateBatchMs(config);
1584
1603
  const maxWaitMs = args.maxWaitMs ?? estimateMs * 3 + 6e4;
1585
- const expectedRuns = config.cases.length * (config.runsPerCase ?? 1);
1604
+ const expectedRuns = expectedRunsFor(config);
1605
+ if (!await waitForRunnerSettled(sync, deviceId, log)) {
1606
+ return fail2(
1607
+ "Another benchmark batch is still running on this device. Wait for it to finish, or cancel it (call_action perf-monitor cancelAutomation), then retry."
1608
+ );
1609
+ }
1586
1610
  await sync.callAction(PERF_TOOL_ID, "acknowledgeAutomation", {}, deviceId).catch(() => {
1587
1611
  });
1588
1612
  await sync.callAction(PERF_TOOL_ID, "setEnabled", { enabled: true }, deviceId).catch(() => {
package/dist/cli.js CHANGED
@@ -927,7 +927,7 @@ var import_node_os2 = __toESM(require("os"));
927
927
  var import_node_path2 = __toESM(require("path"));
928
928
 
929
929
  // src/version.ts
930
- var VERSION = "7.0.39" ? "7.0.39" : "0.0.0-dev";
930
+ var VERSION = "7.0.41" ? "7.0.41" : "0.0.0-dev";
931
931
  var PACKAGE_NAME = "@buoy-gg/mcp";
932
932
 
933
933
  // src/update/checkForUpdate.ts
@@ -1515,6 +1515,24 @@ function failuresFromIndex(index, batchId) {
1515
1515
  }
1516
1516
  return [...byCase.entries()].map(([index2, reason]) => ({ index: index2, reason }));
1517
1517
  }
1518
+ function expectedRunsFor(config) {
1519
+ const caseCount = config.cases.length + (config.discardWarmupCase === true ? 1 : 0);
1520
+ return caseCount * (config.runsPerCase ?? 1);
1521
+ }
1522
+ var SETTLE_WAIT_MS = 1e4;
1523
+ function isRunnerBusy(phase) {
1524
+ return !!phase && phase !== "idle" && phase !== "done" && phase !== "cancelled";
1525
+ }
1526
+ async function waitForRunnerSettled(sync, deviceId, log, maxMs = SETTLE_WAIT_MS) {
1527
+ const start = Date.now();
1528
+ while (Date.now() - start < maxMs) {
1529
+ const snap = await readPerfSnapshot(sync, deviceId).catch(() => null);
1530
+ if (snap && !isRunnerBusy(snap.live?.automation?.phase)) return true;
1531
+ await delay2(POLL_INTERVAL_MS);
1532
+ }
1533
+ log(`automation still busy after ${Math.round(maxMs / 1e3)}s`);
1534
+ return false;
1535
+ }
1518
1536
  async function waitForBatchByIndex(sync, deviceId, opts) {
1519
1537
  const { preBatchIds, expectedRuns, maxWaitMs, log } = opts;
1520
1538
  const start = Date.now();
@@ -1547,6 +1565,7 @@ async function waitForBatchByIndex(sync, deviceId, opts) {
1547
1565
  if (newId2) {
1548
1566
  const count = runCountFor(index, newId2);
1549
1567
  if (expectedRuns > 0 && count >= expectedRuns) {
1568
+ await waitForRunnerSettled(sync, deviceId, log);
1550
1569
  log(`batch ${newId2} complete (${count}/${expectedRuns} runs saved)`);
1551
1570
  return { batchId: newId2, failures: failuresFromIndex(index, newId2) };
1552
1571
  }
@@ -1601,7 +1620,12 @@ function registerPerfMonitorTools(server, sync) {
1601
1620
  const { config, warnings } = buildAutomationConfig(args, base);
1602
1621
  const estimateMs = estimateBatchMs(config);
1603
1622
  const maxWaitMs = args.maxWaitMs ?? estimateMs * 3 + 6e4;
1604
- const expectedRuns = config.cases.length * (config.runsPerCase ?? 1);
1623
+ const expectedRuns = expectedRunsFor(config);
1624
+ if (!await waitForRunnerSettled(sync, deviceId, log)) {
1625
+ return fail2(
1626
+ "Another benchmark batch is still running on this device. Wait for it to finish, or cancel it (call_action perf-monitor cancelAutomation), then retry."
1627
+ );
1628
+ }
1605
1629
  await sync.callAction(PERF_TOOL_ID, "acknowledgeAutomation", {}, deviceId).catch(() => {
1606
1630
  });
1607
1631
  await sync.callAction(PERF_TOOL_ID, "setEnabled", { enabled: true }, deviceId).catch(() => {
@@ -6476,6 +6500,27 @@ async function main() {
6476
6500
  });
6477
6501
  const server = createMcpServer(sync);
6478
6502
  const transport = new import_stdio.StdioServerTransport();
6503
+ let shuttingDown = false;
6504
+ const shutdown = (why) => {
6505
+ if (shuttingDown) return;
6506
+ shuttingDown = true;
6507
+ process.stderr.write(`[buoy-mcp] shutting down (${why})
6508
+ `);
6509
+ setTimeout(() => process.exit(0), 2e3).unref();
6510
+ void (async () => {
6511
+ await sync.stop().catch(() => {
6512
+ });
6513
+ await server.close().catch(() => {
6514
+ });
6515
+ process.exit(0);
6516
+ })();
6517
+ };
6518
+ process.stdin.once("end", () => shutdown("stdin closed"));
6519
+ process.stdin.once("close", () => shutdown("stdin closed"));
6520
+ server.server.onclose = () => shutdown("transport closed");
6521
+ process.on("SIGINT", () => shutdown("SIGINT"));
6522
+ process.on("SIGTERM", () => shutdown("SIGTERM"));
6523
+ process.on("SIGHUP", () => shutdown("SIGHUP"));
6479
6524
  await server.connect(transport);
6480
6525
  process.stderr.write(`[buoy-mcp] serving MCP over stdio; connecting to broker\u2026
6481
6526
  `);
@@ -6486,15 +6531,6 @@ async function main() {
6486
6531
  `
6487
6532
  )
6488
6533
  );
6489
- const shutdown = async () => {
6490
- await sync.stop().catch(() => {
6491
- });
6492
- await server.close().catch(() => {
6493
- });
6494
- process.exit(0);
6495
- };
6496
- process.on("SIGINT", shutdown);
6497
- process.on("SIGTERM", shutdown);
6498
6534
  }
6499
6535
  if (process.argv[2] === "init") {
6500
6536
  try {
package/dist/cli.mjs CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  SyncClient,
4
4
  createMcpServer,
5
5
  runInit
6
- } from "./chunk-UXLRYEUQ.mjs";
6
+ } from "./chunk-YECW2E7L.mjs";
7
7
 
8
8
  // src/cli.ts
9
9
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
@@ -19,6 +19,27 @@ async function main() {
19
19
  });
20
20
  const server = createMcpServer(sync);
21
21
  const transport = new StdioServerTransport();
22
+ let shuttingDown = false;
23
+ const shutdown = (why) => {
24
+ if (shuttingDown) return;
25
+ shuttingDown = true;
26
+ process.stderr.write(`[buoy-mcp] shutting down (${why})
27
+ `);
28
+ setTimeout(() => process.exit(0), 2e3).unref();
29
+ void (async () => {
30
+ await sync.stop().catch(() => {
31
+ });
32
+ await server.close().catch(() => {
33
+ });
34
+ process.exit(0);
35
+ })();
36
+ };
37
+ process.stdin.once("end", () => shutdown("stdin closed"));
38
+ process.stdin.once("close", () => shutdown("stdin closed"));
39
+ server.server.onclose = () => shutdown("transport closed");
40
+ process.on("SIGINT", () => shutdown("SIGINT"));
41
+ process.on("SIGTERM", () => shutdown("SIGTERM"));
42
+ process.on("SIGHUP", () => shutdown("SIGHUP"));
22
43
  await server.connect(transport);
23
44
  process.stderr.write(`[buoy-mcp] serving MCP over stdio; connecting to broker\u2026
24
45
  `);
@@ -29,15 +50,6 @@ async function main() {
29
50
  `
30
51
  )
31
52
  );
32
- const shutdown = async () => {
33
- await sync.stop().catch(() => {
34
- });
35
- await server.close().catch(() => {
36
- });
37
- process.exit(0);
38
- };
39
- process.on("SIGINT", shutdown);
40
- process.on("SIGTERM", shutdown);
41
53
  }
42
54
  if (process.argv[2] === "init") {
43
55
  try {
package/dist/index.js CHANGED
@@ -962,7 +962,7 @@ var import_node_os2 = __toESM(require("os"));
962
962
  var import_node_path2 = __toESM(require("path"));
963
963
 
964
964
  // src/version.ts
965
- var VERSION = "7.0.39" ? "7.0.39" : "0.0.0-dev";
965
+ var VERSION = "7.0.41" ? "7.0.41" : "0.0.0-dev";
966
966
  var PACKAGE_NAME = "@buoy-gg/mcp";
967
967
 
968
968
  // src/update/checkForUpdate.ts
@@ -1550,6 +1550,24 @@ function failuresFromIndex(index, batchId) {
1550
1550
  }
1551
1551
  return [...byCase.entries()].map(([index2, reason]) => ({ index: index2, reason }));
1552
1552
  }
1553
+ function expectedRunsFor(config) {
1554
+ const caseCount = config.cases.length + (config.discardWarmupCase === true ? 1 : 0);
1555
+ return caseCount * (config.runsPerCase ?? 1);
1556
+ }
1557
+ var SETTLE_WAIT_MS = 1e4;
1558
+ function isRunnerBusy(phase) {
1559
+ return !!phase && phase !== "idle" && phase !== "done" && phase !== "cancelled";
1560
+ }
1561
+ async function waitForRunnerSettled(sync, deviceId, log, maxMs = SETTLE_WAIT_MS) {
1562
+ const start = Date.now();
1563
+ while (Date.now() - start < maxMs) {
1564
+ const snap = await readPerfSnapshot(sync, deviceId).catch(() => null);
1565
+ if (snap && !isRunnerBusy(snap.live?.automation?.phase)) return true;
1566
+ await delay2(POLL_INTERVAL_MS);
1567
+ }
1568
+ log(`automation still busy after ${Math.round(maxMs / 1e3)}s`);
1569
+ return false;
1570
+ }
1553
1571
  async function waitForBatchByIndex(sync, deviceId, opts) {
1554
1572
  const { preBatchIds, expectedRuns, maxWaitMs, log } = opts;
1555
1573
  const start = Date.now();
@@ -1582,6 +1600,7 @@ async function waitForBatchByIndex(sync, deviceId, opts) {
1582
1600
  if (newId2) {
1583
1601
  const count = runCountFor(index, newId2);
1584
1602
  if (expectedRuns > 0 && count >= expectedRuns) {
1603
+ await waitForRunnerSettled(sync, deviceId, log);
1585
1604
  log(`batch ${newId2} complete (${count}/${expectedRuns} runs saved)`);
1586
1605
  return { batchId: newId2, failures: failuresFromIndex(index, newId2) };
1587
1606
  }
@@ -1636,7 +1655,12 @@ function registerPerfMonitorTools(server, sync) {
1636
1655
  const { config, warnings } = buildAutomationConfig(args, base);
1637
1656
  const estimateMs = estimateBatchMs(config);
1638
1657
  const maxWaitMs = args.maxWaitMs ?? estimateMs * 3 + 6e4;
1639
- const expectedRuns = config.cases.length * (config.runsPerCase ?? 1);
1658
+ const expectedRuns = expectedRunsFor(config);
1659
+ if (!await waitForRunnerSettled(sync, deviceId, log)) {
1660
+ return fail2(
1661
+ "Another benchmark batch is still running on this device. Wait for it to finish, or cancel it (call_action perf-monitor cancelAutomation), then retry."
1662
+ );
1663
+ }
1640
1664
  await sync.callAction(PERF_TOOL_ID, "acknowledgeAutomation", {}, deviceId).catch(() => {
1641
1665
  });
1642
1666
  await sync.callAction(PERF_TOOL_ID, "setEnabled", { enabled: true }, deviceId).catch(() => {
package/dist/index.mjs CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  registerStorageTools,
28
28
  registerZustandTools,
29
29
  runInit
30
- } from "./chunk-UXLRYEUQ.mjs";
30
+ } from "./chunk-YECW2E7L.mjs";
31
31
  export {
32
32
  ALL_DEVICES,
33
33
  BROKER_PORT,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@buoy-gg/mcp",
3
- "mcpName": "io.github.buoy-gg/mcp",
4
- "version": "7.0.39",
3
+ "mcpName": "io.github.Buoy-gg/mcp",
4
+ "version": "7.0.41",
5
5
  "description": "MCP server exposing supported Buoy inspection and action tools through the device sync protocol. Tool access requires account and Pro setup.",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.mjs",
@@ -32,8 +32,8 @@
32
32
  "socket.io-client": "^4.8.1",
33
33
  "zod": "^3.25.0",
34
34
  "ws": "^8.18.0",
35
- "@buoy-gg/sync-broker": "^7.0.39",
36
- "@buoy-gg/license": "^7.0.39"
35
+ "@buoy-gg/license": "^7.0.41",
36
+ "@buoy-gg/sync-broker": "^7.0.41"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/node": "^22.0.0",
@@ -73,6 +73,6 @@
73
73
  "clean": "rimraf dist",
74
74
  "test": "pnpm run typecheck && pnpm run smoke",
75
75
  "dev": "node dist/cli.js",
76
- "smoke": "node scripts/stdio-smoke.mjs"
76
+ "smoke": "node scripts/stdio-smoke.mjs && node scripts/stdin-exit-smoke.mjs"
77
77
  }
78
78
  }