bdy 1.25.13-dev → 1.25.14-dev

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 (177) hide show
  1. package/distTs/package.json +1 -1
  2. package/distTs/src/agent/manager.js +19 -6
  3. package/distTs/src/agent/system.js +9 -4
  4. package/distTs/src/api/client.js +20 -7
  5. package/distTs/src/cliCommand.js +17 -1
  6. package/distTs/src/cliIndex.js +12 -2
  7. package/distTs/src/command/agent/debug.js +4 -3
  8. package/distTs/src/command/agent/disable.js +4 -3
  9. package/distTs/src/command/agent/enable.js +4 -3
  10. package/distTs/src/command/agent/install.js +28 -12
  11. package/distTs/src/command/agent/proxy/disable.js +4 -3
  12. package/distTs/src/command/agent/proxy/enable.js +4 -3
  13. package/distTs/src/command/agent/proxy/status.js +1 -1
  14. package/distTs/src/command/agent/restart.js +13 -5
  15. package/distTs/src/command/agent/start.js +11 -4
  16. package/distTs/src/command/agent/status.js +1 -1
  17. package/distTs/src/command/agent/stop.js +5 -4
  18. package/distTs/src/command/agent/tags/get.js +1 -1
  19. package/distTs/src/command/agent/tags/set.js +4 -3
  20. package/distTs/src/command/agent/target/disable.js +4 -3
  21. package/distTs/src/command/agent/target/enable.js +4 -3
  22. package/distTs/src/command/agent/target/status.js +1 -1
  23. package/distTs/src/command/agent/tunnel/disable.js +4 -3
  24. package/distTs/src/command/agent/tunnel/enable.js +4 -3
  25. package/distTs/src/command/agent/tunnel/http.js +10 -2
  26. package/distTs/src/command/agent/tunnel/list.js +1 -1
  27. package/distTs/src/command/agent/tunnel/remove.js +4 -3
  28. package/distTs/src/command/agent/tunnel/start.js +9 -5
  29. package/distTs/src/command/agent/tunnel/status.js +1 -1
  30. package/distTs/src/command/agent/tunnel/tcp.js +10 -2
  31. package/distTs/src/command/agent/tunnel/tls.js +10 -2
  32. package/distTs/src/command/agent/uninstall.js +6 -4
  33. package/distTs/src/command/agent/update.js +13 -5
  34. package/distTs/src/command/agent/user.js +4 -3
  35. package/distTs/src/command/agent/version.js +1 -1
  36. package/distTs/src/command/api/info.js +5 -3
  37. package/distTs/src/command/api/list.js +1 -0
  38. package/distTs/src/command/artifact/composer/publish.js +21 -16
  39. package/distTs/src/command/artifact/delete.js +8 -5
  40. package/distTs/src/command/artifact/docker/login.js +22 -5
  41. package/distTs/src/command/artifact/download.js +16 -15
  42. package/distTs/src/command/artifact/get.js +3 -2
  43. package/distTs/src/command/artifact/open.js +3 -2
  44. package/distTs/src/command/artifact/publish.js +3 -2
  45. package/distTs/src/command/artifact/version/create.js +3 -2
  46. package/distTs/src/command/artifact/version/delete.js +9 -6
  47. package/distTs/src/command/artifact/version/get.js +4 -3
  48. package/distTs/src/command/artifact/version/list.js +3 -2
  49. package/distTs/src/command/artifact/version/open.js +7 -6
  50. package/distTs/src/command/config/add/http.js +3 -2
  51. package/distTs/src/command/config/add/tcp.js +3 -2
  52. package/distTs/src/command/config/add/tls.js +3 -2
  53. package/distTs/src/command/config/get/region.js +5 -2
  54. package/distTs/src/command/config/get/timeout.js +5 -2
  55. package/distTs/src/command/config/get/token.js +5 -2
  56. package/distTs/src/command/config/get/tunnel.js +3 -2
  57. package/distTs/src/command/config/get/tunnels.js +1 -1
  58. package/distTs/src/command/config/get/whitelist.js +5 -2
  59. package/distTs/src/command/config/remove/token.js +4 -3
  60. package/distTs/src/command/config/remove/tunnel.js +6 -4
  61. package/distTs/src/command/config/set/region.js +4 -3
  62. package/distTs/src/command/config/set/timeout.js +4 -3
  63. package/distTs/src/command/config/set/token.js +5 -3
  64. package/distTs/src/command/config/set/whitelist.js +4 -3
  65. package/distTs/src/command/crawl/link.js +10 -4
  66. package/distTs/src/command/crawl/run.js +30 -18
  67. package/distTs/src/command/distro/delete.js +8 -5
  68. package/distTs/src/command/distro/get.js +3 -2
  69. package/distTs/src/command/distro/open.js +3 -2
  70. package/distTs/src/command/distro/route/create.js +3 -2
  71. package/distTs/src/command/distro/route/delete.js +8 -5
  72. package/distTs/src/command/distro/route/get.js +3 -2
  73. package/distTs/src/command/distro/route/list.js +3 -2
  74. package/distTs/src/command/distro/route/open.js +3 -2
  75. package/distTs/src/command/distro/route/update.js +3 -2
  76. package/distTs/src/command/distro/update.js +3 -2
  77. package/distTs/src/command/domain/buy.js +36 -17
  78. package/distTs/src/command/domain/get.js +3 -2
  79. package/distTs/src/command/domain/list.js +1 -1
  80. package/distTs/src/command/domain/open.js +4 -2
  81. package/distTs/src/command/domain/search.js +1 -0
  82. package/distTs/src/command/environment/create.js +1 -1
  83. package/distTs/src/command/environment/delete.js +6 -4
  84. package/distTs/src/command/environment/get.js +1 -0
  85. package/distTs/src/command/environment/list.js +1 -1
  86. package/distTs/src/command/environment/open.js +3 -1
  87. package/distTs/src/command/environment/update.js +1 -1
  88. package/distTs/src/command/login.js +29 -17
  89. package/distTs/src/command/logout.js +4 -3
  90. package/distTs/src/command/pipeline/create.js +13 -3
  91. package/distTs/src/command/pipeline/delete.js +9 -6
  92. package/distTs/src/command/pipeline/get.js +4 -3
  93. package/distTs/src/command/pipeline/open.js +2 -1
  94. package/distTs/src/command/pipeline/run/execution.js +3 -3
  95. package/distTs/src/command/pipeline/run/list.js +4 -3
  96. package/distTs/src/command/pipeline/run/open.js +2 -1
  97. package/distTs/src/command/pipeline/update.js +4 -3
  98. package/distTs/src/command/pipeline/yaml.js +4 -3
  99. package/distTs/src/command/project/link.js +74 -36
  100. package/distTs/src/command/project/list.js +1 -0
  101. package/distTs/src/command/project/open.js +3 -1
  102. package/distTs/src/command/register.js +2 -1
  103. package/distTs/src/command/sandbox/app/add.js +1 -0
  104. package/distTs/src/command/sandbox/app/list.js +1 -1
  105. package/distTs/src/command/sandbox/app/logs.js +1 -1
  106. package/distTs/src/command/sandbox/app/remove.js +4 -3
  107. package/distTs/src/command/sandbox/app/start.js +4 -3
  108. package/distTs/src/command/sandbox/app/status.js +3 -2
  109. package/distTs/src/command/sandbox/app/stop.js +4 -3
  110. package/distTs/src/command/sandbox/cp.js +23 -23
  111. package/distTs/src/command/sandbox/create.js +3 -1
  112. package/distTs/src/command/sandbox/destroy.js +6 -4
  113. package/distTs/src/command/sandbox/endpoint/add.js +1 -1
  114. package/distTs/src/command/sandbox/endpoint/delete.js +9 -6
  115. package/distTs/src/command/sandbox/endpoint/get.js +3 -2
  116. package/distTs/src/command/sandbox/endpoint/list.js +1 -1
  117. package/distTs/src/command/sandbox/exec/command.js +1 -0
  118. package/distTs/src/command/sandbox/exec/kill.js +7 -5
  119. package/distTs/src/command/sandbox/exec/list.js +1 -1
  120. package/distTs/src/command/sandbox/exec/logs.js +1 -1
  121. package/distTs/src/command/sandbox/exec/status.js +1 -1
  122. package/distTs/src/command/sandbox/get.js +1 -1
  123. package/distTs/src/command/sandbox/list.js +1 -1
  124. package/distTs/src/command/sandbox/logs.js +1 -1
  125. package/distTs/src/command/sandbox/open.js +3 -1
  126. package/distTs/src/command/sandbox/restart.js +9 -4
  127. package/distTs/src/command/sandbox/snapshot/create.js +1 -1
  128. package/distTs/src/command/sandbox/snapshot/delete.js +8 -5
  129. package/distTs/src/command/sandbox/snapshot/get.js +3 -2
  130. package/distTs/src/command/sandbox/snapshot/list.js +1 -1
  131. package/distTs/src/command/sandbox/snapshot/open.js +4 -2
  132. package/distTs/src/command/sandbox/ssh.js +1 -0
  133. package/distTs/src/command/sandbox/start.js +9 -4
  134. package/distTs/src/command/sandbox/status.js +1 -1
  135. package/distTs/src/command/sandbox/stop.js +9 -4
  136. package/distTs/src/command/sandbox/update.js +12 -6
  137. package/distTs/src/command/sandbox/yaml.js +1 -1
  138. package/distTs/src/command/target/create.js +1 -0
  139. package/distTs/src/command/target/delete.js +6 -3
  140. package/distTs/src/command/target/exec/command.js +1 -1
  141. package/distTs/src/command/target/exec/kill.js +6 -4
  142. package/distTs/src/command/target/exec/list.js +1 -1
  143. package/distTs/src/command/target/exec/logs.js +1 -1
  144. package/distTs/src/command/target/exec/status.js +1 -1
  145. package/distTs/src/command/target/get.js +1 -0
  146. package/distTs/src/command/target/list.js +1 -0
  147. package/distTs/src/command/target/open.js +3 -1
  148. package/distTs/src/command/target/scope.js +4 -4
  149. package/distTs/src/command/target/update.js +1 -0
  150. package/distTs/src/command/tests/capture.js +10 -7
  151. package/distTs/src/command/tests/unit/link.js +10 -4
  152. package/distTs/src/command/tests/visual/link.js +10 -4
  153. package/distTs/src/command/tests/visual/session/close.js +8 -3
  154. package/distTs/src/command/tests/visual/setup.js +6 -3
  155. package/distTs/src/command/tests/visual/upload.js +11 -8
  156. package/distTs/src/command/tunnel/http.js +6 -2
  157. package/distTs/src/command/tunnel/start.js +8 -3
  158. package/distTs/src/command/tunnel/tcp.js +6 -3
  159. package/distTs/src/command/tunnel/tls.js +6 -3
  160. package/distTs/src/command/version.js +24 -2
  161. package/distTs/src/command/whoami.js +1 -1
  162. package/distTs/src/command/workspace/get.js +7 -2
  163. package/distTs/src/command/workspace/list.js +1 -1
  164. package/distTs/src/command/workspace/open.js +4 -2
  165. package/distTs/src/command/workspace/set.js +4 -3
  166. package/distTs/src/command/yaml/actions/info.js +1 -1
  167. package/distTs/src/command/yaml/actions/list.js +1 -1
  168. package/distTs/src/command/yaml/pipeline.js +1 -0
  169. package/distTs/src/command/yaml/validate.js +1 -0
  170. package/distTs/src/discovery.js +169 -50
  171. package/distTs/src/input.js +6 -6
  172. package/distTs/src/output.js +72 -33
  173. package/distTs/src/texts.js +103 -42
  174. package/distTs/src/tunnel/output/noninteractive/tunnelJsonl.js +62 -0
  175. package/distTs/src/utils.js +19 -0
  176. package/distTs/src/visualTest/browser.js +3 -2
  177. package/package.json +1 -1
@@ -6,6 +6,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.discoverCommands = exports.describeCommand = void 0;
7
7
  const cliCommand_1 = __importDefault(require("./cliCommand"));
8
8
  const texts_1 = require("./texts");
9
+ // An option defined identically on at least this many commands is described
10
+ // once in shared_options and referenced by key from each command. --format
11
+ // always stays in options: its choices are where json and jsonl get mixed up.
12
+ const SHARED_OPTION_MIN_USES = 20;
9
13
  const sortedChildren = (command) => command
10
14
  .createHelp()
11
15
  .visibleCommands(command)
@@ -15,6 +19,14 @@ const sortedChildren = (command) => command
15
19
  const commandPath = (command) => command.parent
16
20
  ? `${commandPath(command.parent)} ${command.name()}`
17
21
  : command.name() || 'bdy';
22
+ // Drops null, false, empty-string and empty-array fields: absent means "not set" and keeps
23
+ // the catalog small. required_scopes is built outside this, since null there
24
+ // means "undocumented".
25
+ const compact = (value) => Object.fromEntries(Object.entries(value).filter(([, field]) => field !== null &&
26
+ field !== undefined &&
27
+ field !== false &&
28
+ field !== '' &&
29
+ !(Array.isArray(field) && field.length === 0)));
18
30
  const optionInfo = (option) => {
19
31
  const value = option.flags.match(/[<[]([^>\]]+)[>\]]/)?.[1] ?? null;
20
32
  // These are static documentation, never resolved values from opts(), env or config.
@@ -27,59 +39,162 @@ const optionInfo = (option) => {
27
39
  /^[A-Za-z][A-Za-z0-9_-]*(?:\|[A-Za-z][A-Za-z0-9_-]*)+$/.test(value)
28
40
  ? value.split('|')
29
41
  : null);
30
- return {
42
+ return compact({
31
43
  flags: option.flags,
32
44
  short: option.short ?? null,
33
45
  long: option.long ?? null,
34
46
  description: option.description,
35
47
  required: option.mandatory,
36
48
  value: value
37
- ? {
49
+ ? compact({
38
50
  name: value,
39
51
  required: option.required,
40
52
  variadic: !!option.variadic,
41
- }
53
+ })
42
54
  : null,
43
55
  negated: option.negate,
44
56
  choices,
45
57
  default: option.defaultValue ?? null,
46
58
  documented_default: documentedDefault,
47
59
  env,
60
+ });
61
+ };
62
+ const globalOptions = (program) => program.createHelp().visibleOptions(program).map(optionInfo);
63
+ // Options of a command as shown in its help, minus --help and the options
64
+ // every command inherits from global_options.
65
+ const localOptions = (command, globals) => command
66
+ .createHelp()
67
+ .visibleOptions(command)
68
+ .filter((option) => option.long !== '--help')
69
+ .map(optionInfo)
70
+ .filter((info) => !globals.has(JSON.stringify(info)));
71
+ const allCommands = (command) => [
72
+ command,
73
+ ...sortedChildren(command).flatMap(allCommands),
74
+ ];
75
+ // Stable keys for options repeated across the whole tree: the long name, plus
76
+ // a counter for other variants of the same option with a different description.
77
+ const buildSharedOptions = (program, globals) => {
78
+ const uses = new Map();
79
+ for (const command of allCommands(program).slice(1)) {
80
+ for (const info of localOptions(command, globals)) {
81
+ const key = JSON.stringify(info);
82
+ const entry = uses.get(key) ?? { info, count: 0 };
83
+ entry.count += 1;
84
+ uses.set(key, entry);
85
+ }
86
+ }
87
+ const frequent = [...uses.entries()]
88
+ .filter(([, { info, count }]) => count >= SHARED_OPTION_MIN_USES && info.long !== '--format')
89
+ .sort(([a, x], [b, y]) => y.count - x.count || (a < b ? -1 : 1));
90
+ const keys = new Map();
91
+ const taken = new Set();
92
+ for (const [json, { info }] of frequent) {
93
+ const base = (info.long ?? info.short ?? info.flags ?? '').replace(/^-+/, '');
94
+ let key = base;
95
+ for (let n = 2; taken.has(key); n += 1)
96
+ key = `${base}-${n}`;
97
+ taken.add(key);
98
+ keys.set(json, key);
99
+ }
100
+ return keys;
101
+ };
102
+ const splitOptions = (command, catalog) => {
103
+ const own = [];
104
+ const shared = [];
105
+ for (const info of localOptions(command, catalog.globals)) {
106
+ const key = catalog.shared?.get(JSON.stringify(info));
107
+ if (key)
108
+ shared.push(key);
109
+ else
110
+ own.push(info);
111
+ }
112
+ return { own, shared };
113
+ };
114
+ const requiredScopes = (command) => command instanceof cliCommand_1.default ? command.requiredScopes : null;
115
+ const examplesOf = (command) => command instanceof cliCommand_1.default ? command.examples : [];
116
+ const commandDetails = (command, catalog) => {
117
+ const { own, shared } = splitOptions(command, catalog);
118
+ return {
119
+ ...compact({
120
+ command: commandPath(command),
121
+ aliases: command.aliases(),
122
+ description: command.description(),
123
+ usage: `${commandPath(command)} ${command.usage()}`.trim(),
124
+ arguments: command.registeredArguments.map((argument) => compact({
125
+ name: argument.name(),
126
+ description: argument.description,
127
+ required: argument.required,
128
+ variadic: argument.variadic,
129
+ choices: argument.argChoices ?? null,
130
+ default: argument.defaultValue ?? null,
131
+ })),
132
+ options: own,
133
+ shared_options: shared,
134
+ }),
135
+ required_scopes: requiredScopes(command),
136
+ ...compact({ examples: examplesOf(command) }),
48
137
  };
49
138
  };
50
- const describeCommand = (command) => ({
51
- command: commandPath(command),
52
- aliases: command.aliases(),
53
- description: command.description(),
54
- usage: `${commandPath(command)} ${command.usage()}`.trim(),
55
- arguments: command.registeredArguments.map((argument) => ({
56
- name: argument.name(),
57
- description: argument.description,
58
- required: argument.required,
59
- variadic: argument.variadic,
60
- choices: argument.argChoices ?? null,
61
- default: argument.defaultValue ?? null,
62
- })),
63
- options: command
64
- .createHelp()
65
- .visibleOptions(command)
66
- .filter((option) => option.long !== '--help')
67
- .map(optionInfo),
68
- required_scopes: command instanceof cliCommand_1.default ? command.requiredScopes : null,
69
- examples: command instanceof cliCommand_1.default ? command.examples : [],
70
- });
139
+ /** Full details of one command, self-contained: no shared_options references. */
140
+ const describeCommand = (command) => {
141
+ let root = command;
142
+ while (root.parent)
143
+ root = root.parent;
144
+ // a detached command has no root of its own: use the options every
145
+ // CliCommand gets
146
+ const globals = globalOptions(root === command ? new cliCommand_1.default('bdy') : root)
147
+ .map((info) => JSON.stringify(info));
148
+ return commandDetails(command, { globals: new Set(globals) });
149
+ };
71
150
  exports.describeCommand = describeCommand;
72
- const describeTree = (command) => ({
73
- ...(0, exports.describeCommand)(command),
74
- subcommands: sortedChildren(command).map(describeTree),
151
+ const describeTree = (command, catalog) => ({
152
+ ...commandDetails(command, catalog),
153
+ ...compact({
154
+ subcommands: sortedChildren(command).map((child) => describeTree(child, catalog)),
155
+ }),
75
156
  });
76
- const summarizeTree = (command) => [
77
- {
78
- command: commandPath(command),
79
- description: command.description(),
80
- },
81
- ...sortedChildren(command).flatMap(summarizeTree),
82
- ];
157
+ // Index entry: enough to call a leaf command without a second lookup. Groups
158
+ // carry only their name and description.
159
+ const summarize = (command, catalog) => {
160
+ if (sortedChildren(command).length)
161
+ return compact({
162
+ command: commandPath(command),
163
+ aliases: command.aliases(),
164
+ description: command.description(),
165
+ });
166
+ const { own, shared } = splitOptions(command, catalog);
167
+ return {
168
+ ...compact({
169
+ command: commandPath(command),
170
+ aliases: command.aliases(),
171
+ description: command.description(),
172
+ usage: `${commandPath(command)} ${command.usage()}`.trim(),
173
+ arguments: command.registeredArguments.map((argument) => compact({
174
+ name: argument.name(),
175
+ required: argument.required,
176
+ variadic: argument.variadic,
177
+ })),
178
+ options: own.map((info) => info.flags),
179
+ shared_options: shared,
180
+ }),
181
+ required_scopes: requiredScopes(command),
182
+ ...compact({ examples: examplesOf(command).length || null }),
183
+ };
184
+ };
185
+ const referencedShared = (commands, shared) => {
186
+ const used = new Set();
187
+ const visit = (list) => {
188
+ for (const command of list) {
189
+ command.shared_options?.forEach((key) => used.add(key));
190
+ if (command.subcommands)
191
+ visit(command.subcommands);
192
+ }
193
+ };
194
+ visit(commands);
195
+ const byKey = new Map([...shared].map(([json, key]) => [key, json]));
196
+ return Object.fromEntries([...used].sort().map((key) => [key, JSON.parse(byKey.get(key))]));
197
+ };
83
198
  const discoverCommands = (program, path, version, full = false) => {
84
199
  let selected = program;
85
200
  const selectedPath = [];
@@ -96,23 +211,27 @@ const discoverCommands = (program, path, version, full = false) => {
96
211
  selected = child;
97
212
  selectedPath.push(child.name());
98
213
  }
99
- const commands = selected === program ? sortedChildren(program) : [selected];
100
- const includeDetails = full || (selected !== program && sortedChildren(selected).length === 0);
214
+ const roots = selected === program ? sortedChildren(program) : [selected];
215
+ const global_options = globalOptions(program);
216
+ const globals = new Set(global_options.map((info) => JSON.stringify(info)));
217
+ const single = selected !== program && sortedChildren(selected).length === 0;
218
+ const header = { schema_version: 1, cli_version: version, global_options };
219
+ // A single selected command is returned self-contained, options inlined.
220
+ if (single)
221
+ return {
222
+ ...header,
223
+ commands: [commandDetails(selected, { globals })],
224
+ tips: texts_1.DISCOVERY_TIPS,
225
+ };
226
+ const shared = buildSharedOptions(program, globals);
227
+ const catalog = { globals, shared };
228
+ const commands = full
229
+ ? roots.map((command) => describeTree(command, catalog))
230
+ : roots.flatMap(allCommands).map((command) => summarize(command, catalog));
101
231
  return {
102
- schema_version: 1,
103
- cli_version: version,
104
- // Root flags must precede the subcommand; keep them separate from local options.
105
- ...(includeDetails
106
- ? {
107
- global_options: program
108
- .createHelp()
109
- .visibleOptions(program)
110
- .map(optionInfo),
111
- }
112
- : {}),
113
- commands: includeDetails
114
- ? commands.map(describeTree)
115
- : commands.flatMap(summarizeTree),
232
+ ...header,
233
+ shared_options: referencedShared(commands, shared),
234
+ commands,
116
235
  tips: texts_1.DISCOVERY_TIPS,
117
236
  };
118
237
  };
@@ -588,20 +588,20 @@ class Input {
588
588
  }
589
589
  if (filters.pr) {
590
590
  if (!/^(?:pull\/)?[1-9]\d*$/.test(filters.pr))
591
- throw new cliError_1.default('usage_error', (0, texts_1.ERR_PIPELINE_RUN_FIND_FILTER)('--pr'));
591
+ throw new cliError_1.default('usage_error', texts_1.ERR_PIPELINE_RUN_FIND_PR);
592
592
  filters.pr = 'pull/' + filters.pr.replace(/^pull\//, '');
593
593
  }
594
594
  if (filters.status) {
595
595
  filters.status = filters.status.toUpperCase();
596
596
  if (!Object.values(pipeline_1.PIPELINE_RUN_STATUS).includes(filters.status))
597
- throw new cliError_1.default('usage_error', (0, texts_1.ERR_PIPELINE_RUN_FIND_FILTER)('--status'));
597
+ throw new cliError_1.default('usage_error', (0, texts_1.ERR_PIPELINE_RUN_FIND_STATUS)(Object.values(pipeline_1.PIPELINE_RUN_STATUS)));
598
598
  }
599
599
  if (filters.artifact?.includes(':')) {
600
600
  const separator = filters.artifact.indexOf(':');
601
601
  const version = filters.artifact.slice(separator + 1);
602
602
  const identifier = filters.artifact.slice(0, separator);
603
603
  if (!identifier.trim() || !version.trim())
604
- throw new cliError_1.default('usage_error', (0, texts_1.ERR_PIPELINE_RUN_FIND_FILTER)('--artifact'));
604
+ throw new cliError_1.default('usage_error', texts_1.ERR_PIPELINE_RUN_FIND_ARTIFACT);
605
605
  }
606
606
  return { last, filters };
607
607
  }
@@ -1408,14 +1408,14 @@ class Input {
1408
1408
  // A nonexistent project is rejected by the API client
1409
1409
  // (getResourceByIdentifier); here only the environment itself can miss.
1410
1410
  if (!resolved.environment_id) {
1411
- output_1.default.exitError(texts_1.ERR_ENVIRONMENT_NOT_FOUND);
1411
+ output_1.default.exitError(new cliError_1.default('not_found', texts_1.ERR_ENVIRONMENT_NOT_FOUND, texts_1.HINT_ENVIRONMENT_LIST));
1412
1412
  }
1413
1413
  if (strictProject && options.project) {
1414
1414
  const environment = await client.getEnvironment(workspace, resolved.environment_id);
1415
1415
  // a workspace environment carries no project, so this also fails the
1416
1416
  // workspace-fallback case
1417
1417
  if (environment.project?.name !== resolved.project_identifier) {
1418
- output_1.default.exitError(texts_1.ERR_ENVIRONMENT_NOT_FOUND);
1418
+ output_1.default.exitError(new cliError_1.default('not_found', texts_1.ERR_ENVIRONMENT_NOT_FOUND, texts_1.HINT_ENVIRONMENT_LIST));
1419
1419
  }
1420
1420
  }
1421
1421
  return resolved.environment_id;
@@ -1436,7 +1436,7 @@ class Input {
1436
1436
  sandboxId = await client.findSandboxByIdentifier(workspace, identifier, project, environmentId);
1437
1437
  }
1438
1438
  if (!sandboxId) {
1439
- throw new cliError_1.default('not_found', texts_1.ERR_SANDBOX_NOT_FOUND);
1439
+ throw new cliError_1.default('not_found', texts_1.ERR_SANDBOX_NOT_FOUND, texts_1.HINT_SANDBOX_LIST);
1440
1440
  }
1441
1441
  return sandboxId;
1442
1442
  }
@@ -59,7 +59,18 @@ class Output {
59
59
  static launchBrowser(url) {
60
60
  return require('open').default(url);
61
61
  }
62
- static async openUrl(url) {
62
+ // Ends a command whose text result is a single success line: with
63
+ // --format json the payload takes that line's place on stdout.
64
+ static exitResult(json, data, msg) {
65
+ if (json) {
66
+ this.json(data);
67
+ this.exitNormal();
68
+ }
69
+ if (msg)
70
+ this.exitSuccess(msg);
71
+ this.exitNormal();
72
+ }
73
+ static async openUrl(url, json = false) {
63
74
  let parsed;
64
75
  try {
65
76
  parsed = new URL(url || '');
@@ -71,7 +82,10 @@ class Output {
71
82
  throw new cliError_1.default('not_found', texts_1.ERR_RESOURCE_BROWSER_URL_MISSING);
72
83
  }
73
84
  const browserUrl = parsed.toString();
74
- this.data(browserUrl);
85
+ if (json)
86
+ this.json({ url: browserUrl });
87
+ else
88
+ this.data(browserUrl);
75
89
  try {
76
90
  await this.launchBrowser(browserUrl);
77
91
  }
@@ -405,8 +419,16 @@ class Output {
405
419
  static isTTY() {
406
420
  return this.isStdInTTY() && this.isStdOutTTY();
407
421
  }
408
- static tunnel(tunnel) {
409
- if (this.isTTY())
422
+ static tunnelJsonl(tunnel) {
423
+ this.killSpinner();
424
+ const OutputJsonlTunnel = require('./tunnel/output/noninteractive/tunnelJsonl').default;
425
+ const on = new OutputJsonlTunnel(getTerminal(), tunnel);
426
+ on.start();
427
+ }
428
+ static tunnel(tunnel, jsonl = false) {
429
+ if (jsonl)
430
+ this.tunnelJsonl(tunnel);
431
+ else if (this.isTTY())
410
432
  this.tunnelInteractive(tunnel);
411
433
  else
412
434
  this.tunnelNonInteractive(tunnel);
@@ -464,6 +486,31 @@ class Output {
464
486
  }
465
487
  return await this.confirm(message, quiet);
466
488
  }
489
+ // With --format json/jsonl stdout carries only the result, so prompts and
490
+ // the answers echoed without a TTY go to stderr instead.
491
+ static get promptsToStderr() {
492
+ return this.errorFormat !== 'text';
493
+ }
494
+ static promptContext(signal) {
495
+ return {
496
+ ...(signal ? { signal } : {}),
497
+ ...(this.promptsToStderr ? { output: process.stderr } : {}),
498
+ };
499
+ }
500
+ // Non-interactive stand-in for a prompt: shows the question and the answer
501
+ // taken without asking.
502
+ static promptEcho(message, answer) {
503
+ if (this.promptsToStderr) {
504
+ this.writeStderr(`? ${message}${answer ? ` ${answer}` : ''}`);
505
+ return;
506
+ }
507
+ this.cyan('? ', false);
508
+ this.normal(message, false);
509
+ if (answer)
510
+ this.cyan(` ${answer}`);
511
+ else
512
+ this.normal('');
513
+ }
467
514
  static async confirm(message = 'Are you sure?', quiet = false) {
468
515
  if (this.isStdInTTY()) {
469
516
  const prompts = require('@inquirer/prompts');
@@ -472,17 +519,21 @@ class Output {
472
519
  message,
473
520
  theme: this.getInquirerTheme(),
474
521
  default: false,
475
- }, quiet ? { output: process.stderr } : undefined);
522
+ }, quiet ? { output: process.stderr } : this.promptContext());
476
523
  }
477
524
  catch {
478
525
  this.exitError(texts_1.ERR_CANCELLED);
479
526
  }
480
527
  }
481
- if (!quiet) {
482
- this.cyan('? ', false);
483
- this.label(message, false);
484
- this.cyan(` No`);
528
+ if (quiet)
529
+ return false;
530
+ if (this.promptsToStderr) {
531
+ this.promptEcho(message, 'No');
532
+ return false;
485
533
  }
534
+ this.cyan('? ', false);
535
+ this.label(message, false);
536
+ this.cyan(` No`);
486
537
  return false;
487
538
  }
488
539
  static async inputString(message, def, required, signal) {
@@ -495,7 +546,7 @@ class Output {
495
546
  message,
496
547
  default: def,
497
548
  theme: this.getInquirerTheme(),
498
- }, { signal });
549
+ }, this.promptContext(signal));
499
550
  this.inlineOutput = true;
500
551
  return value;
501
552
  }
@@ -506,14 +557,8 @@ class Output {
506
557
  this.exitError(texts_1.ERR_CANCELLED);
507
558
  }
508
559
  }
509
- this.cyan('? ', false);
510
- this.normal(message, false);
511
- if (def) {
512
- this.cyan(` ${def}`);
513
- return def;
514
- }
515
- this.normal('');
516
- return '';
560
+ this.promptEcho(message, def);
561
+ return def || '';
517
562
  }
518
563
  static async inputMenuAdv(message, items) {
519
564
  const prompts = require('@inquirer/prompts');
@@ -524,21 +569,19 @@ class Output {
524
569
  theme: this.getInquirerTheme(),
525
570
  loop: false,
526
571
  choices: items,
527
- });
572
+ }, this.promptContext());
528
573
  }
529
574
  catch {
530
575
  this.exitError(texts_1.ERR_CANCELLED);
531
576
  }
532
577
  }
533
578
  else {
534
- this.cyan('? ', false);
535
- this.normal(message, false);
536
579
  const item = items.find((item) => !prompts.Separator.isSeparator(item) && !item.disabled);
537
580
  if (item && item.name && item.value) {
538
- this.cyan(` ${item.name}`);
581
+ this.promptEcho(message, item.name);
539
582
  return item.value;
540
583
  }
541
- this.normal('');
584
+ this.promptEcho(message);
542
585
  return '';
543
586
  }
544
587
  }
@@ -594,20 +637,18 @@ class Output {
594
637
  });
595
638
  return result;
596
639
  },
597
- });
640
+ }, this.promptContext());
598
641
  }
599
642
  catch {
600
643
  this.exitError(texts_1.ERR_CANCELLED);
601
644
  }
602
645
  }
603
646
  else {
604
- this.cyan('? ', false);
605
- this.normal(message, false);
606
647
  if (items.length > 0) {
607
- this.cyan(` ${items[0]}`);
648
+ this.promptEcho(message, items[0]);
608
649
  return 0;
609
650
  }
610
- this.normal('');
651
+ this.promptEcho(message);
611
652
  return -1;
612
653
  }
613
654
  }
@@ -620,20 +661,18 @@ class Output {
620
661
  theme: this.getInquirerTheme(),
621
662
  loop: false,
622
663
  choices: items.map((item, index) => ({ value: index, name: item })),
623
- });
664
+ }, this.promptContext());
624
665
  }
625
666
  catch {
626
667
  this.exitError(texts_1.ERR_CANCELLED);
627
668
  }
628
669
  }
629
670
  else {
630
- this.cyan('? ', false);
631
- this.normal(message, false);
632
671
  if (items.length > 0) {
633
- this.cyan(` ${items[0]}`);
672
+ this.promptEcho(message, items[0]);
634
673
  return 0;
635
674
  }
636
- this.normal('');
675
+ this.promptEcho(message);
637
676
  return -1;
638
677
  }
639
678
  }