@buoy-gg/mcp 7.0.64 → 7.0.66
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 +1 -1
- package/dist/camera-F5Q7WMHF.mjs +1 -0
- package/dist/{chunk-EY5YNHSL.mjs → chunk-EPYLVJ7F.mjs} +131 -128
- package/dist/chunk-MHL43LJN.mjs +2 -0
- package/dist/{chunk-HJIQXMRO.mjs → chunk-OCWGZASK.mjs} +4 -3
- package/dist/{chunk-6EOB4FHJ.mjs → chunk-VKWX4XAY.mjs} +2 -2
- package/dist/chunk-Y7SNXKA2.mjs +6 -0
- package/dist/cli.js +85 -81
- package/dist/cli.mjs +4 -4
- package/dist/flowRun-OP4UJXKS.mjs +2 -0
- package/dist/index.d.mts +51 -15
- package/dist/index.d.ts +51 -15
- package/dist/index.js +61 -57
- package/dist/index.mjs +1 -1
- package/dist/{simFarm-HLOW7LIW.mjs → simFarm-EY4R3A4O.mjs} +1 -1
- package/dist/src-XCBUDSR7.mjs +1 -0
- package/package.json +4 -4
- package/dist/camera-JI2FMAKN.mjs +0 -1
- package/dist/chunk-QW2BPKIP.mjs +0 -2
- package/dist/chunk-SWS5NTYM.mjs +0 -6
- package/dist/flowRun-G4VDNSLJ.mjs +0 -2
- package/dist/src-XWK66ACL.mjs +0 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{createRequire as d}from"module";const R=d(import.meta.url);import{runInit as m}from"./chunk-
|
|
2
|
+
import{createRequire as d}from"module";const R=d(import.meta.url);import{runInit as m}from"./chunk-OCWGZASK.mjs";import{SyncClient as u,createMcpServer as w,stopAllHidStreamsNow as f,stopAllRecordingsNow as g}from"./chunk-EPYLVJ7F.mjs";import"./chunk-MHL43LJN.mjs";import"./chunk-VKWX4XAY.mjs";import"./chunk-Y7SNXKA2.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 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:process.env.BUOY_NO_SPAWN!=="1"});const r=w(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
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-
|
|
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-F5Q7WMHF.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}
|
|
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-
|
|
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-OP4UJXKS.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
|
-
`,()=>process.exit(1));setTimeout(()=>process.exit(1),5e3).unref()}})()}else if(process.argv[2]==="farmd"){void import("./simFarm-
|
|
10
|
+
`,()=>process.exit(1));setTimeout(()=>process.exit(1),5e3).unref()}})()}else if(process.argv[2]==="farmd"){void import("./simFarm-EY4R3A4O.mjs").then(e=>e.runFarmd()).catch(e=>{process.stderr.write(`[buoy-mcp] farmd failed: ${e?.message??e}
|
|
11
11
|
`);process.exit(1)})}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;m({mode:s,registry:o});process.exit(0)}catch(e){process.stderr.write(`[buoy-mcp] init failed: ${e?.message??e}
|
|
12
12
|
`);process.exit(1)}}else{v().catch(e=>{process.stderr.write(`[buoy-mcp] fatal: ${e?.message??e}
|
|
13
13
|
`);process.exit(1)})}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{createRequire as v}from"module";const E=v(import.meta.url);import{SyncClient as y,createMcpServer as R}from"./chunk-EPYLVJ7F.mjs";import"./chunk-MHL43LJN.mjs";import"./chunk-VKWX4XAY.mjs";import"./chunk-Y7SNXKA2.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 I(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 P(){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
|
+
`)){const n=e.names.length?e.names:await P();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 w=R(s);const[d,f]=B.createLinkedPair();const i=new _({name:"buoy-flow-run",version:"1"});try{await w.connect(f);await i.connect(d);await s.start();const a=Date.now()+(e.waitMs??6e4);while(Date.now()<a&&!s.connectedDevices().some(r=>(r.isPro||r.tier==="free")&&(!e.deviceId||r.deviceId===e.deviceId))){await new Promise(r=>setTimeout(r,500))}if(!s.connectedDevices().some(r=>r.isPro||r.tier==="free")){throw new Error("No app on a Buoy account is 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 p=l.isError!==true;u.push({name:r,passed:p,ms:Date.now()-m,report:h});o(`${p?"\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,I as parseFlowRunArgs,g as runFlows};
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { ToolCapability } from '@buoy-gg/sync-broker';
|
|
2
2
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
3
|
|
|
4
|
+
type AccessLevel = "free" | "pro";
|
|
5
|
+
|
|
4
6
|
interface SyncClientOptions {
|
|
5
7
|
/** Broker URL to connect to. @default http://localhost:42831 */
|
|
6
8
|
url?: string;
|
|
@@ -24,14 +26,14 @@ interface DeviceInfo {
|
|
|
24
26
|
/** Whether the connected app reported an active Buoy Pro license. */
|
|
25
27
|
isPro: boolean;
|
|
26
28
|
/**
|
|
27
|
-
* The app's tier
|
|
28
|
-
*
|
|
29
|
-
*
|
|
29
|
+
* The app's tier after admission. New sockets are "checking"; an account
|
|
30
|
+
* lock is "locked". Older apps report only `isPro`, which maps to Pro
|
|
31
|
+
* or locked because keys could only grant Pro before the tier split.
|
|
30
32
|
*
|
|
31
33
|
* Surfaced so `list_devices` can say WHY the MCP is blocked: "signed in on
|
|
32
34
|
* the free tier" and "no admitted account" are different problems.
|
|
33
35
|
*/
|
|
34
|
-
tier: "locked" | "free" | "pro";
|
|
36
|
+
tier: "checking" | "locked" | "free" | "pro";
|
|
35
37
|
/**
|
|
36
38
|
* More than one app is registered under this id right now (a pinned
|
|
37
39
|
* `externalSync.deviceId` copied onto two devices). Actions sent to it
|
|
@@ -116,7 +118,10 @@ declare class SyncClient {
|
|
|
116
118
|
* with every simulator erase and fresh dev client, and each one can hold
|
|
117
119
|
* multi-MB snapshots, so a long-lived server has to forget eventually.
|
|
118
120
|
*/
|
|
121
|
+
/** Whether the broker admitted this host's Buoy account. */
|
|
122
|
+
isAdmitted(): boolean;
|
|
119
123
|
private requireAdmission;
|
|
124
|
+
private transportLost;
|
|
120
125
|
private setAdmission;
|
|
121
126
|
private requireDeviceAccount;
|
|
122
127
|
private lockDevice;
|
|
@@ -145,22 +150,53 @@ declare class SyncClient {
|
|
|
145
150
|
*/
|
|
146
151
|
resolveDevice(deviceId?: string): string;
|
|
147
152
|
/**
|
|
148
|
-
* Resolve a target device AND require
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
153
|
+
* Resolve a target device AND require the tier the current tool call needs.
|
|
154
|
+
* Most tools need Buoy Pro; the free ones (access/policy.ts) also take an app
|
|
155
|
+
* on the free tier. The level comes from the call's scope, set centrally in
|
|
156
|
+
* server.ts before any handler runs, so a handler can't pick its own. With no
|
|
157
|
+
* scope (work outside any tool call) the level is Pro. The app's own license
|
|
158
|
+
* check is the source of truth (the device reports it over the broker); this
|
|
159
|
+
* just reads it.
|
|
152
160
|
*
|
|
153
|
-
* `list_devices` deliberately does NOT call this — a
|
|
154
|
-
* their device and
|
|
155
|
-
* is blocked.
|
|
161
|
+
* `list_devices` deliberately does NOT call this — a user without access can
|
|
162
|
+
* still see their device and its tier, which explains what is blocked.
|
|
156
163
|
*/
|
|
157
164
|
requireProDevice(deviceId?: string): string;
|
|
158
165
|
/**
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
166
|
+
* The check under every app call (callAction, getSnapshot, the snapshot
|
|
167
|
+
* cache, lastSync), on top of requireProDevice. A call to a Pro app always
|
|
168
|
+
* passes. A call to any other app passes only inside a free tool call and
|
|
169
|
+
* only for the app calls listed in access/policy.ts, so a Pro tool that
|
|
170
|
+
* forgot requireProDevice still can't act on a free app, and a free tool
|
|
171
|
+
* can't reach Pro data by any path. Work outside any tool call (reconnects,
|
|
172
|
+
* health pings) is plumbing and passes.
|
|
173
|
+
*/
|
|
174
|
+
private checkAppCall;
|
|
175
|
+
/**
|
|
176
|
+
* A free app's tap must land on the app, not on Buoy's own panels: their
|
|
177
|
+
* controls do what Pro tools do. The app side leaves Buoy out of fuzzy
|
|
178
|
+
* matches but lets an exact testID or nativeTag through, so on a free app an
|
|
179
|
+
* exact tap goes through only when the app-only screen list shows that
|
|
180
|
+
* target. Anything this can't prove (a Buoy control, an off-screen target, a
|
|
181
|
+
* failed read, a broadcast to "All") is refused. Resolves to replacement
|
|
182
|
+
* params when it narrows the tap (never edits the caller's object, which a
|
|
183
|
+
* flow reuses on retries). Returns null, without an await, for every call it
|
|
184
|
+
* doesn't apply to.
|
|
185
|
+
*/
|
|
186
|
+
private refuseBuoyPanelTap;
|
|
187
|
+
/**
|
|
188
|
+
* Whether this device was seen on a tier good enough for the current call,
|
|
189
|
+
* connected or not. For host controls that keep working after the app
|
|
190
|
+
* quits or crashes (see hostKit), and for the last-sync fallback.
|
|
191
|
+
*/
|
|
192
|
+
deviceWasAllowed(deviceId: string): boolean;
|
|
193
|
+
/**
|
|
194
|
+
* Where a device stands for `level` (the current call's by default):
|
|
195
|
+
* connected and allowed ("ready"), not connected ("offline"), connected but
|
|
196
|
+
* its account not announced yet ("pending"), or announced on a tier without
|
|
197
|
+
* this access ("denied").
|
|
162
198
|
*/
|
|
163
|
-
accessState(deviceId: string): "ready" | "offline" | "pending" | "denied";
|
|
199
|
+
accessState(deviceId: string, level?: AccessLevel): "ready" | "offline" | "pending" | "denied";
|
|
164
200
|
private healthOf;
|
|
165
201
|
/** The device answered — it's alive. */
|
|
166
202
|
private noteOk;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { ToolCapability } from '@buoy-gg/sync-broker';
|
|
2
2
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
3
|
|
|
4
|
+
type AccessLevel = "free" | "pro";
|
|
5
|
+
|
|
4
6
|
interface SyncClientOptions {
|
|
5
7
|
/** Broker URL to connect to. @default http://localhost:42831 */
|
|
6
8
|
url?: string;
|
|
@@ -24,14 +26,14 @@ interface DeviceInfo {
|
|
|
24
26
|
/** Whether the connected app reported an active Buoy Pro license. */
|
|
25
27
|
isPro: boolean;
|
|
26
28
|
/**
|
|
27
|
-
* The app's tier
|
|
28
|
-
*
|
|
29
|
-
*
|
|
29
|
+
* The app's tier after admission. New sockets are "checking"; an account
|
|
30
|
+
* lock is "locked". Older apps report only `isPro`, which maps to Pro
|
|
31
|
+
* or locked because keys could only grant Pro before the tier split.
|
|
30
32
|
*
|
|
31
33
|
* Surfaced so `list_devices` can say WHY the MCP is blocked: "signed in on
|
|
32
34
|
* the free tier" and "no admitted account" are different problems.
|
|
33
35
|
*/
|
|
34
|
-
tier: "locked" | "free" | "pro";
|
|
36
|
+
tier: "checking" | "locked" | "free" | "pro";
|
|
35
37
|
/**
|
|
36
38
|
* More than one app is registered under this id right now (a pinned
|
|
37
39
|
* `externalSync.deviceId` copied onto two devices). Actions sent to it
|
|
@@ -116,7 +118,10 @@ declare class SyncClient {
|
|
|
116
118
|
* with every simulator erase and fresh dev client, and each one can hold
|
|
117
119
|
* multi-MB snapshots, so a long-lived server has to forget eventually.
|
|
118
120
|
*/
|
|
121
|
+
/** Whether the broker admitted this host's Buoy account. */
|
|
122
|
+
isAdmitted(): boolean;
|
|
119
123
|
private requireAdmission;
|
|
124
|
+
private transportLost;
|
|
120
125
|
private setAdmission;
|
|
121
126
|
private requireDeviceAccount;
|
|
122
127
|
private lockDevice;
|
|
@@ -145,22 +150,53 @@ declare class SyncClient {
|
|
|
145
150
|
*/
|
|
146
151
|
resolveDevice(deviceId?: string): string;
|
|
147
152
|
/**
|
|
148
|
-
* Resolve a target device AND require
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
153
|
+
* Resolve a target device AND require the tier the current tool call needs.
|
|
154
|
+
* Most tools need Buoy Pro; the free ones (access/policy.ts) also take an app
|
|
155
|
+
* on the free tier. The level comes from the call's scope, set centrally in
|
|
156
|
+
* server.ts before any handler runs, so a handler can't pick its own. With no
|
|
157
|
+
* scope (work outside any tool call) the level is Pro. The app's own license
|
|
158
|
+
* check is the source of truth (the device reports it over the broker); this
|
|
159
|
+
* just reads it.
|
|
152
160
|
*
|
|
153
|
-
* `list_devices` deliberately does NOT call this — a
|
|
154
|
-
* their device and
|
|
155
|
-
* is blocked.
|
|
161
|
+
* `list_devices` deliberately does NOT call this — a user without access can
|
|
162
|
+
* still see their device and its tier, which explains what is blocked.
|
|
156
163
|
*/
|
|
157
164
|
requireProDevice(deviceId?: string): string;
|
|
158
165
|
/**
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
166
|
+
* The check under every app call (callAction, getSnapshot, the snapshot
|
|
167
|
+
* cache, lastSync), on top of requireProDevice. A call to a Pro app always
|
|
168
|
+
* passes. A call to any other app passes only inside a free tool call and
|
|
169
|
+
* only for the app calls listed in access/policy.ts, so a Pro tool that
|
|
170
|
+
* forgot requireProDevice still can't act on a free app, and a free tool
|
|
171
|
+
* can't reach Pro data by any path. Work outside any tool call (reconnects,
|
|
172
|
+
* health pings) is plumbing and passes.
|
|
173
|
+
*/
|
|
174
|
+
private checkAppCall;
|
|
175
|
+
/**
|
|
176
|
+
* A free app's tap must land on the app, not on Buoy's own panels: their
|
|
177
|
+
* controls do what Pro tools do. The app side leaves Buoy out of fuzzy
|
|
178
|
+
* matches but lets an exact testID or nativeTag through, so on a free app an
|
|
179
|
+
* exact tap goes through only when the app-only screen list shows that
|
|
180
|
+
* target. Anything this can't prove (a Buoy control, an off-screen target, a
|
|
181
|
+
* failed read, a broadcast to "All") is refused. Resolves to replacement
|
|
182
|
+
* params when it narrows the tap (never edits the caller's object, which a
|
|
183
|
+
* flow reuses on retries). Returns null, without an await, for every call it
|
|
184
|
+
* doesn't apply to.
|
|
185
|
+
*/
|
|
186
|
+
private refuseBuoyPanelTap;
|
|
187
|
+
/**
|
|
188
|
+
* Whether this device was seen on a tier good enough for the current call,
|
|
189
|
+
* connected or not. For host controls that keep working after the app
|
|
190
|
+
* quits or crashes (see hostKit), and for the last-sync fallback.
|
|
191
|
+
*/
|
|
192
|
+
deviceWasAllowed(deviceId: string): boolean;
|
|
193
|
+
/**
|
|
194
|
+
* Where a device stands for `level` (the current call's by default):
|
|
195
|
+
* connected and allowed ("ready"), not connected ("offline"), connected but
|
|
196
|
+
* its account not announced yet ("pending"), or announced on a tier without
|
|
197
|
+
* this access ("denied").
|
|
162
198
|
*/
|
|
163
|
-
accessState(deviceId: string): "ready" | "offline" | "pending" | "denied";
|
|
199
|
+
accessState(deviceId: string, level?: AccessLevel): "ready" | "offline" | "pending" | "denied";
|
|
164
200
|
private healthOf;
|
|
165
201
|
/** The device answered — it's alive. */
|
|
166
202
|
private noteOk;
|