@stim-cli/server 1.11.0 → 1.12.0
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 +82 -5
- package/dist/{protocol-CmlG7X7_.mjs → protocol-BElQc2vm.mjs} +159 -5
- package/dist/protocol.d.mts +109 -4
- package/dist/protocol.mjs +2 -2
- package/dist/protocol.schema.json +399 -2
- package/dist/stim-frames/EmulatorPosture.swift +73 -0
- package/dist/stim-frames/EmulatorRotation.swift +59 -0
- package/dist/stim-frames/InputMessages.swift +56 -6
- package/dist/stim-frames/ScreenshotMessages.swift +27 -4
- package/dist/stim-frames/SimulatorHID.swift +256 -21
- package/dist/stim-frames/SimulatorRotation.swift +64 -0
- package/dist/stim-frames/main.swift +261 -27
- package/dist/stim-frames/sim-fold.entitlements +8 -0
- package/dist/stim-frames/sim-fold.m +47 -0
- package/dist/stim-server.mjs +1011 -155
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -107,12 +107,13 @@ closes its open connections.
|
|
|
107
107
|
## Scopes
|
|
108
108
|
|
|
109
109
|
A paired device has the `read` capability, which serves state, or also
|
|
110
|
-
`control`, which runs [actions](#actions). Pairing grants `read` only, unless
|
|
110
|
+
`control`, which runs [actions](#actions) and [controls devices](#control). Pairing grants `read` only, unless
|
|
111
111
|
the pairing code came from `stim-server pair --control`. On the Mac,
|
|
112
112
|
`stim-server devices grant <id> --control` adds control to a paired device and
|
|
113
113
|
`--read` takes it away. Nothing a client sends changes its own capabilities.
|
|
114
|
-
The server checks the device's capabilities in `devices.json` on every action
|
|
115
|
-
|
|
114
|
+
The server checks the device's capabilities in `devices.json` on every action
|
|
115
|
+
and control session, and ends a device's control sessions when it loses
|
|
116
|
+
`control`, so taking control away applies to open connections at once. `hello` reports
|
|
116
117
|
the capabilities and actions of the connection's device when it connects; a
|
|
117
118
|
connection sees a new grant after it reconnects.
|
|
118
119
|
|
|
@@ -221,12 +222,15 @@ Events are `{ "event", "subscription", ... }`.
|
|
|
221
222
|
(`default` when absent), and returns the payload of
|
|
222
223
|
`stim <platform> --plan --json` run in the workspace: the fingerprint, the
|
|
223
224
|
cache result the next build would get (`local`, `remote` or `false`), the
|
|
224
|
-
prebuild decision,
|
|
225
|
+
prebuild decision, `expectedMs` with its `basis`, and on a predicted cold
|
|
226
|
+
build its `missReason`. It builds, boots and
|
|
225
227
|
installs nothing and writes no Stim state; a remote cache check can
|
|
226
228
|
download the artifact into a temporary directory, so it gets 150 seconds
|
|
227
229
|
instead of 60. A plan predicting that the build would refuse is a result
|
|
228
230
|
whose `refusal` holds the code, message and remedy. A plan that cannot be
|
|
229
|
-
computed is a `stim-failed` error.
|
|
231
|
+
computed is a `stim-failed` error. One plan runs per workspace at a time,
|
|
232
|
+
across all connections; later requests wait their turn, and the 150
|
|
233
|
+
seconds start when the plan starts.
|
|
230
234
|
- `machine.get` returns cheap machine usage, read in the server process
|
|
231
235
|
without running `stim`: `volumes`, one per volume that holds a Stim
|
|
232
236
|
workspace, Stim home, or the simulators, with `mount`, `holds`, `freeBytes`
|
|
@@ -297,6 +301,79 @@ and `durationMs` when it ran. Strings from the client and error messages are
|
|
|
297
301
|
cut to 256 characters. `stim-server log` prints them, with control characters
|
|
298
302
|
replaced by `?`.
|
|
299
303
|
|
|
304
|
+
## Control
|
|
305
|
+
|
|
306
|
+
A device with `control` can drive a simulator or emulator that `stim status`
|
|
307
|
+
lists as owned by a workspace. Nothing it sends reaches any other device.
|
|
308
|
+
|
|
309
|
+
- `control.begin` takes `workspace`, `platform`, `slot` (`default` when
|
|
310
|
+
absent) and `takeOver`, and returns `{ "session", "platform", "lease",
|
|
311
|
+
"postures" }`. `postures` lists what `input.posture` takes for the device:
|
|
312
|
+
`folded` and `unfolded` for an iPhone Duo, `folded`, `half-open` and
|
|
313
|
+
`unfolded` for an emulator with a hinge, such as a `pixel_fold` AVD, and
|
|
314
|
+
none otherwise.
|
|
315
|
+
The server refuses with `device-busy` when status reports the device driven
|
|
316
|
+
(agent-device, a `stim device lock`, a test runner) or another client
|
|
317
|
+
controls it, naming the driver. With `takeOver: true` it proceeds anyway;
|
|
318
|
+
another client's session then ends with `taken-over`.
|
|
319
|
+
- The session holds a `stim device lock <platform> <id> --for 2m` lease,
|
|
320
|
+
renewed every minute, so `stim status` shows the device as driven by
|
|
321
|
+
`stim device lock` and agents leave it alone. `lease` carries its
|
|
322
|
+
`grantedAt`, the `since` of that driver, so a client can tell its own lease
|
|
323
|
+
from an agent's. The server releases the lease with `stim device unlock`
|
|
324
|
+
when the session ends, unless the lease was already held before the session
|
|
325
|
+
began, as when it took the device over from an agent in the same workspace;
|
|
326
|
+
it renews only a lease it took. Leases belong to the workspace, not to the
|
|
327
|
+
session: an agent in the same workspace that runs `stim device lock` on the
|
|
328
|
+
device during a session shares the lease, and the session's end releases
|
|
329
|
+
it.
|
|
330
|
+
- `input.touch` takes `session`, `phase` (`down`, `move`, `up`), `x` and `y`
|
|
331
|
+
as fractions of the upright screen, and `display` (0, the main display).
|
|
332
|
+
`input.text` takes up to 256 printable ASCII characters, where `\n` presses
|
|
333
|
+
Return, `\t` Tab and `\b` Delete. `input.button` takes `home` or `lock`,
|
|
334
|
+
and on Android also `back` or `app-switch`. `input.rotate` takes
|
|
335
|
+
`direction` (`left` or `right`) and turns the device a quarter turn.
|
|
336
|
+
`input.posture` takes one of the session's `postures`. Each answers `{}` once the input
|
|
337
|
+
is handed to the device: when it goes through the helper, that is when the
|
|
338
|
+
helper receives it, so a failure there shows only in the server's log. A connection may send 120 inputs a second and type 40
|
|
339
|
+
characters a second, with a burst of 256, and rotate or change posture twice a
|
|
340
|
+
second; more fail with `limit-exceeded`.
|
|
341
|
+
- `control.end` ends a session. The server also ends it with a
|
|
342
|
+
`control-ended` event `{ "session", "reason", "message" }` after 5 minutes
|
|
343
|
+
without input (`idle`), when another client takes the device over
|
|
344
|
+
(`taken-over`), when the device stops or changes owner (`device-gone`),
|
|
345
|
+
when the paired device loses `control` (`forbidden`), or when input cannot
|
|
346
|
+
reach the device (`failed`). Closing the connection ends its sessions.
|
|
347
|
+
|
|
348
|
+
Input goes through the device's `stim-frames` helper, the process that
|
|
349
|
+
streams its frames:
|
|
350
|
+
|
|
351
|
+
- Simulators take touches, keys and buttons through the simulator's
|
|
352
|
+
CoreDevice HID service (`dtuhidd`), the one Xcode's Device Hub uses, so
|
|
353
|
+
input keeps working while Device Hub or Siniulator shows the simulator.
|
|
354
|
+
With an Xcode whose simulators have no such service, input goes through
|
|
355
|
+
SimulatorKit's legacy HID client instead. The first input starts that service, as Device
|
|
356
|
+
Hub does, and from then until the simulator reboots it ignores tools that
|
|
357
|
+
still use SimulatorKit's legacy HID client. Text is typed key by key on a US
|
|
358
|
+
layout. `lock` is the side button.
|
|
359
|
+
- Emulators take touches through the emulator's gRPC `sendTouch`. Text and
|
|
360
|
+
buttons go through gRPC `sendKey` when the emulator reports a hardware
|
|
361
|
+
keyboard, which AVDs Stim creates have. An emulator without one drops key
|
|
362
|
+
events, so for it text and buttons go through `adb -s <serial> shell input`.
|
|
363
|
+
- Rotation and posture go the way Stim Desktop sends them: a simulator turns
|
|
364
|
+
through the orientation message Simulator.app sends it, and an emulator
|
|
365
|
+
through gRPC `setPhysicalModel` for rotation and `setPosture` for its hinge.
|
|
366
|
+
An iPhone Duo folds with `sim-fold`, which the server builds from Stim
|
|
367
|
+
Desktop's sources on the first fold and runs inside the simulator with
|
|
368
|
+
`xcrun simctl spawn`; it answers `{}` once the fold finished. `sim-fold`
|
|
369
|
+
swaps the posture, so the server runs it only when the Duo's latest frame
|
|
370
|
+
shows the other posture, and refuses the request until a frame showed one.
|
|
371
|
+
|
|
372
|
+
Every session start, takeover and end, and every refused `control.begin`,
|
|
373
|
+
appends a line to the action log, with `action` set to `control.begin`,
|
|
374
|
+
`control.take-over` or `control.end`, and a `reason` that says why the session
|
|
375
|
+
ended or whom it took the device from. Inputs are not logged.
|
|
376
|
+
|
|
300
377
|
The error codes `unauthorized`, `pairing-expired`, and `protocol-unsupported`
|
|
301
378
|
refuse the client until it pairs again or updates; clients retry the others.
|
|
302
379
|
|
|
@@ -16,7 +16,14 @@ const METHODS = [
|
|
|
16
16
|
"machine.get",
|
|
17
17
|
"machine.history",
|
|
18
18
|
"unsubscribe",
|
|
19
|
-
"action"
|
|
19
|
+
"action",
|
|
20
|
+
"control.begin",
|
|
21
|
+
"control.end",
|
|
22
|
+
"input.touch",
|
|
23
|
+
"input.text",
|
|
24
|
+
"input.button",
|
|
25
|
+
"input.rotate",
|
|
26
|
+
"input.posture"
|
|
20
27
|
];
|
|
21
28
|
/**
|
|
22
29
|
* `unauthorized`, `pairing-expired` and `protocol-unsupported` refuse the client until it pairs again or
|
|
@@ -41,7 +48,9 @@ const ERROR_CODES = [
|
|
|
41
48
|
"forbidden",
|
|
42
49
|
"unknown-action",
|
|
43
50
|
"action-busy",
|
|
44
|
-
"action-failed"
|
|
51
|
+
"action-failed",
|
|
52
|
+
"device-busy",
|
|
53
|
+
"unknown-session"
|
|
45
54
|
];
|
|
46
55
|
const LOG_SOURCES = [
|
|
47
56
|
"metro",
|
|
@@ -74,6 +83,33 @@ const VIDEO_HEADER_VERSION = 1;
|
|
|
74
83
|
const VIDEO_KEYFRAME = 1;
|
|
75
84
|
/** Each action runs one fixed `stim` command in the workspace. */
|
|
76
85
|
const ACTIONS = ["reload", "stop"];
|
|
86
|
+
const TOUCH_PHASES = [
|
|
87
|
+
"down",
|
|
88
|
+
"move",
|
|
89
|
+
"up"
|
|
90
|
+
];
|
|
91
|
+
const MAX_INPUT_TEXT = 256;
|
|
92
|
+
/** `home` and `lock` on both platforms; `back` and `app-switch` on Android only. */
|
|
93
|
+
const INPUT_BUTTONS = [
|
|
94
|
+
"home",
|
|
95
|
+
"lock",
|
|
96
|
+
"back",
|
|
97
|
+
"app-switch"
|
|
98
|
+
];
|
|
99
|
+
/** `left` turns the device a quarter turn counterclockwise, `right` clockwise. */
|
|
100
|
+
const ROTATE_DIRECTIONS = ["left", "right"];
|
|
101
|
+
const DEVICE_POSTURES = [
|
|
102
|
+
"folded",
|
|
103
|
+
"half-open",
|
|
104
|
+
"unfolded"
|
|
105
|
+
];
|
|
106
|
+
const CONTROL_END_REASONS = [
|
|
107
|
+
"idle",
|
|
108
|
+
"taken-over",
|
|
109
|
+
"device-gone",
|
|
110
|
+
"forbidden",
|
|
111
|
+
"failed"
|
|
112
|
+
];
|
|
77
113
|
const requestId = { type: ["integer", "string"] };
|
|
78
114
|
const protocolError = {
|
|
79
115
|
type: "object",
|
|
@@ -103,6 +139,17 @@ function request(method, params) {
|
|
|
103
139
|
}
|
|
104
140
|
};
|
|
105
141
|
}
|
|
142
|
+
function session(properties, required = []) {
|
|
143
|
+
return {
|
|
144
|
+
type: "object",
|
|
145
|
+
required: ["session", ...required],
|
|
146
|
+
additionalProperties: false,
|
|
147
|
+
properties: {
|
|
148
|
+
session: { type: "string" },
|
|
149
|
+
...properties
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
106
153
|
function optionalParams(method, params) {
|
|
107
154
|
return {
|
|
108
155
|
type: "object",
|
|
@@ -236,10 +283,11 @@ function protocolJsonSchema() {
|
|
|
236
283
|
level: { enum: [...LOG_LEVELS] },
|
|
237
284
|
slot: {
|
|
238
285
|
type: "string",
|
|
239
|
-
|
|
286
|
+
pattern: "^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$"
|
|
240
287
|
},
|
|
241
288
|
grep: {
|
|
242
289
|
type: "string",
|
|
290
|
+
pattern: "^[^\\u0000]*$",
|
|
243
291
|
description: "A regular expression matched against each message."
|
|
244
292
|
},
|
|
245
293
|
errors: { type: "boolean" },
|
|
@@ -326,6 +374,61 @@ function protocolJsonSchema() {
|
|
|
326
374
|
}
|
|
327
375
|
}
|
|
328
376
|
},
|
|
377
|
+
ControlBeginParams: {
|
|
378
|
+
type: "object",
|
|
379
|
+
required: ["workspace", "platform"],
|
|
380
|
+
additionalProperties: false,
|
|
381
|
+
properties: {
|
|
382
|
+
workspace: {
|
|
383
|
+
type: "string",
|
|
384
|
+
description: "An environment path from a status payload."
|
|
385
|
+
},
|
|
386
|
+
platform: { enum: ["ios", "android"] },
|
|
387
|
+
slot: {
|
|
388
|
+
type: "string",
|
|
389
|
+
minLength: 1,
|
|
390
|
+
default: "default"
|
|
391
|
+
},
|
|
392
|
+
takeOver: {
|
|
393
|
+
type: "boolean",
|
|
394
|
+
default: false
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
},
|
|
398
|
+
ControlBeginResult: {
|
|
399
|
+
type: "object",
|
|
400
|
+
required: [
|
|
401
|
+
"session",
|
|
402
|
+
"platform",
|
|
403
|
+
"lease",
|
|
404
|
+
"postures"
|
|
405
|
+
],
|
|
406
|
+
additionalProperties: false,
|
|
407
|
+
properties: {
|
|
408
|
+
session: { type: "string" },
|
|
409
|
+
platform: { enum: ["ios", "android"] },
|
|
410
|
+
lease: { oneOf: [{ type: "null" }, {
|
|
411
|
+
type: "object",
|
|
412
|
+
required: ["grantedAt", "expiresAt"],
|
|
413
|
+
additionalProperties: false,
|
|
414
|
+
properties: {
|
|
415
|
+
grantedAt: {
|
|
416
|
+
type: ["string", "null"],
|
|
417
|
+
format: "date-time"
|
|
418
|
+
},
|
|
419
|
+
expiresAt: {
|
|
420
|
+
type: "string",
|
|
421
|
+
format: "date-time"
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}] },
|
|
425
|
+
postures: {
|
|
426
|
+
type: "array",
|
|
427
|
+
items: { enum: [...DEVICE_POSTURES] },
|
|
428
|
+
uniqueItems: true
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
},
|
|
329
432
|
BuildPlanParams: {
|
|
330
433
|
type: "object",
|
|
331
434
|
required: ["workspace", "platform"],
|
|
@@ -495,7 +598,41 @@ function protocolJsonSchema() {
|
|
|
495
598
|
additionalProperties: false,
|
|
496
599
|
properties: { subscription: { type: "string" } }
|
|
497
600
|
}),
|
|
498
|
-
request("action", { $ref: "#/$defs/ActionParams" })
|
|
601
|
+
request("action", { $ref: "#/$defs/ActionParams" }),
|
|
602
|
+
request("control.begin", { $ref: "#/$defs/ControlBeginParams" }),
|
|
603
|
+
request("control.end", session({})),
|
|
604
|
+
request("input.touch", session({
|
|
605
|
+
phase: { enum: [...TOUCH_PHASES] },
|
|
606
|
+
x: {
|
|
607
|
+
type: "number",
|
|
608
|
+
minimum: 0,
|
|
609
|
+
maximum: 1
|
|
610
|
+
},
|
|
611
|
+
y: {
|
|
612
|
+
type: "number",
|
|
613
|
+
minimum: 0,
|
|
614
|
+
maximum: 1
|
|
615
|
+
},
|
|
616
|
+
display: {
|
|
617
|
+
type: "integer",
|
|
618
|
+
minimum: 0,
|
|
619
|
+
maximum: 3,
|
|
620
|
+
default: 0
|
|
621
|
+
}
|
|
622
|
+
}, [
|
|
623
|
+
"phase",
|
|
624
|
+
"x",
|
|
625
|
+
"y"
|
|
626
|
+
])),
|
|
627
|
+
request("input.text", session({ text: {
|
|
628
|
+
type: "string",
|
|
629
|
+
minLength: 1,
|
|
630
|
+
maxLength: 256,
|
|
631
|
+
pattern: "^[\\x20-\\x7e\\n\\t\\b]+$"
|
|
632
|
+
} }, ["text"])),
|
|
633
|
+
request("input.button", session({ button: { enum: [...INPUT_BUTTONS] } }, ["button"])),
|
|
634
|
+
request("input.rotate", session({ direction: { enum: [...ROTATE_DIRECTIONS] } }, ["direction"])),
|
|
635
|
+
request("input.posture", session({ posture: { enum: [...DEVICE_POSTURES] } }, ["posture"]))
|
|
499
636
|
] },
|
|
500
637
|
ServerResponse: { oneOf: [{
|
|
501
638
|
type: "object",
|
|
@@ -505,6 +642,7 @@ function protocolJsonSchema() {
|
|
|
505
642
|
id: requestId,
|
|
506
643
|
result: { anyOf: [
|
|
507
644
|
{ $ref: "#/$defs/HelloResult" },
|
|
645
|
+
{ $ref: "#/$defs/ControlBeginResult" },
|
|
508
646
|
{ $ref: "#/$defs/ActionResult" },
|
|
509
647
|
{ $ref: "#/$defs/MachineUsage" },
|
|
510
648
|
{ $ref: "#/$defs/MachineHistory" },
|
|
@@ -627,6 +765,22 @@ function protocolJsonSchema() {
|
|
|
627
765
|
delayed: { type: "boolean" }
|
|
628
766
|
}
|
|
629
767
|
},
|
|
768
|
+
{
|
|
769
|
+
type: "object",
|
|
770
|
+
required: [
|
|
771
|
+
"event",
|
|
772
|
+
"session",
|
|
773
|
+
"reason",
|
|
774
|
+
"message"
|
|
775
|
+
],
|
|
776
|
+
additionalProperties: false,
|
|
777
|
+
properties: {
|
|
778
|
+
event: { const: "control-ended" },
|
|
779
|
+
session: { type: "string" },
|
|
780
|
+
reason: { enum: [...CONTROL_END_REASONS] },
|
|
781
|
+
message: { type: "string" }
|
|
782
|
+
}
|
|
783
|
+
},
|
|
630
784
|
{
|
|
631
785
|
type: "object",
|
|
632
786
|
required: [
|
|
@@ -651,4 +805,4 @@ function protocolJsonSchema() {
|
|
|
651
805
|
};
|
|
652
806
|
}
|
|
653
807
|
//#endregion
|
|
654
|
-
export {
|
|
808
|
+
export { TOUCH_PHASES as _, ERROR_CODES as a, VIDEO_KEYFRAME as b, INPUT_BUTTONS as c, MAX_INPUT_TEXT as d, MAX_LOG_TAIL as f, ROTATE_DIRECTIONS as g, PROTOCOL_VERSION as h, DEVICE_POSTURES as i, LOG_LEVELS as l, PROTOCOL_SCHEMA_FILE as m, CAPABILITIES as n, FRAME_EDGE as o, METHODS as p, CONTROL_END_REASONS as r, FRAME_FPS as s, ACTIONS as t, LOG_SOURCES as u, VIDEO_CODECS as v, protocolJsonSchema as x, VIDEO_HEADER_VERSION as y };
|
package/dist/protocol.d.mts
CHANGED
|
@@ -5,13 +5,13 @@ declare const PROTOCOL_SCHEMA_FILE = "protocol.schema.json";
|
|
|
5
5
|
/** `read` serves state. `control` also runs {@link ACTIONS}; only the Mac grants it. */
|
|
6
6
|
declare const CAPABILITIES: readonly ["read", "control"];
|
|
7
7
|
type Capability = (typeof CAPABILITIES)[number];
|
|
8
|
-
declare const METHODS: readonly ["hello", "status.subscribe", "logs.query", "logs.subscribe", "stats.get", "settings.get", "frames.subscribe", "frames.keyframe", "build.plan", "machine.get", "machine.history", "unsubscribe", "action"];
|
|
8
|
+
declare const METHODS: readonly ["hello", "status.subscribe", "logs.query", "logs.subscribe", "stats.get", "settings.get", "frames.subscribe", "frames.keyframe", "build.plan", "machine.get", "machine.history", "unsubscribe", "action", "control.begin", "control.end", "input.touch", "input.text", "input.button", "input.rotate", "input.posture"];
|
|
9
9
|
type Method = (typeof METHODS)[number];
|
|
10
10
|
/**
|
|
11
11
|
* `unauthorized`, `pairing-expired` and `protocol-unsupported` refuse the client until it pairs again or
|
|
12
12
|
* updates; clients retry the others.
|
|
13
13
|
*/
|
|
14
|
-
declare const ERROR_CODES: readonly ["unauthorized", "pairing-expired", "protocol-unsupported", "identity-unavailable", "bad-request", "unknown-method", "already-authenticated", "unknown-subscription", "unknown-workspace", "limit-exceeded", "slow-client", "status-failed", "logs-failed", "stim-failed", "frames-failed", "forbidden", "unknown-action", "action-busy", "action-failed"];
|
|
14
|
+
declare const ERROR_CODES: readonly ["unauthorized", "pairing-expired", "protocol-unsupported", "identity-unavailable", "bad-request", "unknown-method", "already-authenticated", "unknown-subscription", "unknown-workspace", "limit-exceeded", "slow-client", "status-failed", "logs-failed", "stim-failed", "frames-failed", "forbidden", "unknown-action", "action-busy", "action-failed", "device-busy", "unknown-session"];
|
|
15
15
|
type ErrorCode = (typeof ERROR_CODES)[number];
|
|
16
16
|
type RequestId = number | string;
|
|
17
17
|
/** Spends a single-use pairing token; the result carries the new device token. */
|
|
@@ -171,6 +171,72 @@ interface ActionResult {
|
|
|
171
171
|
workspace: string;
|
|
172
172
|
output: Record<string, unknown>;
|
|
173
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Starts a control session on the device `stim status` lists as owned by `workspace` in `slot`. Needs
|
|
176
|
+
* `control`. Refused with `device-busy` while an agent, a device lock or another client drives the device,
|
|
177
|
+
* unless `takeOver` is true.
|
|
178
|
+
*/
|
|
179
|
+
interface ControlBeginParams {
|
|
180
|
+
workspace: string;
|
|
181
|
+
platform: Platform;
|
|
182
|
+
slot?: string;
|
|
183
|
+
takeOver?: boolean;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* `lease` is the `stim device lock` lease the server holds for the session, or null when it holds none, such
|
|
187
|
+
* as after taking over a device another workspace leases. `postures` lists what `input.posture` accepts for
|
|
188
|
+
* the device: `folded` and `unfolded` for an iPhone Duo, all three for an emulator with a hinge, and none
|
|
189
|
+
* otherwise.
|
|
190
|
+
*/
|
|
191
|
+
interface ControlBeginResult {
|
|
192
|
+
session: string;
|
|
193
|
+
platform: Platform;
|
|
194
|
+
lease: {
|
|
195
|
+
grantedAt: string | null;
|
|
196
|
+
expiresAt: string;
|
|
197
|
+
} | null;
|
|
198
|
+
postures: DevicePosture[];
|
|
199
|
+
}
|
|
200
|
+
interface ControlEndParams {
|
|
201
|
+
session: string;
|
|
202
|
+
}
|
|
203
|
+
declare const TOUCH_PHASES: readonly ["down", "move", "up"];
|
|
204
|
+
type TouchPhase = (typeof TOUCH_PHASES)[number];
|
|
205
|
+
/** `x` and `y` are fractions of the upright screen, origin top-left. `display` is 0 for the main display. */
|
|
206
|
+
interface InputTouchParams {
|
|
207
|
+
session: string;
|
|
208
|
+
phase: TouchPhase;
|
|
209
|
+
x: number;
|
|
210
|
+
y: number;
|
|
211
|
+
display?: number;
|
|
212
|
+
}
|
|
213
|
+
declare const MAX_INPUT_TEXT = 256;
|
|
214
|
+
/** Printable ASCII, where `\n` presses Return, `\t` Tab and `\b` Delete. */
|
|
215
|
+
interface InputTextParams {
|
|
216
|
+
session: string;
|
|
217
|
+
text: string;
|
|
218
|
+
}
|
|
219
|
+
/** `home` and `lock` on both platforms; `back` and `app-switch` on Android only. */
|
|
220
|
+
declare const INPUT_BUTTONS: readonly ["home", "lock", "back", "app-switch"];
|
|
221
|
+
type InputButton = (typeof INPUT_BUTTONS)[number];
|
|
222
|
+
interface InputButtonParams {
|
|
223
|
+
session: string;
|
|
224
|
+
button: InputButton;
|
|
225
|
+
}
|
|
226
|
+
/** `left` turns the device a quarter turn counterclockwise, `right` clockwise. */
|
|
227
|
+
declare const ROTATE_DIRECTIONS: readonly ["left", "right"];
|
|
228
|
+
type RotateDirection = (typeof ROTATE_DIRECTIONS)[number];
|
|
229
|
+
interface InputRotateParams {
|
|
230
|
+
session: string;
|
|
231
|
+
direction: RotateDirection;
|
|
232
|
+
}
|
|
233
|
+
declare const DEVICE_POSTURES: readonly ["folded", "half-open", "unfolded"];
|
|
234
|
+
type DevicePosture = (typeof DEVICE_POSTURES)[number];
|
|
235
|
+
/** Moves the hinge of a device whose `control.begin` result lists `posture`. */
|
|
236
|
+
interface InputPostureParams {
|
|
237
|
+
session: string;
|
|
238
|
+
posture: DevicePosture;
|
|
239
|
+
}
|
|
174
240
|
/** Predicts the next `ios` or `android` build of `workspace` in `slot` (`default` when absent). */
|
|
175
241
|
interface BuildPlanParams {
|
|
176
242
|
workspace: string;
|
|
@@ -292,6 +358,34 @@ interface Methods {
|
|
|
292
358
|
params: ActionParams;
|
|
293
359
|
result: ActionResult;
|
|
294
360
|
};
|
|
361
|
+
"control.begin": {
|
|
362
|
+
params: ControlBeginParams;
|
|
363
|
+
result: ControlBeginResult;
|
|
364
|
+
};
|
|
365
|
+
"control.end": {
|
|
366
|
+
params: ControlEndParams;
|
|
367
|
+
result: Record<string, never>;
|
|
368
|
+
};
|
|
369
|
+
"input.touch": {
|
|
370
|
+
params: InputTouchParams;
|
|
371
|
+
result: Record<string, never>;
|
|
372
|
+
};
|
|
373
|
+
"input.text": {
|
|
374
|
+
params: InputTextParams;
|
|
375
|
+
result: Record<string, never>;
|
|
376
|
+
};
|
|
377
|
+
"input.button": {
|
|
378
|
+
params: InputButtonParams;
|
|
379
|
+
result: Record<string, never>;
|
|
380
|
+
};
|
|
381
|
+
"input.rotate": {
|
|
382
|
+
params: InputRotateParams;
|
|
383
|
+
result: Record<string, never>;
|
|
384
|
+
};
|
|
385
|
+
"input.posture": {
|
|
386
|
+
params: InputPostureParams;
|
|
387
|
+
result: Record<string, never>;
|
|
388
|
+
};
|
|
295
389
|
}
|
|
296
390
|
type ClientRequest = { [M in Method]: {
|
|
297
391
|
id: RequestId;
|
|
@@ -357,10 +451,21 @@ interface FrameDelayedEvent {
|
|
|
357
451
|
subscription: string;
|
|
358
452
|
delayed: boolean;
|
|
359
453
|
}
|
|
360
|
-
|
|
454
|
+
declare const CONTROL_END_REASONS: readonly ["idle", "taken-over", "device-gone", "forbidden", "failed"];
|
|
455
|
+
/**
|
|
456
|
+
* The server ended a control session: no input for 5 minutes, another client took the device over, the device
|
|
457
|
+
* stopped or changed owner, the device lost `control`, or input could not reach the device.
|
|
458
|
+
*/
|
|
459
|
+
interface ControlEndedEvent {
|
|
460
|
+
event: "control-ended";
|
|
461
|
+
session: string;
|
|
462
|
+
reason: (typeof CONTROL_END_REASONS)[number];
|
|
463
|
+
message: string;
|
|
464
|
+
}
|
|
465
|
+
type ServerEvent = StatusEvent | LogsEvent | FrameEvent | FrameDelayedEvent | ErrorEvent | ControlEndedEvent;
|
|
361
466
|
type ServerMessage = ServerResponse | ServerEvent;
|
|
362
467
|
type JsonSchema = Record<string, unknown>;
|
|
363
468
|
/** The JSON Schema of every message on the wire, written to `dist/protocol.schema.json` at build time. */
|
|
364
469
|
declare function protocolJsonSchema(): JsonSchema;
|
|
365
470
|
//#endregion
|
|
366
|
-
export { ACTIONS, ActionName, ActionParams, ActionResult, BuildPlanParams, BuildPlanResult, CAPABILITIES, Capability, ClientRequest, DeviceAuth, ERROR_CODES, ErrorCode, ErrorEvent, FRAME_EDGE, FRAME_FPS, FrameDelayedEvent, FrameEvent, FrameTarget, FramesSubscribeResult, HelloParams, HelloResult, KeyframeParams, LOG_LEVELS, LOG_SOURCES, LogFilter, LogLevel, LogRecord, LogSource, LogsEvent, LogsQueryResult, MAX_LOG_TAIL, METHODS, MachineHistory, MachineHistoryParams, MachineUsage, MachineVolume, MemoryPressure, Method, Methods, PROTOCOL_SCHEMA_FILE, PROTOCOL_VERSION, PairingAuth, Platform, ProtocolError, RequestId, ServerEvent, ServerMessage, ServerResponse, SettingsResult, StatsResult, StatusEvent, SubscribeResult, UnsubscribeParams, UsageSample, VIDEO_CODECS, VIDEO_HEADER_VERSION, VIDEO_KEYFRAME, VideoCodec, VideoPacket, WorkspaceParams, protocolJsonSchema };
|
|
471
|
+
export { ACTIONS, ActionName, ActionParams, ActionResult, BuildPlanParams, BuildPlanResult, CAPABILITIES, CONTROL_END_REASONS, Capability, ClientRequest, ControlBeginParams, ControlBeginResult, ControlEndParams, ControlEndedEvent, DEVICE_POSTURES, DeviceAuth, DevicePosture, ERROR_CODES, ErrorCode, ErrorEvent, FRAME_EDGE, FRAME_FPS, FrameDelayedEvent, FrameEvent, FrameTarget, FramesSubscribeResult, HelloParams, HelloResult, INPUT_BUTTONS, InputButton, InputButtonParams, InputPostureParams, InputRotateParams, InputTextParams, InputTouchParams, KeyframeParams, LOG_LEVELS, LOG_SOURCES, LogFilter, LogLevel, LogRecord, LogSource, LogsEvent, LogsQueryResult, MAX_INPUT_TEXT, MAX_LOG_TAIL, METHODS, MachineHistory, MachineHistoryParams, MachineUsage, MachineVolume, MemoryPressure, Method, Methods, PROTOCOL_SCHEMA_FILE, PROTOCOL_VERSION, PairingAuth, Platform, ProtocolError, ROTATE_DIRECTIONS, RequestId, RotateDirection, ServerEvent, ServerMessage, ServerResponse, SettingsResult, StatsResult, StatusEvent, SubscribeResult, TOUCH_PHASES, TouchPhase, UnsubscribeParams, UsageSample, VIDEO_CODECS, VIDEO_HEADER_VERSION, VIDEO_KEYFRAME, VideoCodec, VideoPacket, WorkspaceParams, protocolJsonSchema };
|
package/dist/protocol.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { ACTIONS, CAPABILITIES, ERROR_CODES, FRAME_EDGE, FRAME_FPS, LOG_LEVELS, LOG_SOURCES, MAX_LOG_TAIL, METHODS, PROTOCOL_SCHEMA_FILE, PROTOCOL_VERSION, VIDEO_CODECS, VIDEO_HEADER_VERSION, VIDEO_KEYFRAME, protocolJsonSchema };
|
|
1
|
+
import { _ as TOUCH_PHASES, a as ERROR_CODES, b as VIDEO_KEYFRAME, c as INPUT_BUTTONS, d as MAX_INPUT_TEXT, f as MAX_LOG_TAIL, g as ROTATE_DIRECTIONS, h as PROTOCOL_VERSION, i as DEVICE_POSTURES, l as LOG_LEVELS, m as PROTOCOL_SCHEMA_FILE, n as CAPABILITIES, o as FRAME_EDGE, p as METHODS, r as CONTROL_END_REASONS, s as FRAME_FPS, t as ACTIONS, u as LOG_SOURCES, v as VIDEO_CODECS, x as protocolJsonSchema, y as VIDEO_HEADER_VERSION } from "./protocol-BElQc2vm.mjs";
|
|
2
|
+
export { ACTIONS, CAPABILITIES, CONTROL_END_REASONS, DEVICE_POSTURES, ERROR_CODES, FRAME_EDGE, FRAME_FPS, INPUT_BUTTONS, LOG_LEVELS, LOG_SOURCES, MAX_INPUT_TEXT, MAX_LOG_TAIL, METHODS, PROTOCOL_SCHEMA_FILE, PROTOCOL_VERSION, ROTATE_DIRECTIONS, TOUCH_PHASES, VIDEO_CODECS, VIDEO_HEADER_VERSION, VIDEO_KEYFRAME, protocolJsonSchema };
|