@bctrl/cli 0.1.7 → 0.1.9

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.
Files changed (34) hide show
  1. package/README.md +17 -89
  2. package/dist/api/client.d.ts +1 -0
  3. package/dist/api/client.js +1 -0
  4. package/dist/api/errors.js +2 -2
  5. package/dist/bin/bctrl.js +0 -0
  6. package/dist/commands/{vault → account}/index.d.ts +1 -1
  7. package/dist/commands/account/index.js +21 -0
  8. package/dist/commands/ai/index.js +13 -8
  9. package/dist/commands/api-key/index.js +1 -1
  10. package/dist/commands/browser-extension/index.js +8 -8
  11. package/dist/commands/conversation/index.d.ts +3 -0
  12. package/dist/commands/conversation/index.js +51 -0
  13. package/dist/commands/file/index.js +8 -3
  14. package/dist/commands/run/index.js +23 -292
  15. package/dist/commands/runtime/index.js +32 -453
  16. package/dist/commands/shared/operation.d.ts +3 -0
  17. package/dist/commands/shared/operation.js +20 -7
  18. package/dist/commands/space/index.js +0 -25
  19. package/dist/commands/subaccount/index.js +2 -2
  20. package/dist/commands/tool/index.js +15 -5
  21. package/dist/commands/tool-call/index.js +22 -6
  22. package/dist/commands/toolset/index.js +1 -1
  23. package/dist/commands/view/index.d.ts +3 -0
  24. package/dist/commands/view/index.js +26 -0
  25. package/dist/commands/webhook/index.d.ts +3 -0
  26. package/dist/commands/webhook/index.js +64 -0
  27. package/dist/generated/help.d.ts +4896 -5977
  28. package/dist/generated/help.js +6208 -7532
  29. package/dist/generated/openapi-routes.d.ts +114 -142
  30. package/dist/generated/openapi-routes.js +37 -44
  31. package/dist/generated/openapi-types.d.ts +4451 -5302
  32. package/dist/root.js +8 -2
  33. package/package.json +14 -12
  34. package/dist/commands/vault/index.js +0 -171
@@ -1,465 +1,44 @@
1
- import { Command, Option } from 'commander';
2
- import { parseJsonString, readBlob, readJsonFile } from '../shared/io.js';
3
- import { addPaginationFlags, buildOperationInput, createOperationJsonBodyCommand, outputFlags, requestOperationAndPrint, uploadOperationFile, } from '../shared/operation.js';
4
- import { parsePositiveInteger } from '../shared/options.js';
5
- import { addOutputFlags, outputData } from '../shared/output.js';
6
- import { CliError } from '../../runtime/errors.js';
7
- import { addCliOperationHelp } from '../shared/help.js';
1
+ import { Command } from 'commander';
2
+ import { createOperationDeleteCommand, createOperationJsonBodyCommand, createOperationListCommand, createOperationViewCommand, } from '../shared/operation.js';
8
3
  export function createRuntimeCommand(factory) {
9
- const command = new Command('runtime').description('Manage runtimes');
10
- command.addCommand(addOutputFlags(addPaginationFlags(new Command('list').description('List runtimes'))
11
- .option('--space <id>', 'Filter by space id')
12
- .addOption(new Option('--status <status>', 'Filter by runtime status').choices([
13
- 'active',
14
- 'failed',
15
- 'stopped',
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, {
19
- query: {
20
- spaceId: options.space,
21
- status: options.status ? [options.status] : undefined,
22
- limit: options.limit,
23
- cursor: options.cursor,
24
- },
25
- output: outputFlags(options),
26
- }));
4
+ const command = new Command('runtime').description('Manage runtime lifecycle');
5
+ command.addCommand(createOperationListCommand(factory, {
6
+ operationId: 'runtimes.list',
7
+ description: 'List runtimes',
27
8
  }));
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, {
33
- pathParams: { runtimeId },
34
- output: outputFlags(options),
35
- }));
36
- }));
37
- command.addCommand(createRuntimeCreateCommand(factory));
38
- command.addCommand(createRuntimePatchCommand(factory));
39
- command.addCommand(addOutputFlags(new Command('delete')
40
- .description('Delete a runtime and its browser state')
41
- .argument('<runtimeId>')
42
- .option('-y, --yes', 'Confirm deletion')
43
- .option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')).action(async (runtimeId, options) => {
44
- if (options.yes !== true) {
45
- throw new CliError('Refusing to delete without --yes');
46
- }
47
- await requestOperationAndPrint(factory, 'runtimes.delete', await buildOperationInput('runtimes.delete', options, {
48
- pathParams: { runtimeId },
49
- output: outputFlags(options),
50
- }));
51
- }));
52
- command.addCommand(createRuntimeStartCommand(factory));
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, {
58
- pathParams: { runtimeId },
59
- output: outputFlags(options),
60
- }));
61
- }));
62
- command.addCommand(createRuntimeFileCommand(factory));
63
- command.addCommand(createRuntimeInvocationCommand(factory));
64
- command.addCommand(createRuntimeHumanActionCommand(factory));
65
- command.addCommand(createRuntimeTargetCommand(factory));
66
- return command;
67
- }
68
- function createRuntimeTargetCommand(factory) {
69
- const command = new Command('target').description('Manage runtime targets (tabs)');
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, {
75
- pathParams: { runtimeId },
76
- output: outputFlags(options),
77
- }));
78
- }));
79
- command.addCommand(addOutputFlags(new Command('create')
80
- .description('Open a new target')
81
- .argument('<runtimeId>')
82
- .option('--uri <uri>', 'Navigate the new target to this URI')
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, {
87
- pathParams: { runtimeId },
88
- body: {
89
- ...(options.uri ? { uri: options.uri } : {}),
90
- ...(options.activate ? { activate: true } : {}),
91
- },
92
- output: outputFlags(options),
93
- }));
94
- }));
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, {
101
- pathParams: { runtimeId, targetId },
102
- output: outputFlags(options),
103
- }));
104
- }));
105
- command.addCommand(addOutputFlags(new Command('activate')
106
- .description('Focus a target')
107
- .argument('<runtimeId>')
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, {
111
- pathParams: { runtimeId, targetId },
112
- output: outputFlags(options),
113
- }));
114
- }));
115
- command.addCommand(addOutputFlags(new Command('delete')
116
- .description('Close a target')
117
- .argument('<runtimeId>')
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, {
121
- pathParams: { runtimeId, targetId },
122
- output: outputFlags(options),
123
- }));
124
- }));
125
- return command;
126
- }
127
- function createRuntimeCreateCommand(factory) {
128
- return addOutputFlags(addCliOperationHelp(new Command('create')
129
- .description('Create a runtime')
130
- .option('--space <id>', 'Space id; omitted uses caller default space')
131
- .option('--name <name>', 'Runtime name')
132
- .option('--profile', 'Persist browser state across runtime starts')
133
- .option('--proxy <id-or-url>', 'Saved proxy id or inline custom proxy URL')
134
- .addOption(new Option('--device <device>', 'Fingerprint device filter').choices([
135
- 'desktop',
136
- 'mobile',
137
- ]))
138
- .addOption(new Option('--os <os>', 'Fingerprint OS filter').choices([
139
- 'windows',
140
- 'macos',
141
- 'android',
142
- 'ios',
143
- ]))
144
- .addOption(new Option('--browser <browser>', 'Fingerprint browser filter').choices([
145
- 'chrome',
146
- 'edge',
147
- 'safari',
148
- ]))
149
- .option('--browser-version <version>', 'Fingerprint browser version filter')
150
- .option('--locale <locale>', 'Fingerprint locale/language filter; repeat to set an ordered language stack', collectLocale, [])
151
- .option('--config-file <path>', 'Runtime config JSON file')
152
- .option('--metadata-file <path>', 'Runtime metadata JSON file')
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.
158
- const config = typeof options.configFile === 'string'
159
- ? await readJsonFile(options.configFile, '--config-file')
160
- : undefined;
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
- },
171
- output: outputFlags(options),
172
- }));
173
- });
174
- }
175
- function collectLocale(value, previous) {
176
- return [...previous, value];
177
- }
178
- function isRecord(value) {
179
- return value !== null && typeof value === 'object' && !Array.isArray(value);
180
- }
181
- function buildRuntimeCreateConfig(config, options) {
182
- const fingerprint = {
183
- ...(options.device ? { device: options.device } : {}),
184
- ...(options.os ? { os: options.os } : {}),
185
- ...(options.browser ? { browser: options.browser } : {}),
186
- ...(options.browserVersion ? { browserVersion: options.browserVersion } : {}),
187
- ...(options.locale && options.locale.length === 1 ? { locale: options.locale[0] } : {}),
188
- ...(options.locale && options.locale.length > 1 ? { locale: options.locale } : {}),
189
- };
190
- const overrides = {
191
- ...(options.profile === true ? { profile: true } : {}),
192
- ...(options.proxy ? { proxy: options.proxy } : {}),
193
- ...(Object.keys(fingerprint).length > 0 ? { fingerprint } : {}),
194
- };
195
- if (Object.keys(overrides).length === 0) {
196
- return config;
197
- }
198
- if (config !== undefined && !isRecord(config)) {
199
- throw new Error('--config-file must contain a JSON object when combined with runtime flags');
200
- }
201
- if (!isRecord(config)) {
202
- return overrides;
203
- }
204
- return {
205
- ...config,
206
- ...overrides,
207
- ...(isRecord(config.fingerprint) || 'fingerprint' in overrides
208
- ? {
209
- fingerprint: {
210
- ...(isRecord(config.fingerprint) ? config.fingerprint : {}),
211
- ...(isRecord(overrides.fingerprint) ? overrides.fingerprint : {}),
212
- },
213
- }
214
- : {}),
215
- };
216
- }
217
- function createRuntimePatchCommand(factory) {
218
- return addOutputFlags(new Command('patch')
219
- .description('Update a runtime')
220
- .argument('<runtimeId>')
221
- .option('--name <name>', 'Runtime name')
222
- .option('--idle-timeout-seconds <seconds>', 'Idle timeout in seconds', parsePositiveInteger)
223
- .option('--config-file <path>', 'Runtime config JSON file')
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, {
227
- pathParams: { runtimeId },
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
- },
235
- output: outputFlags(options),
236
- }));
237
- });
238
- }
239
- function createRuntimeStartCommand(factory) {
240
- return addOutputFlags(new Command('start')
241
- .description('Start a runtime')
242
- .argument('<runtimeId>')
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, {
246
- pathParams: { runtimeId },
247
- idempotencyKey: options.idempotencyKey,
248
- output: outputFlags(options),
249
- }));
250
- });
251
- }
252
- function createRuntimeInvocationCommand(factory) {
253
- const command = new Command('invocation').description('Create, wait for, and cancel invocations');
254
- command.addCommand(createRuntimeInvocationCreateCommand(factory));
255
- command.addCommand(createRuntimeInvocationWaitCommand(factory));
256
- command.addCommand(addOutputFlags(new Command('cancel')
257
- .description('Cancel an invocation')
258
- .argument('<runtimeId>')
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, {
262
- pathParams: { runtimeId, invocationId },
263
- output: outputFlags(options),
264
- }));
265
- }));
266
- return command;
267
- }
268
- function createRuntimeInvocationCreateCommand(factory) {
269
- return addOutputFlags(new Command('create')
270
- .description('Create a runtime invocation')
271
- .argument('<runtimeId>')
272
- .option('--action <action>', 'Invocation action')
273
- .option('--instruction <text>', 'Instruction for action/agent invocations')
274
- .option('--target <target>', "Target to act on: 'active' (default), 'new', or a target id")
275
- .option('--model <model>', 'Model id')
276
- .option('--tool <id...>', 'Inline tool id')
277
- .option('--toolset <id>', 'Toolset id')
278
- .option('--timeout-seconds <seconds>', 'Invocation timeout in seconds', parsePositiveInteger)
279
- .option('--idempotency-key <key>', 'Idempotency key for retry-safe 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, {
296
- pathParams: { runtimeId },
297
- body: body,
298
- idempotencyKey: options.idempotencyKey,
299
- output: outputFlags(options),
300
- }));
301
- });
302
- }
303
- function createRuntimeInvocationWaitCommand(factory) {
304
- return createOperationJsonBodyCommand(factory, {
305
- operationId: 'runtimes.invocations.wait',
306
- name: 'wait',
307
- description: 'Wait for an invocation',
308
- argNames: ['runtimeId', 'invocationId'],
309
- configure: (cmd) => cmd
310
- .option('--timeout-seconds <seconds>', 'Wait timeout in seconds', parsePositiveInteger),
311
- body: async (_args, options) => {
312
- return {
313
- timeoutSeconds: options.timeoutSeconds,
314
- };
315
- },
316
- });
317
- }
318
- function createRuntimeHumanActionCommand(factory) {
319
- const command = new Command('human-action').description('Manage runtime human actions');
320
9
  command.addCommand(createOperationJsonBodyCommand(factory, {
321
- operationId: 'runtimes.human-actions.create',
10
+ operationId: 'runtimes.create',
322
11
  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
- },
12
+ description: 'Create a runtime',
334
13
  }));
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
- }));
14
+ command.addCommand(createOperationViewCommand(factory, {
15
+ operationId: 'runtimes.get',
16
+ name: 'get',
17
+ description: 'Get a runtime',
18
+ argName: 'runtimeId',
343
19
  }));
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
- }));
20
+ command.addCommand(createOperationJsonBodyCommand(factory, {
21
+ operationId: 'runtimes.update',
22
+ name: 'patch',
23
+ description: 'Update a runtime',
24
+ argNames: ['runtimeId'],
352
25
  }));
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
- }));
26
+ command.addCommand(createOperationDeleteCommand(factory, {
27
+ operationId: 'runtimes.delete',
28
+ description: 'Delete a runtime',
29
+ argNames: ['runtimeId'],
361
30
  }));
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
- }));
31
+ command.addCommand(createOperationJsonBodyCommand(factory, {
32
+ operationId: 'runtimes.start',
33
+ name: 'start',
34
+ description: 'Start a runtime',
35
+ argNames: ['runtimeId'],
375
36
  }));
376
- return command;
377
- }
378
- function createRuntimeFileCommand(factory) {
379
- const command = new Command('file').description('Move files into and out of runtimes');
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, {
384
- pathParams: { runtimeId },
385
- query: {
386
- type: options.type,
387
- limit: options.limit,
388
- cursor: options.cursor,
389
- },
390
- output: outputFlags(options),
391
- }));
37
+ command.addCommand(createOperationJsonBodyCommand(factory, {
38
+ operationId: 'runtimes.stop',
39
+ name: 'stop',
40
+ description: 'Stop a runtime',
41
+ argNames: ['runtimeId'],
392
42
  }));
393
- command.addCommand(createRuntimeFileUploadCommand(factory));
394
- command.addCommand(createRuntimeFileStageCommand(factory));
395
- command.addCommand(createRuntimeFileCollectCommand(factory));
396
43
  return command;
397
44
  }
398
- function createRuntimeFileUploadCommand(factory) {
399
- return addOutputFlags(new Command('upload')
400
- .description('Upload a local file into a runtime workspace')
401
- .argument('<runtimeId>')
402
- .argument('<localPath>')
403
- .option('--destination-path <path>', 'Durable BCTRL storage destination')
404
- .option('--runtime-path <path>', 'Runtime workspace destination')
405
- .option('--name <name>', 'Display name')
406
- .option('--metadata <json>', 'Metadata as inline JSON (overrides --metadata-file)')
407
- .option('--metadata-file <path>', 'Metadata JSON file')).action(async (runtimeId, localPath, options) => {
408
- const file = await readBlob(localPath);
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;
414
- const result = await uploadOperationFile(factory, 'runtimes.files.upload', {
415
- pathParams: { runtimeId },
416
- file: file.blob,
417
- fileName: options.name ?? file.fileName,
418
- fields: {
419
- ...(options.destinationPath ? { destinationPath: options.destinationPath } : {}),
420
- ...(options.runtimePath ? { runtimePath: options.runtimePath } : {}),
421
- ...(options.name ? { name: options.name } : {}),
422
- ...(metadata ? { metadata } : {}),
423
- },
424
- });
425
- await outputData(factory.io, result, options);
426
- });
427
- }
428
- function createRuntimeFileStageCommand(factory) {
429
- return createOperationJsonBodyCommand(factory, {
430
- operationId: 'runtimes.files.stage',
431
- name: 'stage',
432
- description: 'Stage a durable file into a runtime',
433
- argNames: ['runtimeId'],
434
- configure: (cmd) => cmd
435
- .option('--file <id>', 'Durable file id')
436
- .option('--runtime-path <path>', 'Runtime workspace destination')
437
- .option('--name <name>', 'Runtime-local display name'),
438
- body: async (_args, options) => {
439
- return {
440
- fileId: options.file,
441
- runtimePath: options.runtimePath,
442
- name: options.name,
443
- };
444
- },
445
- });
446
- }
447
- function createRuntimeFileCollectCommand(factory) {
448
- return createOperationJsonBodyCommand(factory, {
449
- operationId: 'runtimes.files.collect',
450
- name: 'collect',
451
- description: 'Collect a runtime-local file into durable storage',
452
- argNames: ['runtimeId'],
453
- configure: (cmd) => cmd
454
- .requiredOption('--runtime-path <path>', 'Runtime workspace source')
455
- .option('--name <name>', 'Durable file name')
456
- .option('--destination-path <path>', 'Durable BCTRL storage destination'),
457
- body: async (_args, options) => {
458
- return {
459
- runtimePath: options.runtimePath,
460
- name: options.name,
461
- destinationPath: options.destinationPath,
462
- };
463
- },
464
- });
465
- }
@@ -43,6 +43,7 @@ type OperationBodyInput<OperationId extends CliOperationId> = [
43
43
  export type OperationRequestInput<OperationId extends CliOperationId> = OperationPathInput<OperationId> & OperationQueryInput<OperationId> & OperationBodyInput<OperationId> & {
44
44
  idempotencyKey?: string;
45
45
  actingSubaccountId?: string;
46
+ runtimeId?: string;
46
47
  output?: OutputFlags;
47
48
  };
48
49
  export declare function optionString(options: Record<string, unknown>, name: string): string | undefined;
@@ -94,6 +95,7 @@ export declare function streamOperationText<OperationId extends CliOperationId>(
94
95
  export declare function createOperationListCommand<OperationId extends CliOperationId>(factory: ApiDeps, config: {
95
96
  operationId: OperationId;
96
97
  name?: string;
98
+ argNames?: string[];
97
99
  description: string;
98
100
  configure?: (command: Command) => Command;
99
101
  query?: (options: Record<string, unknown>) => CliOperationQuery<OperationId>;
@@ -126,5 +128,6 @@ export declare function createOperationJsonBodyCommand<OperationId extends CliOp
126
128
  body?: (args: Record<string, string>, options: Record<string, unknown>) => Promise<CliOperationJsonBody<OperationId>>;
127
129
  query?: (args: Record<string, string>, options: Record<string, unknown>) => CliOperationQuery<OperationId>;
128
130
  actingSubaccountId?: (args: Record<string, string>, options: Record<string, unknown>) => string | undefined;
131
+ runtimeId?: (args: Record<string, string>, options: Record<string, unknown>) => string | undefined;
129
132
  }): Command;
130
133
  export {};
@@ -122,6 +122,8 @@ export async function buildOperationInput(operationId, options, curated) {
122
122
  merged.idempotencyKey = c.idempotencyKey;
123
123
  if (c.actingSubaccountId)
124
124
  merged.actingSubaccountId = c.actingSubaccountId;
125
+ if (c.runtimeId)
126
+ merged.runtimeId = c.runtimeId;
125
127
  if (c.output)
126
128
  merged.output = c.output;
127
129
  return merged;
@@ -171,6 +173,7 @@ export async function requestOperation(deps, operationId, input) {
171
173
  ...('body' in input && input.body !== undefined ? { body: input.body } : {}),
172
174
  ...(input.idempotencyKey ? { idempotencyKey: input.idempotencyKey } : {}),
173
175
  ...(input.actingSubaccountId ? { actingSubaccountId: input.actingSubaccountId } : {}),
176
+ ...(input.runtimeId ? { runtimeId: input.runtimeId } : {}),
174
177
  };
175
178
  const options = Object.keys(requestOptions).length > 0 ? requestOptions : undefined;
176
179
  const result = route.method === 'get'
@@ -179,9 +182,7 @@ export async function requestOperation(deps, operationId, input) {
179
182
  ? await client.post(path, options)
180
183
  : route.method === 'patch'
181
184
  ? await client.patch(path, options)
182
- : route.method === 'put'
183
- ? await client.put(path, options)
184
- : await client.delete(path, options);
185
+ : await client.delete(path, options);
185
186
  return result;
186
187
  }
187
188
  export async function uploadOperationFile(deps, operationId, input) {
@@ -208,17 +209,26 @@ export async function streamOperationText(deps, operationId, input) {
208
209
  });
209
210
  }
210
211
  export function createOperationListCommand(factory, config) {
212
+ const argNames = config.argNames ?? [];
211
213
  let command = new Command(config.name ?? 'list').description(config.description);
212
214
  command = addCliOperationHelp(command, config.operationId);
215
+ for (const arg of argNames)
216
+ command = command.argument(`<${arg}>`);
213
217
  command = config.configure ? config.configure(command) : addPaginationFlags(command);
214
218
  command = addRequestOverrideFlags(command);
215
219
  command = addOutputFlags(command);
216
- return command.action(async (options) => {
220
+ return command.action(async (...actionArgs) => {
221
+ const options = getActionOptions(actionArgs);
222
+ const args = {};
223
+ for (let i = 0; i < argNames.length; i += 1)
224
+ args[argNames[i]] = String(actionArgs[i]);
217
225
  const overrides = await resolveRequestOverrides(config.operationId, options);
218
226
  const curatedQuery = config.query ? config.query(options) : defaultListQuery(options);
219
227
  const actingSubaccountId = config.actingSubaccountId?.(options);
220
228
  await requestOperationAndPrint(factory, config.operationId, withActingSubaccount({
221
- ...(overrides.pathParams ? { pathParams: overrides.pathParams } : {}),
229
+ ...(argNames.length > 0 || overrides.pathParams
230
+ ? { pathParams: overlayDefined(overrides.pathParams, args) }
231
+ : {}),
222
232
  query: overlayDefined(overrides.query, curatedQuery),
223
233
  output: outputFlags(options),
224
234
  }, actingSubaccountId));
@@ -293,12 +303,15 @@ export function createOperationJsonBodyCommand(factory, config) {
293
303
  const body = overrides.body !== undefined ? overrides.body : (curatedBody ?? {});
294
304
  const curatedQuery = config.query ? config.query(args, options) : undefined;
295
305
  const actingSubaccountId = config.actingSubaccountId?.(args, options);
296
- await requestOperationAndPrint(factory, config.operationId, withActingSubaccount({
306
+ const runtimeId = config.runtimeId?.(args, options);
307
+ const requestInput = withActingSubaccount({
297
308
  pathParams: overlayDefined(overrides.pathParams, args),
298
309
  body,
299
310
  query: overlayDefined(overrides.query, curatedQuery),
300
311
  output: outputFlags(options),
301
- }, actingSubaccountId));
312
+ ...(runtimeId ? { runtimeId } : {}),
313
+ }, actingSubaccountId);
314
+ await requestOperationAndPrint(factory, config.operationId, requestInput);
302
315
  });
303
316
  }
304
317
  function defaultListQuery(options) {
@@ -54,30 +54,5 @@ export function createSpaceCommand(factory) {
54
54
  output: outputFlags(options),
55
55
  }));
56
56
  }));
57
- command.addCommand(createSpaceEnvironmentCommand(factory));
58
- return command;
59
- }
60
- function createSpaceEnvironmentCommand(factory) {
61
- const command = new Command('env').description('Manage a space environment');
62
- command.addCommand(addOutputFlags(new Command('get')
63
- .description('Get a space environment')
64
- .argument('<spaceId>')
65
- .option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')).action(async (spaceId, options) => {
66
- await requestOperationAndPrint(factory, 'spaces.environment.get', await buildOperationInput('spaces.environment.get', options, {
67
- pathParams: { spaceId },
68
- output: outputFlags(options),
69
- }));
70
- }));
71
- command.addCommand(addOutputFlags(new Command('patch')
72
- .description('Update a space environment')
73
- .argument('<spaceId>')
74
- .option('--params <json>', 'Path/query parameters as a JSON object (inline, @file, or - for stdin)')
75
- .option('--body <json>', 'Request body as JSON (inline, @file, or - for stdin)')).action(async (spaceId, options) => {
76
- await requestOperationAndPrint(factory, 'spaces.environment.update', await buildOperationInput('spaces.environment.update', options, {
77
- pathParams: { spaceId },
78
- body: {},
79
- output: outputFlags(options),
80
- }));
81
- }));
82
57
  return command;
83
58
  }
@@ -14,13 +14,13 @@ export function createSubaccountCommand(factory) {
14
14
  include: options.includeUsage === true ? 'usage' : undefined,
15
15
  status: typeof options.status === 'string' ? options.status : undefined,
16
16
  externalId: typeof options.externalId === 'string' ? options.externalId : undefined,
17
- query: typeof options.query === 'string' ? options.query : undefined,
17
+ q: typeof options.q === 'string' ? options.q : undefined,
18
18
  }),
19
19
  configure: (cmd) => addPaginationFlags(cmd)
20
20
  .option('--include-usage', 'Inline current usage')
21
21
  .option('--status <status>', 'Filter by status')
22
22
  .option('--external-id <id>', 'Filter by external id')
23
- .option('--query <text>', 'Search by id, name, or external id'),
23
+ .option('--q <text>', 'Search by id, name, or external id'),
24
24
  }));
25
25
  command.addCommand(createOperationViewCommand(factory, {
26
26
  operationId: 'subaccounts.get',