@buoy-gg/mcp 7.0.76 → 7.0.78
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/README.md +10 -0
- package/dist/{camera-V7J5ZQUM.mjs → camera-6HTJDU4Y.mjs} +1 -1
- package/dist/{chunk-GDVMXPFL.mjs → chunk-2IWYZICF.mjs} +1 -1
- package/dist/{chunk-KJOH5NDI.mjs → chunk-3STZVJQG.mjs} +1 -1
- package/dist/{chunk-FRGTROJC.mjs → chunk-5NOZVPWB.mjs} +1 -1
- package/dist/{chunk-PAOWVPJM.mjs → chunk-D5K6WO6B.mjs} +1 -1
- package/dist/{chunk-WKQTAALH.mjs → chunk-HEPFVYZG.mjs} +75 -74
- package/dist/{chunk-ZRL5AY5M.mjs → chunk-LHGIYW7N.mjs} +3 -3
- package/dist/{chunk-TKNYLZJ4.mjs → chunk-ODGXMS2O.mjs} +19 -19
- package/dist/{chunk-RVUAVOJU.mjs → chunk-XA74T4JN.mjs} +2 -2
- package/dist/cli.js +11 -10
- package/dist/cli.mjs +7 -7
- package/dist/{flowRun-A5KBJUS5.mjs → flowRun-XEK65IL7.mjs} +1 -1
- package/dist/index.js +49 -48
- package/dist/index.mjs +1 -1
- package/dist/{init-KDX5VSCZ.mjs → init-VCQMVZXB.mjs} +1 -1
- package/dist/{main-B5VNTI32.mjs → main-6OX5577P.mjs} +2 -2
- package/dist/{policy-72DKIGU2.mjs → policy-UNODNYFR.mjs} +1 -1
- package/dist/{simFarm-4UNZBEMG.mjs → simFarm-R4P6QXRK.mjs} +1 -1
- package/dist/{src-IQBNAXE4.mjs → src-R7ICMP6Q.mjs} +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -14,6 +14,16 @@ Connect an MCP client to supported Buoy tools in a running app. Read captured st
|
|
|
14
14
|
|
|
15
15
|
## Install
|
|
16
16
|
|
|
17
|
+
Sign in first. Run this in your app's folder:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npx --package=@buoy-gg/core buoy login
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Your browser opens buoy.gg. Click Allow. This signs in your computer. The MCP uses that sign-in, so it needs no key. As a backup, it reads a key from the env files in the folder it runs in.
|
|
24
|
+
|
|
25
|
+
Then set up the MCP:
|
|
26
|
+
|
|
17
27
|
```bash
|
|
18
28
|
npx -y @buoy-gg/mcp@latest init
|
|
19
29
|
```
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createRequire as e}from"module";const c=e(import.meta.url);import{cliPath as r,describeDevices as t,describeDiagnosis as i,describeInputs as o,entitlementHasPro as s,proRequired as m,readEntitlement as n,run as a,setEntitlementFileForTests as p}from"./chunk-
|
|
1
|
+
import{createRequire as e}from"module";const c=e(import.meta.url);import{cliPath as r,describeDevices as t,describeDiagnosis as i,describeInputs as o,entitlementHasPro as s,proRequired as m,readEntitlement as n,run as a,setEntitlementFileForTests as p}from"./chunk-5NOZVPWB.mjs";import"./chunk-D5K6WO6B.mjs";import"./chunk-MTTWR4T7.mjs";export{r as cliPath,t as describeDevices,i as describeDiagnosis,o as describeInputs,s as entitlementHasPro,m as proRequired,n as readEntitlement,a as run,p as setEntitlementFileForTests};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import{createRequire as q}from"module";const fe=q(import.meta.url);import I from"fs";import R from"os";import y from"path";var G='// Buoy Web helper. Chrome starts it for the Buoy Web extension (native messaging) and\n// ends it when Chrome closes. It passes messages between the extension and Buoy MCP\n// sessions, which connect over a Unix socket only this user can open.\n//\n// extension <-- stdin/stdout (native messaging) --> helper <-- ~/.buoy/web/chrome-<pid>.sock --> MCP sessions\nimport fs from "node:fs";\nimport net from "node:net";\nimport os from "node:os";\nimport path from "node:path";\n\nconst dir = process.env.BUOY_WEB_DIR ?? path.join(os.homedir(), ".buoy", "web");\nfs.mkdirSync(dir, { recursive: true, mode: 0o700 });\nfs.chmodSync(dir, 0o700);\nconst sock = path.join(dir, `chrome-${process.pid}.sock`);\nconst info = path.join(dir, `chrome-${process.pid}.json`);\n\n// ---- native messaging: 4-byte little-endian length, then JSON -----------------\nlet inbuf = Buffer.alloc(0);\nprocess.stdin.on("data", (chunk) => {\n inbuf = Buffer.concat([inbuf, chunk]);\n while (inbuf.length >= 4) {\n const n = inbuf.readUInt32LE(0);\n if (inbuf.length < 4 + n) break;\n const msg = JSON.parse(inbuf.subarray(4, 4 + n).toString("utf8"));\n inbuf = inbuf.subarray(4 + n);\n fromExtension(msg);\n }\n});\nprocess.stdin.on("end", quit); // Chrome closed or the extension let go\nprocess.stdout.on("error", quit);\nfunction toExtension(msg) {\n const body = Buffer.from(JSON.stringify(msg), "utf8");\n if (body.length > 1024 * 1024) throw new Error("Message too big for Chrome (over 1 MB).");\n const head = Buffer.alloc(4);\n head.writeUInt32LE(body.length, 0);\n process.stdout.write(Buffer.concat([head, body]));\n}\n\n// ---- MCP sessions: one JSON message per line ------------------------------------\nconst clients = new Map(); // id -> socket\nlet nextClient = 1;\nfunction fromExtension(msg) {\n const s = clients.get(msg.c);\n if (!s) return;\n const { c, ...rest } = msg;\n s.write(JSON.stringify(rest) + "\\n");\n}\n\nconst server = net.createServer((s) => {\n const c = nextClient++;\n clients.set(c, s);\n let buf = "";\n s.setEncoding("utf8");\n s.on("data", (d) => {\n buf += d;\n let i;\n while ((i = buf.indexOf("\\n")) >= 0) {\n const line = buf.slice(0, i);\n buf = buf.slice(i + 1);\n if (!line) continue;\n let msg;\n try {\n msg = JSON.parse(line);\n toExtension({ ...msg, c });\n } catch (e) {\n if (msg?.id != null) s.write(JSON.stringify({ id: msg.id, error: String(e.message ?? e) }) + "\\n");\n }\n }\n });\n const gone = () => {\n if (!clients.delete(c)) return;\n try {\n toExtension({ c, method: "client.closed" });\n } catch {}\n };\n s.on("close", gone);\n s.on("error", gone);\n});\n\n// Clear out sockets left by helpers that died without cleaning up.\nfor (const f of fs.readdirSync(dir)) {\n const m = /^chrome-(\\d+)\\.(sock|json)$/.exec(f);\n if (!m || Number(m[1]) === process.pid) continue;\n try {\n process.kill(Number(m[1]), 0);\n } catch {\n fs.rmSync(path.join(dir, f), { force: true });\n }\n}\n\nconst old = process.umask(0o177); // the socket file is created 0600\nserver.listen(sock, () => {\n process.umask(old);\n fs.writeFileSync(info, JSON.stringify({ pid: process.pid, sock, started: Date.now() }), { mode: 0o600 });\n // Tells Buoy the extension is set up, so a closed Chrome isn\'t mistaken for "no extension".\n fs.writeFileSync(path.join(dir, "seen"), new Date().toISOString(), { mode: 0o600 });\n toExtension({ ready: true }); // the extension shows "connected" only after this\n});\n\nfunction quit() {\n for (const f of [sock, info]) fs.rmSync(f, { force: true });\n process.exit(0);\n}\nprocess.on("SIGTERM", quit);\nprocess.on("SIGINT", quit);\n';import V from"crypto";import N from"fs";import X from"http";import K from"net";import z from"os";import U from"path";import{WebSocketServer as Q}from"ws";var Z=process.env.BUOY_WEB_RELAYLOG==="1";var M=(...n)=>Z&&process.stderr.write(`[buoy-web relay] ${n.join(" ")}
|
|
2
2
|
`);var x=()=>process.env.BUOY_WEB_DIR??U.join(z.homedir(),".buoy","web");function ee(n=x()){let e=[];try{e=N.readdirSync(n)}catch{return[]}const i=[];for(const o of e){const a=/^chrome-(\d+)\.json$/.exec(o);if(!a)continue;try{process.kill(Number(a[1]),0);const b=JSON.parse(N.readFileSync(U.join(n,o),"utf8"));if(N.existsSync(b.sock))i.push(b)}catch{}}return i.sort((o,a)=>a.started-o.started)}function te(n){return new Promise((e,i)=>{const o=K.createConnection(n);const a=new Map;let b=1;let l="";let d=false;let v=false;const w={onEvent:()=>{},onClose:()=>{},call(m,S){if(v)return Promise.reject(new Error("Chrome's Buoy helper closed."));const c=b++;o.write(JSON.stringify({id:c,method:m,params:S})+"\n");return new Promise((O,B)=>a.set(c,{res:O,rej:B}))},close:()=>o.end()};o.setEncoding("utf8");o.on("connect",()=>{d=true;e(w)});o.on("error",m=>{if(!d)i(m)});o.on("data",m=>{l+=m;let S;while((S=l.indexOf("\n"))>=0){const c=JSON.parse(l.slice(0,S));l=l.slice(S+1);if(c.id!=null&&a.has(c.id)){const{res:O,rej:B}=a.get(c.id);a.delete(c.id);if(c.error)B(new Error(c.error));else O(c.result)}else if(c.event)w.onEvent(c.event,c.params)}});o.on("close",()=>{v=true;for(const{rej:m}of a.values())m(new Error("Chrome's Buoy helper closed."));a.clear();w.onClose()})})}async function ne({sock:n}){const e=await te(n);const i=await e.call("hello");const o=new Map;let a=1;let b=false;let l=null;const d=new Set;const v=t=>{if(l?.readyState===1)l.send(JSON.stringify(t))};const w=t=>[...o.values()].find(t);const m={url:"",hello:i,onDetach:()=>{},onClose:()=>{},idle:()=>Promise.all([...d]),close:()=>{}};async function S(t,{settle:r=false}={}){const s=o.get(t);if(s)return s;await e.call("debugger.attach",{tabId:t});if(r){const E=Date.now();while(Date.now()-E<5e3){const T=await e.call("debugger.send",{tabId:t,method:"Runtime.evaluate",params:{expression:"[location.href, document.readyState]",returnByValue:true}}).catch(()=>null);const[D,L]=T?.result?.value??[];if(D&&D!=="about:blank"&&L!=="loading")break;await new Promise(H=>setTimeout(H,50))}}const{targetInfo:u}=await e.call("debugger.send",{tabId:t,method:"Target.getTargetInfo"});const{openerId:g,openerFrameId:f,...p}=u;p.canAccessOpener=false;const h={tabId:t,sessionId:`buoy-tab-${a++}`,targetInfo:p,children:new Set,framesSent:false,held:[]};o.set(t,h);v({method:"Target.attachedToTarget",params:{sessionId:h.sessionId,targetInfo:{...p,attached:true},waitingForDebugger:false}});return h}function c(t){const r=o.get(t);if(!r)return;o.delete(t);v({method:"Target.detachedFromTarget",params:{sessionId:r.sessionId,targetId:r.targetInfo?.targetId}})}e.onEvent=(t,r)=>{if(t==="debugger.event"){const s=o.get(r.tabId);if(!s)return;const u=r.params?.sessionId;if(r.method==="Target.attachedToTarget"&&u)s.children.add(u);if(r.method==="Target.detachedFromTarget"&&u)s.children.delete(u);const g={sessionId:r.sessionId||s.sessionId,method:r.method,params:r.params};if(!s.framesSent)s.held.push(g);else v(g)}else if(t==="debugger.detached"){c(r.tabId);m.onDetach(r)}else if(t==="tabs.created"){if(b){const s=S(r.id,{settle:true}).catch(()=>{});d.add(s);void s.finally(()=>d.delete(s))}}else if(t==="tabs.removed")c(r.tabId)};e.onClose=()=>{for(const t of[...o.keys()])c(t);l?.close();m.onClose()};async function O(t,r,s){if(!s){switch(t){case"Browser.getVersion":return{protocolVersion:"1.3",product:"Chrome/BuoyWeb",userAgent:i.userAgent,jsVersion:""};case"Browser.setDownloadBehavior":case"Target.setDiscoverTargets":case"Browser.close":return{};case"Target.setAutoAttach":b=true;return{};case"Target.getTargetInfo":return{targetInfo:{targetId:"buoy-browser",type:"browser",title:"",url:"",attached:true,canAccessOpener:false}};case"Target.getBrowserContexts":return{browserContextIds:[]};case"Target.createTarget":{const p=await e.call("tabs.create",{url:r?.url});const h=await S(p.id);return{targetId:h.targetInfo.targetId}}case"Target.closeTarget":{const p=w(h=>h.targetInfo?.targetId===r?.targetId);if(!p)return{success:false};await e.call("tabs.remove",{tabId:p.tabId});return{success:true}}}const f=o.values().next().value;if(!f)throw new Error(`No Buoy tab to run ${t} on.`);return e.call("debugger.send",{tabId:f.tabId,method:t,params:r})}if(t==="Target.getTargetInfo"){const f=w(p=>p.sessionId===s);if(f)return{targetInfo:f.targetInfo}}let u=w(f=>f.sessionId===s);let g;if(!u){u=w(f=>f.children.has(s));g=s}if(!u)throw new Error(`No Buoy tab for session ${s}.`);return e.call("debugger.send",{tabId:u.tabId,sessionId:g,method:t,params:r})}const B=V.randomUUID();const _=X.createServer((t,r)=>r.writeHead(404).end());const C=new Q({server:_});C.on("connection",(t,r)=>{if(r.url!==`/${B}`||l)return t.close(4004,"No.");l=t;t.on("message",async s=>{const{id:u,sessionId:g,method:f,params:p}=JSON.parse(s.toString());try{const h=await O(f,p,g);M("ok ",g??"-",f);t.send(JSON.stringify({id:u,sessionId:g,result:h??{}}));if(f==="Page.getFrameTree"){const E=w(T=>T.sessionId===g);if(E&&!E.framesSent){E.framesSent=true;for(const T of E.held.splice(0))v(T)}}}catch(h){M("ERR",g??"-",f,h.message);t.send(JSON.stringify({id:u,sessionId:g,error:{message:String(h.message??h)}}))}});t.on("close",()=>{l=null;e.close()})});await new Promise(t=>_.listen(0,"127.0.0.1",t));m.url=`ws://127.0.0.1:${_.address().port}/${B}`;m.close=()=>{e.close();C.close();_.close()};return m}var J="gg.buoy.web";var $=["cfolfiajhlenfifknbomdogooagnlamf","kjbgbjimhjiocnfifnemmenkondjeifp",...(process.env.BUOY_WEB_EXTENSION_IDS??"").split(",").filter(Boolean)];var A=["Google/Chrome","Google/Chrome Beta","Google/Chrome Dev","Google/Chrome Canary","Chromium","BraveSoftware/Brave-Browser","Microsoft Edge","Vivaldi","Arc/User Data"];function P(){if(process.env.BUOY_WEB_NMH_DIRS)return process.env.BUOY_WEB_NMH_DIRS.split(y.delimiter).filter(Boolean);if(process.platform!=="darwin")return[];const n=y.join(R.homedir(),"Library","Application Support");return A.map(e=>y.join(n,e)).filter(e=>I.existsSync(e)).map(e=>y.join(e,"NativeMessagingHosts"))}var j=(n,e,i)=>{try{if(I.readFileSync(n,"utf8")===e)return}catch{}I.writeFileSync(n,e,{mode:i});I.chmodSync(n,i)};function oe(){try{const n=y.join(x(),"helper");I.mkdirSync(n,{recursive:true,mode:448});const e=y.join(n,"helper.mjs");const i=y.join(n,"helper.sh");j(e,G,384);const o=d=>`'${d.replace(/'/g,`'\\''`)}'`;const a=process.env.BUOY_WEB_DIR?`BUOY_WEB_DIR=${o(process.env.BUOY_WEB_DIR)} `:"";j(i,`#!/bin/sh
|
|
3
3
|
${a}exec ${o(process.execPath)} ${o(e)} "$@"
|
|
4
|
-
`,448);const b=JSON.stringify({name:J,description:"Buoy Web helper: lets the Buoy MCP use Buoy's own tabs through the Buoy Web extension.",path:i,type:"stdio",allowed_origins:$.map(d=>`chrome-extension://${d}/`)},null,2);const l=[];for(const d of P()){try{I.mkdirSync(d,{recursive:true});j(y.join(d,`${J}.json`),b+"\n",420);l.push(d)}catch{}}return l}catch{return[]}}function re(){if(process.env.BUOY_WEB_NMH_DIRS)return false;if(process.platform!=="darwin")return false;const n=y.join(R.homedir(),"Library","Application Support");for(const e of A){let i=[];try{i=I.readdirSync(y.join(n,e))}catch{continue}for(const o of i){if(o!=="Default"&&!/^Profile \d+$/.test(o))continue;if($.some(a=>I.existsSync(y.join(n,e,o,"Extensions",a))))return true}}return false}import se from"crypto";import k from"fs";import W from"path";var ie=process.env.BUOY_TELEMETRY_URL??"https://buoy.gg/api/t";var ae=24*60*60*1e3;function Y(){const n=(process.env.BUOY_TELEMETRY??"").toLowerCase();return n==="0"||n==="false"||n==="off"||process.env.DO_NOT_TRACK==="1"}var F=false;function ce(){if(F||Y())return;F=true;try{const n=W.join(x(),"install.json");let e={};try{e=JSON.parse(k.readFileSync(n,"utf8"))}catch{}if(typeof e.installId!=="string")e={installId:se.randomUUID(),lastPingAt:0};if(Date.now()-(e.lastPingAt??0)<ae)return;e.lastPingAt=Date.now();k.mkdirSync(W.dirname(n),{recursive:true,mode:448});k.writeFileSync(n,JSON.stringify(e),{mode:384});const i=JSON.stringify({installId:e.installId,version:"7.0.
|
|
4
|
+
`,448);const b=JSON.stringify({name:J,description:"Buoy Web helper: lets the Buoy MCP use Buoy's own tabs through the Buoy Web extension.",path:i,type:"stdio",allowed_origins:$.map(d=>`chrome-extension://${d}/`)},null,2);const l=[];for(const d of P()){try{I.mkdirSync(d,{recursive:true});j(y.join(d,`${J}.json`),b+"\n",420);l.push(d)}catch{}}return l}catch{return[]}}function re(){if(process.env.BUOY_WEB_NMH_DIRS)return false;if(process.platform!=="darwin")return false;const n=y.join(R.homedir(),"Library","Application Support");for(const e of A){let i=[];try{i=I.readdirSync(y.join(n,e))}catch{continue}for(const o of i){if(o!=="Default"&&!/^Profile \d+$/.test(o))continue;if($.some(a=>I.existsSync(y.join(n,e,o,"Extensions",a))))return true}}return false}import se from"crypto";import k from"fs";import W from"path";var ie=process.env.BUOY_TELEMETRY_URL??"https://buoy.gg/api/t";var ae=24*60*60*1e3;function Y(){const n=(process.env.BUOY_TELEMETRY??"").toLowerCase();return n==="0"||n==="false"||n==="off"||process.env.DO_NOT_TRACK==="1"}var F=false;function ce(){if(F||Y())return;F=true;try{const n=W.join(x(),"install.json");let e={};try{e=JSON.parse(k.readFileSync(n,"utf8"))}catch{}if(typeof e.installId!=="string")e={installId:se.randomUUID(),lastPingAt:0};if(Date.now()-(e.lastPingAt??0)<ae)return;e.lastPingAt=Date.now();k.mkdirSync(W.dirname(n),{recursive:true,mode:448});k.writeFileSync(n,JSON.stringify(e),{mode:384});const i=JSON.stringify({installId:e.installId,version:"7.0.78",platform:process.platform==="darwin"?"macos":process.platform==="win32"?"windows":"linux",tier:"locked",surface:"web-mcp"});void fetch(ie,{method:"POST",headers:{"content-type":"application/json"},body:i,signal:AbortSignal.timeout(5e3)}).catch(()=>{})}catch{}}export{x as webDir,ee as findHelpers,ne as startRelay,P as helperManifestDirs,oe as ensureHelper,re as extensionInstalled,Y as telemetryOff,ce as noteUse};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createRequire as e}from"module";const a=e(import.meta.url);var r="7.0.
|
|
1
|
+
import{createRequire as e}from"module";const a=e(import.meta.url);var r="7.0.78"?"7.0.78":"0.0.0-dev";var o="@buoy-gg/mcp";export{r as VERSION,o as PACKAGE_NAME};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{createRequire as p}from"module";const D=p(import.meta.url);import{weekendNow as h}from"./chunk-
|
|
1
|
+
import{createRequire as p}from"module";const D=p(import.meta.url);import{weekendNow as h}from"./chunk-D5K6WO6B.mjs";import{execFile as f}from"child_process";import{promisify as y}from"util";import{existsSync as c,readFileSync as g}from"fs";import u from"os";import a from"path";var b=y(f);function k(){const n=process.env.BUOY_SIMCAM_DIR;const t=[...n?[a.join(n,"buoycam")]:[],"/Applications/Buoy.app/Contents/Resources/simcam/buoycam",a.join(u.homedir(),"Applications/Buoy.app/Contents/Resources/simcam/buoycam")];let e=__dirname;for(let o=0;o<8;o++){t.push(a.join(e,"apps/desktop/resources/simcam/buoycam"));const i=a.dirname(e);if(i===e)break;e=i}return t}var s=null;function m(){if(s)return s;s=k().find(n=>c(n))??null;return s}async function _(n){const t=m();if(!t){return{ok:false,error:"The simulator camera components were not found. They ship with the Buoy desktop app \u2014 install it, or set BUOY_SIMCAM_DIR to the directory holding `buoycam`."}}try{const{stdout:e}=await b(t,[...n,"--json"],{timeout:3e4});return{ok:true,data:JSON.parse(e)}}catch(e){const o=e.stdout??"";try{return{ok:false,data:JSON.parse(o)}}catch{return{ok:false,error:e.message||"the simulator camera CLI failed"}}}}function $(n){const t=n.filter(r=>r.level==="fail");const e=n.filter(r=>r.level==="warn");if(t.length===0&&e.length===0){return"The simulator camera is healthy \u2014 every check passed."}const o=[];for(const r of[...t,...e]){o.push(`- **${r.name}** (${r.level}): ${r.detail}`);if(r.fix)o.push(` ${r.fix}`)}const i=t.length>0?`${t.length} problem${t.length===1?"":"s"} found.`:`No hard failures, but ${e.length} thing${e.length===1?"":"s"} worth knowing.`;return[i,"",...o].join("\n")}function S(n,t){if(n.length===0){return"No booted simulators.\n\n_Boot one first \u2014 `xcrun simctl boot <udid>`, or open Simulator.app. The camera attaches to a simulator, so nothing else here works until one is running._"}const e=[n.length===1?"1 booted simulator:":`${n.length} booted simulators:`,...n.map(o=>`- **${o.name}** (${o.runtime}) \u2014 \`${o.udid}\``)];if(n.length>1&&t===null){e.push("","_More than one is booted, so pass `udid` to list a specific one's apps \u2014 and to every other camera tool that takes one._");return e.join("\n")}if(t===null){e.push("","_Could not read the installed apps._");return e.join("\n")}if(t.length===0){e.push("","No apps installed on it.");return e.join("\n")}e.push("",`${t.length} installed app${t.length===1?"":"s"}:`,...t.map(o=>`- ${o.name} \u2014 \`${o.bundleId}\``),"","_Pass one of these bundle ids to `camera_launch` to relaunch it with the camera attached._");return e.join("\n")}function w(n,t){const e=[];e.push(n.length?'**Mac cameras** (for `kind: "camera"`):':"**Mac cameras**: none found.");if(n.length){e.push(...n.map(o=>`- ${o.name} \u2014 \`${o.uniqueId}\``))}else{e.push("_If this Mac has a webcam, Buoy has not been granted Camera permission (System Settings \u2192 Privacy & Security \u2192 Camera)._")}e.push("");e.push(t.length?'**Capturable windows** (for `kind: "screen"`, `value: "window:<id>"`):':"**Capturable windows**: none found.");if(t.length){e.push(...t.map(o=>`- ${o.app}${o.title?` \u2014 ${o.title}`:""} \u2014 \`window:${o.id}\``))}else{e.push("_Screen Recording permission is almost certainly missing (System Settings \u2192 Privacy & Security \u2192 Screen & System Audio Recording)._")}return e.join("\n")}var l=null;function v(n){l=n}function j(){if(l)return[l];return[a.join(u.homedir(),"Library/Application Support/Buoy/entitlement.json"),a.join(u.homedir(),"Library/Application Support/buoy-desktop/entitlement.json")]}function d(){for(const n of j()){try{if(!c(n))continue;const t=JSON.parse(g(n,"utf8"));const e=t.tier==="pro"||t.tier==="free"?t.tier:"locked";const o=t.hasDesktopAccess===true&&typeof t.validUntil==="number"&&Number.isFinite(t.validUntil)&&Date.now()<t.validUntil;const i=o&&t.isPro===true&&typeof t.proValidUntil==="number"&&Number.isFinite(t.proValidUntil)&&Date.now()<t.proValidUntil;return{tier:e,isPro:i,admitted:i||o&&e!=="locked"}}catch{}}return{tier:"locked",isPro:false,admitted:false}}function P(n=d()){return n.isPro||n.admitted===true&&h()}function C(n){return`\`${n}\` is a Buoy Pro feature.
|
|
2
2
|
|
|
3
3
|
The simulator camera itself is free \u2014 the Mac camera, image, video, test-pattern and QR sources all work in the Buoy desktop panel with a Free account. Pro adds the screen region, the non-QR symbologies (PDF417, Aztec, DataMatrix, Code 128), and driving any of it from an agent.
|
|
4
4
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createRequire as m}from"module";const
|
|
1
|
+
import{createRequire as m}from"module";const O=m(import.meta.url);import{AsyncLocalStorage as h}from"async_hooks";var r={list_devices:null,list_tool_actions:null,camera_diagnose:null,describe_screen:e=>e.includeBuoy?"includeBuoy":null,tap_element:e=>e.includeBuoy?"includeBuoy":null,native_tap:e=>e.allowBuoy?"allowBuoy":null,native_type:null,native_swipe:e=>e.allowBuoy?"allowBuoy":null,native_pinch:e=>e.allowBuoy?"allowBuoy":null,native_inspect:null,run_flow:null,screenshot_component:null,screen_recording:null,device_control:null,reload_app:null,navigate:null,get_routes:null,get_console:null,get_network_requests:e=>e.includeBodies?"includeBodies":null,get_triage:null,run_benchmark_batch:null,wait_for_automation:null,get_automation_status:null,get_batch_report:null,compare_reports:null,get_benchmark_settings:null,set_benchmark_settings:null,get_js_thread_top:null,run_web_benchmark:e=>e.traceDir?"traceDir":null,find_web_ceiling:null,screenshot_web_variants:null,start_optimize_session:null,sim_farm_status:null,sim_farm_setup:null,sim_farm_acquire:null,sim_farm_release:null,sim_farm_action:null,sim_farm_lock:null,sim_farm_report:null,sim_farm_extend:null,sim_farm_finish:null,chrome_farm_status:null,chrome_farm_up:null,chrome_farm_down:null,chrome_farm_reset:null,chrome_farm_quiet:null,chrome_farm_pause:null,chrome_farm_screenshot:null};var u={"highlight-updates":["describeScreen","tapElement","hitTest","readMaps","setSilentTracking"],"route-events":["@snapshot","getCurrentRoute","navigate"],app:["@snapshot","ping","reloadApp"],console:["@snapshot"],network:["@snapshot"],storage:["async.getAllKeys","secure.keys"],"perf-monitor":["@snapshot","getAutomationConfig","setAutomationConfig","acknowledgeAutomation","setEnabled","refreshIndex","startAutomation","loadReport"],"js-top":["sample"]};function f(e,t){return Object.prototype.hasOwnProperty.call(u,e)&&u[e].includes(t)}var i=()=>new Date;function g(e){i=e??(()=>new Date)}function l(e=i()){const t=e.getDay();return t===0||t===6}function d(e,t){const n=l();if(!Object.prototype.hasOwnProperty.call(r,e))return{tool:e,level:"pro",weekend:n};const s=r[e];const a=s?s(t&&typeof t==="object"?t:{}):null;return a?{tool:e,level:"pro",proOption:a,weekend:n}:{tool:e,level:"free",weekend:n}}function c(){return o.getStore()?.weekend??l()}function _(e){if(!e)return false;if(e.isPro===true)return true;return e.tier==="free"&&c()}function y(e){return Object.prototype.hasOwnProperty.call(r,e)}function w(){return Object.keys(r).sort()}var o=new h;function b(e,t){return o.run(Object.freeze({...e}),t)}function k(e){return o.exit(e)}function v(){return o.getStore()??{tool:"",level:"pro"}}function A(e,t){if(!e)return false;if(_(e))return true;return t==="free"&&e.tier==="free"}var p="Free covers reading the screen, taps, swipes and typing, run_flow, screenshots, screen recording, device_control, reload_app, navigate, get_routes, get_console, the request list and get_triage. It also covers Buoy Optimize and the Sim Farm: benchmark batches, reports, web benchmarks and JS thread totals, without the render names, script names and JS origins that say why. Every Saturday and Sunday a free account gets everything Pro does.";function B(e,t){const n=e.proOption?`\`${e.tool}\` with \`${e.proOption}\` needs Buoy Pro.`:e.tool?`\`${e.tool}\` needs Buoy Pro.`:"This needs Buoy Pro.";return`${n}${t} ${p} Tell the user Pro unlocks the rest (https://buoy.gg/pricing). After upgrading, the user runs \`npx --package=@buoy-gg/core buoy login\` again, or signs in again in the app. An app with no on-device UI can take a Pro key through \`licenseKey\`. No setting, argument or other tool turns Pro on, so don't try to work around it.`}export{f as isFreeAppCall,g as setClockForTests,l as isWeekendPass,d as accessFor,c as weekendNow,_ as hasProAccess,y as isFreeTool,w as freeToolNames,b as runWithAccess,k as outsideCalls,v as currentAccess,A as meetsAccess,p as FREE_SUMMARY,B as proRequiredMessage};
|