@newly/cli 0.1.115 → 0.1.117
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.runcloud.md +25 -0
- package/dist/api.js +4 -2
- package/dist/commands/run-cloud.js +229 -3
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/README.runcloud.md
CHANGED
|
@@ -66,6 +66,7 @@ runcloud ios get <id> # inspect a session (
|
|
|
66
66
|
runcloud ios open-url myapp://path --id <id> # open a URL or deep link
|
|
67
67
|
runcloud ios tap <id> 0.5 0.75 # normalized top-left display coordinates
|
|
68
68
|
runcloud ios type-text <id> "Hello from iOS!" # printable US ASCII, tab, and line feed
|
|
69
|
+
runcloud ios accessibility-tree <id> --json # read the current typed accessibility hierarchy
|
|
69
70
|
runcloud ios screenshot <id> --output ios.png # save a PNG without exposing the viewer URL
|
|
70
71
|
runcloud ios recording start <id> --json # start an idempotent MP4 screen recording
|
|
71
72
|
runcloud ios recording stop <id> <recording-id> --json # stop and finalize it
|
|
@@ -79,9 +80,27 @@ runcloud ios delete <id> # release the session
|
|
|
79
80
|
runcloud android create --model pixel
|
|
80
81
|
runcloud android swipe <id> 0.5 0.8 0.5 0.2 --duration 250
|
|
81
82
|
runcloud android press-key <id> enter
|
|
83
|
+
runcloud android accessibility-tree <id> --json
|
|
82
84
|
runcloud android screenshot <id> --output android.png --json
|
|
83
85
|
```
|
|
84
86
|
|
|
87
|
+
`open-url` accepts HTTPS URLs and application deep links on both platforms. Keep
|
|
88
|
+
the complete target quoted so its URI delimiters stay in one argument:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
runcloud ios open-url \
|
|
92
|
+
'runcloudproof://open/items%2F42?message=hello%20world&return=https%3A%2F%2Fexample.com%2Fdone%3Fx%3D1%26y%3Dtwo#proof' \
|
|
93
|
+
--id <id> \
|
|
94
|
+
--json
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Success returns `ok`, `platform`, `sessionId`, `device`, `leaseId`, and the
|
|
98
|
+
exact input `url`. Replace `ios` with `android` for an emulator. See
|
|
99
|
+
[Open URLs and Deep Links](https://docs.run.cloud/platform/open-urls) for SDK
|
|
100
|
+
and REST examples, platform behavior, validation, and troubleshooting.
|
|
101
|
+
On iOS, a first custom-scheme handoff can still require confirming the system's
|
|
102
|
+
**Open in “App”?** prompt after the success acknowledgement.
|
|
103
|
+
|
|
85
104
|
Useful `create` flags: `--region`, `--display-name`, `--inactivity-timeout 3m`,
|
|
86
105
|
`--hard-timeout 1h`, `--install-asset <name-or-id>`, `--rm` (release when the
|
|
87
106
|
command exits), `--json`.
|
|
@@ -100,6 +119,12 @@ report `capsLock`, `numLock`, and `scrollLock` as unsupported keys.
|
|
|
100
119
|
Coordinates are inclusive normalized display coordinates: `(0, 0)` is the
|
|
101
120
|
top-left and `(1, 1)` is the bottom-right.
|
|
102
121
|
|
|
122
|
+
`accessibility-tree` (`accessibility` alias) returns an indented terminal tree
|
|
123
|
+
or a versioned JSON hierarchy with cross-platform roles, labels, values,
|
|
124
|
+
states, bounds, identifiers, and nested children. Secure field values are
|
|
125
|
+
always redacted. The command reads only the authenticated active session and
|
|
126
|
+
never releases it; use `--timeout` to change the 20-second client wait.
|
|
127
|
+
|
|
103
128
|
The `recording` group is shared by iOS and Android. It provides `start`,
|
|
104
129
|
`list`, `status` (`get` alias), `stop`, and `download`. Pass a stable
|
|
105
130
|
`--idempotency-key` to retry `start` without creating a second recording.
|
package/dist/api.js
CHANGED
|
@@ -10,6 +10,7 @@ export class ApiError extends Error {
|
|
|
10
10
|
sessionId;
|
|
11
11
|
platform;
|
|
12
12
|
action;
|
|
13
|
+
suggestedAction;
|
|
13
14
|
interactionStatus;
|
|
14
15
|
acceptedAt;
|
|
15
16
|
completedAt;
|
|
@@ -65,6 +66,7 @@ function parsedError(body) {
|
|
|
65
66
|
...(typeof parsed.sessionId === 'string' ? { sessionId: parsed.sessionId } : {}),
|
|
66
67
|
...(platform ? { platform } : {}),
|
|
67
68
|
...(typeof parsed.action === 'string' ? { action: parsed.action } : {}),
|
|
69
|
+
...(typeof nested?.action === 'string' ? { suggestedAction: nested.action } : {}),
|
|
68
70
|
...(interactionStatus ? { interactionStatus } : {}),
|
|
69
71
|
...(typeof parsed.acceptedAt === 'string' ? { acceptedAt: parsed.acceptedAt } : {}),
|
|
70
72
|
...(typeof parsed.completedAt === 'string' ? { completedAt: parsed.completedAt } : {}),
|
|
@@ -114,8 +116,8 @@ export class ApiClient {
|
|
|
114
116
|
const contentType = res.headers.get('content-type') ?? '';
|
|
115
117
|
return contentType.includes('application/json') ? res.json() : res;
|
|
116
118
|
}
|
|
117
|
-
get(path) {
|
|
118
|
-
return this.request('GET', path);
|
|
119
|
+
get(path, options = {}) {
|
|
120
|
+
return this.request('GET', path, undefined, options);
|
|
119
121
|
}
|
|
120
122
|
async getText(path) {
|
|
121
123
|
const response = await this.request('GET', path);
|
|
@@ -53,8 +53,19 @@ export const SIMULATOR_SCREENSHOT_ERROR_CODES = [
|
|
|
53
53
|
'screenshot_invalid_response',
|
|
54
54
|
'screenshot_failed',
|
|
55
55
|
];
|
|
56
|
+
export const SIMULATOR_ACCESSIBILITY_ERROR_CODES = [
|
|
57
|
+
'active_session_not_found',
|
|
58
|
+
'simulator_capacity_unavailable',
|
|
59
|
+
'simulator_session_ended',
|
|
60
|
+
'accessibility_unavailable',
|
|
61
|
+
'accessibility_cancelled',
|
|
62
|
+
'accessibility_timeout',
|
|
63
|
+
'accessibility_transport_error',
|
|
64
|
+
'accessibility_invalid_response',
|
|
65
|
+
];
|
|
56
66
|
const simulatorInteractionErrorCodeSet = new Set(SIMULATOR_INTERACTION_ERROR_CODES);
|
|
57
67
|
const simulatorScreenshotErrorCodeSet = new Set(SIMULATOR_SCREENSHOT_ERROR_CODES);
|
|
68
|
+
const simulatorAccessibilityErrorCodeSet = new Set(SIMULATOR_ACCESSIBILITY_ERROR_CODES);
|
|
58
69
|
function normalizedInteractionErrorCode(value) {
|
|
59
70
|
if (typeof value === 'string' && simulatorInteractionErrorCodeSet.has(value)) {
|
|
60
71
|
return value;
|
|
@@ -85,7 +96,13 @@ function normalizedScreenshotErrorCode(value) {
|
|
|
85
96
|
? value
|
|
86
97
|
: 'screenshot_failed';
|
|
87
98
|
}
|
|
99
|
+
function normalizedAccessibilityErrorCode(value) {
|
|
100
|
+
return typeof value === 'string' && simulatorAccessibilityErrorCodeSet.has(value)
|
|
101
|
+
? value
|
|
102
|
+
: 'accessibility_unavailable';
|
|
103
|
+
}
|
|
88
104
|
const DEFAULT_INTERACTION_TIMEOUT_MS = 15_000;
|
|
105
|
+
const DEFAULT_ACCESSIBILITY_TIMEOUT_MS = 20_000;
|
|
89
106
|
const INTERACTION_RESPONSE_MARGIN_MS = 250;
|
|
90
107
|
const REQUEST_ID_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/;
|
|
91
108
|
export const RUN_CLOUD_SKILL_NAMES = [
|
|
@@ -392,10 +409,21 @@ class CliInteractionError extends Error {
|
|
|
392
409
|
}
|
|
393
410
|
}
|
|
394
411
|
async function withInteractionCancellation(timeoutMs, requestId, actionName, sessionId, platform, operation, run) {
|
|
412
|
+
const operationLabel = operation === 'interaction' ? 'interaction' : operation;
|
|
413
|
+
const cancelledCode = operation === 'screenshot'
|
|
414
|
+
? 'screenshot_cancelled'
|
|
415
|
+
: operation === 'accessibility'
|
|
416
|
+
? 'accessibility_cancelled'
|
|
417
|
+
: 'interaction_cancelled';
|
|
418
|
+
const timeoutCode = operation === 'screenshot'
|
|
419
|
+
? 'screenshot_timeout'
|
|
420
|
+
: operation === 'accessibility'
|
|
421
|
+
? 'accessibility_timeout'
|
|
422
|
+
: 'interaction_timeout';
|
|
395
423
|
const controller = new AbortController();
|
|
396
|
-
const onSigint = () => controller.abort(new CliInteractionError(`Simulator ${
|
|
424
|
+
const onSigint = () => controller.abort(new CliInteractionError(`Simulator ${operationLabel} cancelled by SIGINT`, cancelledCode, requestId, actionName, sessionId, platform));
|
|
397
425
|
process.once('SIGINT', onSigint);
|
|
398
|
-
const timer = setTimeout(() => controller.abort(new CliInteractionError(`Simulator ${actionName} did not complete within ${timeoutMs} ms`,
|
|
426
|
+
const timer = setTimeout(() => controller.abort(new CliInteractionError(`Simulator ${actionName} did not complete within ${timeoutMs} ms`, timeoutCode, requestId, actionName, sessionId, platform)), timeoutMs + INTERACTION_RESPONSE_MARGIN_MS);
|
|
399
427
|
try {
|
|
400
428
|
return await run(controller.signal);
|
|
401
429
|
}
|
|
@@ -485,6 +513,143 @@ async function captureSimulatorScreenshot(platform, id, opts) {
|
|
|
485
513
|
else
|
|
486
514
|
console.log(`Saved ${platform} simulator screenshot to ${output} (${bytes.byteLength} bytes)`);
|
|
487
515
|
}
|
|
516
|
+
function validatedAccessibilitySnapshot(value, platform) {
|
|
517
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
518
|
+
throw new Error('accessibility response must be an object');
|
|
519
|
+
}
|
|
520
|
+
const snapshot = value;
|
|
521
|
+
if (snapshot.schemaVersion !== 1 || snapshot.platform !== platform) {
|
|
522
|
+
throw new Error('accessibility schema or platform did not match the request');
|
|
523
|
+
}
|
|
524
|
+
if (!Array.isArray(snapshot.roots))
|
|
525
|
+
throw new Error('accessibility roots must be an array');
|
|
526
|
+
if (typeof snapshot.nodeCount !== 'number'
|
|
527
|
+
|| !Number.isInteger(snapshot.nodeCount)
|
|
528
|
+
|| snapshot.nodeCount < 0
|
|
529
|
+
|| snapshot.nodeCount > 500) {
|
|
530
|
+
throw new Error('accessibility nodeCount must be an integer from 0 to 500');
|
|
531
|
+
}
|
|
532
|
+
if (!snapshot.screen || typeof snapshot.screen !== 'object' || Array.isArray(snapshot.screen)) {
|
|
533
|
+
throw new Error('accessibility screen must be an object');
|
|
534
|
+
}
|
|
535
|
+
const screen = snapshot.screen;
|
|
536
|
+
if (screen.unit !== (platform === 'ios' ? 'points' : 'pixels')) {
|
|
537
|
+
throw new Error('accessibility screen unit did not match the platform');
|
|
538
|
+
}
|
|
539
|
+
const ids = new Set();
|
|
540
|
+
let count = 0;
|
|
541
|
+
const visit = (candidate, path, depth) => {
|
|
542
|
+
if (depth > 80 || count >= 500 || !candidate || typeof candidate !== 'object' || Array.isArray(candidate)) {
|
|
543
|
+
throw new Error('accessibility tree exceeded its schema bounds');
|
|
544
|
+
}
|
|
545
|
+
const node = candidate;
|
|
546
|
+
if (typeof node.id !== 'string' || !node.id || ids.has(node.id)) {
|
|
547
|
+
throw new Error('accessibility node identifiers must be non-empty and unique');
|
|
548
|
+
}
|
|
549
|
+
if (node.path !== path || typeof node.role !== 'string' || !Array.isArray(node.children)) {
|
|
550
|
+
throw new Error('accessibility node structure is invalid');
|
|
551
|
+
}
|
|
552
|
+
const states = node.states && typeof node.states === 'object' && !Array.isArray(node.states)
|
|
553
|
+
? node.states
|
|
554
|
+
: null;
|
|
555
|
+
const native = node.native && typeof node.native === 'object' && !Array.isArray(node.native)
|
|
556
|
+
? node.native
|
|
557
|
+
: null;
|
|
558
|
+
if (!states || !native || native.platform !== platform) {
|
|
559
|
+
throw new Error('accessibility node state or platform detail is invalid');
|
|
560
|
+
}
|
|
561
|
+
const secure = states.secure === true
|
|
562
|
+
|| native.password === true
|
|
563
|
+
|| (platform === 'ios' && /(?:secure|password)/iu.test([
|
|
564
|
+
native.type,
|
|
565
|
+
native.roleDescription,
|
|
566
|
+
native.subrole,
|
|
567
|
+
].filter((part) => typeof part === 'string').join(' ')));
|
|
568
|
+
if (secure) {
|
|
569
|
+
states.secure = true;
|
|
570
|
+
node.value = null;
|
|
571
|
+
}
|
|
572
|
+
ids.add(node.id);
|
|
573
|
+
count += 1;
|
|
574
|
+
node.children.forEach((child, index) => visit(child, `${path}.${index}`, depth + 1));
|
|
575
|
+
};
|
|
576
|
+
snapshot.roots.forEach((root, index) => visit(root, String(index), 0));
|
|
577
|
+
if (count !== snapshot.nodeCount)
|
|
578
|
+
throw new Error('accessibility nodeCount did not match the tree');
|
|
579
|
+
return snapshot;
|
|
580
|
+
}
|
|
581
|
+
function printAccessibilitySnapshot(snapshot) {
|
|
582
|
+
const platform = String(snapshot.platform);
|
|
583
|
+
const screen = snapshot.screen;
|
|
584
|
+
console.log(`${platform} accessibility tree: ${String(snapshot.nodeCount)} nodes, `
|
|
585
|
+
+ `${String(screen.width)}x${String(screen.height)} ${String(screen.unit)}`
|
|
586
|
+
+ `${snapshot.truncated === true ? ' (truncated)' : ''}`);
|
|
587
|
+
const visit = (candidate, depth) => {
|
|
588
|
+
const node = candidate;
|
|
589
|
+
const states = node.states;
|
|
590
|
+
const bounds = node.bounds && typeof node.bounds === 'object'
|
|
591
|
+
? node.bounds
|
|
592
|
+
: null;
|
|
593
|
+
const stateLabels = [
|
|
594
|
+
states.enabled === false ? 'disabled' : null,
|
|
595
|
+
states.focused === true ? 'focused' : null,
|
|
596
|
+
states.selected === true ? 'selected' : null,
|
|
597
|
+
states.checked === true ? 'checked' : states.checked === 'mixed' ? 'mixed' : null,
|
|
598
|
+
states.expanded === true ? 'expanded' : states.expanded === false ? 'collapsed' : null,
|
|
599
|
+
states.secure === true ? 'secure' : null,
|
|
600
|
+
].filter(Boolean);
|
|
601
|
+
const label = typeof node.label === 'string' && node.label ? ` "${node.label}"` : '';
|
|
602
|
+
const identifier = typeof node.identifier === 'string' && node.identifier
|
|
603
|
+
? ` #${node.identifier}`
|
|
604
|
+
: '';
|
|
605
|
+
const value = typeof node.value === 'string' && node.value
|
|
606
|
+
? ` = ${JSON.stringify(node.value.slice(0, 120))}`
|
|
607
|
+
: '';
|
|
608
|
+
const frame = bounds
|
|
609
|
+
? ` @ ${String(bounds.x)},${String(bounds.y)} ${String(bounds.width)}x${String(bounds.height)}`
|
|
610
|
+
: '';
|
|
611
|
+
const state = stateLabels.length ? ` [${stateLabels.join(', ')}]` : '';
|
|
612
|
+
console.log(`${' '.repeat(depth)}${String(node.role)}${label}${identifier}${value}${state}${frame}`);
|
|
613
|
+
for (const child of node.children)
|
|
614
|
+
visit(child, depth + 1);
|
|
615
|
+
};
|
|
616
|
+
for (const root of snapshot.roots)
|
|
617
|
+
visit(root, 0);
|
|
618
|
+
}
|
|
619
|
+
async function captureSimulatorAccessibilityTree(platform, id, opts) {
|
|
620
|
+
const timeoutMs = integerInRange(opts.timeout, '--timeout', 100, 60_000, DEFAULT_ACCESSIBILITY_TIMEOUT_MS);
|
|
621
|
+
const requestId = `cli_${randomUUID()}`;
|
|
622
|
+
let value;
|
|
623
|
+
try {
|
|
624
|
+
value = await withInteractionCancellation(timeoutMs, requestId, 'accessibility', id, platform, 'accessibility', async (signal) => await client().get(`/run-cloud/${platform}/${encodeURIComponent(id)}/accessibility`, { signal }));
|
|
625
|
+
}
|
|
626
|
+
catch (error) {
|
|
627
|
+
if (error instanceof ApiError) {
|
|
628
|
+
Object.assign(error, {
|
|
629
|
+
code: normalizedAccessibilityErrorCode(error.code),
|
|
630
|
+
requestId: error.requestId ?? requestId,
|
|
631
|
+
sessionId: error.sessionId ?? id,
|
|
632
|
+
platform: error.platform ?? platform,
|
|
633
|
+
action: error.action ?? 'accessibility',
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
if (error instanceof ApiTransportError) {
|
|
637
|
+
throw new CliInteractionError('Simulator accessibility could not reach the run.cloud API', 'accessibility_transport_error', requestId, 'accessibility', id, platform);
|
|
638
|
+
}
|
|
639
|
+
throw error;
|
|
640
|
+
}
|
|
641
|
+
let snapshot;
|
|
642
|
+
try {
|
|
643
|
+
snapshot = validatedAccessibilitySnapshot(value, platform);
|
|
644
|
+
}
|
|
645
|
+
catch {
|
|
646
|
+
throw new CliInteractionError('Simulator accessibility returned an invalid tree', 'accessibility_invalid_response', requestId, 'accessibility', id, platform);
|
|
647
|
+
}
|
|
648
|
+
if (opts.json)
|
|
649
|
+
console.log(JSON.stringify(snapshot, null, 2));
|
|
650
|
+
else
|
|
651
|
+
printAccessibilitySnapshot(snapshot);
|
|
652
|
+
}
|
|
488
653
|
function simulatorRecordingBase(platform, sessionId) {
|
|
489
654
|
return `/run-cloud/${platform}/${encodeURIComponent(sessionId)}/recordings`;
|
|
490
655
|
}
|
|
@@ -733,6 +898,58 @@ async function createSimulatorSession(platform, opts) {
|
|
|
733
898
|
...(opts.devHost ? { devHost: opts.devHost } : {}),
|
|
734
899
|
});
|
|
735
900
|
}
|
|
901
|
+
async function openSimulatorSessionUrl(platform, sessionId, url) {
|
|
902
|
+
const path = `/run-cloud/${platform}/${encodeURIComponent(sessionId)}/open-url`;
|
|
903
|
+
try {
|
|
904
|
+
const response = await client().post(path, { url });
|
|
905
|
+
const result = typeof response === 'object' && response !== null && !Array.isArray(response)
|
|
906
|
+
? response
|
|
907
|
+
: {};
|
|
908
|
+
if (result.ok !== true
|
|
909
|
+
|| result.platform !== platform
|
|
910
|
+
|| result.sessionId !== sessionId
|
|
911
|
+
|| typeof result.device !== 'string'
|
|
912
|
+
|| result.device.length === 0
|
|
913
|
+
|| typeof result.leaseId !== 'string'
|
|
914
|
+
|| result.leaseId.length === 0
|
|
915
|
+
|| result.url !== url) {
|
|
916
|
+
throw new ApiError(0, 'Simulator open URL returned an invalid acknowledgement', path, {
|
|
917
|
+
code: 'open_url_invalid_response',
|
|
918
|
+
retryable: true,
|
|
919
|
+
sessionId,
|
|
920
|
+
platform,
|
|
921
|
+
action: 'open-url',
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
return {
|
|
925
|
+
ok: true,
|
|
926
|
+
platform,
|
|
927
|
+
sessionId,
|
|
928
|
+
device: result.device,
|
|
929
|
+
leaseId: result.leaseId,
|
|
930
|
+
url,
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
catch (error) {
|
|
934
|
+
if (error instanceof ApiTransportError) {
|
|
935
|
+
throw new ApiError(0, 'Simulator open URL could not reach the run.cloud API', path, {
|
|
936
|
+
code: 'open_url_transport_error',
|
|
937
|
+
retryable: true,
|
|
938
|
+
sessionId,
|
|
939
|
+
platform,
|
|
940
|
+
action: 'open-url',
|
|
941
|
+
});
|
|
942
|
+
}
|
|
943
|
+
if (error instanceof ApiError) {
|
|
944
|
+
Object.assign(error, {
|
|
945
|
+
sessionId: error.sessionId ?? sessionId,
|
|
946
|
+
platform: error.platform ?? platform,
|
|
947
|
+
action: error.action ?? 'open-url',
|
|
948
|
+
});
|
|
949
|
+
}
|
|
950
|
+
throw error;
|
|
951
|
+
}
|
|
952
|
+
}
|
|
736
953
|
function registerSimulatorCommands(program, platform) {
|
|
737
954
|
const label = platform === 'android' ? 'Android emulator' : 'iOS simulator';
|
|
738
955
|
const article = platform === 'android' ? 'an' : 'an';
|
|
@@ -792,7 +1009,7 @@ function registerSimulatorCommands(program, platform) {
|
|
|
792
1009
|
.requiredOption('--id <id>', 'session id')
|
|
793
1010
|
.option('--json', 'output JSON', false)
|
|
794
1011
|
.action((url, opts) => action(async () => {
|
|
795
|
-
print(await
|
|
1012
|
+
print(await openSimulatorSessionUrl(platform, opts.id, url), opts);
|
|
796
1013
|
}, opts));
|
|
797
1014
|
addInteractionOptions(simulator
|
|
798
1015
|
.command('tap')
|
|
@@ -921,6 +1138,14 @@ function registerSimulatorCommands(program, platform) {
|
|
|
921
1138
|
option: renderDebugOption(rawOption),
|
|
922
1139
|
enabled: booleanArgument(rawEnabled, 'enabled'),
|
|
923
1140
|
}, opts), opts));
|
|
1141
|
+
simulator
|
|
1142
|
+
.command('accessibility-tree')
|
|
1143
|
+
.alias('accessibility')
|
|
1144
|
+
.description(`Read the current accessibility hierarchy from ${article} active ${label} session`)
|
|
1145
|
+
.argument('<id>', 'session id')
|
|
1146
|
+
.option('--timeout <milliseconds>', 'capture timeout in milliseconds (100-60000)', String(DEFAULT_ACCESSIBILITY_TIMEOUT_MS))
|
|
1147
|
+
.option('--json', 'output the stable typed tree as JSON', false)
|
|
1148
|
+
.action((id, opts) => action(() => captureSimulatorAccessibilityTree(platform, id, opts), opts));
|
|
924
1149
|
addInteractionOptions(simulator
|
|
925
1150
|
.command('screenshot')
|
|
926
1151
|
.description(`Capture the current display from ${article} ${label} session`)
|
|
@@ -1036,6 +1261,7 @@ function jsonErrorEnvelope(error) {
|
|
|
1036
1261
|
retryable: error.retryable ?? (error.status === 408 || error.status === 429 || error.status >= 500),
|
|
1037
1262
|
httpStatus: error.status,
|
|
1038
1263
|
...(error.details === undefined ? {} : { details: error.details }),
|
|
1264
|
+
...(error.suggestedAction ? { action: error.suggestedAction } : {}),
|
|
1039
1265
|
},
|
|
1040
1266
|
};
|
|
1041
1267
|
}
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const CLI_VERSION = '0.1.
|
|
1
|
+
export const CLI_VERSION = '0.1.117';
|