@botiverse/testbed-cli 0.5.0 → 0.5.1
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/lib/main.mjs +26 -7
- package/package.json +1 -1
package/lib/main.mjs
CHANGED
|
@@ -15,8 +15,10 @@ export const USAGE = `testbed — cloud phones + the acceptance testbed in the R
|
|
|
15
15
|
testbed whoami who the API thinks you are
|
|
16
16
|
|
|
17
17
|
testbed pool warm-pool devices and free/leased state
|
|
18
|
-
testbed acquire [--ttl MIN] [--instance ID] [--request-id ID] [--key-out FILE]
|
|
19
|
-
lease a phone;
|
|
18
|
+
testbed acquire [--ttl MIN] [--instance ID] [--request-id ID] [--key-out FILE] [--wait-ms N]
|
|
19
|
+
lease a phone; waits through in_flight (same request id) up to --wait-ms (90000);
|
|
20
|
+
the ADB private key goes to --key-out (0600) or --json
|
|
21
|
+
testbed <command> --help usage only — never sends a request
|
|
20
22
|
testbed devices your leases
|
|
21
23
|
testbed renew <lease-id> [--ttl MIN]
|
|
22
24
|
testbed release <lease-id>
|
|
@@ -95,6 +97,10 @@ export async function main(argv, opts) {
|
|
|
95
97
|
const env = opts.env ?? process.env;
|
|
96
98
|
const exit = opts.exit ?? ((code) => process.exit(code));
|
|
97
99
|
const json = takeSwitch(args, "json");
|
|
100
|
+
// `--help` / `-h` anywhere prints usage and NEVER reaches the API. 2026-09-05:
|
|
101
|
+
// `testbed acquire --help` acquired a device (HuaTuo) because flags were
|
|
102
|
+
// only consumed by the command that expected them.
|
|
103
|
+
if (args.includes("--help") || args.includes("-h")) { out(USAGE); return exit(0); }
|
|
98
104
|
const cmd = args.shift();
|
|
99
105
|
const emit = (data, human) => { if (json) out(JSON.stringify(data, null, 2)); else human(); };
|
|
100
106
|
|
|
@@ -148,11 +154,24 @@ export async function main(argv, opts) {
|
|
|
148
154
|
const body = {};
|
|
149
155
|
if (ttl !== undefined) body.ttl_minutes = Number(ttl);
|
|
150
156
|
if (instance) body.instance_id = instance;
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
157
|
+
// Always send a request id so a retry never takes a second device: the
|
|
158
|
+
// broker answers 202 in_flight (retryable) while it is still preparing
|
|
159
|
+
// the lease, and the SAME request id retried returns the acquired lease
|
|
160
|
+
// with its one-time key. 2026-09-05 (HuaTuo): the old CLI printed the
|
|
161
|
+
// in_flight receipt and exited 2, leaving a lease held with no key.
|
|
162
|
+
body.request_id = requestId ?? `testbed-cli-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
163
|
+
const waitMs = Number(takeFlag(args, "wait-ms", "90000"));
|
|
164
|
+
const sleep = opts.sleepImpl ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
165
|
+
const started = Date.now();
|
|
166
|
+
let d = await api("POST", "/device-broker/leases", body);
|
|
167
|
+
while (d.status === "in_flight") {
|
|
168
|
+
if (Date.now() - started > waitMs) {
|
|
169
|
+
err(`testbed: acquire still in_flight after ${Math.round(waitMs / 1000)}s (request ${body.request_id}${d.instance_id ? ` on ${d.instance_id}` : ""}); the broker may still hold a lease for this request — run \`testbed devices\` and release it, or retry with --request-id ${body.request_id}`);
|
|
170
|
+
return exit(2);
|
|
171
|
+
}
|
|
172
|
+
if (!json) err(`testbed: in_flight${d.instance_id ? ` on ${d.instance_id}` : ""}, retrying with the same request id…`);
|
|
173
|
+
await sleep(2000);
|
|
174
|
+
d = await api("POST", "/device-broker/leases", body);
|
|
156
175
|
}
|
|
157
176
|
let keyPath = null;
|
|
158
177
|
if (keyOut && d.adb_private_key) {
|