@neta-art/cohub-cli 9.0.0 → 9.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -28
- package/dist/commands/boards.js +31 -12
- package/dist/commands/runtime.js +3 -2
- package/dist/commands/sandboxd-binary.d.ts +1 -1
- package/dist/commands/sandboxd-binary.js +2 -23
- package/dist/index.js +1 -1
- package/dist/runtime/launch.d.ts +1 -1
- package/dist/runtime/launch.js +12 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -115,6 +115,13 @@ cohub runtime down
|
|
|
115
115
|
cohub runtime up -n --name another-project
|
|
116
116
|
```
|
|
117
117
|
|
|
118
|
+
On macOS and Linux X11, a new Runtime offers screen sharing by default. The prompt
|
|
119
|
+
explains that collaborators and agents can see and control the screen; Enter accepts,
|
|
120
|
+
and `n` declines. Use `--no-display` to skip sharing, or `--display xvfb[:WIDTHxHEIGHT]`
|
|
121
|
+
for a virtual screen. `--yes` also authorizes default screen sharing. Headless and
|
|
122
|
+
Wayland-only Linux sessions skip the default offer; an existing Runtime keeps its
|
|
123
|
+
screen configuration unless explicitly overridden (configuration changes require a restart).
|
|
124
|
+
|
|
118
125
|
Runtime diagnostics stay as redacted JSONL under the local Runtime state directory and
|
|
119
126
|
are never uploaded automatically. Use `runtime logs --json` to export a failure report;
|
|
120
127
|
events carry the local `runtimeId` plus server `requestId` / `traceparent` when a turn has
|
|
@@ -225,57 +232,63 @@ cohub -s <spaceId> spaces activity 365 --json
|
|
|
225
232
|
|
|
226
233
|
## Boards
|
|
227
234
|
|
|
228
|
-
Board
|
|
235
|
+
A Board is one JSON document with three collections — `board` settings, `items`,
|
|
236
|
+
and `animations`. Board targets accept a Board ID or a `.board` path. Every
|
|
237
|
+
command supports `-h`, and the global `--json` makes the output machine-readable:
|
|
229
238
|
|
|
230
239
|
```bash
|
|
231
240
|
cohub boards -h
|
|
232
|
-
cohub -s <spaceId> boards
|
|
233
|
-
cohub -s <spaceId> boards
|
|
234
|
-
cohub -s <spaceId> boards
|
|
235
|
-
cohub -s <spaceId> boards
|
|
241
|
+
cohub -s <spaceId> boards get boards/plan.board --json
|
|
242
|
+
cohub -s <spaceId> boards get <boardId> --only items
|
|
243
|
+
cohub -s <spaceId> boards get <boardId> --only board
|
|
244
|
+
cohub -s <spaceId> boards schema
|
|
245
|
+
cohub -s <spaceId> boards history <boardId> --json
|
|
236
246
|
cohub -s <spaceId> boards watch <boardId> --json
|
|
237
247
|
```
|
|
238
248
|
|
|
239
|
-
Use
|
|
249
|
+
Use the filters so a large Board is not read whole:
|
|
240
250
|
|
|
241
251
|
```bash
|
|
242
|
-
cohub -s <spaceId> boards
|
|
243
|
-
cohub -s <spaceId> boards
|
|
244
|
-
cohub -s <spaceId> boards
|
|
245
|
-
cohub -s <spaceId> boards compositions get <boardId> <compositionId> --json
|
|
252
|
+
cohub -s <spaceId> boards get <boardId> --items title,note
|
|
253
|
+
cohub -s <spaceId> boards get <boardId> --within s1
|
|
254
|
+
cohub -s <spaceId> boards get <boardId> --rect 0,0,1600,900
|
|
246
255
|
```
|
|
247
256
|
|
|
248
|
-
|
|
257
|
+
Start from an example and write it with `apply`, a JSON Merge Patch where fields
|
|
258
|
+
merge, `null` deletes, and unmentioned fields stay:
|
|
249
259
|
|
|
250
260
|
```bash
|
|
251
|
-
cohub boards examples
|
|
252
|
-
cohub -s <spaceId> boards
|
|
261
|
+
cohub boards examples workflow > seed.json
|
|
262
|
+
cohub -s <spaceId> boards create boards/plan.board --title "Plan" -i seed.json
|
|
253
263
|
|
|
254
|
-
cohub
|
|
255
|
-
cohub -s <spaceId> boards
|
|
264
|
+
cohub -s <spaceId> boards apply <boardId> '{"items":{"title":{"props":{"text":"Updated"}}}}'
|
|
265
|
+
cohub -s <spaceId> boards apply <boardId> -i changes.json
|
|
256
266
|
```
|
|
257
267
|
|
|
258
|
-
|
|
268
|
+
Group a whole change into one patch so it lands as one version. `--replace` makes
|
|
269
|
+
the document equal to the patch instead of merging; `--cascade` also deletes
|
|
270
|
+
children and the tracks targeting a deleted item:
|
|
259
271
|
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
{"type":"connection.create","connection":{"id":"title-agent","source":{"itemId":"title"},"target":{"itemId":"agent"}}}
|
|
264
|
-
]}
|
|
272
|
+
```bash
|
|
273
|
+
cohub -s <spaceId> boards apply <boardId> -i changes.json --dry-run
|
|
274
|
+
cohub -s <spaceId> boards apply <boardId> -i changes.json --base-version 12 --mutation-id deploy-1
|
|
265
275
|
```
|
|
266
276
|
|
|
277
|
+
Use `--base-version` and `--mutation-id` for controlled, retry-safe scripts, and
|
|
278
|
+
`--dry-run` to validate without writing. `boards preset` prints a preset motion as
|
|
279
|
+
tracks — an apply-ready patch with `--animation`, bare tracks without it:
|
|
280
|
+
|
|
267
281
|
```bash
|
|
268
|
-
cohub boards
|
|
269
|
-
cohub -s <spaceId> boards
|
|
270
|
-
cohub -s <spaceId> boards batch <boardId> --input changes.json
|
|
282
|
+
cohub -s <spaceId> boards preset rise --targets a,b --animation intro | cohub boards apply <boardId> -i -
|
|
283
|
+
cohub -s <spaceId> boards preset float --targets ship > idle-tracks.json
|
|
271
284
|
```
|
|
272
285
|
|
|
273
|
-
|
|
286
|
+
Playback commands sit on `boards` directly:
|
|
274
287
|
|
|
275
288
|
```bash
|
|
276
|
-
cohub -s <spaceId> boards
|
|
277
|
-
cohub -s <spaceId> boards
|
|
278
|
-
cohub -s <spaceId> boards
|
|
289
|
+
cohub -s <spaceId> boards play <boardId> <animationId> --at 2.5s
|
|
290
|
+
cohub -s <spaceId> boards seek <boardId> 12.5s
|
|
291
|
+
cohub -s <spaceId> boards stop <boardId>
|
|
279
292
|
```
|
|
280
293
|
|
|
281
294
|
## Search
|
package/dist/commands/boards.js
CHANGED
|
@@ -145,7 +145,7 @@ function registerExportCommand(boards) {
|
|
|
145
145
|
.option("--scale <factor>", "Output pixels per board unit", "2")
|
|
146
146
|
.option("--padding <units>", "Padding around the content in board units")
|
|
147
147
|
.option("--theme <mode>", "dark or light", "dark")
|
|
148
|
-
.option("--
|
|
148
|
+
.option("--paper <mode>", "Output paper: paper or transparent", "paper")
|
|
149
149
|
.option("--format <format>", `Override the format (${BOARD_EXPORT_FORMATS.join(", ")}, ${BOARD_VIDEO_FORMATS.join(", ")})`)
|
|
150
150
|
.option("--quality <q>", "JPEG/WebP quality from 0 to 1", "0.92")
|
|
151
151
|
.option("--fps <rate>", "Video frame rate; defaults to the --at step")
|
|
@@ -189,7 +189,7 @@ Examples:
|
|
|
189
189
|
scale: parseNumber(options.scale ?? "2", "--scale", { min: 0.01, max: 16 }),
|
|
190
190
|
...(options.padding === undefined ? {} : { padding: parseNumber(options.padding, "--padding", { min: 0 }) }),
|
|
191
191
|
colorScheme: parseChoice(options.theme, "--theme", ["dark", "light"]),
|
|
192
|
-
background: parseChoice(options.
|
|
192
|
+
background: parseChoice(options.paper, "--paper", ["paper", "transparent"]),
|
|
193
193
|
format: videoFormat,
|
|
194
194
|
fps,
|
|
195
195
|
output: out,
|
|
@@ -213,7 +213,7 @@ Examples:
|
|
|
213
213
|
scale: parseNumber(options.scale ?? "2", "--scale", { min: 0.01, max: 16 }),
|
|
214
214
|
...(options.padding === undefined ? {} : { padding: parseNumber(options.padding, "--padding", { min: 0 }) }),
|
|
215
215
|
colorScheme: parseChoice(options.theme, "--theme", ["dark", "light"]),
|
|
216
|
-
background: parseChoice(options.
|
|
216
|
+
background: parseChoice(options.paper, "--paper", ["paper", "transparent"]),
|
|
217
217
|
format: parseExportFormat(options, out),
|
|
218
218
|
quality: parseNumber(options.quality ?? "0.92", "--quality", { min: 0, max: 1 }),
|
|
219
219
|
withImages: options.images !== false,
|
|
@@ -252,6 +252,9 @@ A Board is one JSON document: { board, items, animations }.
|
|
|
252
252
|
get read it
|
|
253
253
|
apply write it with a JSON Merge Patch; null deletes
|
|
254
254
|
schema the schema of any part, and what tracks can animate
|
|
255
|
+
preset tracks for a preset motion, ready to apply
|
|
256
|
+
history list versions, or restore one
|
|
257
|
+
export render an image, a frame sequence or a video
|
|
255
258
|
examples starter documents
|
|
256
259
|
Times are milliseconds; 500ms, 12.5s and 2m also work on the command line.`);
|
|
257
260
|
withJson(boards.command("create <path>")
|
|
@@ -288,7 +291,7 @@ Times are milliseconds; 500ms, 12.5s and 2m also work on the command line.`);
|
|
|
288
291
|
});
|
|
289
292
|
boards.command("get <board>")
|
|
290
293
|
.description("Print the Board document as JSON")
|
|
291
|
-
.option("--only <sections>", "items, animations
|
|
294
|
+
.option("--only <sections>", "board, items, animations (comma-separated)")
|
|
292
295
|
.option("--items <ids>", "Only these items")
|
|
293
296
|
.option("--within <frame-id>", "A frame and everything inside it")
|
|
294
297
|
.option("--rect <rect>", "Items intersecting x,y,width,height")
|
|
@@ -298,14 +301,15 @@ Times are milliseconds; 500ms, 12.5s and 2m also work on the command line.`);
|
|
|
298
301
|
.addHelpText("after", `
|
|
299
302
|
cohub boards get plan.board
|
|
300
303
|
cohub boards get plan.board --within s2
|
|
301
|
-
cohub boards get plan.board --only
|
|
304
|
+
cohub boards get plan.board --only board`)
|
|
302
305
|
.action(async (target, options) => {
|
|
303
306
|
try {
|
|
304
307
|
const only = list(options.only);
|
|
305
|
-
if (only?.some((section) => section !== "items" && section !== "animations"))
|
|
306
|
-
throw new Error("--only takes items, animations, or
|
|
308
|
+
if (only?.some((section) => section !== "board" && section !== "items" && section !== "animations"))
|
|
309
|
+
throw new Error("--only takes board, items, animations, or a combination.");
|
|
310
|
+
const sections = only ? new Set(only) : null;
|
|
307
311
|
const input = {
|
|
308
|
-
...(only ? { only: only } : {}),
|
|
312
|
+
...(only ? { only: only.filter((section) => section !== "board") } : {}),
|
|
309
313
|
...(list(options.items) ? { items: list(options.items) } : {}),
|
|
310
314
|
...(options.within ? { within: options.within } : {}),
|
|
311
315
|
...(options.rect ? { rect: parseRect(options.rect) } : {}),
|
|
@@ -313,7 +317,20 @@ Times are milliseconds; 500ms, 12.5s and 2m also work on the command line.`);
|
|
|
313
317
|
...(options.limit ? { limit: parseNumber(options.limit, "--limit", { min: 1, integer: true }) } : {}),
|
|
314
318
|
...(options.cursor ? { cursor: options.cursor } : {}),
|
|
315
319
|
};
|
|
316
|
-
|
|
320
|
+
const result = await (await boardClient(boards, target)).get(input);
|
|
321
|
+
if (!sections)
|
|
322
|
+
return outJson(result);
|
|
323
|
+
outJson({
|
|
324
|
+
id: result.id,
|
|
325
|
+
title: result.title,
|
|
326
|
+
version: result.version,
|
|
327
|
+
updatedAt: result.updatedAt,
|
|
328
|
+
playback: result.playback,
|
|
329
|
+
...(sections.has("board") ? { board: result.board } : {}),
|
|
330
|
+
...(sections.has("items") && result.items ? { items: result.items } : {}),
|
|
331
|
+
...(sections.has("animations") && result.animations ? { animations: result.animations } : {}),
|
|
332
|
+
...(result.next ? { next: result.next } : {}),
|
|
333
|
+
});
|
|
317
334
|
}
|
|
318
335
|
catch (cause) {
|
|
319
336
|
handleHttp(cause);
|
|
@@ -393,6 +410,7 @@ Times are milliseconds; 500ms, 12.5s and 2m also work on the command line.`);
|
|
|
393
410
|
boards.command("schema [target]")
|
|
394
411
|
.description("Print JSON Schema for a part of a Board")
|
|
395
412
|
.addHelpText("after", `
|
|
413
|
+
With a target: one item type, or animation, track, or camera.
|
|
396
414
|
Targets: ${BOARD_SCHEMA_TARGETS.join(", ")}
|
|
397
415
|
Without a target: units, item types, colors and every animatable property.`)
|
|
398
416
|
.action((target) => {
|
|
@@ -411,14 +429,15 @@ Without a target: units, item types, colors and every animatable property.`)
|
|
|
411
429
|
boards.command("preset <name>")
|
|
412
430
|
.description("Print tracks for a preset motion as a patch for apply")
|
|
413
431
|
.requiredOption("--targets <ids>", "Comma-separated item ids")
|
|
414
|
-
.
|
|
432
|
+
.option("--animation <id>", "Wrap the tracks in this animation; omit to get bare tracks")
|
|
415
433
|
.option("--at <time>", "Start of the first target", "0")
|
|
416
434
|
.option("--stagger <time>", "Delay added per target", "0")
|
|
417
435
|
.option("--duration <time>", "Length of each target's motion")
|
|
418
436
|
.option("--ease <ease>", "CSS easing, e.g. ease-out or cubic-bezier(.2,.8,.2,1)")
|
|
419
437
|
.addHelpText("after", `
|
|
420
438
|
Presets: ${BOARD_PRESET_NAMES.join(", ")}
|
|
421
|
-
cohub boards preset rise --targets a,b,c --animation intro --stagger 120ms | cohub boards apply plan.board -i
|
|
439
|
+
cohub boards preset rise --targets a,b,c --animation intro --stagger 120ms | cohub boards apply plan.board -i -
|
|
440
|
+
cohub boards preset float --targets ship | jq -c '{animations:{idle:.}}' | cohub boards apply plan.board -i -`)
|
|
422
441
|
.action((name, options) => {
|
|
423
442
|
try {
|
|
424
443
|
if (!isBoardPresetName(name))
|
|
@@ -433,7 +452,7 @@ Presets: ${BOARD_PRESET_NAMES.join(", ")}
|
|
|
433
452
|
...(options.duration ? { duration: parseBoardTime(options.duration, "--duration") } : {}),
|
|
434
453
|
...(options.ease ? { ease: options.ease } : {}),
|
|
435
454
|
});
|
|
436
|
-
outJson({ animations: { [options.animation]: { tracks } } });
|
|
455
|
+
outJson(options.animation ? { animations: { [options.animation]: { tracks } } } : { tracks });
|
|
437
456
|
}
|
|
438
457
|
catch (cause) {
|
|
439
458
|
handleHttp(cause);
|
package/dist/commands/runtime.js
CHANGED
|
@@ -41,8 +41,9 @@ export function registerRuntime(program) {
|
|
|
41
41
|
.option("--harness <name>", "Pi or Codex; repeatable", (value, previous) => [...previous, value], [])
|
|
42
42
|
.option("--pi <path>", "Pi executable")
|
|
43
43
|
.option("--codex <path>", "Codex executable")
|
|
44
|
-
.option("--display [screen]", "Share a screen: auto
|
|
45
|
-
.option("-
|
|
44
|
+
.option("--display [screen]", "Share a screen (default: auto when available), or xvfb[:WIDTHxHEIGHT] for a virtual one")
|
|
45
|
+
.option("--no-display", "Disable screen sharing and skip its confirmation")
|
|
46
|
+
.option("-y, --yes", "Accept defaults and authorize local execution, native sync, and screen sharing")
|
|
46
47
|
.option("--verbose", "Show diagnostic details")
|
|
47
48
|
.option("--json", "JSON output")
|
|
48
49
|
.action(async (dir, options) => {
|
|
@@ -6,29 +6,8 @@ import { homedir, tmpdir } from "node:os";
|
|
|
6
6
|
import { dirname, join } from "node:path";
|
|
7
7
|
import { pipeline } from "node:stream/promises";
|
|
8
8
|
import { Readable } from "node:stream";
|
|
9
|
-
//
|
|
10
|
-
|
|
11
|
-
// protocol ("1") guarantees backward compatibility.
|
|
12
|
-
//
|
|
13
|
-
// IMPORTANT: this must point at a tag whose CDN artifacts have already been
|
|
14
|
-
// published by .github/workflows/sandbox-binaries-build.yml. Only bump it AFTER
|
|
15
|
-
// that tag's publish-cdn job has succeeded, otherwise `runtime up` 404s on the
|
|
16
|
-
// default download.
|
|
17
|
-
//
|
|
18
|
-
// v2.54.0 is the first published tag with the private managed Runtime control
|
|
19
|
-
// pipe (`COHUB_RUNTIME_MANAGED` over fd 3), so `runtime up` reads connection
|
|
20
|
-
// state from the daemon instead of polling the API every five seconds. It also
|
|
21
|
-
// carries the optional workspace-search runner download. v2.53.1 already has
|
|
22
|
-
// the native FSEvents backends and the `runtimeId` control frame, and older
|
|
23
|
-
// releases stay usable through the compatibility readiness/restart path.
|
|
24
|
-
//
|
|
25
|
-
// v2.54.1 keeps the same wire protocol and adds relay diagnostics: data-channel
|
|
26
|
-
// pairing outlives the runner's dial timeout, dial failures distinguish a
|
|
27
|
-
// timeout from an explicit rejection, and teardown-time websocket write
|
|
28
|
-
// failures log at debug instead of warn. v2.55.0 republishes that compatible
|
|
29
|
-
// runner alongside the matching platform release; no new runner capability is
|
|
30
|
-
// required.
|
|
31
|
-
export const SANDBOXD_VERSION = "v2.55.0";
|
|
9
|
+
// Pin only after all platform artifacts are published to the public CDN.
|
|
10
|
+
export const SANDBOXD_VERSION = "v2.61.1";
|
|
32
11
|
const BINARY_NAME = "cohub-sandboxd";
|
|
33
12
|
// Public CDN prefix hosting the release archives (the repo is private, so the
|
|
34
13
|
// GitHub Release assets are not publicly downloadable). Overridable for staging
|
package/dist/index.js
CHANGED
|
@@ -56,7 +56,7 @@ Common commands:
|
|
|
56
56
|
cohub runtime up ./my-project
|
|
57
57
|
cohub runtime logs --follow
|
|
58
58
|
cohub search "release notes"
|
|
59
|
-
cohub -s <space-id> boards
|
|
59
|
+
cohub -s <space-id> boards get <board-id>
|
|
60
60
|
cohub -s <space-id> spaces turns ls --author others
|
|
61
61
|
cohub -s <space-id> spaces sessions turns ls <session-id>
|
|
62
62
|
cohub -s home spaces files ls
|
package/dist/runtime/launch.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export type RuntimeUpOptions = {
|
|
|
16
16
|
};
|
|
17
17
|
export declare const resolveLocalSpaceName: (root: string, name?: string) => string;
|
|
18
18
|
export declare function parseRuntimeHarnesses(values: string[]): ("pi" | "codex")[];
|
|
19
|
-
export declare function parseRuntimeDisplay(value: string | boolean | undefined): string | undefined;
|
|
19
|
+
export declare function parseRuntimeDisplay(value: string | boolean | undefined, platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv): string | undefined;
|
|
20
20
|
export declare function resolveRuntimeTarget(program: Command, target?: string): Promise<string>;
|
|
21
21
|
export declare function startBackgroundRuntime(config: RuntimeLaunch): Promise<RuntimeSummary>;
|
|
22
22
|
export declare function runtimeUp(program: Command, dir: string | undefined, options: RuntimeUpOptions): Promise<void>;
|
package/dist/runtime/launch.js
CHANGED
|
@@ -20,15 +20,17 @@ export function parseRuntimeHarnesses(values) {
|
|
|
20
20
|
throw new Error("Harness must be pi or codex");
|
|
21
21
|
return [...new Set(names.length ? names : ["pi"])];
|
|
22
22
|
}
|
|
23
|
-
export function parseRuntimeDisplay(value) {
|
|
24
|
-
if (value ===
|
|
23
|
+
export function parseRuntimeDisplay(value, platform = process.platform, env = process.env) {
|
|
24
|
+
if (value === false)
|
|
25
25
|
return undefined;
|
|
26
|
-
|
|
26
|
+
if (value === undefined && platform !== "darwin" && (platform !== "linux" || !env.DISPLAY))
|
|
27
|
+
return undefined;
|
|
28
|
+
const spec = value === undefined || value === true ? "auto" : value.trim();
|
|
27
29
|
if (!/^(auto|macos|x11(:[\w.:-]+)?|xvfb(:\d{3,4}x\d{3,4})?)$/.test(spec)) {
|
|
28
30
|
throw new Error("Display must be auto, macos, x11[:display] or xvfb[:WIDTHxHEIGHT]");
|
|
29
31
|
}
|
|
30
|
-
if (
|
|
31
|
-
throw new Error(
|
|
32
|
+
if (platform === "linux" && spec === "auto" && !env.DISPLAY) {
|
|
33
|
+
throw new Error(env.WAYLAND_DISPLAY
|
|
32
34
|
? "Wayland sessions cannot be shared yet: log in with an X11 session, or use --display xvfb for a virtual screen"
|
|
33
35
|
: "No X11 session to share (DISPLAY is unset): use --display xvfb for a virtual screen");
|
|
34
36
|
}
|
|
@@ -106,11 +108,11 @@ export async function runtimeUp(program, dir, options) {
|
|
|
106
108
|
const binding = await getRuntimeSpaceBinding(root, identity);
|
|
107
109
|
const existingId = requested || binding?.spaceId;
|
|
108
110
|
let harnesses = parseRuntimeHarnesses(options.harness);
|
|
109
|
-
let display = parseRuntimeDisplay(options.display);
|
|
111
|
+
let display = options.display === undefined ? undefined : parseRuntimeDisplay(options.display);
|
|
110
112
|
if (existingId && !options.new) {
|
|
111
113
|
const existing = await requestRuntimeInstance(runtimeInstanceDirectory(identity, existingId));
|
|
112
114
|
if (existing) {
|
|
113
|
-
if (existing.root !== root || options.harness.length && [...existing.harnesses].sort().join() !== [...harnesses].sort().join() || options.pi || options.codex || display && display !== existing.display) {
|
|
115
|
+
if (existing.root !== root || options.harness.length && [...existing.harnesses].sort().join() !== [...harnesses].sort().join() || options.pi || options.codex || options.display !== undefined && display !== existing.display) {
|
|
114
116
|
throw new Error("Runtime is running with a different configuration. Use down first");
|
|
115
117
|
}
|
|
116
118
|
// `up` is the single idempotent entry: a reused instance adopts its running
|
|
@@ -125,6 +127,7 @@ export async function runtimeUp(program, dir, options) {
|
|
|
125
127
|
return;
|
|
126
128
|
}
|
|
127
129
|
}
|
|
130
|
+
display = parseRuntimeDisplay(options.display);
|
|
128
131
|
if (!options.harness.length)
|
|
129
132
|
harnesses = await installedHarnesses(root, options);
|
|
130
133
|
if (!harnesses.length)
|
|
@@ -157,8 +160,8 @@ export async function runtimeUp(program, dir, options) {
|
|
|
157
160
|
if (/^n(o)?$/i.test(answer.trim()))
|
|
158
161
|
return;
|
|
159
162
|
if (display && !isVirtualDisplay(display)) {
|
|
160
|
-
const share = await rl.question("Collaborators and agents can see and control this screen. Share it? [
|
|
161
|
-
if (!/^y(es)?$/i.test(share.trim()))
|
|
163
|
+
const share = await rl.question("Collaborators and agents can see and control this screen. Share it? [Y/n] ");
|
|
164
|
+
if (!/^(y(es)?)?$/i.test(share.trim()))
|
|
162
165
|
display = undefined;
|
|
163
166
|
}
|
|
164
167
|
}
|