@buoy-gg/mcp 7.0.61 → 7.0.63

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/cli.mjs CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import{createRequire as d}from"module";const h=d(import.meta.url);import{runInit as w}from"./chunk-QBPXMMWS.mjs";import{SyncClient as u,createMcpServer as m,stopAllRecordingsNow as f}from"./chunk-CRYV6OHD.mjs";import"./chunk-6EOB4FHJ.mjs";import"./chunk-OPHPYPJD.mjs";import"./chunk-MTTWR4T7.mjs";import{StdioServerTransport as g}from"@modelcontextprotocol/sdk/server/stdio.js";console.log=(...e)=>console.error(...e);console.info=(...e)=>console.error(...e);console.debug=(...e)=>console.error(...e);async function b(){const e=process.env.BUOY_BROKER_PORT;const s=new u({url:process.env.BUOY_BROKER_URL,port:e?Number(e):void 0,autoSpawnBroker:process.env.BUOY_NO_SPAWN!=="1"});const r=m(s);const o=new g;let n=false;const c=t=>{if(n)return;n=true;process.stderr.write(`[buoy-mcp] shutting down (${t})
3
- `);f();setTimeout(()=>process.exit(0),2e3).unref();void(async()=>{await s.stop().catch(()=>{});await r.close().catch(()=>{});process.exit(0)})()};process.stdin.once("end",()=>c("stdin closed"));process.stdin.once("close",()=>c("stdin closed"));r.server.onclose=()=>c("transport closed");process.on("SIGINT",()=>c("SIGINT"));process.on("SIGTERM",()=>c("SIGTERM"));process.on("SIGHUP",()=>c("SIGHUP"));await r.connect(o);process.stderr.write(`[buoy-mcp] serving MCP over stdio; connecting to broker\u2026
2
+ import{createRequire as d}from"module";const R=d(import.meta.url);import{runInit as w}from"./chunk-G5SISI2H.mjs";import{SyncClient as u,createMcpServer as m,stopAllHidStreamsNow as f,stopAllRecordingsNow as g}from"./chunk-PGOSBKGQ.mjs";import"./chunk-6EOB4FHJ.mjs";import"./chunk-OPHPYPJD.mjs";import"./chunk-MTTWR4T7.mjs";import{StdioServerTransport as b}from"@modelcontextprotocol/sdk/server/stdio.js";console.log=(...e)=>console.error(...e);console.info=(...e)=>console.error(...e);console.debug=(...e)=>console.error(...e);async function y(){const e=process.env.BUOY_BROKER_PORT;const s=new u({url:process.env.BUOY_BROKER_URL,port:e?Number(e):void 0,autoSpawnBroker:process.env.BUOY_NO_SPAWN!=="1"});const r=m(s);const o=new b;let n=false;const c=t=>{if(n)return;n=true;process.stderr.write(`[buoy-mcp] shutting down (${t})
3
+ `);g();f();setTimeout(()=>process.exit(0),2e3).unref();void(async()=>{await s.stop().catch(()=>{});await r.close().catch(()=>{});process.exit(0)})()};process.stdin.once("end",()=>c("stdin closed"));process.stdin.once("close",()=>c("stdin closed"));r.server.onclose=()=>c("transport closed");process.on("SIGINT",()=>c("SIGINT"));process.on("SIGTERM",()=>c("SIGTERM"));process.on("SIGHUP",()=>c("SIGHUP"));await r.connect(o);process.stderr.write(`[buoy-mcp] serving MCP over stdio; connecting to broker\u2026
4
4
  `);s.start().then(t=>process.stderr.write(`[buoy-mcp] broker ${t}
5
5
  `)).catch(t=>process.stderr.write(`[buoy-mcp] broker connection failed: ${t?.message??t} \u2014 tools will report no devices until it recovers
6
- `))}async function y(){const e=process.env.BUOY_BROKER_PORT;const s=new u({url:process.env.BUOY_BROKER_URL,port:e?Number(e):void 0,autoSpawnBroker:false});try{const r=await Promise.race([s.start().then(()=>true,()=>false),new Promise(o=>setTimeout(()=>o(false),4e3))]);if(!r)return false;for(let o=0;o<10;o++){if(s.connectedDevices().some(n=>n.tier==="pro"))return true;await new Promise(n=>setTimeout(n,300))}return false}finally{await Promise.race([s.stop().catch(()=>{}),new Promise(r=>setTimeout(r,2e3))])}}if(process.argv[2]==="web-bench"){void(async()=>{try{const e=process.argv.slice(3);const s=e.find(a=>!a.startsWith("--"));if(!s)throw new Error("usage: buoy-mcp web-bench <config.json> [--json]");const{readFileSync:r}=await import("fs");const{runWebBench:o,formatWebBenchMarkdown:n}=await import("./webBench-QCHYXYCA.mjs");const{readEntitlement:c}=await import("./camera-JI2FMAKN.mjs");if(!c().isPro&&!await y()){throw new Error("web-bench is a Buoy Pro feature. Sign in to Buoy Desktop with a Pro account, or open an app signed in to Pro. See https://buoy.gg/pricing.")}const t=JSON.parse(r(s,"utf8"));const i=await o({...t,durationMs:t.durationMs??t.perCaseDurationMs},a=>process.stderr.write(`[web-bench] ${a}
6
+ `))}async function v(){const e=process.env.BUOY_BROKER_PORT;const s=new u({url:process.env.BUOY_BROKER_URL,port:e?Number(e):void 0,autoSpawnBroker:false});try{const r=await Promise.race([s.start().then(()=>true,()=>false),new Promise(o=>setTimeout(()=>o(false),4e3))]);if(!r)return false;for(let o=0;o<10;o++){if(s.connectedDevices().some(n=>n.tier==="pro"))return true;await new Promise(n=>setTimeout(n,300))}return false}finally{await Promise.race([s.stop().catch(()=>{}),new Promise(r=>setTimeout(r,2e3))])}}if(process.argv[2]==="web-bench"){void(async()=>{try{const e=process.argv.slice(3);const s=e.find(a=>!a.startsWith("--"));if(!s)throw new Error("usage: buoy-mcp web-bench <config.json> [--json]");const{readFileSync:r}=await import("fs");const{runWebBench:o,formatWebBenchMarkdown:n}=await import("./webBench-QCHYXYCA.mjs");const{readEntitlement:c}=await import("./camera-JI2FMAKN.mjs");if(!c().isPro&&!await v()){throw new Error("web-bench is a Buoy Pro feature. Sign in to Buoy Desktop with a Pro account, or open an app signed in to Pro. See https://buoy.gg/pricing.")}const t=JSON.parse(r(s,"utf8"));const i=await o({...t,durationMs:t.durationMs??t.perCaseDurationMs},a=>process.stderr.write(`[web-bench] ${a}
7
7
  `));const p=i.status==="failed"||i.browserLeftRunning?1:0;const l=(e.includes("--json")?JSON.stringify(i,null,2):n(i))+"\n";setTimeout(()=>process.exit(p),5e3).unref();process.stdout.write(l,()=>process.exit(p))}catch(e){process.stderr.write(`[buoy-mcp] web-bench failed: ${e?.message??e}
8
- `,()=>process.exit(1));setTimeout(()=>process.exit(1),5e3).unref()}})()}else if(process.argv[2]==="flow"&&process.argv[3]==="run"){void(async()=>{try{const{parseFlowRunArgs:e,runFlows:s,formatFlowResults:r}=await import("./flowRun-WQQBDMBN.mjs");const o=e(process.argv.slice(4));const n=await s(o);const c=o.json?JSON.stringify(n,null,2):r(n);const t=n.every(i=>i.passed)?0:1;setTimeout(()=>process.exit(t),5e3).unref();process.stdout.write(`${c}
8
+ `,()=>process.exit(1));setTimeout(()=>process.exit(1),5e3).unref()}})()}else if(process.argv[2]==="flow"&&process.argv[3]==="run"){void(async()=>{try{const{parseFlowRunArgs:e,runFlows:s,formatFlowResults:r}=await import("./flowRun-UYRYZVRR.mjs");const o=e(process.argv.slice(4));const n=await s(o);const c=o.json?JSON.stringify(n,null,2):r(n);const t=n.every(i=>i.passed)?0:1;setTimeout(()=>process.exit(t),5e3).unref();process.stdout.write(`${c}
9
9
  `,()=>process.exit(t))}catch(e){process.stderr.write(`[buoy-mcp] flow run failed: ${e?.message??e}
10
10
  `,()=>process.exit(1));setTimeout(()=>process.exit(1),5e3).unref()}})()}else if(process.argv[2]==="init"){try{const e=process.argv.slice(3);let s="auto";if(e.includes("--local"))s="local";else if(e.includes("--npx"))s="npx";const r=e.indexOf("--registry");const o=r!==-1?e[r+1]:void 0;w({mode:s,registry:o});process.exit(0)}catch(e){process.stderr.write(`[buoy-mcp] init failed: ${e?.message??e}
11
- `);process.exit(1)}}else{b().catch(e=>{process.stderr.write(`[buoy-mcp] fatal: ${e?.message??e}
11
+ `);process.exit(1)}}else{y().catch(e=>{process.stderr.write(`[buoy-mcp] fatal: ${e?.message??e}
12
12
  `);process.exit(1)})}
@@ -1,2 +1,2 @@
1
- import{createRequire as v}from"module";const E=v(import.meta.url);import{SyncClient as y,createMcpServer as R}from"./chunk-CRYV6OHD.mjs";import"./chunk-6EOB4FHJ.mjs";import"./chunk-OPHPYPJD.mjs";import"./chunk-MTTWR4T7.mjs";import{promises as S}from"fs";import $ from"path";import{Client as _}from"@modelcontextprotocol/sdk/client/index.js";import{InMemoryTransport as B}from"@modelcontextprotocol/sdk/inMemory.js";function P(e){const o={names:[]};for(let n=0;n<e.length;n++){const t=e[n];if(t==="--device")o.deviceId=e[++n];else if(t==="--update-snapshots")o.updateSnapshots=true;else if(t==="--json")o.json=true;else if(t==="--wait")o.waitMs=Number(e[++n])*1e3;else if(t==="--all")continue;else if(!t.startsWith("--"))o.names.push(t);else throw new Error(`Unknown option ${t}.`)}return o}async function I(){const e=$.join(process.cwd(),".buoy","flows");return(await S.readdir(e).catch(()=>[])).filter(o=>o.endsWith(".json")).map(o=>o.replace(/\.json$/,"")).sort()}async function g(e,o=n=>process.stderr.write(`${n}
1
+ import{createRequire as v}from"module";const E=v(import.meta.url);import{SyncClient as y,createMcpServer as R}from"./chunk-PGOSBKGQ.mjs";import"./chunk-6EOB4FHJ.mjs";import"./chunk-OPHPYPJD.mjs";import"./chunk-MTTWR4T7.mjs";import{promises as S}from"fs";import $ from"path";import{Client as _}from"@modelcontextprotocol/sdk/client/index.js";import{InMemoryTransport as B}from"@modelcontextprotocol/sdk/inMemory.js";function P(e){const o={names:[]};for(let n=0;n<e.length;n++){const t=e[n];if(t==="--device")o.deviceId=e[++n];else if(t==="--update-snapshots")o.updateSnapshots=true;else if(t==="--json")o.json=true;else if(t==="--wait")o.waitMs=Number(e[++n])*1e3;else if(t==="--all")continue;else if(!t.startsWith("--"))o.names.push(t);else throw new Error(`Unknown option ${t}.`)}return o}async function I(){const e=$.join(process.cwd(),".buoy","flows");return(await S.readdir(e).catch(()=>[])).filter(o=>o.endsWith(".json")).map(o=>o.replace(/\.json$/,"")).sort()}async function g(e,o=n=>process.stderr.write(`${n}
2
2
  `)){const n=e.names.length?e.names:await I();if(n.length===0)throw new Error('No saved flows. Save one with run_flow and save:"name", or pass a flow name.');const t=process.env.BUOY_BROKER_PORT;const s=new y({url:process.env.BUOY_BROKER_URL,port:t?Number(t):void 0,autoSpawnBroker:process.env.BUOY_NO_SPAWN!=="1"});const p=R(s);const[w,f]=B.createLinkedPair();const i=new _({name:"buoy-flow-run",version:"1"});try{await p.connect(f);await i.connect(w);await s.start();const a=Date.now()+(e.waitMs??6e4);while(Date.now()<a&&!s.connectedDevices().some(r=>r.isPro&&(!e.deviceId||r.deviceId===e.deviceId))){await new Promise(r=>setTimeout(r,500))}if(!s.connectedDevices().some(r=>r.isPro)){throw new Error("No Buoy Pro app connected. Start the app (with Buoy) on a simulator or device, then run again.")}const u=[];for(const r of n){const m=Date.now();o(`\u25B6 ${r}`);const l=await i.callTool({name:"run_flow",arguments:{flow:r,include:"none",...e.deviceId?{deviceId:e.deviceId}:{},...e.updateSnapshots?{updateSnapshots:true}:{}}},void 0,{timeout:10*6e4});const h=(l.content??[]).filter(c=>c.type==="text").map(c=>c.text).join("\n");const d=l.isError!==true;u.push({name:r,passed:d,ms:Date.now()-m,report:h});o(`${d?"\u2713":"\u2717"} ${r} (${((Date.now()-m)/1e3).toFixed(1)}s)`)}return u}finally{await i.close().catch(()=>void 0);await Promise.race([s.stop().catch(()=>void 0),new Promise(a=>setTimeout(a,2e3))])}}function j(e){const o=e.filter(t=>!t.passed);const n=[`${e.length-o.length} of ${e.length} flows passed.`];for(const t of o){n.push("",`\u2717 ${t.name}`,t.report.trim(),` Rerun: npx @buoy-gg/mcp flow run ${t.name}`)}return n.join("\n")}export{j as formatFlowResults,P as parseFlowRunArgs,g as runFlows};
package/dist/index.d.mts CHANGED
@@ -133,6 +133,11 @@ declare class SyncClient {
133
133
  deviceName: string;
134
134
  actions: string[];
135
135
  }[];
136
+ /**
137
+ * This project's own connected app, if the broker has admitted it. Picks
138
+ * nothing for the session; for warming up host tools before the first call.
139
+ */
140
+ peekProjectDevice(): string | null;
136
141
  /**
137
142
  * Resolve a concrete target deviceId. If `deviceId` is given it's used as-is.
138
143
  * Otherwise, if exactly one device is connected, that one is chosen; if none
package/dist/index.d.ts CHANGED
@@ -133,6 +133,11 @@ declare class SyncClient {
133
133
  deviceName: string;
134
134
  actions: string[];
135
135
  }[];
136
+ /**
137
+ * This project's own connected app, if the broker has admitted it. Picks
138
+ * nothing for the session; for warming up host tools before the first call.
139
+ */
140
+ peekProjectDevice(): string | null;
136
141
  /**
137
142
  * Resolve a concrete target deviceId. If `deviceId` is given it's used as-is.
138
143
  * Otherwise, if exactly one device is connected, that one is chosen; if none