@positronic/cli 0.0.51 → 0.0.52

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 (36) hide show
  1. package/dist/src/cli.js +37 -68
  2. package/dist/src/commands/brain.js +14 -23
  3. package/dist/src/commands/server.js +28 -41
  4. package/dist/src/components/brain-rerun.js +1 -1
  5. package/dist/src/components/brain-resolver.js +18 -49
  6. package/dist/src/components/brain-run.js +26 -43
  7. package/dist/src/components/brain-top-table.js +153 -0
  8. package/dist/src/components/brain-top.js +139 -0
  9. package/dist/src/components/project-select.js +32 -52
  10. package/dist/src/components/select-list.js +102 -0
  11. package/dist/src/components/top-navigator.js +259 -0
  12. package/dist/src/components/watch-resolver.js +592 -0
  13. package/dist/src/components/watch.js +114 -112
  14. package/dist/src/hooks/useBrainMachine.js +19 -0
  15. package/dist/types/cli.d.ts.map +1 -1
  16. package/dist/types/commands/brain.d.ts +6 -3
  17. package/dist/types/commands/brain.d.ts.map +1 -1
  18. package/dist/types/commands/server.d.ts.map +1 -1
  19. package/dist/types/components/brain-resolver.d.ts.map +1 -1
  20. package/dist/types/components/brain-run.d.ts.map +1 -1
  21. package/dist/types/components/brain-top-table.d.ts +22 -0
  22. package/dist/types/components/brain-top-table.d.ts.map +1 -0
  23. package/dist/types/components/brain-top.d.ts +6 -0
  24. package/dist/types/components/brain-top.d.ts.map +1 -0
  25. package/dist/types/components/project-select.d.ts.map +1 -1
  26. package/dist/types/components/select-list.d.ts +23 -0
  27. package/dist/types/components/select-list.d.ts.map +1 -0
  28. package/dist/types/components/top-navigator.d.ts +6 -0
  29. package/dist/types/components/top-navigator.d.ts.map +1 -0
  30. package/dist/types/components/watch-resolver.d.ts +15 -0
  31. package/dist/types/components/watch-resolver.d.ts.map +1 -0
  32. package/dist/types/components/watch.d.ts +3 -1
  33. package/dist/types/components/watch.d.ts.map +1 -1
  34. package/dist/types/hooks/useBrainMachine.d.ts +37 -0
  35. package/dist/types/hooks/useBrainMachine.d.ts.map +1 -0
  36. package/package.json +5 -4
package/dist/src/cli.js CHANGED
@@ -421,7 +421,10 @@ export function buildCli(options) {
421
421
  render(element);
422
422
  });
423
423
  // --- Run Brain Command ---
424
- cli = cli.command('run <brain>', 'Run a brain and optionally watch its execution\n', function(yargsRun) {
424
+ cli = cli.command([
425
+ 'run <brain>',
426
+ 'r <brain>'
427
+ ], 'Run a brain and optionally watch its execution\n', function(yargsRun) {
425
428
  return yargsRun.positional('brain', {
426
429
  describe: 'Brain identifier (title, filename, or search term)',
427
430
  type: 'string',
@@ -443,41 +446,25 @@ export function buildCli(options) {
443
446
  render(element);
444
447
  });
445
448
  // --- Watch Brain Run Command ---
446
- cli = cli.command('watch [brain]', 'Watch a brain run: latest by brain name (default) or specific by ID\n', function(yargsWatch) {
447
- return yargsWatch.positional('brain', {
448
- describe: 'Brain identifier to watch (watches the most recent active run)',
449
- type: 'string'
450
- }).option('run-id', {
451
- describe: 'ID of the specific brain run to watch',
449
+ cli = cli.command('watch <identifier>', 'Watch a brain run by brain name or run ID\n', function(yargsWatch) {
450
+ return yargsWatch.positional('identifier', {
451
+ describe: 'Brain name or run ID to watch',
452
452
  type: 'string',
453
- alias: 'id'
454
- }).conflicts('brain', 'run-id').check(function(argv) {
455
- if (!argv.brain && !argv.runId) {
456
- throw new Error('You must provide either a brain identifier or a --run-id.');
457
- }
458
- return true;
459
- }).example('$0 watch my-brain', "Watch the latest run of the brain named 'my-brain'").example('$0 watch --run-id abc123def', 'Watch a specific brain run by its ID');
453
+ demandOption: true
454
+ }).example('$0 watch my-brain', "Watch the latest run of the brain named 'my-brain'").example('$0 watch abc123def', 'Watch a specific brain run by its ID');
460
455
  }, function(argv) {
461
- return _async_to_generator(function() {
462
- var element;
463
- return _ts_generator(this, function(_state) {
464
- switch(_state.label){
465
- case 0:
466
- return [
467
- 4,
468
- brainCommand.watch(argv)
469
- ];
470
- case 1:
471
- element = _state.sent();
472
- if (element) {
473
- render(element);
474
- }
475
- return [
476
- 2
477
- ];
478
- }
479
- });
480
- })();
456
+ var element = brainCommand.watch(argv);
457
+ render(element);
458
+ });
459
+ // --- Top Command (view running brains) ---
460
+ cli = cli.command('top [brain]', 'View live status of all running brains\n', function(yargsTop) {
461
+ return yargsTop.positional('brain', {
462
+ describe: 'Filter to brains matching this name',
463
+ type: 'string'
464
+ }).example('$0 top', 'View all running brains').example('$0 top my-brain', 'View running brains matching "my-brain"');
465
+ }, function(argv) {
466
+ var element = brainCommand.top(argv);
467
+ render(element);
481
468
  });
482
469
  // --- Brain Commands ---
483
470
  cli = cli.command('brain', 'Manage your brains\n', function(yargsBrain) {
@@ -556,41 +543,15 @@ export function buildCli(options) {
556
543
  }, function(argv) {
557
544
  var element = brainCommand.run(argv);
558
545
  render(element);
559
- }).command('watch [brain]', 'Watch a brain run: latest by brain name (default) or specific by ID\n', function(yargsWatch) {
560
- return yargsWatch.positional('brain', {
561
- describe: 'Brain identifier to watch (watches the most recent active run)',
562
- type: 'string'
563
- }).option('run-id', {
564
- describe: 'ID of the specific brain run to watch',
546
+ }).command('watch <identifier>', 'Watch a brain run by brain name or run ID\n', function(yargsWatch) {
547
+ return yargsWatch.positional('identifier', {
548
+ describe: 'Brain name or run ID to watch',
565
549
  type: 'string',
566
- alias: 'id'
567
- }).conflicts('brain', 'run-id').check(function(argv) {
568
- if (!argv.brain && !argv.runId) {
569
- throw new Error('You must provide either a brain identifier or a --run-id.');
570
- }
571
- return true;
572
- }).example('$0 brain watch my-brain', "Watch the latest run of the brain named 'my-brain'").example('$0 brain watch --run-id abc123def', 'Watch a specific brain run by its ID');
550
+ demandOption: true
551
+ }).example('$0 brain watch my-brain', "Watch the latest run of the brain named 'my-brain'").example('$0 brain watch abc123def', 'Watch a specific brain run by its ID');
573
552
  }, function(argv) {
574
- return _async_to_generator(function() {
575
- var element;
576
- return _ts_generator(this, function(_state) {
577
- switch(_state.label){
578
- case 0:
579
- return [
580
- 4,
581
- brainCommand.watch(argv)
582
- ];
583
- case 1:
584
- element = _state.sent();
585
- if (element) {
586
- render(element);
587
- }
588
- return [
589
- 2
590
- ];
591
- }
592
- });
593
- })();
553
+ var element = brainCommand.watch(argv);
554
+ render(element);
594
555
  }).command('kill <run-id>', 'Kill a running brain\n', function(yargsKill) {
595
556
  return yargsKill.positional('run-id', {
596
557
  describe: 'ID of the brain run to kill',
@@ -605,7 +566,15 @@ export function buildCli(options) {
605
566
  }, function(argv) {
606
567
  var element = brainCommand.kill(argv);
607
568
  render(element);
608
- }).demandCommand(1, 'You need to specify a brain command (list, history, show, rerun, run, watch, kill).');
569
+ }).command('top [brain]', 'View live status of all running brains\n', function(yargsTop) {
570
+ return yargsTop.positional('brain', {
571
+ describe: 'Filter to brains matching this name',
572
+ type: 'string'
573
+ }).example('$0 brain top', 'View all running brains').example('$0 brain top my-brain', 'View running brains matching "my-brain"');
574
+ }, function(argv) {
575
+ var element = brainCommand.top(argv);
576
+ render(element);
577
+ }).demandCommand(1, 'You need to specify a brain command (list, history, show, rerun, run, watch, kill, top).');
609
578
  return yargsBrain;
610
579
  });
611
580
  // --- Resource Management Commands ---
@@ -18,7 +18,6 @@ function _create_class(Constructor, protoProps, staticProps) {
18
18
  return Constructor;
19
19
  }
20
20
  import React from 'react';
21
- import { Watch } from '../components/watch.js';
22
21
  import { BrainList } from '../components/brain-list.js';
23
22
  import { BrainHistory } from '../components/brain-history.js';
24
23
  import { RunShow } from '../components/run-show.js';
@@ -27,7 +26,8 @@ import { BrainRerun } from '../components/brain-rerun.js';
27
26
  import { BrainKill } from '../components/brain-kill.js';
28
27
  import { BrainRun } from '../components/brain-run.js';
29
28
  import { BrainResolver } from '../components/brain-resolver.js';
30
- import { BrainWatchWithResolver } from '../components/brain-watch.js';
29
+ import { WatchResolver } from '../components/watch-resolver.js';
30
+ import { TopNavigator } from '../components/top-navigator.js';
31
31
  import { ErrorComponent } from '../components/error.js';
32
32
  export var BrainCommand = /*#__PURE__*/ function() {
33
33
  "use strict";
@@ -114,27 +114,9 @@ export var BrainCommand = /*#__PURE__*/ function() {
114
114
  {
115
115
  key: "watch",
116
116
  value: function watch(param) {
117
- var runId = param.runId, brain = param.brain;
118
- // If a specific run ID is provided, return the Watch component
119
- if (runId) {
120
- return React.createElement(Watch, {
121
- runId: runId
122
- });
123
- }
124
- // If watching by brain identifier is requested, use BrainWatchWithResolver
125
- // which handles fuzzy search, disambiguation, and active run lookup
126
- if (brain) {
127
- return React.createElement(BrainWatchWithResolver, {
128
- identifier: brain
129
- });
130
- }
131
- // Neither runId nor brainName provided – return an error element.
132
- return React.createElement(ErrorComponent, {
133
- error: {
134
- title: 'Missing Argument',
135
- message: 'You must provide either a brain run ID or a brain identifier.',
136
- details: 'Use --run-id to watch a specific run, or --brain to watch the active run of a brain.'
137
- }
117
+ var identifier = param.identifier;
118
+ return React.createElement(WatchResolver, {
119
+ identifier: identifier
138
120
  });
139
121
  }
140
122
  },
@@ -147,6 +129,15 @@ export var BrainCommand = /*#__PURE__*/ function() {
147
129
  force: force
148
130
  });
149
131
  }
132
+ },
133
+ {
134
+ key: "top",
135
+ value: function top(param) {
136
+ var brain = param.brain;
137
+ return React.createElement(TopNavigator, {
138
+ brainFilter: brain
139
+ });
140
+ }
150
141
  }
151
142
  ]);
152
143
  return BrainCommand;
@@ -279,6 +279,12 @@ export var ServerCommand = /*#__PURE__*/ function() {
279
279
  serverHandle = null;
280
280
  watcher = null;
281
281
  logStream = null;
282
+ // Restore terminal state on ANY exit - this is synchronous and guaranteed to run
283
+ process.on('exit', function() {
284
+ if (process.stdin.isTTY && process.stdin.setRawMode) {
285
+ process.stdin.setRawMode(false);
286
+ }
287
+ });
282
288
  // Always create a log file (use default if not specified)
283
289
  logFilePath = argv.logFile ? path.resolve(argv.logFile) : path.join(this.server.projectRootDir, '.positronic-server.log');
284
290
  // Ensure directory exists
@@ -314,47 +320,25 @@ export var ServerCommand = /*#__PURE__*/ function() {
314
320
  return logBoth('WARN', message);
315
321
  });
316
322
  cleanup = function() {
317
- return _async_to_generator(function() {
318
- return _ts_generator(this, function(_state) {
319
- switch(_state.label){
320
- case 0:
321
- if (!watcher) return [
322
- 3,
323
- 2
324
- ];
325
- return [
326
- 4,
327
- watcher.close()
328
- ];
329
- case 1:
330
- _state.sent();
331
- watcher = null;
332
- _state.label = 2;
333
- case 2:
334
- if (serverHandle && !serverHandle.killed) {
335
- serverHandle.kill();
336
- serverHandle = null;
337
- }
338
- // Close log stream
339
- if (logStream) {
340
- logStream.end();
341
- logStream = null;
342
- }
343
- // Remove PID file
344
- if (fs.existsSync(pidFile)) {
345
- fs.unlinkSync(pidFile);
346
- }
347
- // Restore terminal from raw mode (dev server may have set it)
348
- if (process.stdin.isTTY && process.stdin.setRawMode) {
349
- process.stdin.setRawMode(false);
350
- }
351
- process.exit(0);
352
- return [
353
- 2
354
- ];
355
- }
356
- });
357
- })();
323
+ if (watcher) {
324
+ watcher.close();
325
+ watcher = null;
326
+ }
327
+ if (serverHandle && !serverHandle.killed) {
328
+ serverHandle.kill();
329
+ serverHandle = null;
330
+ }
331
+ // Close log stream
332
+ if (logStream) {
333
+ logStream.end();
334
+ logStream = null;
335
+ }
336
+ // Remove PID file
337
+ if (fs.existsSync(pidFile)) {
338
+ fs.unlinkSync(pidFile);
339
+ }
340
+ // Terminal is restored by process.on('exit') handler
341
+ process.exit(0);
358
342
  };
359
343
  process.on('SIGINT', cleanup); // Catches Ctrl+C
360
344
  process.on('SIGTERM', cleanup); // Catches kill commands
@@ -385,6 +369,7 @@ export var ServerCommand = /*#__PURE__*/ function() {
385
369
  watcher.close();
386
370
  watcher = null;
387
371
  }
372
+ // Terminal is restored by process.on('exit') handler
388
373
  process.exit(code !== null && code !== void 0 ? code : 1); // Exit with server's code or 1 if null
389
374
  });
390
375
  serverHandle.onError(function(err) {
@@ -393,6 +378,7 @@ export var ServerCommand = /*#__PURE__*/ function() {
393
378
  watcher.close();
394
379
  watcher = null;
395
380
  }
381
+ // Terminal is restored by process.on('exit') handler
396
382
  process.exit(1);
397
383
  });
398
384
  return [
@@ -407,6 +393,7 @@ export var ServerCommand = /*#__PURE__*/ function() {
407
393
  if (serverHandle && !serverHandle.killed) {
408
394
  serverHandle.kill();
409
395
  }
396
+ // Terminal is restored by process.on('exit') handler
410
397
  process.exit(1);
411
398
  }
412
399
  _state.label = 5;
@@ -300,7 +300,7 @@ export var BrainRerun = function(param) {
300
300
  marginTop: 1
301
301
  }, /*#__PURE__*/ React.createElement(Text, {
302
302
  dimColor: true
303
- }, "Watch the run with: positronic watch --run-id ", newRunId))) : /*#__PURE__*/ React.createElement(Text, {
303
+ }, "Watch the run with: positronic watch ", newRunId))) : /*#__PURE__*/ React.createElement(Text, {
304
304
  color: "red"
305
305
  }, "❌ Unexpected error occurred"));
306
306
  };
@@ -217,8 +217,9 @@ function _ts_generator(thisArg, body) {
217
217
  }
218
218
  }
219
219
  import React, { useState, useEffect, useCallback } from 'react';
220
- import { Box, Text, useInput, useApp } from 'ink';
220
+ import { Box, Text } from 'ink';
221
221
  import { ErrorComponent } from './error.js';
222
+ import { SelectList } from './select-list.js';
222
223
  import { apiClient, isApiLocalDevMode } from '../commands/helpers.js';
223
224
  /**
224
225
  * BrainResolver - A reusable component that resolves a brain identifier to a title.
@@ -231,10 +232,8 @@ import { apiClient, isApiLocalDevMode } from '../commands/helpers.js';
231
232
  var identifier = param.identifier, children = param.children;
232
233
  var _useState = _sliced_to_array(useState('searching'), 2), phase = _useState[0], setPhase = _useState[1];
233
234
  var _useState1 = _sliced_to_array(useState([]), 2), brains = _useState1[0], setBrains = _useState1[1];
234
- var _useState2 = _sliced_to_array(useState(0), 2), selectedIndex = _useState2[0], setSelectedIndex = _useState2[1];
235
- var _useState3 = _sliced_to_array(useState(null), 2), resolvedTitle = _useState3[0], setResolvedTitle = _useState3[1];
236
- var _useState4 = _sliced_to_array(useState(null), 2), error = _useState4[0], setError = _useState4[1];
237
- var exit = useApp().exit;
235
+ var _useState2 = _sliced_to_array(useState(null), 2), resolvedTitle = _useState2[0], setResolvedTitle = _useState2[1];
236
+ var _useState3 = _sliced_to_array(useState(null), 2), error = _useState3[0], setError = _useState3[1];
238
237
  var getConnectionError = useCallback(function() {
239
238
  if (isApiLocalDevMode()) {
240
239
  return {
@@ -343,25 +342,6 @@ import { apiClient, isApiLocalDevMode } from '../commands/helpers.js';
343
342
  identifier,
344
343
  getConnectionError
345
344
  ]);
346
- // Handle keyboard input for disambiguation
347
- useInput(function(input, key) {
348
- if (phase !== 'disambiguating') return;
349
- if (key.upArrow) {
350
- setSelectedIndex(function(prev) {
351
- return (prev - 1 + brains.length) % brains.length;
352
- });
353
- } else if (key.downArrow) {
354
- setSelectedIndex(function(prev) {
355
- return (prev + 1) % brains.length;
356
- });
357
- } else if (key.return) {
358
- var selectedBrain = brains[selectedIndex];
359
- setResolvedTitle(selectedBrain.title);
360
- setPhase('resolved');
361
- } else if (input === 'q' || key.escape) {
362
- exit();
363
- }
364
- });
365
345
  // Render based on phase
366
346
  if (phase === 'searching') {
367
347
  return /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, null, "Searching for brain '", identifier, "'..."));
@@ -372,31 +352,20 @@ import { apiClient, isApiLocalDevMode } from '../commands/helpers.js';
372
352
  });
373
353
  }
374
354
  if (phase === 'disambiguating') {
375
- return /*#__PURE__*/ React.createElement(Box, {
376
- flexDirection: "column"
377
- }, /*#__PURE__*/ React.createElement(Text, {
378
- bold: true
379
- }, "Multiple brains match '", identifier, "':"), /*#__PURE__*/ React.createElement(Box, {
380
- marginTop: 1,
381
- flexDirection: "column"
382
- }, brains.map(function(brain, index) {
383
- var isSelected = index === selectedIndex;
384
- return /*#__PURE__*/ React.createElement(Box, {
385
- key: brain.title,
386
- flexDirection: "column",
387
- marginBottom: 1
388
- }, /*#__PURE__*/ React.createElement(Text, {
389
- color: isSelected ? 'cyan' : undefined
390
- }, isSelected ? '▶ ' : ' ', /*#__PURE__*/ React.createElement(Text, {
391
- bold: true
392
- }, brain.title)), /*#__PURE__*/ React.createElement(Text, {
393
- dimColor: true
394
- }, ' ', brain.description));
395
- })), /*#__PURE__*/ React.createElement(Box, {
396
- marginTop: 1
397
- }, /*#__PURE__*/ React.createElement(Text, {
398
- dimColor: true
399
- }, "Use arrow keys to navigate, Enter to select, q to quit")));
355
+ return /*#__PURE__*/ React.createElement(SelectList, {
356
+ items: brains.map(function(b) {
357
+ return {
358
+ id: b.title,
359
+ label: b.title,
360
+ description: b.description
361
+ };
362
+ }),
363
+ header: "Multiple brains match '".concat(identifier, "':"),
364
+ onSelect: function(item) {
365
+ setResolvedTitle(item.label);
366
+ setPhase('resolved');
367
+ }
368
+ });
400
369
  }
401
370
  if (phase === 'resolved' && resolvedTitle) {
402
371
  return /*#__PURE__*/ React.createElement(React.Fragment, null, children(resolvedTitle));
@@ -217,17 +217,17 @@ function _ts_generator(thisArg, body) {
217
217
  }
218
218
  }
219
219
  import React, { useState, useEffect, useCallback } from 'react';
220
- import { Box, Text, useInput, useApp } from 'ink';
220
+ import { Box, Text, useApp } from 'ink';
221
221
  import { ErrorComponent } from './error.js';
222
+ import { SelectList } from './select-list.js';
222
223
  import { Watch } from './watch.js';
223
224
  import { apiClient, isApiLocalDevMode } from '../commands/helpers.js';
224
225
  export var BrainRun = function(param) {
225
226
  var identifier = param.identifier, watch = param.watch, options = param.options;
226
227
  var _useState = _sliced_to_array(useState('searching'), 2), phase = _useState[0], setPhase = _useState[1];
227
228
  var _useState1 = _sliced_to_array(useState([]), 2), brains = _useState1[0], setBrains = _useState1[1];
228
- var _useState2 = _sliced_to_array(useState(0), 2), selectedIndex = _useState2[0], setSelectedIndex = _useState2[1];
229
- var _useState3 = _sliced_to_array(useState(null), 2), runId = _useState3[0], setRunId = _useState3[1];
230
- var _useState4 = _sliced_to_array(useState(null), 2), error = _useState4[0], setError = _useState4[1];
229
+ var _useState2 = _sliced_to_array(useState(null), 2), runId = _useState2[0], setRunId = _useState2[1];
230
+ var _useState3 = _sliced_to_array(useState(null), 2), error = _useState3[0], setError = _useState3[1];
231
231
  var exit = useApp().exit;
232
232
  var getConnectionError = useCallback(function() {
233
233
  if (isApiLocalDevMode()) {
@@ -460,53 +460,36 @@ export var BrainRun = function(param) {
460
460
  runBrain,
461
461
  getConnectionError
462
462
  ]);
463
- // Handle keyboard input for disambiguation
464
- useInput(function(input, key) {
465
- if (phase !== 'disambiguating') return;
466
- if (key.upArrow) {
467
- setSelectedIndex(function(prev) {
468
- return (prev - 1 + brains.length) % brains.length;
469
- });
470
- } else if (key.downArrow) {
471
- setSelectedIndex(function(prev) {
472
- return (prev + 1) % brains.length;
473
- });
474
- } else if (key.return) {
475
- var selectedBrain = brains[selectedIndex];
476
- runBrain(selectedBrain.title);
477
- } else if (input === 'q' || key.escape) {
463
+ // Exit the app when run completes without watch mode
464
+ useEffect(function() {
465
+ if (phase === 'complete' && runId && !watch) {
478
466
  exit();
479
467
  }
480
- });
468
+ }, [
469
+ phase,
470
+ runId,
471
+ watch,
472
+ exit
473
+ ]);
481
474
  // Maintain consistent Box wrapper to help Ink properly calculate
482
475
  // terminal clearing between renders (prevents appending instead of overwriting)
483
476
  return /*#__PURE__*/ React.createElement(Box, {
484
477
  flexDirection: "column"
485
478
  }, phase === 'searching' ? /*#__PURE__*/ React.createElement(Text, null, "Searching for brain '", identifier, "'...") : phase === 'error' && error ? /*#__PURE__*/ React.createElement(ErrorComponent, {
486
479
  error: error
487
- }) : phase === 'disambiguating' ? /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(Text, {
488
- bold: true
489
- }, "Multiple brains match '", identifier, "':"), /*#__PURE__*/ React.createElement(Box, {
490
- marginTop: 1,
491
- flexDirection: "column"
492
- }, brains.map(function(brain, index) {
493
- var isSelected = index === selectedIndex;
494
- return /*#__PURE__*/ React.createElement(Box, {
495
- key: brain.title,
496
- flexDirection: "column",
497
- marginBottom: 1
498
- }, /*#__PURE__*/ React.createElement(Text, {
499
- color: isSelected ? 'cyan' : undefined
500
- }, isSelected ? '▶ ' : ' ', /*#__PURE__*/ React.createElement(Text, {
501
- bold: true
502
- }, brain.title)), /*#__PURE__*/ React.createElement(Text, {
503
- dimColor: true
504
- }, ' ', brain.description));
505
- })), /*#__PURE__*/ React.createElement(Box, {
506
- marginTop: 1
507
- }, /*#__PURE__*/ React.createElement(Text, {
508
- dimColor: true
509
- }, "Use arrow keys to navigate, Enter to select, q to quit"))) : phase === 'running' ? /*#__PURE__*/ React.createElement(Text, null, "Starting brain run...") : phase === 'complete' && runId ? watch ? /*#__PURE__*/ React.createElement(Watch, {
480
+ }) : phase === 'disambiguating' ? /*#__PURE__*/ React.createElement(SelectList, {
481
+ items: brains.map(function(b) {
482
+ return {
483
+ id: b.title,
484
+ label: b.title,
485
+ description: b.description
486
+ };
487
+ }),
488
+ header: "Multiple brains match '".concat(identifier, "':"),
489
+ onSelect: function(item) {
490
+ runBrain(item.label);
491
+ }
492
+ }) : phase === 'running' ? /*#__PURE__*/ React.createElement(Text, null, "Starting brain run...") : phase === 'complete' && runId ? watch ? /*#__PURE__*/ React.createElement(Watch, {
510
493
  runId: runId
511
494
  }) : /*#__PURE__*/ React.createElement(Text, null, "Run ID: ", runId) : null);
512
495
  };