@bctrl/cli 0.1.6 → 0.1.7
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/LICENSE +15 -0
- package/README.md +109 -95
- package/dist/api/auth.d.ts +10 -1
- package/dist/api/auth.js +10 -1
- package/dist/api/client.d.ts +2 -1
- package/dist/api/client.js +37 -37
- package/dist/api/device-auth.d.ts +39 -0
- package/dist/api/device-auth.js +93 -0
- package/dist/api/errors.d.ts +1 -0
- package/dist/api/errors.js +8 -0
- package/dist/bin/bctrl.js +0 -0
- package/dist/commands/ai/index.js +10 -11
- package/dist/commands/api-key/index.js +3 -8
- package/dist/commands/auth/device-login.d.ts +6 -0
- package/dist/commands/auth/device-login.js +19 -0
- package/dist/commands/auth/login.d.ts +11 -0
- package/dist/commands/auth/login.js +140 -20
- package/dist/commands/auth/logout.d.ts +2 -0
- package/dist/commands/auth/logout.js +19 -2
- package/dist/commands/auth/status.d.ts +1 -0
- package/dist/commands/auth/status.js +22 -5
- package/dist/commands/auth/token.js +6 -0
- package/dist/commands/browser-extension/index.js +7 -15
- package/dist/commands/file/index.js +8 -7
- package/dist/commands/help/index.js +5 -4
- package/dist/commands/notification-recipient/index.d.ts +3 -0
- package/dist/commands/notification-recipient/index.js +72 -0
- package/dist/commands/proxy/index.js +6 -4
- package/dist/commands/run/index.js +31 -32
- package/dist/commands/runtime/index.js +185 -106
- package/dist/commands/shared/help.d.ts +26 -3
- package/dist/commands/shared/help.js +87 -23
- package/dist/commands/shared/io.d.ts +1 -0
- package/dist/commands/shared/io.js +4 -2
- package/dist/commands/shared/operation.d.ts +50 -3
- package/dist/commands/shared/operation.js +171 -25
- package/dist/commands/shared/output.js +3 -7
- package/dist/commands/space/index.js +35 -32
- package/dist/commands/space/list.js +6 -5
- package/dist/commands/subaccount/index.js +12 -14
- package/dist/commands/usage/index.js +9 -5
- package/dist/commands/vault/index.js +15 -21
- package/dist/config/auth-store.d.ts +75 -9
- package/dist/config/auth-store.js +133 -27
- package/dist/config/config.d.ts +2 -2
- package/dist/config/config.js +9 -17
- package/dist/config/paths.d.ts +16 -0
- package/dist/config/paths.js +34 -0
- package/dist/config/pending-auth.d.ts +19 -0
- package/dist/config/pending-auth.js +72 -0
- package/dist/config/secret-store.d.ts +24 -0
- package/dist/config/secret-store.js +123 -0
- package/dist/factory.js +2 -1
- package/dist/generated/help.d.ts +7424 -2768
- package/dist/generated/help.js +10116 -4014
- package/dist/generated/openapi-routes.d.ts +52 -8
- package/dist/generated/openapi-routes.js +20 -9
- package/dist/generated/openapi-types.d.ts +2688 -883
- package/dist/root.js +2 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +4 -0
- package/package.json +56 -47
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import { CliError } from '../../runtime/errors.js';
|
|
3
|
-
import {
|
|
3
|
+
import { writeBinary } from '../shared/io.js';
|
|
4
4
|
import { parsePositiveInteger } from '../shared/options.js';
|
|
5
5
|
import { addOutputFlags } from '../shared/output.js';
|
|
6
|
-
import { addPaginationFlags, createOperationJsonBodyCommand, createOperationListCommand, createOperationViewCommand, downloadOperation, outputFlags, requestOperation, requestOperationAndPrint, streamOperationText, } from '../shared/operation.js';
|
|
6
|
+
import { actingSubaccountOption, addPaginationFlags, buildOperationInput, createOperationJsonBodyCommand, createOperationListCommand, createOperationViewCommand, downloadOperation, outputFlags, requestOperation, requestOperationAndPrint, streamOperationText, } from '../shared/operation.js';
|
|
7
7
|
export function createRunCommand(factory) {
|
|
8
8
|
const command = new Command('run').description('Inspect and stream runs');
|
|
9
9
|
command.addCommand(createOperationListCommand(factory, {
|
|
@@ -18,10 +18,10 @@ export function createRunCommand(factory) {
|
|
|
18
18
|
spaceId: typeof options.space === 'string' ? options.space : undefined,
|
|
19
19
|
runtimeId: typeof options.runtime === 'string' ? options.runtime : undefined,
|
|
20
20
|
status: typeof options.status === 'string' ? options.status : undefined,
|
|
21
|
-
subaccountId: typeof options.subaccount === 'string' ? options.subaccount : undefined,
|
|
22
21
|
limit: typeof options.limit === 'number' ? options.limit : undefined,
|
|
23
22
|
cursor: typeof options.cursor === 'string' ? options.cursor : undefined,
|
|
24
23
|
}),
|
|
24
|
+
actingSubaccountId: actingSubaccountOption('subaccount'),
|
|
25
25
|
}));
|
|
26
26
|
command.addCommand(createOperationViewCommand(factory, {
|
|
27
27
|
operationId: 'runs.get',
|
|
@@ -72,8 +72,9 @@ function createRunActivityListCommand(factory) {
|
|
|
72
72
|
.option('--category <category>', 'Filter by activity category')
|
|
73
73
|
.option('--severity <severity>', 'Filter by severity')
|
|
74
74
|
.option('--invocation <id>', 'Filter by invocation id')
|
|
75
|
-
.option('--file <id>', 'Filter by file id')
|
|
76
|
-
|
|
75
|
+
.option('--file <id>', 'Filter by file id')
|
|
76
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')).action(async (runId, options) => {
|
|
77
|
+
await requestOperationAndPrint(factory, 'runs.activity.list', await buildOperationInput('runs.activity.list', options, {
|
|
77
78
|
pathParams: { runId },
|
|
78
79
|
query: {
|
|
79
80
|
view: options.view,
|
|
@@ -86,7 +87,7 @@ function createRunActivityListCommand(factory) {
|
|
|
86
87
|
cursor: options.cursor,
|
|
87
88
|
},
|
|
88
89
|
output: outputFlags(options),
|
|
89
|
-
});
|
|
90
|
+
}));
|
|
90
91
|
});
|
|
91
92
|
}
|
|
92
93
|
function createRunEventsCommand(factory) {
|
|
@@ -117,8 +118,9 @@ function createRunEventsListCommand(factory) {
|
|
|
117
118
|
.option('--type <type>', 'Filter by event type')
|
|
118
119
|
.option('--status <status>', 'Filter by event status')
|
|
119
120
|
.option('--page-id <id>', 'Filter by page id')
|
|
120
|
-
.option('--context-id <id>', 'Filter by browser context id')
|
|
121
|
-
|
|
121
|
+
.option('--context-id <id>', 'Filter by browser context id')
|
|
122
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')).action(async (runId, options) => {
|
|
123
|
+
await requestOperationAndPrint(factory, 'runs.events.list', await buildOperationInput('runs.events.list', options, {
|
|
122
124
|
pathParams: { runId },
|
|
123
125
|
query: {
|
|
124
126
|
type: options.type,
|
|
@@ -129,7 +131,7 @@ function createRunEventsListCommand(factory) {
|
|
|
129
131
|
cursor: options.cursor,
|
|
130
132
|
},
|
|
131
133
|
output: outputFlags(options),
|
|
132
|
-
});
|
|
134
|
+
}));
|
|
133
135
|
});
|
|
134
136
|
}
|
|
135
137
|
function createRunFilesCommand(factory) {
|
|
@@ -139,8 +141,10 @@ function createRunFilesCommand(factory) {
|
|
|
139
141
|
return command;
|
|
140
142
|
}
|
|
141
143
|
function createRunFilesListCommand(factory) {
|
|
142
|
-
return addOutputFlags(addPaginationFlags(new Command('list').description('List run files').argument('<runId>'))
|
|
143
|
-
|
|
144
|
+
return addOutputFlags(addPaginationFlags(new Command('list').description('List run files').argument('<runId>'))
|
|
145
|
+
.option('--type <type>', 'Filter by file type')
|
|
146
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')).action(async (runId, options) => {
|
|
147
|
+
await requestOperationAndPrint(factory, 'runs.files.list', await buildOperationInput('runs.files.list', options, {
|
|
144
148
|
pathParams: { runId },
|
|
145
149
|
query: {
|
|
146
150
|
type: options.type,
|
|
@@ -148,7 +152,7 @@ function createRunFilesListCommand(factory) {
|
|
|
148
152
|
cursor: options.cursor,
|
|
149
153
|
},
|
|
150
154
|
output: outputFlags(options),
|
|
151
|
-
});
|
|
155
|
+
}));
|
|
152
156
|
});
|
|
153
157
|
}
|
|
154
158
|
function createRunFilesExportCommand(factory) {
|
|
@@ -157,15 +161,12 @@ function createRunFilesExportCommand(factory) {
|
|
|
157
161
|
.argument('<runId>')
|
|
158
162
|
.requiredOption('--to <path>', 'Output archive path, or - for stdout')
|
|
159
163
|
.option('--name <name>', 'Export file name', 'run-files.zip')
|
|
160
|
-
.option('--type <type...>', 'Filter exported file types')
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
: {
|
|
165
|
-
|
|
166
|
-
name: options.name,
|
|
167
|
-
filter: options.type ? { type: options.type } : undefined,
|
|
168
|
-
};
|
|
164
|
+
.option('--type <type...>', 'Filter exported file types')).action(async (runId, options) => {
|
|
165
|
+
const body = {
|
|
166
|
+
format: 'zip',
|
|
167
|
+
name: options.name,
|
|
168
|
+
filter: options.type ? { type: options.type } : undefined,
|
|
169
|
+
};
|
|
169
170
|
const result = (await requestOperation(factory, 'runs.files.export', {
|
|
170
171
|
pathParams: { runId },
|
|
171
172
|
body: body,
|
|
@@ -183,9 +184,10 @@ function createRunFilesExportCommand(factory) {
|
|
|
183
184
|
function createRunInvocationsCommand(factory) {
|
|
184
185
|
const command = addOutputFlags(addPaginationFlags(new Command('invocations').description('List run invocations').argument('<runId>'))
|
|
185
186
|
.option('--status <status>', 'Filter by invocation status')
|
|
186
|
-
.option('--action <action>', 'Filter by invocation action')
|
|
187
|
+
.option('--action <action>', 'Filter by invocation action')
|
|
188
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)'));
|
|
187
189
|
command.action(async (runId, options) => {
|
|
188
|
-
await requestOperationAndPrint(factory, 'runs.invocations.list', {
|
|
190
|
+
await requestOperationAndPrint(factory, 'runs.invocations.list', await buildOperationInput('runs.invocations.list', options, {
|
|
189
191
|
pathParams: { runId },
|
|
190
192
|
query: {
|
|
191
193
|
status: options.status,
|
|
@@ -194,7 +196,7 @@ function createRunInvocationsCommand(factory) {
|
|
|
194
196
|
cursor: options.cursor,
|
|
195
197
|
},
|
|
196
198
|
output: outputFlags(options),
|
|
197
|
-
});
|
|
199
|
+
}));
|
|
198
200
|
});
|
|
199
201
|
return command;
|
|
200
202
|
}
|
|
@@ -203,11 +205,12 @@ function createRunInvocationCommand(factory) {
|
|
|
203
205
|
command.addCommand(addOutputFlags(new Command('get')
|
|
204
206
|
.description('Get a run invocation')
|
|
205
207
|
.argument('<runId>')
|
|
206
|
-
.argument('<invocationId>')
|
|
207
|
-
|
|
208
|
+
.argument('<invocationId>')
|
|
209
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')).action(async (runId, invocationId, options) => {
|
|
210
|
+
await requestOperationAndPrint(factory, 'runs.invocations.get', await buildOperationInput('runs.invocations.get', options, {
|
|
208
211
|
pathParams: { runId, invocationId },
|
|
209
212
|
output: outputFlags(options),
|
|
210
|
-
});
|
|
213
|
+
}));
|
|
211
214
|
}));
|
|
212
215
|
return command;
|
|
213
216
|
}
|
|
@@ -219,12 +222,8 @@ function createRunViewerCommand(factory, name, description) {
|
|
|
219
222
|
argNames: ['runId'],
|
|
220
223
|
configure: (cmd) => cmd
|
|
221
224
|
.option('--expires-in-seconds <seconds>', 'Viewer expiration in seconds', parsePositiveInteger)
|
|
222
|
-
.option('--control <none|input>', 'Live viewer control mode')
|
|
223
|
-
.option('--input <path>', 'Read JSON request body from file, or - for stdin'),
|
|
225
|
+
.option('--control <none|input>', 'Live viewer control mode'),
|
|
224
226
|
body: async (_args, options) => {
|
|
225
|
-
if (typeof options.input === 'string') {
|
|
226
|
-
return (await readJsonFile(options.input));
|
|
227
|
-
}
|
|
228
227
|
return {
|
|
229
228
|
expiresInSeconds: typeof options.expiresInSeconds === 'number' ? options.expiresInSeconds : undefined,
|
|
230
229
|
control: name === 'live' ? options.control : undefined,
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Command, Option } from 'commander';
|
|
2
|
-
import { readBlob, readJsonFile } from '../shared/io.js';
|
|
3
|
-
import { addPaginationFlags, createOperationJsonBodyCommand, outputFlags, requestOperationAndPrint, uploadOperationFile, } from '../shared/operation.js';
|
|
2
|
+
import { parseJsonString, readBlob, readJsonFile } from '../shared/io.js';
|
|
3
|
+
import { addPaginationFlags, buildOperationInput, createOperationJsonBodyCommand, outputFlags, requestOperationAndPrint, uploadOperationFile, } from '../shared/operation.js';
|
|
4
4
|
import { parsePositiveInteger } from '../shared/options.js';
|
|
5
5
|
import { addOutputFlags, outputData } from '../shared/output.js';
|
|
6
6
|
import { CliError } from '../../runtime/errors.js';
|
|
7
|
+
import { addCliOperationHelp } from '../shared/help.js';
|
|
7
8
|
export function createRuntimeCommand(factory) {
|
|
8
9
|
const command = new Command('runtime').description('Manage runtimes');
|
|
9
10
|
command.addCommand(addOutputFlags(addPaginationFlags(new Command('list').description('List runtimes'))
|
|
@@ -12,8 +13,9 @@ export function createRuntimeCommand(factory) {
|
|
|
12
13
|
'active',
|
|
13
14
|
'failed',
|
|
14
15
|
'stopped',
|
|
15
|
-
]))
|
|
16
|
-
|
|
16
|
+
]))
|
|
17
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')).action(async (options) => {
|
|
18
|
+
await requestOperationAndPrint(factory, 'runtimes.list', await buildOperationInput('runtimes.list', options, {
|
|
17
19
|
query: {
|
|
18
20
|
spaceId: options.space,
|
|
19
21
|
status: options.status ? [options.status] : undefined,
|
|
@@ -21,13 +23,16 @@ export function createRuntimeCommand(factory) {
|
|
|
21
23
|
cursor: options.cursor,
|
|
22
24
|
},
|
|
23
25
|
output: outputFlags(options),
|
|
24
|
-
});
|
|
26
|
+
}));
|
|
25
27
|
}));
|
|
26
|
-
command.addCommand(addOutputFlags(new Command('get')
|
|
27
|
-
|
|
28
|
+
command.addCommand(addOutputFlags(new Command('get')
|
|
29
|
+
.description('Get a runtime')
|
|
30
|
+
.argument('<runtimeId>')
|
|
31
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')).action(async (runtimeId, options) => {
|
|
32
|
+
await requestOperationAndPrint(factory, 'runtimes.get', await buildOperationInput('runtimes.get', options, {
|
|
28
33
|
pathParams: { runtimeId },
|
|
29
34
|
output: outputFlags(options),
|
|
30
|
-
});
|
|
35
|
+
}));
|
|
31
36
|
}));
|
|
32
37
|
command.addCommand(createRuntimeCreateCommand(factory));
|
|
33
38
|
command.addCommand(createRuntimePatchCommand(factory));
|
|
@@ -35,84 +40,101 @@ export function createRuntimeCommand(factory) {
|
|
|
35
40
|
.description('Delete a runtime and its browser state')
|
|
36
41
|
.argument('<runtimeId>')
|
|
37
42
|
.option('-y, --yes', 'Confirm deletion')
|
|
38
|
-
.option('--
|
|
43
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')).action(async (runtimeId, options) => {
|
|
39
44
|
if (options.yes !== true) {
|
|
40
45
|
throw new CliError('Refusing to delete without --yes');
|
|
41
46
|
}
|
|
42
|
-
await requestOperationAndPrint(factory, 'runtimes.delete', {
|
|
47
|
+
await requestOperationAndPrint(factory, 'runtimes.delete', await buildOperationInput('runtimes.delete', options, {
|
|
43
48
|
pathParams: { runtimeId },
|
|
44
|
-
query: { force: options.force === true ? true : undefined },
|
|
45
49
|
output: outputFlags(options),
|
|
46
|
-
});
|
|
50
|
+
}));
|
|
47
51
|
}));
|
|
48
52
|
command.addCommand(createRuntimeStartCommand(factory));
|
|
49
|
-
command.addCommand(addOutputFlags(new Command('stop')
|
|
50
|
-
|
|
53
|
+
command.addCommand(addOutputFlags(new Command('stop')
|
|
54
|
+
.description('Stop a runtime')
|
|
55
|
+
.argument('<runtimeId>')
|
|
56
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')).action(async (runtimeId, options) => {
|
|
57
|
+
await requestOperationAndPrint(factory, 'runtimes.stop', await buildOperationInput('runtimes.stop', options, {
|
|
51
58
|
pathParams: { runtimeId },
|
|
52
59
|
output: outputFlags(options),
|
|
53
|
-
});
|
|
60
|
+
}));
|
|
54
61
|
}));
|
|
55
62
|
command.addCommand(createRuntimeFileCommand(factory));
|
|
56
63
|
command.addCommand(createRuntimeInvocationCommand(factory));
|
|
64
|
+
command.addCommand(createRuntimeHumanActionCommand(factory));
|
|
57
65
|
command.addCommand(createRuntimeTargetCommand(factory));
|
|
58
66
|
return command;
|
|
59
67
|
}
|
|
60
68
|
function createRuntimeTargetCommand(factory) {
|
|
61
69
|
const command = new Command('target').description('Manage runtime targets (tabs)');
|
|
62
|
-
command.addCommand(addOutputFlags(new Command('list')
|
|
63
|
-
|
|
70
|
+
command.addCommand(addOutputFlags(new Command('list')
|
|
71
|
+
.description('List targets')
|
|
72
|
+
.argument('<runtimeId>')
|
|
73
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')).action(async (runtimeId, options) => {
|
|
74
|
+
await requestOperationAndPrint(factory, 'runtimes.targets.list', await buildOperationInput('runtimes.targets.list', options, {
|
|
64
75
|
pathParams: { runtimeId },
|
|
65
76
|
output: outputFlags(options),
|
|
66
|
-
});
|
|
77
|
+
}));
|
|
67
78
|
}));
|
|
68
79
|
command.addCommand(addOutputFlags(new Command('create')
|
|
69
80
|
.description('Open a new target')
|
|
70
81
|
.argument('<runtimeId>')
|
|
71
82
|
.option('--uri <uri>', 'Navigate the new target to this URI')
|
|
72
|
-
.option('--activate', 'Focus the new target')
|
|
73
|
-
|
|
83
|
+
.option('--activate', 'Focus the new target')
|
|
84
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')
|
|
85
|
+
.option('--body <json>', 'Request body as JSON (inline, @file, or - for stdin)')).action(async (runtimeId, options) => {
|
|
86
|
+
await requestOperationAndPrint(factory, 'runtimes.targets.create', await buildOperationInput('runtimes.targets.create', options, {
|
|
74
87
|
pathParams: { runtimeId },
|
|
75
88
|
body: {
|
|
76
89
|
...(options.uri ? { uri: options.uri } : {}),
|
|
77
90
|
...(options.activate ? { activate: true } : {}),
|
|
78
91
|
},
|
|
79
92
|
output: outputFlags(options),
|
|
80
|
-
});
|
|
93
|
+
}));
|
|
81
94
|
}));
|
|
82
|
-
command.addCommand(addOutputFlags(new Command('get')
|
|
83
|
-
|
|
95
|
+
command.addCommand(addOutputFlags(new Command('get')
|
|
96
|
+
.description('Get a target')
|
|
97
|
+
.argument('<runtimeId>')
|
|
98
|
+
.argument('<targetId>')
|
|
99
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')).action(async (runtimeId, targetId, options) => {
|
|
100
|
+
await requestOperationAndPrint(factory, 'runtimes.targets.get', await buildOperationInput('runtimes.targets.get', options, {
|
|
84
101
|
pathParams: { runtimeId, targetId },
|
|
85
102
|
output: outputFlags(options),
|
|
86
|
-
});
|
|
103
|
+
}));
|
|
87
104
|
}));
|
|
88
105
|
command.addCommand(addOutputFlags(new Command('activate')
|
|
89
106
|
.description('Focus a target')
|
|
90
107
|
.argument('<runtimeId>')
|
|
91
|
-
.argument('<targetId>')
|
|
92
|
-
|
|
108
|
+
.argument('<targetId>')
|
|
109
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')).action(async (runtimeId, targetId, options) => {
|
|
110
|
+
await requestOperationAndPrint(factory, 'runtimes.targets.activate', await buildOperationInput('runtimes.targets.activate', options, {
|
|
93
111
|
pathParams: { runtimeId, targetId },
|
|
94
112
|
output: outputFlags(options),
|
|
95
|
-
});
|
|
113
|
+
}));
|
|
96
114
|
}));
|
|
97
115
|
command.addCommand(addOutputFlags(new Command('delete')
|
|
98
116
|
.description('Close a target')
|
|
99
117
|
.argument('<runtimeId>')
|
|
100
|
-
.argument('<targetId>')
|
|
101
|
-
|
|
118
|
+
.argument('<targetId>')
|
|
119
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')).action(async (runtimeId, targetId, options) => {
|
|
120
|
+
await requestOperationAndPrint(factory, 'runtimes.targets.delete', await buildOperationInput('runtimes.targets.delete', options, {
|
|
102
121
|
pathParams: { runtimeId, targetId },
|
|
103
122
|
output: outputFlags(options),
|
|
104
|
-
});
|
|
123
|
+
}));
|
|
105
124
|
}));
|
|
106
125
|
return command;
|
|
107
126
|
}
|
|
108
127
|
function createRuntimeCreateCommand(factory) {
|
|
109
|
-
return addOutputFlags(new Command('create')
|
|
128
|
+
return addOutputFlags(addCliOperationHelp(new Command('create')
|
|
110
129
|
.description('Create a runtime')
|
|
111
130
|
.option('--space <id>', 'Space id; omitted uses caller default space')
|
|
112
131
|
.option('--name <name>', 'Runtime name')
|
|
113
132
|
.option('--profile', 'Persist browser state across runtime starts')
|
|
114
133
|
.option('--proxy <id-or-url>', 'Saved proxy id or inline custom proxy URL')
|
|
115
|
-
.addOption(new Option('--device <device>', 'Fingerprint device filter').choices([
|
|
134
|
+
.addOption(new Option('--device <device>', 'Fingerprint device filter').choices([
|
|
135
|
+
'desktop',
|
|
136
|
+
'mobile',
|
|
137
|
+
]))
|
|
116
138
|
.addOption(new Option('--os <os>', 'Fingerprint OS filter').choices([
|
|
117
139
|
'windows',
|
|
118
140
|
'macos',
|
|
@@ -128,24 +150,26 @@ function createRuntimeCreateCommand(factory) {
|
|
|
128
150
|
.option('--locale <locale>', 'Fingerprint locale/language filter; repeat to set an ordered language stack', collectLocale, [])
|
|
129
151
|
.option('--config-file <path>', 'Runtime config JSON file')
|
|
130
152
|
.option('--metadata-file <path>', 'Runtime metadata JSON file')
|
|
131
|
-
.option('--
|
|
153
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')
|
|
154
|
+
.option('--body <json>', 'Full request body as JSON (inline, @file, or - for stdin)'), 'runtimes.create')).action(async (options) => {
|
|
155
|
+
// --body (raw JSON) is the complete body; otherwise build it from
|
|
156
|
+
// the curated flags. --params can still add query params. The control-plane
|
|
157
|
+
// validates the body against the runtimes.create schema either way.
|
|
132
158
|
const config = typeof options.configFile === 'string'
|
|
133
159
|
? await readJsonFile(options.configFile, '--config-file')
|
|
134
160
|
: undefined;
|
|
135
|
-
await requestOperationAndPrint(factory, 'runtimes.create', {
|
|
136
|
-
body:
|
|
137
|
-
|
|
138
|
-
:
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
: undefined,
|
|
146
|
-
},
|
|
161
|
+
await requestOperationAndPrint(factory, 'runtimes.create', await buildOperationInput('runtimes.create', options, {
|
|
162
|
+
body: {
|
|
163
|
+
type: 'browser',
|
|
164
|
+
spaceId: options.space,
|
|
165
|
+
name: options.name,
|
|
166
|
+
config: buildRuntimeCreateConfig(config, options),
|
|
167
|
+
metadata: typeof options.metadataFile === 'string'
|
|
168
|
+
? await readJsonFile(options.metadataFile, '--metadata-file')
|
|
169
|
+
: undefined,
|
|
170
|
+
},
|
|
147
171
|
output: outputFlags(options),
|
|
148
|
-
});
|
|
172
|
+
}));
|
|
149
173
|
});
|
|
150
174
|
}
|
|
151
175
|
function collectLocale(value, previous) {
|
|
@@ -195,34 +219,34 @@ function createRuntimePatchCommand(factory) {
|
|
|
195
219
|
.description('Update a runtime')
|
|
196
220
|
.argument('<runtimeId>')
|
|
197
221
|
.option('--name <name>', 'Runtime name')
|
|
198
|
-
.option('--idle-timeout-
|
|
222
|
+
.option('--idle-timeout-seconds <seconds>', 'Idle timeout in seconds', parsePositiveInteger)
|
|
199
223
|
.option('--config-file <path>', 'Runtime config JSON file')
|
|
200
|
-
.option('--
|
|
201
|
-
|
|
224
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')
|
|
225
|
+
.option('--body <json>', 'Request body as JSON (inline, @file, or - for stdin)')).action(async (runtimeId, options) => {
|
|
226
|
+
await requestOperationAndPrint(factory, 'runtimes.update', await buildOperationInput('runtimes.update', options, {
|
|
202
227
|
pathParams: { runtimeId },
|
|
203
|
-
body:
|
|
204
|
-
|
|
205
|
-
:
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
: undefined,
|
|
211
|
-
},
|
|
228
|
+
body: {
|
|
229
|
+
name: options.name,
|
|
230
|
+
idleTimeoutSeconds: options.idleTimeoutSeconds,
|
|
231
|
+
config: typeof options.configFile === 'string'
|
|
232
|
+
? await readJsonFile(options.configFile, '--config-file')
|
|
233
|
+
: undefined,
|
|
234
|
+
},
|
|
212
235
|
output: outputFlags(options),
|
|
213
|
-
});
|
|
236
|
+
}));
|
|
214
237
|
});
|
|
215
238
|
}
|
|
216
239
|
function createRuntimeStartCommand(factory) {
|
|
217
240
|
return addOutputFlags(new Command('start')
|
|
218
241
|
.description('Start a runtime')
|
|
219
242
|
.argument('<runtimeId>')
|
|
220
|
-
.option('--idempotency-key <key>', 'Idempotency key for retry-safe start')
|
|
221
|
-
|
|
243
|
+
.option('--idempotency-key <key>', 'Idempotency key for retry-safe start')
|
|
244
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')).action(async (runtimeId, options) => {
|
|
245
|
+
await requestOperationAndPrint(factory, 'runtimes.start', await buildOperationInput('runtimes.start', options, {
|
|
222
246
|
pathParams: { runtimeId },
|
|
223
247
|
idempotencyKey: options.idempotencyKey,
|
|
224
248
|
output: outputFlags(options),
|
|
225
|
-
});
|
|
249
|
+
}));
|
|
226
250
|
});
|
|
227
251
|
}
|
|
228
252
|
function createRuntimeInvocationCommand(factory) {
|
|
@@ -232,11 +256,12 @@ function createRuntimeInvocationCommand(factory) {
|
|
|
232
256
|
command.addCommand(addOutputFlags(new Command('cancel')
|
|
233
257
|
.description('Cancel an invocation')
|
|
234
258
|
.argument('<runtimeId>')
|
|
235
|
-
.argument('<invocationId>')
|
|
236
|
-
|
|
259
|
+
.argument('<invocationId>')
|
|
260
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')).action(async (runtimeId, invocationId, options) => {
|
|
261
|
+
await requestOperationAndPrint(factory, 'runtimes.invocations.cancel', await buildOperationInput('runtimes.invocations.cancel', options, {
|
|
237
262
|
pathParams: { runtimeId, invocationId },
|
|
238
263
|
output: outputFlags(options),
|
|
239
|
-
});
|
|
264
|
+
}));
|
|
240
265
|
}));
|
|
241
266
|
return command;
|
|
242
267
|
}
|
|
@@ -250,30 +275,29 @@ function createRuntimeInvocationCreateCommand(factory) {
|
|
|
250
275
|
.option('--model <model>', 'Model id')
|
|
251
276
|
.option('--tool <id...>', 'Inline tool id')
|
|
252
277
|
.option('--toolset <id>', 'Toolset id')
|
|
253
|
-
.option('--timeout-
|
|
278
|
+
.option('--timeout-seconds <seconds>', 'Invocation timeout in seconds', parsePositiveInteger)
|
|
254
279
|
.option('--idempotency-key <key>', 'Idempotency key for retry-safe create')
|
|
255
|
-
.option('--
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
:
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
await requestOperationAndPrint(factory, 'runtimes.invocations.create', {
|
|
280
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')
|
|
281
|
+
.option('--body <json>', 'Request body as JSON (inline, @file, or - for stdin)')).action(async (runtimeId, options) => {
|
|
282
|
+
const body = {
|
|
283
|
+
action: options.action,
|
|
284
|
+
instruction: options.instruction,
|
|
285
|
+
target: options.target === undefined
|
|
286
|
+
? undefined
|
|
287
|
+
: options.target === 'active' || options.target === 'new'
|
|
288
|
+
? options.target
|
|
289
|
+
: { id: options.target },
|
|
290
|
+
model: options.model,
|
|
291
|
+
toolIds: options.tool,
|
|
292
|
+
toolsetId: options.toolset,
|
|
293
|
+
timeoutSeconds: options.timeoutSeconds,
|
|
294
|
+
};
|
|
295
|
+
await requestOperationAndPrint(factory, 'runtimes.invocations.create', await buildOperationInput('runtimes.invocations.create', options, {
|
|
272
296
|
pathParams: { runtimeId },
|
|
273
297
|
body: body,
|
|
274
298
|
idempotencyKey: options.idempotencyKey,
|
|
275
299
|
output: outputFlags(options),
|
|
276
|
-
});
|
|
300
|
+
}));
|
|
277
301
|
});
|
|
278
302
|
}
|
|
279
303
|
function createRuntimeInvocationWaitCommand(factory) {
|
|
@@ -283,20 +307,80 @@ function createRuntimeInvocationWaitCommand(factory) {
|
|
|
283
307
|
description: 'Wait for an invocation',
|
|
284
308
|
argNames: ['runtimeId', 'invocationId'],
|
|
285
309
|
configure: (cmd) => cmd
|
|
286
|
-
.option('--timeout-
|
|
287
|
-
.option('--input <path>', 'Read JSON request body from file, or - for stdin'),
|
|
310
|
+
.option('--timeout-seconds <seconds>', 'Wait timeout in seconds', parsePositiveInteger),
|
|
288
311
|
body: async (_args, options) => {
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
}
|
|
292
|
-
return { timeoutMs: options.timeoutMs };
|
|
312
|
+
return {
|
|
313
|
+
timeoutSeconds: options.timeoutSeconds,
|
|
314
|
+
};
|
|
293
315
|
},
|
|
294
316
|
});
|
|
295
317
|
}
|
|
318
|
+
function createRuntimeHumanActionCommand(factory) {
|
|
319
|
+
const command = new Command('human-action').description('Manage runtime human actions');
|
|
320
|
+
command.addCommand(createOperationJsonBodyCommand(factory, {
|
|
321
|
+
operationId: 'runtimes.human-actions.create',
|
|
322
|
+
name: 'create',
|
|
323
|
+
description: 'Request human action',
|
|
324
|
+
argNames: ['runtimeId'],
|
|
325
|
+
configure: (cmd) => cmd
|
|
326
|
+
.option('--message <message>', 'Instructions for the human')
|
|
327
|
+
.option('--timeout-seconds <seconds>', 'Human action timeout in seconds', parsePositiveInteger),
|
|
328
|
+
body: async (_args, options) => {
|
|
329
|
+
return {
|
|
330
|
+
message: options.message,
|
|
331
|
+
timeoutSeconds: options.timeoutSeconds,
|
|
332
|
+
};
|
|
333
|
+
},
|
|
334
|
+
}));
|
|
335
|
+
command.addCommand(addOutputFlags(addCliOperationHelp(new Command('get')
|
|
336
|
+
.description('Get a human action')
|
|
337
|
+
.argument('<runtimeId>')
|
|
338
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)'), 'runtimes.human-actions.get')).action(async (runtimeId, options) => {
|
|
339
|
+
await requestOperationAndPrint(factory, 'runtimes.human-actions.get', await buildOperationInput('runtimes.human-actions.get', options, {
|
|
340
|
+
pathParams: { runtimeId },
|
|
341
|
+
output: outputFlags(options),
|
|
342
|
+
}));
|
|
343
|
+
}));
|
|
344
|
+
command.addCommand(addOutputFlags(addCliOperationHelp(new Command('complete')
|
|
345
|
+
.description('Complete a human action')
|
|
346
|
+
.argument('<runtimeId>')
|
|
347
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)'), 'runtimes.human-actions.complete')).action(async (runtimeId, options) => {
|
|
348
|
+
await requestOperationAndPrint(factory, 'runtimes.human-actions.complete', await buildOperationInput('runtimes.human-actions.complete', options, {
|
|
349
|
+
pathParams: { runtimeId },
|
|
350
|
+
output: outputFlags(options),
|
|
351
|
+
}));
|
|
352
|
+
}));
|
|
353
|
+
command.addCommand(addOutputFlags(addCliOperationHelp(new Command('cancel')
|
|
354
|
+
.description('Cancel a human action')
|
|
355
|
+
.argument('<runtimeId>')
|
|
356
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)'), 'runtimes.human-actions.cancel')).action(async (runtimeId, options) => {
|
|
357
|
+
await requestOperationAndPrint(factory, 'runtimes.human-actions.cancel', await buildOperationInput('runtimes.human-actions.cancel', options, {
|
|
358
|
+
pathParams: { runtimeId },
|
|
359
|
+
output: outputFlags(options),
|
|
360
|
+
}));
|
|
361
|
+
}));
|
|
362
|
+
command.addCommand(addOutputFlags(addCliOperationHelp(new Command('wait')
|
|
363
|
+
.description('Wait for a human action')
|
|
364
|
+
.argument('<runtimeId>')
|
|
365
|
+
.option('--timeout-seconds <seconds>', 'Long-poll timeout', parsePositiveInteger)
|
|
366
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')
|
|
367
|
+
.option('--body <json>', 'Request body as JSON (inline, @file, or - for stdin)'), 'runtimes.human-actions.wait')).action(async (runtimeId, options) => {
|
|
368
|
+
await requestOperationAndPrint(factory, 'runtimes.human-actions.wait', await buildOperationInput('runtimes.human-actions.wait', options, {
|
|
369
|
+
pathParams: { runtimeId },
|
|
370
|
+
body: {
|
|
371
|
+
timeoutSeconds: options.timeoutSeconds,
|
|
372
|
+
},
|
|
373
|
+
output: outputFlags(options),
|
|
374
|
+
}));
|
|
375
|
+
}));
|
|
376
|
+
return command;
|
|
377
|
+
}
|
|
296
378
|
function createRuntimeFileCommand(factory) {
|
|
297
379
|
const command = new Command('file').description('Move files into and out of runtimes');
|
|
298
|
-
command.addCommand(addOutputFlags(addPaginationFlags(new Command('list').description('List runtime files').argument('<runtimeId>'))
|
|
299
|
-
|
|
380
|
+
command.addCommand(addOutputFlags(addPaginationFlags(new Command('list').description('List runtime files').argument('<runtimeId>'))
|
|
381
|
+
.option('--type <type>', 'Filter by file type')
|
|
382
|
+
.option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')).action(async (runtimeId, options) => {
|
|
383
|
+
await requestOperationAndPrint(factory, 'runtimes.files.list', await buildOperationInput('runtimes.files.list', options, {
|
|
300
384
|
pathParams: { runtimeId },
|
|
301
385
|
query: {
|
|
302
386
|
type: options.type,
|
|
@@ -304,7 +388,7 @@ function createRuntimeFileCommand(factory) {
|
|
|
304
388
|
cursor: options.cursor,
|
|
305
389
|
},
|
|
306
390
|
output: outputFlags(options),
|
|
307
|
-
});
|
|
391
|
+
}));
|
|
308
392
|
}));
|
|
309
393
|
command.addCommand(createRuntimeFileUploadCommand(factory));
|
|
310
394
|
command.addCommand(createRuntimeFileStageCommand(factory));
|
|
@@ -319,11 +403,14 @@ function createRuntimeFileUploadCommand(factory) {
|
|
|
319
403
|
.option('--destination-path <path>', 'Durable BCTRL storage destination')
|
|
320
404
|
.option('--runtime-path <path>', 'Runtime workspace destination')
|
|
321
405
|
.option('--name <name>', 'Display name')
|
|
406
|
+
.option('--metadata <json>', 'Metadata as inline JSON (overrides --metadata-file)')
|
|
322
407
|
.option('--metadata-file <path>', 'Metadata JSON file')).action(async (runtimeId, localPath, options) => {
|
|
323
408
|
const file = await readBlob(localPath);
|
|
324
|
-
const metadata =
|
|
325
|
-
? JSON.stringify(
|
|
326
|
-
:
|
|
409
|
+
const metadata = options.metadata !== undefined
|
|
410
|
+
? JSON.stringify(parseJsonString(options.metadata, '--metadata'))
|
|
411
|
+
: typeof options.metadataFile === 'string'
|
|
412
|
+
? JSON.stringify(await readJsonFile(options.metadataFile, '--metadata-file'))
|
|
413
|
+
: undefined;
|
|
327
414
|
const result = await uploadOperationFile(factory, 'runtimes.files.upload', {
|
|
328
415
|
pathParams: { runtimeId },
|
|
329
416
|
file: file.blob,
|
|
@@ -347,12 +434,8 @@ function createRuntimeFileStageCommand(factory) {
|
|
|
347
434
|
configure: (cmd) => cmd
|
|
348
435
|
.option('--file <id>', 'Durable file id')
|
|
349
436
|
.option('--runtime-path <path>', 'Runtime workspace destination')
|
|
350
|
-
.option('--name <name>', 'Runtime-local display name')
|
|
351
|
-
.option('--input <path>', 'Read JSON request body from file, or - for stdin'),
|
|
437
|
+
.option('--name <name>', 'Runtime-local display name'),
|
|
352
438
|
body: async (_args, options) => {
|
|
353
|
-
if (typeof options.input === 'string') {
|
|
354
|
-
return (await readJsonFile(options.input));
|
|
355
|
-
}
|
|
356
439
|
return {
|
|
357
440
|
fileId: options.file,
|
|
358
441
|
runtimePath: options.runtimePath,
|
|
@@ -370,12 +453,8 @@ function createRuntimeFileCollectCommand(factory) {
|
|
|
370
453
|
configure: (cmd) => cmd
|
|
371
454
|
.requiredOption('--runtime-path <path>', 'Runtime workspace source')
|
|
372
455
|
.option('--name <name>', 'Durable file name')
|
|
373
|
-
.option('--destination-path <path>', 'Durable BCTRL storage destination')
|
|
374
|
-
.option('--input <path>', 'Read JSON request body from file, or - for stdin'),
|
|
456
|
+
.option('--destination-path <path>', 'Durable BCTRL storage destination'),
|
|
375
457
|
body: async (_args, options) => {
|
|
376
|
-
if (typeof options.input === 'string') {
|
|
377
|
-
return (await readJsonFile(options.input));
|
|
378
|
-
}
|
|
379
458
|
return {
|
|
380
459
|
runtimePath: options.runtimePath,
|
|
381
460
|
name: options.name,
|