@positronic/cli 0.0.55 → 0.0.57

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 (94) hide show
  1. package/dist/src/cli.js +142 -2
  2. package/dist/src/commands/auth.js +98 -0
  3. package/dist/src/commands/brain.js +3 -2
  4. package/dist/src/commands/helpers.js +48 -10
  5. package/dist/src/commands/project-config-manager.js +119 -0
  6. package/dist/src/commands/users.js +91 -0
  7. package/dist/src/components/agent-chat-view.js +125 -0
  8. package/dist/src/components/auth-list.js +56 -0
  9. package/dist/src/components/auth-login.js +209 -0
  10. package/dist/src/components/auth-logout.js +75 -0
  11. package/dist/src/components/auth-status.js +88 -0
  12. package/dist/src/components/brain-run.js +287 -254
  13. package/dist/src/components/brain-top-table.js +4 -0
  14. package/dist/src/components/event-detail.js +364 -0
  15. package/dist/src/components/events-view.js +379 -0
  16. package/dist/src/components/state-view.js +52 -0
  17. package/dist/src/components/top-navigator.js +80 -6
  18. package/dist/src/components/types.js +1 -0
  19. package/dist/src/components/users-create.js +293 -0
  20. package/dist/src/components/users-delete.js +294 -0
  21. package/dist/src/components/users-keys-add.js +156 -0
  22. package/dist/src/components/users-keys-list.js +119 -0
  23. package/dist/src/components/users-keys-remove.js +299 -0
  24. package/dist/src/components/users-list.js +109 -0
  25. package/dist/src/components/watch-keyboard.js +136 -0
  26. package/dist/src/components/watch-machine.js +573 -0
  27. package/dist/src/components/watch-resolver.js +3 -2
  28. package/dist/src/components/watch.js +390 -36
  29. package/dist/src/hooks/useApi.js +80 -42
  30. package/dist/src/lib/request-signer.js +208 -0
  31. package/dist/src/lib/ssh-key-utils.js +212 -0
  32. package/dist/src/utils/agent-utils.js +107 -0
  33. package/dist/types/cli.d.ts.map +1 -1
  34. package/dist/types/commands/auth.d.ts +36 -0
  35. package/dist/types/commands/auth.d.ts.map +1 -0
  36. package/dist/types/commands/brain.d.ts +2 -1
  37. package/dist/types/commands/brain.d.ts.map +1 -1
  38. package/dist/types/commands/helpers.d.ts.map +1 -1
  39. package/dist/types/commands/project-config-manager.d.ts +43 -0
  40. package/dist/types/commands/project-config-manager.d.ts.map +1 -1
  41. package/dist/types/commands/users.d.ts +33 -0
  42. package/dist/types/commands/users.d.ts.map +1 -0
  43. package/dist/types/components/agent-chat-view.d.ts +12 -0
  44. package/dist/types/components/agent-chat-view.d.ts.map +1 -0
  45. package/dist/types/components/auth-list.d.ts +7 -0
  46. package/dist/types/components/auth-list.d.ts.map +1 -0
  47. package/dist/types/components/auth-login.d.ts +9 -0
  48. package/dist/types/components/auth-login.d.ts.map +1 -0
  49. package/dist/types/components/auth-logout.d.ts +8 -0
  50. package/dist/types/components/auth-logout.d.ts.map +1 -0
  51. package/dist/types/components/auth-status.d.ts +7 -0
  52. package/dist/types/components/auth-status.d.ts.map +1 -0
  53. package/dist/types/components/brain-run.d.ts +11 -1
  54. package/dist/types/components/brain-run.d.ts.map +1 -1
  55. package/dist/types/components/brain-top-table.d.ts.map +1 -1
  56. package/dist/types/components/event-detail.d.ts +10 -0
  57. package/dist/types/components/event-detail.d.ts.map +1 -0
  58. package/dist/types/components/events-view.d.ts +13 -0
  59. package/dist/types/components/events-view.d.ts.map +1 -0
  60. package/dist/types/components/state-view.d.ts +13 -0
  61. package/dist/types/components/state-view.d.ts.map +1 -0
  62. package/dist/types/components/top-navigator.d.ts.map +1 -1
  63. package/dist/types/components/types.d.ts +11 -0
  64. package/dist/types/components/types.d.ts.map +1 -0
  65. package/dist/types/components/users-create.d.ts +6 -0
  66. package/dist/types/components/users-create.d.ts.map +1 -0
  67. package/dist/types/components/users-delete.d.ts +7 -0
  68. package/dist/types/components/users-delete.d.ts.map +1 -0
  69. package/dist/types/components/users-keys-add.d.ts +8 -0
  70. package/dist/types/components/users-keys-add.d.ts.map +1 -0
  71. package/dist/types/components/users-keys-list.d.ts +6 -0
  72. package/dist/types/components/users-keys-list.d.ts.map +1 -0
  73. package/dist/types/components/users-keys-remove.d.ts +8 -0
  74. package/dist/types/components/users-keys-remove.d.ts.map +1 -0
  75. package/dist/types/components/users-list.d.ts +2 -0
  76. package/dist/types/components/users-list.d.ts.map +1 -0
  77. package/dist/types/components/watch-keyboard.d.ts +56 -0
  78. package/dist/types/components/watch-keyboard.d.ts.map +1 -0
  79. package/dist/types/components/watch-machine.d.ts +171 -0
  80. package/dist/types/components/watch-machine.d.ts.map +1 -0
  81. package/dist/types/components/watch-resolver.d.ts +2 -1
  82. package/dist/types/components/watch-resolver.d.ts.map +1 -1
  83. package/dist/types/components/watch.d.ts +2 -1
  84. package/dist/types/components/watch.d.ts.map +1 -1
  85. package/dist/types/hooks/useApi.d.ts.map +1 -1
  86. package/dist/types/hooks/useBrainMachine.d.ts +9 -3
  87. package/dist/types/hooks/useBrainMachine.d.ts.map +1 -1
  88. package/dist/types/lib/request-signer.d.ts +51 -0
  89. package/dist/types/lib/request-signer.d.ts.map +1 -0
  90. package/dist/types/lib/ssh-key-utils.d.ts +45 -0
  91. package/dist/types/lib/ssh-key-utils.d.ts.map +1 -0
  92. package/dist/types/utils/agent-utils.d.ts +20 -0
  93. package/dist/types/utils/agent-utils.d.ts.map +1 -0
  94. package/package.json +7 -4
@@ -6,6 +6,9 @@ function _array_like_to_array(arr, len) {
6
6
  function _array_with_holes(arr) {
7
7
  if (Array.isArray(arr)) return arr;
8
8
  }
9
+ function _array_without_holes(arr) {
10
+ if (Array.isArray(arr)) return _array_like_to_array(arr);
11
+ }
9
12
  function _define_property(obj, key, value) {
10
13
  if (key in obj) {
11
14
  Object.defineProperty(obj, key, {
@@ -19,6 +22,9 @@ function _define_property(obj, key, value) {
19
22
  }
20
23
  return obj;
21
24
  }
25
+ function _iterable_to_array(iter) {
26
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
27
+ }
22
28
  function _iterable_to_array_limit(arr, i) {
23
29
  var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
24
30
  if (_i == null) return;
@@ -46,6 +52,9 @@ function _iterable_to_array_limit(arr, i) {
46
52
  function _non_iterable_rest() {
47
53
  throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
48
54
  }
55
+ function _non_iterable_spread() {
56
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
57
+ }
49
58
  function _object_spread(target) {
50
59
  for(var i = 1; i < arguments.length; i++){
51
60
  var source = arguments[i] != null ? arguments[i] : {};
@@ -64,6 +73,9 @@ function _object_spread(target) {
64
73
  function _sliced_to_array(arr, i) {
65
74
  return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
66
75
  }
76
+ function _to_consumable_array(arr) {
77
+ return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
78
+ }
67
79
  function _unsupported_iterable_to_array(o, minLen) {
68
80
  if (!o) return;
69
81
  if (typeof o === "string") return _array_like_to_array(o, minLen);
@@ -74,12 +86,19 @@ function _unsupported_iterable_to_array(o, minLen) {
74
86
  }
75
87
  import React, { useState, useEffect, useRef } from 'react';
76
88
  import { Text, Box, useStdout, useInput, useApp } from 'ink';
89
+ import TextInput from 'ink-text-input';
77
90
  import { EventSource } from 'eventsource';
78
- import { BRAIN_EVENTS, STATUS } from '@positronic/core';
91
+ import { BRAIN_EVENTS, STATUS, reconstructBrainTree, createBrainExecutionMachine, sendEvent } from '@positronic/core';
79
92
  import { useBrainMachine } from '../hooks/useBrainMachine.js';
80
93
  import { getApiBaseUrl, isApiLocalDevMode } from '../commands/helpers.js';
81
- import { useApiDelete } from '../hooks/useApi.js';
82
94
  import { ErrorComponent } from './error.js';
95
+ import { EventsView } from './events-view.js';
96
+ import { StateView } from './state-view.js';
97
+ import { AgentChatView } from './agent-chat-view.js';
98
+ import { SelectList } from './select-list.js';
99
+ import { getAgentLoops } from '../utils/agent-utils.js';
100
+ import { handleKeyboardInput } from './watch-keyboard.js';
101
+ import { useWatchMachine, machineStateToViewMode, isConfirmingKill, isKillingState, isPausingState, isResumingState, isSendingMessageState } from './watch-machine.js';
83
102
  // Get the index of the currently running step (or last completed if none running)
84
103
  var getCurrentStepIndex = function(steps) {
85
104
  var runningIndex = steps.findIndex(function(s) {
@@ -200,9 +219,25 @@ var BrainSection = function(param) {
200
219
  })));
201
220
  };
202
221
  export var Watch = function(param) {
203
- var runId = param.runId, _param_manageScreenBuffer = param.manageScreenBuffer, manageScreenBuffer = _param_manageScreenBuffer === void 0 ? true : _param_manageScreenBuffer, _param_footer = param.footer, footer = _param_footer === void 0 ? 'x kill • esc quit' : _param_footer;
222
+ var runId = param.runId, _param_manageScreenBuffer = param.manageScreenBuffer, manageScreenBuffer = _param_manageScreenBuffer === void 0 ? true : _param_manageScreenBuffer, footer = param.footer, _param_startWithEvents = param.startWithEvents, startWithEvents = _param_startWithEvents === void 0 ? false : _param_startWithEvents;
204
223
  var write = useStdout().write;
205
224
  var exit = useApp().exit;
225
+ // UI navigation state machine - handles view transitions and related context
226
+ var _useWatchMachine = _sliced_to_array(useWatchMachine(runId, startWithEvents), 2), watchState = _useWatchMachine[0], sendWatch = _useWatchMachine[1];
227
+ // Derive viewMode from machine state
228
+ var viewMode = machineStateToViewMode(watchState.name);
229
+ // Read navigation and async operation state from machine context
230
+ var _watchState_context = watchState.context, previousViewMode = _watchState_context.previousView, stateSnapshot = _watchState_context.stateSnapshot, stateTitle = _watchState_context.stateTitle, stateScrollOffset = _watchState_context.stateScrollOffset, selectedAgentId = _watchState_context.selectedAgentId, agentChatScrollOffset = _watchState_context.agentChatScrollOffset, eventsSelectedIndex = _watchState_context.eventsSelectedIndex, killError = _watchState_context.killError, isKilled = _watchState_context.isKilled, pauseResumeMessage = _watchState_context.pauseResumeMessage, messageText = _watchState_context.messageText, messageSentFeedback = _watchState_context.messageFeedback;
231
+ // Derive async operation flags from machine state
232
+ var confirmingKill = isConfirmingKill(watchState.name);
233
+ var isKilling = isKillingState(watchState.name);
234
+ var isPausing = isPausingState(watchState.name);
235
+ var isResuming = isResumingState(watchState.name);
236
+ var isSendingMessage = isSendingMessageState(watchState.name);
237
+ // Events array (large, not navigation state)
238
+ var _useState = _sliced_to_array(useState([]), 2), events = _useState[0], setEvents = _useState[1];
239
+ // Events view mode (delegated to EventsView component)
240
+ var _useState1 = _sliced_to_array(useState('auto'), 2), eventsViewMode = _useState1[0], setEventsViewMode = _useState1[1];
206
241
  // Use state machine to track brain execution state
207
242
  // Machine is recreated when runId changes, giving us fresh context
208
243
  var _useBrainMachine = _sliced_to_array(useBrainMachine(runId), 2), current = _useBrainMachine[0], send = _useBrainMachine[1];
@@ -216,16 +251,15 @@ export var Watch = function(param) {
216
251
  send
217
252
  ]);
218
253
  // Read brain state directly from machine context - useMachine handles re-renders
219
- var _current_context = current.context, rootBrain = _current_context.rootBrain, isComplete = _current_context.isComplete;
254
+ var _current_context = current.context, brains = _current_context.brains, brainIdStack = _current_context.brainIdStack, isComplete = _current_context.isComplete;
255
+ // Reconstruct the tree for UI display - this is O(depth) but depth is tiny
256
+ var rootBrain = reconstructBrainTree(brains, brainIdStack);
220
257
  // Additional state for connection and errors (not part of the brain state machine)
221
- var _useState = _sliced_to_array(useState(undefined), 2), brainError = _useState[0], setBrainError = _useState[1];
222
- var _useState1 = _sliced_to_array(useState(null), 2), connectionError = _useState1[0], setConnectionError = _useState1[1];
223
- var _useState2 = _sliced_to_array(useState(false), 2), isConnected = _useState2[0], setIsConnected = _useState2[1];
224
- // Kill state
225
- var _useState3 = _sliced_to_array(useState(false), 2), confirmingKill = _useState3[0], setConfirmingKill = _useState3[1];
226
- var _useState4 = _sliced_to_array(useState(false), 2), isKilling = _useState4[0], setIsKilling = _useState4[1];
227
- var _useState5 = _sliced_to_array(useState(false), 2), isKilled = _useState5[0], setIsKilled = _useState5[1];
228
- var _useApiDelete = useApiDelete('brain'), killBrain = _useApiDelete.execute, killError = _useApiDelete.error;
258
+ var _useState2 = _sliced_to_array(useState(undefined), 2), brainError = _useState2[0], setBrainError = _useState2[1];
259
+ var _useState3 = _sliced_to_array(useState(null), 2), connectionError = _useState3[0], setConnectionError = _useState3[1];
260
+ var _useState4 = _sliced_to_array(useState(false), 2), isConnected = _useState4[0], setIsConnected = _useState4[1];
261
+ // Track paused status from brain state machine
262
+ var isPaused = current.context.status === STATUS.PAUSED;
229
263
  // Enter alternate screen buffer on mount, exit on unmount
230
264
  // Skip in test environment or when parent manages screen buffer
231
265
  useEffect(function() {
@@ -258,6 +292,16 @@ export var Watch = function(param) {
258
292
  es.onmessage = function(event) {
259
293
  try {
260
294
  var eventData = JSON.parse(event.data);
295
+ // Store event for events view (keep last 500 events to prevent memory issues)
296
+ setEvents(function(prev) {
297
+ var newEvents = _to_consumable_array(prev).concat([
298
+ {
299
+ timestamp: new Date(),
300
+ event: eventData
301
+ }
302
+ ]);
303
+ return newEvents.slice(-500);
304
+ });
261
305
  // Send event to state machine - useMachine handles re-renders automatically
262
306
  // Use ref to ensure we always call the latest send function
263
307
  sendRef.current(eventData);
@@ -281,28 +325,177 @@ export var Watch = function(param) {
281
325
  }, [
282
326
  runId
283
327
  ]);
284
- // Keyboard handling
328
+ // Handler for viewing state at a specific event index (called from EventsView)
329
+ var handleViewStateAtEvent = function(eventIndex) {
330
+ // Store selected index before transitioning
331
+ sendWatch({
332
+ type: 'SET_EVENTS_SELECTED_INDEX',
333
+ index: eventIndex
334
+ });
335
+ // Use the brain state machine to reconstruct state at this point
336
+ var machine = createBrainExecutionMachine();
337
+ for(var i = 0; i <= eventIndex && i < events.length; i++){
338
+ sendEvent(machine, events[i].event);
339
+ }
340
+ // Transition to state view with the reconstructed state
341
+ sendWatch({
342
+ type: 'GO_TO_STATE',
343
+ stateSnapshot: machine.context.currentState,
344
+ stateTitle: "State at event #".concat(eventIndex + 1),
345
+ fromView: 'events'
346
+ });
347
+ };
348
+ // Handler for sending a USER_MESSAGE signal
349
+ var handleSendMessage = function() {
350
+ if (!messageText.trim() || isSendingMessage) return;
351
+ // Trigger the machine's sending-message invoke state
352
+ sendWatch({
353
+ type: 'SEND_MESSAGE'
354
+ });
355
+ };
356
+ // Auto-clear message feedback after success
357
+ useEffect(function() {
358
+ if (messageSentFeedback === 'success') {
359
+ var timer = setTimeout(function() {
360
+ sendWatch({
361
+ type: 'CLEAR_FEEDBACK'
362
+ });
363
+ }, 1000);
364
+ return function() {
365
+ return clearTimeout(timer);
366
+ };
367
+ }
368
+ }, [
369
+ messageSentFeedback,
370
+ sendWatch
371
+ ]);
372
+ // Auto-clear pause/resume message after showing
373
+ useEffect(function() {
374
+ if (pauseResumeMessage) {
375
+ var timer = setTimeout(function() {
376
+ sendWatch({
377
+ type: 'CLEAR_PAUSE_RESUME_MESSAGE'
378
+ });
379
+ }, 2000);
380
+ return function() {
381
+ return clearTimeout(timer);
382
+ };
383
+ }
384
+ }, [
385
+ pauseResumeMessage,
386
+ sendWatch
387
+ ]);
388
+ // Build keyboard context for the handler
389
+ var brainTitle = rootBrain === null || rootBrain === void 0 ? void 0 : rootBrain.brainTitle;
390
+ var agentLoops = getAgentLoops(events, brainTitle);
391
+ var hasAgents = agentLoops.length > 0;
392
+ // Keyboard handling - uses extracted handler for event mapping
285
393
  useInput(function(input, key) {
286
- if (confirmingKill) {
287
- if (input === 'y') {
288
- setConfirmingKill(false);
289
- setIsKilling(true);
290
- killBrain("/brains/runs/".concat(runId)).then(function() {
291
- setIsKilled(true);
292
- }).finally(function() {
293
- setIsKilling(false);
394
+ var keyboardContext = {
395
+ viewMode: viewMode,
396
+ eventsViewMode: eventsViewMode,
397
+ confirmingKill: confirmingKill,
398
+ isKilling: isKilling,
399
+ isKilled: isKilled,
400
+ isComplete: isComplete,
401
+ isPaused: isPaused,
402
+ isPausing: isPausing,
403
+ isResuming: isResuming,
404
+ hasAgents: hasAgents,
405
+ manageScreenBuffer: manageScreenBuffer
406
+ };
407
+ var event = handleKeyboardInput(input, key, keyboardContext);
408
+ if (!event) return;
409
+ // Handle each event type - forward to the state machine
410
+ switch(event.type){
411
+ case 'CONFIRM_KILL':
412
+ sendWatch({
413
+ type: 'CONFIRM_KILL'
294
414
  });
295
- } else if (input === 'n' || key.escape) {
296
- setConfirmingKill(false);
297
- }
298
- } else {
299
- if (input === 'x' && !isKilling && !isKilled && !isComplete) {
300
- setConfirmingKill(true);
301
- } else if ((input === 'q' || key.escape) && manageScreenBuffer) {
302
- // Only handle quit when standalone (manageScreenBuffer=true)
303
- // When embedded, parent handles q/escape
415
+ break;
416
+ case 'CANCEL_KILL':
417
+ sendWatch({
418
+ type: 'CANCEL_KILL'
419
+ });
420
+ break;
421
+ case 'GO_BACK':
422
+ sendWatch({
423
+ type: 'GO_BACK'
424
+ });
425
+ break;
426
+ case 'CANCEL_MESSAGE_INPUT':
427
+ sendWatch({
428
+ type: 'GO_BACK'
429
+ });
430
+ break;
431
+ case 'GO_TO_EVENTS':
432
+ sendWatch({
433
+ type: 'GO_TO_EVENTS'
434
+ });
435
+ break;
436
+ case 'GO_TO_PROGRESS':
437
+ sendWatch({
438
+ type: 'GO_TO_PROGRESS'
439
+ });
440
+ break;
441
+ case 'GO_TO_STATE':
442
+ {
443
+ var _current_context_currentState;
444
+ var currentState = (_current_context_currentState = current.context.currentState) !== null && _current_context_currentState !== void 0 ? _current_context_currentState : {};
445
+ sendWatch({
446
+ type: 'GO_TO_STATE',
447
+ stateSnapshot: currentState,
448
+ stateTitle: 'Current State',
449
+ fromView: 'progress'
450
+ });
451
+ break;
452
+ }
453
+ case 'INITIATE_KILL':
454
+ sendWatch({
455
+ type: 'INITIATE_KILL'
456
+ });
457
+ break;
458
+ case 'GO_TO_AGENTS':
459
+ {
460
+ var fromView = viewMode === 'events' ? 'events' : 'progress';
461
+ if (agentLoops.length === 1) {
462
+ // Go directly to chat view for single agent
463
+ sendWatch({
464
+ type: 'GO_TO_AGENTS',
465
+ selectedAgentId: agentLoops[0].stepId,
466
+ fromView: fromView
467
+ });
468
+ } else {
469
+ // Show picker for multiple agents
470
+ sendWatch({
471
+ type: 'GO_TO_AGENTS',
472
+ fromView: fromView
473
+ });
474
+ }
475
+ break;
476
+ }
477
+ case 'GO_TO_MESSAGE_INPUT':
478
+ {
479
+ var fromView1 = viewMode === 'events' ? 'events' : 'progress';
480
+ sendWatch({
481
+ type: 'GO_TO_MESSAGE_INPUT',
482
+ fromView: fromView1
483
+ });
484
+ break;
485
+ }
486
+ case 'PAUSE':
487
+ sendWatch({
488
+ type: 'PAUSE'
489
+ });
490
+ break;
491
+ case 'RESUME':
492
+ sendWatch({
493
+ type: 'RESUME'
494
+ });
495
+ break;
496
+ case 'QUIT':
304
497
  exit();
305
- }
498
+ break;
306
499
  }
307
500
  });
308
501
  // Prepare error props using destructuring
@@ -317,12 +510,154 @@ export var Watch = function(param) {
317
510
  // Prepare kill error props
318
511
  var killErrorProps = killError ? {
319
512
  title: 'Kill Error',
320
- message: killError.message,
321
- details: killError.details
513
+ message: killError.message
322
514
  } : null;
515
+ // Build footer based on current mode
516
+ var getFooter = function() {
517
+ var canSendMessage = hasAgents && !isComplete;
518
+ if (viewMode === 'state') {
519
+ return 'j/k scroll | space/shift+space page | b back';
520
+ } else if (viewMode === 'agent-chat') {
521
+ return 'j/k scroll | space/shift+space page | b back';
522
+ } else if (viewMode === 'agent-picker') {
523
+ return 'j/k select | Enter view | b back';
524
+ } else if (viewMode === 'message-input') {
525
+ return 'Enter send | Esc cancel';
526
+ } else if (viewMode === 'events') {
527
+ if (eventsViewMode === 'detail') {
528
+ return 'j/k scroll • b back';
529
+ } else if (eventsViewMode === 'navigating') {
530
+ var msgPart = canSendMessage ? ' | m message' : '';
531
+ return "j/k select | Enter detail | s state | a agents".concat(msgPart, " | b back | esc auto-scroll");
532
+ } else {
533
+ var msgPart1 = canSendMessage ? ' | m message' : '';
534
+ return "j/k select | a agents".concat(msgPart1, " | b back | x kill | esc quit");
535
+ }
536
+ } else {
537
+ var msgPart2 = canSendMessage ? ' | m message' : '';
538
+ var pauseResumePart = isPaused ? ' | r resume' : !isComplete ? ' | p pause' : '';
539
+ return "s state | e events | a agents".concat(pauseResumePart).concat(msgPart2, " | x kill | esc quit");
540
+ }
541
+ };
542
+ var displayFooter = footer !== null && footer !== void 0 ? footer : getFooter();
323
543
  return /*#__PURE__*/ React.createElement(Box, {
324
544
  flexDirection: "column"
325
- }, !isConnected && !rootBrain ? /*#__PURE__*/ React.createElement(Text, null, "Connecting to watch service...") : !rootBrain ? /*#__PURE__*/ React.createElement(Text, null, "Waiting for brain to start...") : /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(BrainSection, {
545
+ }, !isConnected && !rootBrain ? /*#__PURE__*/ React.createElement(Text, null, "Connecting to watch service...") : viewMode === 'state' && stateSnapshot !== null ? /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(StateView, {
546
+ state: stateSnapshot,
547
+ title: stateTitle,
548
+ scrollOffset: stateScrollOffset,
549
+ onScrollChange: function(offset) {
550
+ return sendWatch({
551
+ type: 'SET_STATE_SCROLL_OFFSET',
552
+ offset: offset
553
+ });
554
+ },
555
+ isActive: viewMode === 'state'
556
+ }), connectionErrorProps && /*#__PURE__*/ React.createElement(ErrorComponent, {
557
+ error: connectionErrorProps
558
+ }), brainErrorProps && /*#__PURE__*/ React.createElement(ErrorComponent, {
559
+ error: brainErrorProps
560
+ })) : viewMode === 'agent-picker' ? /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(SelectList, {
561
+ items: agentLoops.map(function(agent) {
562
+ return {
563
+ id: agent.stepId,
564
+ label: agent.label,
565
+ description: "".concat(agent.rawResponseEvents.length, " response(s)")
566
+ };
567
+ }),
568
+ header: "Select an agent to view:",
569
+ onSelect: function(item) {
570
+ sendWatch({
571
+ type: 'AGENT_SELECTED',
572
+ agentId: item.id
573
+ });
574
+ },
575
+ onCancel: function() {
576
+ return sendWatch({
577
+ type: 'GO_BACK'
578
+ });
579
+ },
580
+ footer: "j/k select | Enter view | b back"
581
+ }), connectionErrorProps && /*#__PURE__*/ React.createElement(ErrorComponent, {
582
+ error: connectionErrorProps
583
+ }), brainErrorProps && /*#__PURE__*/ React.createElement(ErrorComponent, {
584
+ error: brainErrorProps
585
+ })) : viewMode === 'agent-chat' && selectedAgentId ? function() {
586
+ var selectedAgent = agentLoops.find(function(a) {
587
+ return a.stepId === selectedAgentId;
588
+ });
589
+ if (!selectedAgent) {
590
+ return /*#__PURE__*/ React.createElement(Text, null, "Agent not found");
591
+ }
592
+ return /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(AgentChatView, {
593
+ label: selectedAgent.label,
594
+ agentStartEvent: selectedAgent.startEvent,
595
+ rawResponseEvents: selectedAgent.rawResponseEvents,
596
+ scrollOffset: agentChatScrollOffset,
597
+ onScrollChange: function(offset) {
598
+ return sendWatch({
599
+ type: 'SET_AGENT_CHAT_SCROLL_OFFSET',
600
+ offset: offset
601
+ });
602
+ },
603
+ isActive: viewMode === 'agent-chat'
604
+ }), connectionErrorProps && /*#__PURE__*/ React.createElement(ErrorComponent, {
605
+ error: connectionErrorProps
606
+ }), brainErrorProps && /*#__PURE__*/ React.createElement(ErrorComponent, {
607
+ error: brainErrorProps
608
+ }));
609
+ }() : viewMode === 'events' ? /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(EventsView, {
610
+ events: events,
611
+ totalTokens: current.context.totalTokens,
612
+ isActive: viewMode === 'events',
613
+ onModeChange: setEventsViewMode,
614
+ onViewState: handleViewStateAtEvent,
615
+ selectedIndex: eventsSelectedIndex,
616
+ onSelectedIndexChange: function(index) {
617
+ return sendWatch({
618
+ type: 'SET_EVENTS_SELECTED_INDEX',
619
+ index: index
620
+ });
621
+ }
622
+ }), connectionErrorProps && /*#__PURE__*/ React.createElement(ErrorComponent, {
623
+ error: connectionErrorProps
624
+ }), brainErrorProps && /*#__PURE__*/ React.createElement(ErrorComponent, {
625
+ error: brainErrorProps
626
+ })) : viewMode === 'message-input' ? /*#__PURE__*/ React.createElement(Box, {
627
+ flexDirection: "column"
628
+ }, /*#__PURE__*/ React.createElement(Box, {
629
+ marginBottom: 1
630
+ }, /*#__PURE__*/ React.createElement(Text, {
631
+ bold: true
632
+ }, "Send message to agent:")), /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, {
633
+ color: "cyan"
634
+ }, "> "), /*#__PURE__*/ React.createElement(TextInput, {
635
+ value: messageText,
636
+ onChange: function(text) {
637
+ return sendWatch({
638
+ type: 'SET_MESSAGE_TEXT',
639
+ text: text
640
+ });
641
+ },
642
+ onSubmit: handleSendMessage,
643
+ focus: true
644
+ })), isSendingMessage && /*#__PURE__*/ React.createElement(Box, {
645
+ marginTop: 1
646
+ }, /*#__PURE__*/ React.createElement(Text, {
647
+ color: "yellow"
648
+ }, "Sending...")), messageSentFeedback === 'success' && /*#__PURE__*/ React.createElement(Box, {
649
+ marginTop: 1
650
+ }, /*#__PURE__*/ React.createElement(Text, {
651
+ color: "green"
652
+ }, "Message sent!")), messageSentFeedback === 'error' && /*#__PURE__*/ React.createElement(Box, {
653
+ marginTop: 1
654
+ }, /*#__PURE__*/ React.createElement(Text, {
655
+ color: "red"
656
+ }, "Failed to send message")), connectionErrorProps && /*#__PURE__*/ React.createElement(ErrorComponent, {
657
+ error: connectionErrorProps
658
+ }), brainErrorProps && /*#__PURE__*/ React.createElement(ErrorComponent, {
659
+ error: brainErrorProps
660
+ })) : !rootBrain ? /*#__PURE__*/ React.createElement(Text, null, "Waiting for brain to start...") : /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(BrainSection, {
326
661
  brain: rootBrain
327
662
  }), confirmingKill && /*#__PURE__*/ React.createElement(Box, {
328
663
  marginTop: 1
@@ -339,7 +674,26 @@ export var Watch = function(param) {
339
674
  paddingX: 1
340
675
  }, /*#__PURE__*/ React.createElement(Text, {
341
676
  color: "red"
342
- }, "Brain killed.")), isComplete && !connectionError && !brainError && !isKilled && /*#__PURE__*/ React.createElement(Box, {
677
+ }, "Brain killed.")), isPaused && !isKilled && /*#__PURE__*/ React.createElement(Box, {
678
+ marginTop: 1,
679
+ borderStyle: "round",
680
+ borderColor: "cyan",
681
+ paddingX: 1
682
+ }, /*#__PURE__*/ React.createElement(Text, {
683
+ color: "cyan"
684
+ }, "Brain paused. Press 'r' to resume.")), isPausing && /*#__PURE__*/ React.createElement(Box, {
685
+ marginTop: 1
686
+ }, /*#__PURE__*/ React.createElement(Text, {
687
+ color: "yellow"
688
+ }, "Sending pause signal...")), isResuming && /*#__PURE__*/ React.createElement(Box, {
689
+ marginTop: 1
690
+ }, /*#__PURE__*/ React.createElement(Text, {
691
+ color: "yellow"
692
+ }, "Sending resume signal...")), pauseResumeMessage && !isPausing && !isResuming && /*#__PURE__*/ React.createElement(Box, {
693
+ marginTop: 1
694
+ }, /*#__PURE__*/ React.createElement(Text, {
695
+ color: "cyan"
696
+ }, pauseResumeMessage)), isComplete && !connectionError && !brainError && !isKilled && /*#__PURE__*/ React.createElement(Box, {
343
697
  marginTop: 1,
344
698
  borderStyle: "round",
345
699
  borderColor: "green",
@@ -356,5 +710,5 @@ export var Watch = function(param) {
356
710
  marginTop: 1
357
711
  }, /*#__PURE__*/ React.createElement(Text, {
358
712
  dimColor: true
359
- }, footer)));
713
+ }, displayFooter)));
360
714
  };