@positronic/cli 0.0.56 → 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 (87) hide show
  1. package/dist/src/cli.js +130 -0
  2. package/dist/src/commands/auth.js +98 -0
  3. package/dist/src/commands/helpers.js +48 -10
  4. package/dist/src/commands/project-config-manager.js +119 -0
  5. package/dist/src/commands/users.js +91 -0
  6. package/dist/src/components/agent-chat-view.js +125 -0
  7. package/dist/src/components/auth-list.js +56 -0
  8. package/dist/src/components/auth-login.js +209 -0
  9. package/dist/src/components/auth-logout.js +75 -0
  10. package/dist/src/components/auth-status.js +88 -0
  11. package/dist/src/components/brain-run.js +287 -254
  12. package/dist/src/components/brain-top-table.js +4 -0
  13. package/dist/src/components/event-detail.js +364 -0
  14. package/dist/src/components/events-view.js +221 -25
  15. package/dist/src/components/state-view.js +52 -0
  16. package/dist/src/components/top-navigator.js +80 -6
  17. package/dist/src/components/types.js +1 -0
  18. package/dist/src/components/users-create.js +293 -0
  19. package/dist/src/components/users-delete.js +294 -0
  20. package/dist/src/components/users-keys-add.js +156 -0
  21. package/dist/src/components/users-keys-list.js +119 -0
  22. package/dist/src/components/users-keys-remove.js +299 -0
  23. package/dist/src/components/users-list.js +109 -0
  24. package/dist/src/components/watch-keyboard.js +136 -0
  25. package/dist/src/components/watch-machine.js +573 -0
  26. package/dist/src/components/watch.js +357 -44
  27. package/dist/src/hooks/useApi.js +80 -42
  28. package/dist/src/lib/request-signer.js +208 -0
  29. package/dist/src/lib/ssh-key-utils.js +212 -0
  30. package/dist/src/utils/agent-utils.js +107 -0
  31. package/dist/types/cli.d.ts.map +1 -1
  32. package/dist/types/commands/auth.d.ts +36 -0
  33. package/dist/types/commands/auth.d.ts.map +1 -0
  34. package/dist/types/commands/helpers.d.ts.map +1 -1
  35. package/dist/types/commands/project-config-manager.d.ts +43 -0
  36. package/dist/types/commands/project-config-manager.d.ts.map +1 -1
  37. package/dist/types/commands/users.d.ts +33 -0
  38. package/dist/types/commands/users.d.ts.map +1 -0
  39. package/dist/types/components/agent-chat-view.d.ts +12 -0
  40. package/dist/types/components/agent-chat-view.d.ts.map +1 -0
  41. package/dist/types/components/auth-list.d.ts +7 -0
  42. package/dist/types/components/auth-list.d.ts.map +1 -0
  43. package/dist/types/components/auth-login.d.ts +9 -0
  44. package/dist/types/components/auth-login.d.ts.map +1 -0
  45. package/dist/types/components/auth-logout.d.ts +8 -0
  46. package/dist/types/components/auth-logout.d.ts.map +1 -0
  47. package/dist/types/components/auth-status.d.ts +7 -0
  48. package/dist/types/components/auth-status.d.ts.map +1 -0
  49. package/dist/types/components/brain-run.d.ts +11 -1
  50. package/dist/types/components/brain-run.d.ts.map +1 -1
  51. package/dist/types/components/brain-top-table.d.ts.map +1 -1
  52. package/dist/types/components/event-detail.d.ts +10 -0
  53. package/dist/types/components/event-detail.d.ts.map +1 -0
  54. package/dist/types/components/events-view.d.ts +9 -7
  55. package/dist/types/components/events-view.d.ts.map +1 -1
  56. package/dist/types/components/state-view.d.ts +13 -0
  57. package/dist/types/components/state-view.d.ts.map +1 -0
  58. package/dist/types/components/top-navigator.d.ts.map +1 -1
  59. package/dist/types/components/types.d.ts +11 -0
  60. package/dist/types/components/types.d.ts.map +1 -0
  61. package/dist/types/components/users-create.d.ts +6 -0
  62. package/dist/types/components/users-create.d.ts.map +1 -0
  63. package/dist/types/components/users-delete.d.ts +7 -0
  64. package/dist/types/components/users-delete.d.ts.map +1 -0
  65. package/dist/types/components/users-keys-add.d.ts +8 -0
  66. package/dist/types/components/users-keys-add.d.ts.map +1 -0
  67. package/dist/types/components/users-keys-list.d.ts +6 -0
  68. package/dist/types/components/users-keys-list.d.ts.map +1 -0
  69. package/dist/types/components/users-keys-remove.d.ts +8 -0
  70. package/dist/types/components/users-keys-remove.d.ts.map +1 -0
  71. package/dist/types/components/users-list.d.ts +2 -0
  72. package/dist/types/components/users-list.d.ts.map +1 -0
  73. package/dist/types/components/watch-keyboard.d.ts +56 -0
  74. package/dist/types/components/watch-keyboard.d.ts.map +1 -0
  75. package/dist/types/components/watch-machine.d.ts +171 -0
  76. package/dist/types/components/watch-machine.d.ts.map +1 -0
  77. package/dist/types/components/watch.d.ts.map +1 -1
  78. package/dist/types/hooks/useApi.d.ts.map +1 -1
  79. package/dist/types/hooks/useBrainMachine.d.ts +9 -3
  80. package/dist/types/hooks/useBrainMachine.d.ts.map +1 -1
  81. package/dist/types/lib/request-signer.d.ts +51 -0
  82. package/dist/types/lib/request-signer.d.ts.map +1 -0
  83. package/dist/types/lib/ssh-key-utils.d.ts +45 -0
  84. package/dist/types/lib/ssh-key-utils.d.ts.map +1 -0
  85. package/dist/types/utils/agent-utils.d.ts +20 -0
  86. package/dist/types/utils/agent-utils.d.ts.map +1 -0
  87. package/package.json +7 -4
@@ -86,13 +86,19 @@ function _unsupported_iterable_to_array(o, minLen) {
86
86
  }
87
87
  import React, { useState, useEffect, useRef } from 'react';
88
88
  import { Text, Box, useStdout, useInput, useApp } from 'ink';
89
+ import TextInput from 'ink-text-input';
89
90
  import { EventSource } from 'eventsource';
90
- import { BRAIN_EVENTS, STATUS } from '@positronic/core';
91
+ import { BRAIN_EVENTS, STATUS, reconstructBrainTree, createBrainExecutionMachine, sendEvent } from '@positronic/core';
91
92
  import { useBrainMachine } from '../hooks/useBrainMachine.js';
92
93
  import { getApiBaseUrl, isApiLocalDevMode } from '../commands/helpers.js';
93
- import { useApiDelete } from '../hooks/useApi.js';
94
94
  import { ErrorComponent } from './error.js';
95
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';
96
102
  // Get the index of the currently running step (or last completed if none running)
97
103
  var getCurrentStepIndex = function(steps) {
98
104
  var runningIndex = steps.findIndex(function(s) {
@@ -216,9 +222,22 @@ export var Watch = function(param) {
216
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;
217
223
  var write = useStdout().write;
218
224
  var exit = useApp().exit;
219
- // View mode state (progress view vs events log)
220
- var _useState = _sliced_to_array(useState(startWithEvents ? 'events' : 'progress'), 2), viewMode = _useState[0], setViewMode = _useState[1];
221
- var _useState1 = _sliced_to_array(useState([]), 2), events = _useState1[0], setEvents = _useState1[1];
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];
222
241
  // Use state machine to track brain execution state
223
242
  // Machine is recreated when runId changes, giving us fresh context
224
243
  var _useBrainMachine = _sliced_to_array(useBrainMachine(runId), 2), current = _useBrainMachine[0], send = _useBrainMachine[1];
@@ -232,16 +251,15 @@ export var Watch = function(param) {
232
251
  send
233
252
  ]);
234
253
  // Read brain state directly from machine context - useMachine handles re-renders
235
- 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);
236
257
  // Additional state for connection and errors (not part of the brain state machine)
237
258
  var _useState2 = _sliced_to_array(useState(undefined), 2), brainError = _useState2[0], setBrainError = _useState2[1];
238
259
  var _useState3 = _sliced_to_array(useState(null), 2), connectionError = _useState3[0], setConnectionError = _useState3[1];
239
260
  var _useState4 = _sliced_to_array(useState(false), 2), isConnected = _useState4[0], setIsConnected = _useState4[1];
240
- // Kill state
241
- var _useState5 = _sliced_to_array(useState(false), 2), confirmingKill = _useState5[0], setConfirmingKill = _useState5[1];
242
- var _useState6 = _sliced_to_array(useState(false), 2), isKilling = _useState6[0], setIsKilling = _useState6[1];
243
- var _useState7 = _sliced_to_array(useState(false), 2), isKilled = _useState7[0], setIsKilled = _useState7[1];
244
- var _useApiDelete = useApiDelete('brain'), killBrain = _useApiDelete.execute, killError = _useApiDelete.error;
261
+ // Track paused status from brain state machine
262
+ var isPaused = current.context.status === STATUS.PAUSED;
245
263
  // Enter alternate screen buffer on mount, exit on unmount
246
264
  // Skip in test environment or when parent manages screen buffer
247
265
  useEffect(function() {
@@ -307,33 +325,177 @@ export var Watch = function(param) {
307
325
  }, [
308
326
  runId
309
327
  ]);
310
- // 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
311
393
  useInput(function(input, key) {
312
- if (confirmingKill) {
313
- if (input === 'y') {
314
- setConfirmingKill(false);
315
- setIsKilling(true);
316
- killBrain("/brains/runs/".concat(runId)).then(function() {
317
- setIsKilled(true);
318
- }).finally(function() {
319
- 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'
320
414
  });
321
- } else if (input === 'n' || key.escape) {
322
- setConfirmingKill(false);
323
- }
324
- } else {
325
- // View toggle
326
- if (input === 'e') {
327
- setViewMode('events');
328
- } else if (input === 'w') {
329
- setViewMode('progress');
330
- } else if (input === 'x' && !isKilling && !isKilled && !isComplete) {
331
- setConfirmingKill(true);
332
- } else if ((input === 'q' || key.escape) && manageScreenBuffer) {
333
- // Only handle quit when standalone (manageScreenBuffer=true)
334
- // 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':
335
497
  exit();
336
- }
498
+ break;
337
499
  }
338
500
  });
339
501
  // Prepare error props using destructuring
@@ -348,21 +510,153 @@ export var Watch = function(param) {
348
510
  // Prepare kill error props
349
511
  var killErrorProps = killError ? {
350
512
  title: 'Kill Error',
351
- message: killError.message,
352
- details: killError.details
513
+ message: killError.message
353
514
  } : null;
354
- // Dynamic footer showing view toggle hint
355
- var viewToggle = viewMode === 'progress' ? 'e events' : 'w progress';
356
- var defaultFooter = "".concat(viewToggle, " | x kill | esc quit");
357
- var displayFooter = footer !== null && footer !== void 0 ? footer : defaultFooter;
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();
358
543
  return /*#__PURE__*/ React.createElement(Box, {
359
544
  flexDirection: "column"
360
- }, !isConnected && !rootBrain ? /*#__PURE__*/ React.createElement(Text, null, "Connecting to watch service...") : viewMode === 'events' ? /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(EventsView, {
361
- events: events
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'
362
556
  }), connectionErrorProps && /*#__PURE__*/ React.createElement(ErrorComponent, {
363
557
  error: connectionErrorProps
364
558
  }), brainErrorProps && /*#__PURE__*/ React.createElement(ErrorComponent, {
365
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
366
660
  })) : !rootBrain ? /*#__PURE__*/ React.createElement(Text, null, "Waiting for brain to start...") : /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(BrainSection, {
367
661
  brain: rootBrain
368
662
  }), confirmingKill && /*#__PURE__*/ React.createElement(Box, {
@@ -380,7 +674,26 @@ export var Watch = function(param) {
380
674
  paddingX: 1
381
675
  }, /*#__PURE__*/ React.createElement(Text, {
382
676
  color: "red"
383
- }, "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, {
384
697
  marginTop: 1,
385
698
  borderStyle: "round",
386
699
  borderColor: "green",