@positronic/cli 0.0.50 → 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
@@ -6,9 +6,6 @@ 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
- }
12
9
  function _define_property(obj, key, value) {
13
10
  if (key in obj) {
14
11
  Object.defineProperty(obj, key, {
@@ -22,9 +19,6 @@ function _define_property(obj, key, value) {
22
19
  }
23
20
  return obj;
24
21
  }
25
- function _iterable_to_array(iter) {
26
- if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
27
- }
28
22
  function _iterable_to_array_limit(arr, i) {
29
23
  var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
30
24
  if (_i == null) return;
@@ -52,9 +46,6 @@ function _iterable_to_array_limit(arr, i) {
52
46
  function _non_iterable_rest() {
53
47
  throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
54
48
  }
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
- }
58
49
  function _object_spread(target) {
59
50
  for(var i = 1; i < arguments.length; i++){
60
51
  var source = arguments[i] != null ? arguments[i] : {};
@@ -70,36 +61,9 @@ function _object_spread(target) {
70
61
  }
71
62
  return target;
72
63
  }
73
- function ownKeys(object, enumerableOnly) {
74
- var keys = Object.keys(object);
75
- if (Object.getOwnPropertySymbols) {
76
- var symbols = Object.getOwnPropertySymbols(object);
77
- if (enumerableOnly) {
78
- symbols = symbols.filter(function(sym) {
79
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
80
- });
81
- }
82
- keys.push.apply(keys, symbols);
83
- }
84
- return keys;
85
- }
86
- function _object_spread_props(target, source) {
87
- source = source != null ? source : {};
88
- if (Object.getOwnPropertyDescriptors) {
89
- Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
90
- } else {
91
- ownKeys(Object(source)).forEach(function(key) {
92
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
93
- });
94
- }
95
- return target;
96
- }
97
64
  function _sliced_to_array(arr, i) {
98
65
  return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
99
66
  }
100
- function _to_consumable_array(arr) {
101
- return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
102
- }
103
67
  function _unsupported_iterable_to_array(o, minLen) {
104
68
  if (!o) return;
105
69
  if (typeof o === "string") return _array_like_to_array(o, minLen);
@@ -109,10 +73,12 @@ function _unsupported_iterable_to_array(o, minLen) {
109
73
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
110
74
  }
111
75
  import React, { useState, useEffect, useRef } from 'react';
112
- import { Text, Box, useStdout } from 'ink';
76
+ import { Text, Box, useStdout, useInput, useApp } from 'ink';
113
77
  import { EventSource } from 'eventsource';
114
- import { BRAIN_EVENTS, STATUS, createBrainExecutionMachine, sendEvent } from '@positronic/core';
78
+ import { BRAIN_EVENTS, STATUS } from '@positronic/core';
79
+ import { useBrainMachine } from '../hooks/useBrainMachine.js';
115
80
  import { getApiBaseUrl, isApiLocalDevMode } from '../commands/helpers.js';
81
+ import { useApiDelete } from '../hooks/useApi.js';
116
82
  import { ErrorComponent } from './error.js';
117
83
  // Get the index of the currently running step (or last completed if none running)
118
84
  var getCurrentStepIndex = function(steps) {
@@ -202,19 +168,11 @@ var StepWindow = function(param) {
202
168
  }, getStatusChar(nextStep.status), " ", nextStep.title)));
203
169
  };
204
170
  var BrainSection = function(param) {
205
- var brain = param.brain, _param_isInner = param.isInner, isInner = _param_isInner === void 0 ? false : _param_isInner, brainStack = param.brainStack;
171
+ var brain = param.brain, _param_isInner = param.isInner, isInner = _param_isInner === void 0 ? false : _param_isInner;
206
172
  var indent = isInner ? 2 : 0;
207
173
  var completed = getCompletedCount(brain.steps);
208
174
  var total = brain.steps.length;
209
- // Find the currently running step to check for inner brain
210
- var currentIndex = getCurrentStepIndex(brain.steps);
211
- var currentStep = brain.steps[currentIndex];
212
- // Find any inner brain associated with the current step (active inner brains are on the stack)
213
- // Must exclude the current brain to prevent infinite recursion when a restarted brain
214
- // has parentStepId matching its own step IDs
215
- var innerBrain = currentStep ? brainStack.find(function(b) {
216
- return b.parentStepId === currentStep.id && b !== brain;
217
- }) : null;
175
+ var innerBrain = brain.innerBrain;
218
176
  return /*#__PURE__*/ React.createElement(Box, {
219
177
  flexDirection: "column",
220
178
  marginLeft: indent
@@ -238,25 +196,40 @@ var BrainSection = function(param) {
238
196
  marginTop: 1
239
197
  }, /*#__PURE__*/ React.createElement(BrainSection, {
240
198
  brain: innerBrain,
241
- isInner: true,
242
- brainStack: brainStack
199
+ isInner: true
243
200
  })));
244
201
  };
245
202
  export var Watch = function(param) {
246
- var runId = param.runId;
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;
247
204
  var write = useStdout().write;
205
+ var exit = useApp().exit;
248
206
  // Use state machine to track brain execution state
249
- var machineRef = useRef(createBrainExecutionMachine());
250
- // Store brain stack in state to trigger re-renders when it changes
251
- var _useState = _sliced_to_array(useState([]), 2), brainStack = _useState[0], setBrainStack = _useState[1];
252
- var _useState1 = _sliced_to_array(useState(undefined), 2), brainError = _useState1[0], setBrainError = _useState1[1];
253
- var _useState2 = _sliced_to_array(useState(null), 2), error = _useState2[0], setError = _useState2[1];
254
- var _useState3 = _sliced_to_array(useState(false), 2), isConnected = _useState3[0], setIsConnected = _useState3[1];
255
- var _useState4 = _sliced_to_array(useState(false), 2), isCompleted = _useState4[0], setIsCompleted = _useState4[1];
207
+ // Machine is recreated when runId changes, giving us fresh context
208
+ var _useBrainMachine = _sliced_to_array(useBrainMachine(runId), 2), current = _useBrainMachine[0], send = _useBrainMachine[1];
209
+ // Keep a ref to the latest send function to avoid stale closure issues
210
+ // When runId changes, useMachine updates send asynchronously, but our EventSource
211
+ // effect runs immediately. Using a ref ensures we always call the current send.
212
+ var sendRef = useRef(send);
213
+ useEffect(function() {
214
+ sendRef.current = send;
215
+ }, [
216
+ send
217
+ ]);
218
+ // 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;
220
+ // 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;
256
229
  // Enter alternate screen buffer on mount, exit on unmount
257
- // Skip in test environment to avoid interfering with test output capture
230
+ // Skip in test environment or when parent manages screen buffer
258
231
  useEffect(function() {
259
- if (process.env.NODE_ENV === 'test') {
232
+ if (process.env.NODE_ENV === 'test' || !manageScreenBuffer) {
260
233
  return;
261
234
  }
262
235
  // Enter alternate screen buffer and clear
@@ -266,59 +239,39 @@ export var Watch = function(param) {
266
239
  write('\x1B[?1049l');
267
240
  };
268
241
  }, [
269
- write
242
+ write,
243
+ manageScreenBuffer
270
244
  ]);
271
245
  useEffect(function() {
272
246
  var baseUrl = getApiBaseUrl();
273
247
  var url = "".concat(baseUrl, "/brains/runs/").concat(runId, "/watch");
274
248
  var es = new EventSource(url);
275
- // Reset state machine for new connection
276
- machineRef.current = createBrainExecutionMachine();
249
+ // Reset connection state for new connection
250
+ // Note: rootBrain and isComplete are handled by the new machine (via useMemo)
277
251
  setIsConnected(false);
278
- setError(null);
279
- setBrainStack([]);
252
+ setConnectionError(null);
280
253
  setBrainError(undefined);
281
- setIsCompleted(false);
282
254
  es.onopen = function() {
283
255
  setIsConnected(true);
284
- setError(null);
256
+ setConnectionError(null);
285
257
  };
286
258
  es.onmessage = function(event) {
287
259
  try {
288
260
  var eventData = JSON.parse(event.data);
289
- var machine = machineRef.current;
290
- // Feed event to state machine - it handles all the state tracking
291
- sendEvent(machine, eventData);
292
- // Update React state from machine context to trigger re-render
293
- // Deep copy brainStack to ensure React detects the change
294
- // Note: Only update if brainStack has entries - preserve last known state for completed brains
295
- var currentStack = machine.context.brainStack;
296
- if (currentStack.length > 0) {
297
- setBrainStack(currentStack.map(function(entry) {
298
- return _object_spread_props(_object_spread({}, entry), {
299
- steps: _to_consumable_array(entry.steps)
300
- });
301
- }));
302
- }
303
- // Check for completion (outer brain)
304
- if (machine.context.isComplete) {
305
- setIsCompleted(true);
306
- }
307
- // Check for error (capture the error event for display)
261
+ // Send event to state machine - useMachine handles re-renders automatically
262
+ // Use ref to ensure we always call the latest send function
263
+ sendRef.current(eventData);
264
+ // Capture error event for display (error state is separate from machine)
308
265
  if (eventData.type === BRAIN_EVENTS.ERROR) {
309
- var errorEvent = eventData;
310
- // Only show error for the main brain (isTopLevel check)
311
- if (machine.context.brainRunId === errorEvent.brainRunId) {
312
- setBrainError(errorEvent);
313
- }
266
+ setBrainError(eventData);
314
267
  }
315
268
  } catch (e) {
316
- setError(new Error("Error parsing event data: ".concat(e.message)));
269
+ setConnectionError(new Error("Error parsing event data: ".concat(e.message)));
317
270
  }
318
271
  };
319
272
  es.onerror = function() {
320
273
  var errorMessage = isApiLocalDevMode() ? "Connection to ".concat(url, " failed. Ensure the local development server is running ('positronic server' or 'px s').") : "Connection to ".concat(url, " failed. Please check your network connection and verify the project URL is correct.");
321
- setError(new Error(errorMessage));
274
+ setConnectionError(new Error(errorMessage));
322
275
  setIsConnected(false);
323
276
  es.close();
324
277
  };
@@ -328,31 +281,80 @@ export var Watch = function(param) {
328
281
  }, [
329
282
  runId
330
283
  ]);
331
- // Main brain is the first entry in the stack (outer brain)
332
- var mainBrain = brainStack.length > 0 ? brainStack[0] : null;
284
+ // Keyboard handling
285
+ 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);
294
+ });
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
304
+ exit();
305
+ }
306
+ }
307
+ });
308
+ // Prepare error props using destructuring
309
+ var connectionErrorProps = connectionError ? {
310
+ title: 'Connection Error',
311
+ message: connectionError.message,
312
+ details: connectionError.stack
313
+ } : null;
314
+ var brainErrorProps = brainError ? _object_spread({
315
+ title: brainError.error.name || 'Brain Error'
316
+ }, brainError.error) : null;
317
+ // Prepare kill error props
318
+ var killErrorProps = killError ? {
319
+ title: 'Kill Error',
320
+ message: killError.message,
321
+ details: killError.details
322
+ } : null;
333
323
  return /*#__PURE__*/ React.createElement(Box, {
334
324
  flexDirection: "column"
335
- }, !isConnected && brainStack.length === 0 ? /*#__PURE__*/ React.createElement(Text, null, "Connecting to watch service...") : !mainBrain ? /*#__PURE__*/ React.createElement(Text, null, "Waiting for brain to start...") : /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(BrainSection, {
336
- brain: mainBrain,
337
- brainStack: brainStack
338
- }), isCompleted && !error && !brainError && /*#__PURE__*/ React.createElement(Box, {
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, {
326
+ brain: rootBrain
327
+ }), confirmingKill && /*#__PURE__*/ React.createElement(Box, {
328
+ marginTop: 1
329
+ }, /*#__PURE__*/ React.createElement(Text, {
330
+ color: "yellow"
331
+ }, "Kill brain? (y/n)")), isKilling && /*#__PURE__*/ React.createElement(Box, {
332
+ marginTop: 1
333
+ }, /*#__PURE__*/ React.createElement(Text, {
334
+ color: "yellow"
335
+ }, "Killing brain...")), isKilled && /*#__PURE__*/ React.createElement(Box, {
336
+ marginTop: 1,
337
+ borderStyle: "round",
338
+ borderColor: "red",
339
+ paddingX: 1
340
+ }, /*#__PURE__*/ React.createElement(Text, {
341
+ color: "red"
342
+ }, "Brain killed.")), isComplete && !connectionError && !brainError && !isKilled && /*#__PURE__*/ React.createElement(Box, {
339
343
  marginTop: 1,
340
344
  borderStyle: "round",
341
345
  borderColor: "green",
342
346
  paddingX: 1
343
347
  }, /*#__PURE__*/ React.createElement(Text, {
344
348
  color: "green"
345
- }, "Brain completed.")), error && /*#__PURE__*/ React.createElement(ErrorComponent, {
346
- error: {
347
- title: 'Connection Error',
348
- message: error.message,
349
- details: error.stack
350
- }
351
- }), brainError && /*#__PURE__*/ React.createElement(ErrorComponent, {
352
- error: {
353
- title: brainError.error.name || 'Brain Error',
354
- message: brainError.error.message,
355
- details: brainError.error.stack
356
- }
357
- })));
349
+ }, "Brain completed.")), connectionErrorProps && /*#__PURE__*/ React.createElement(ErrorComponent, {
350
+ error: connectionErrorProps
351
+ }), brainErrorProps && /*#__PURE__*/ React.createElement(ErrorComponent, {
352
+ error: brainErrorProps
353
+ }), killErrorProps && /*#__PURE__*/ React.createElement(ErrorComponent, {
354
+ error: killErrorProps
355
+ })), /*#__PURE__*/ React.createElement(Box, {
356
+ marginTop: 1
357
+ }, /*#__PURE__*/ React.createElement(Text, {
358
+ dimColor: true
359
+ }, footer)));
358
360
  };
@@ -0,0 +1,19 @@
1
+ import { useMemo } from 'react';
2
+ import { useMachine } from 'react-robot';
3
+ import { createBrainMachine } from '@positronic/core';
4
+ /**
5
+ * React hook for brain execution state machine.
6
+ * Creates a fresh machine when `key` changes.
7
+ *
8
+ * @param key - When this value changes, a new machine is created (like React's key prop)
9
+ * @param options - Optional machine configuration
10
+ * @returns [current, send] - Current state and send function from useMachine
11
+ */ export function useBrainMachine(key, options) {
12
+ // eslint-disable-next-line react-hooks/exhaustive-deps
13
+ var machine = useMemo(function() {
14
+ return createBrainMachine(options);
15
+ }, [
16
+ key
17
+ ]);
18
+ return useMachine(machine);
19
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAK5D,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,YAAY,KAAK,GAAG,CAAC;CAC9C;AAoBD,wBAAgB,QAAQ,CAAC,OAAO,EAAE,UAAU,4BAomC3C"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAK5D,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,YAAY,KAAK,GAAG,CAAC;CAC9C;AAoBD,wBAAgB,QAAQ,CAAC,OAAO,EAAE,UAAU,4BA0mC3C"}
@@ -23,21 +23,24 @@ interface BrainRunArgs {
23
23
  options?: Record<string, string>;
24
24
  }
25
25
  interface BrainWatchArgs {
26
- runId?: string;
27
- brain?: string;
26
+ identifier: string;
28
27
  }
29
28
  interface BrainKillArgs {
30
29
  runId: string;
31
30
  force: boolean;
32
31
  }
32
+ interface BrainTopArgs {
33
+ brain?: string;
34
+ }
33
35
  export declare class BrainCommand {
34
36
  list(argv: ArgumentsCamelCase<BrainListArgs>): React.ReactElement;
35
37
  history({ brain, limit, }: ArgumentsCamelCase<BrainHistoryArgs>): React.ReactElement;
36
38
  show({ brain, runId, steps, }: ArgumentsCamelCase<BrainShowArgs>): React.ReactElement;
37
39
  rerun({ brain, runId, startsAt, stopsAfter, }: ArgumentsCamelCase<BrainRerunArgs>): React.ReactElement;
38
40
  run({ brain, watch, options }: ArgumentsCamelCase<BrainRunArgs>): React.ReactElement;
39
- watch({ runId, brain, }: ArgumentsCamelCase<BrainWatchArgs>): React.ReactElement;
41
+ watch({ identifier, }: ArgumentsCamelCase<BrainWatchArgs>): React.ReactElement;
40
42
  kill({ runId, force, }: ArgumentsCamelCase<BrainKillArgs>): React.ReactElement;
43
+ top({ brain }: ArgumentsCamelCase<BrainTopArgs>): React.ReactElement;
41
44
  }
42
45
  export {};
43
46
  //# sourceMappingURL=brain.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"brain.d.ts","sourceRoot":"","sources":["../../../src/commands/brain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAChD,OAAO,KAAK,MAAM,OAAO,CAAC;AAa1B,UAAU,aAAa;CAAG;AAC1B,UAAU,gBAAgB;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AACD,UAAU,aAAa;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AACD,UAAU,cAAc;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AACD,UAAU,YAAY;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AACD,UAAU,cAAc;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AACD,UAAU,aAAa;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,qBAAa,YAAY;IACvB,IAAI,CAAC,IAAI,EAAE,kBAAkB,CAAC,aAAa,CAAC,GAAG,KAAK,CAAC,YAAY;IAIjE,OAAO,CAAC,EACN,KAAK,EACL,KAAK,GACN,EAAE,kBAAkB,CAAC,gBAAgB,CAAC,GAAG,KAAK,CAAC,YAAY;IAQ5D,IAAI,CAAC,EACH,KAAK,EACL,KAAK,EACL,KAAK,GACN,EAAE,kBAAkB,CAAC,aAAa,CAAC,GAAG,KAAK,CAAC,YAAY;IAqBzD,KAAK,CAAC,EACJ,KAAK,EACL,KAAK,EACL,QAAQ,EACR,UAAU,GACX,EAAE,kBAAkB,CAAC,cAAc,CAAC,GAAG,KAAK,CAAC,YAAY;IAa1D,GAAG,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,kBAAkB,CAAC,YAAY,CAAC,GAAG,KAAK,CAAC,YAAY;IAQpF,KAAK,CAAC,EACJ,KAAK,EACL,KAAK,GACN,EAAE,kBAAkB,CAAC,cAAc,CAAC,GAAG,KAAK,CAAC,YAAY;IAyB1D,IAAI,CAAC,EACH,KAAK,EACL,KAAK,GACN,EAAE,kBAAkB,CAAC,aAAa,CAAC,GAAG,KAAK,CAAC,YAAY;CAI1D"}
1
+ {"version":3,"file":"brain.d.ts","sourceRoot":"","sources":["../../../src/commands/brain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAChD,OAAO,KAAK,MAAM,OAAO,CAAC;AAa1B,UAAU,aAAa;CAAG;AAC1B,UAAU,gBAAgB;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AACD,UAAU,aAAa;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AACD,UAAU,cAAc;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AACD,UAAU,YAAY;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AACD,UAAU,cAAc;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB;AACD,UAAU,aAAa;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CAChB;AACD,UAAU,YAAY;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,YAAY;IACvB,IAAI,CAAC,IAAI,EAAE,kBAAkB,CAAC,aAAa,CAAC,GAAG,KAAK,CAAC,YAAY;IAIjE,OAAO,CAAC,EACN,KAAK,EACL,KAAK,GACN,EAAE,kBAAkB,CAAC,gBAAgB,CAAC,GAAG,KAAK,CAAC,YAAY;IAQ5D,IAAI,CAAC,EACH,KAAK,EACL,KAAK,EACL,KAAK,GACN,EAAE,kBAAkB,CAAC,aAAa,CAAC,GAAG,KAAK,CAAC,YAAY;IAqBzD,KAAK,CAAC,EACJ,KAAK,EACL,KAAK,EACL,QAAQ,EACR,UAAU,GACX,EAAE,kBAAkB,CAAC,cAAc,CAAC,GAAG,KAAK,CAAC,YAAY;IAa1D,GAAG,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,kBAAkB,CAAC,YAAY,CAAC,GAAG,KAAK,CAAC,YAAY;IAQpF,KAAK,CAAC,EACJ,UAAU,GACX,EAAE,kBAAkB,CAAC,cAAc,CAAC,GAAG,KAAK,CAAC,YAAY;IAI1D,IAAI,CAAC,EACH,KAAK,EACL,KAAK,GACN,EAAE,kBAAkB,CAAC,aAAa,CAAC,GAAG,KAAK,CAAC,YAAY;IAIzD,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,kBAAkB,CAAC,YAAY,CAAC,GAAG,KAAK,CAAC,YAAY;CAGrE"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/commands/server.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAEhD,OAAO,KAAK,EAAE,mBAAmB,EAAgB,MAAM,kBAAkB,CAAC;AAE1E,qBAAa,aAAa;IACZ,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,mBAAmB;IAEzC,MAAM,CAAC,IAAI,EAAE,kBAAkB,CAAC,GAAG,CAAC;YAwP5B,cAAc;IA4C5B,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,gBAAgB;YAUV,UAAU;CAiDzB"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/commands/server.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAEhD,OAAO,KAAK,EAAE,mBAAmB,EAAgB,MAAM,kBAAkB,CAAC;AAE1E,qBAAa,aAAa;IACZ,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,mBAAmB;IAEzC,MAAM,CAAC,IAAI,EAAE,kBAAkB,CAAC,GAAG,CAAC;YA8P5B,cAAc;IA4C5B,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,gBAAgB;YAUV,UAAU;CAiDzB"}
@@ -1 +1 @@
1
- {"version":3,"file":"brain-resolver.d.ts","sourceRoot":"","sources":["../../../src/components/brain-resolver.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAehE,UAAU,kBAAkB;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,CAAC,kBAAkB,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;CAC3D;AAID;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GAAI,0BAA0B,kBAAkB,mDA8IzE,CAAC"}
1
+ {"version":3,"file":"brain-resolver.d.ts","sourceRoot":"","sources":["../../../src/components/brain-resolver.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAgBhE,UAAU,kBAAkB;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,CAAC,kBAAkB,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;CAC3D;AAID;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GAAI,0BAA0B,kBAAkB,mDA0GzE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"brain-run.d.ts","sourceRoot":"","sources":["../../../src/components/brain-run.tsx"],"names":[],"mappings":"AAgBA,UAAU,aAAa;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAID,eAAO,MAAM,QAAQ,GAAI,gCAAgC,aAAa,4CAgLrE,CAAC"}
1
+ {"version":3,"file":"brain-run.d.ts","sourceRoot":"","sources":["../../../src/components/brain-run.tsx"],"names":[],"mappings":"AAiBA,UAAU,aAAa;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAID,eAAO,MAAM,QAAQ,GAAI,gCAAgC,aAAa,4CAoJrE,CAAC"}
@@ -0,0 +1,22 @@
1
+ interface RunningBrain {
2
+ brainRunId: string;
3
+ brainTitle: string;
4
+ brainDescription?: string;
5
+ type: string;
6
+ status: string;
7
+ options?: any;
8
+ error?: any;
9
+ createdAt: number;
10
+ startedAt?: number;
11
+ completedAt?: number;
12
+ }
13
+ interface BrainTopTableProps {
14
+ runningBrains: RunningBrain[];
15
+ selectedIndex?: number;
16
+ interactive?: boolean;
17
+ brainFilter?: string;
18
+ footer?: string;
19
+ }
20
+ export declare const BrainTopTable: ({ runningBrains, selectedIndex, interactive, brainFilter, footer, }: BrainTopTableProps) => import("react/jsx-runtime").JSX.Element;
21
+ export type { RunningBrain };
22
+ //# sourceMappingURL=brain-top-table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brain-top-table.d.ts","sourceRoot":"","sources":["../../../src/components/brain-top-table.tsx"],"names":[],"mappings":"AAIA,UAAU,YAAY;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,kBAAkB;IAC1B,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA2ED,eAAO,MAAM,aAAa,GAAI,qEAM3B,kBAAkB,4CAiHpB,CAAC;AAGF,YAAY,EAAE,YAAY,EAAE,CAAC"}
@@ -0,0 +1,6 @@
1
+ interface BrainTopProps {
2
+ brainFilter?: string;
3
+ }
4
+ export declare const BrainTop: ({ brainFilter }: BrainTopProps) => import("react/jsx-runtime").JSX.Element;
5
+ export {};
6
+ //# sourceMappingURL=brain-top.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brain-top.d.ts","sourceRoot":"","sources":["../../../src/components/brain-top.tsx"],"names":[],"mappings":"AAWA,UAAU,aAAa;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,QAAQ,GAAI,iBAAiB,aAAa,4CAuGtD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"project-select.d.ts","sourceRoot":"","sources":["../../../src/components/project-select.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAW,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAE3F,UAAU,kBAAkB;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,oBAAoB,CAAC;CACrC;AAgFD,eAAO,MAAM,aAAa,GAAI,yBAAyB,kBAAkB,4CAgHxE,CAAC"}
1
+ {"version":3,"file":"project-select.d.ts","sourceRoot":"","sources":["../../../src/components/project-select.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAW,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAE3F,UAAU,kBAAkB;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,oBAAoB,CAAC;CACrC;AAuDD,eAAO,MAAM,aAAa,GAAI,yBAAyB,kBAAkB,4CAgHxE,CAAC"}
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ export interface SelectListItem {
3
+ id: string;
4
+ label: string;
5
+ description?: string;
6
+ extra?: React.ReactNode;
7
+ }
8
+ export interface SelectListProps {
9
+ items: SelectListItem[];
10
+ header: string;
11
+ onSelect: (item: SelectListItem, index: number) => void;
12
+ onCancel?: () => void;
13
+ initialIndex?: number;
14
+ footer?: string;
15
+ }
16
+ /**
17
+ * SelectList - A reusable component for keyboard-navigable list selection.
18
+ *
19
+ * Manages its own selectedIndex state and handles keyboard navigation.
20
+ * Use arrow keys to navigate, Enter to select, q/Escape to cancel.
21
+ */
22
+ export declare const SelectList: ({ items, header, onSelect, onCancel, initialIndex, footer, }: SelectListProps) => import("react/jsx-runtime").JSX.Element;
23
+ //# sourceMappingURL=select-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-list.d.ts","sourceRoot":"","sources":["../../../src/components/select-list.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,eAAO,MAAM,UAAU,GAAI,8DAOxB,eAAe,4CAgDjB,CAAC"}
@@ -0,0 +1,6 @@
1
+ interface TopNavigatorProps {
2
+ brainFilter?: string;
3
+ }
4
+ export declare const TopNavigator: ({ brainFilter }: TopNavigatorProps) => import("react/jsx-runtime").JSX.Element;
5
+ export {};
6
+ //# sourceMappingURL=top-navigator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"top-navigator.d.ts","sourceRoot":"","sources":["../../../src/components/top-navigator.tsx"],"names":[],"mappings":"AAaA,UAAU,iBAAiB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAID,eAAO,MAAM,YAAY,GAAI,iBAAiB,iBAAiB,4CAuO9D,CAAC"}
@@ -0,0 +1,15 @@
1
+ interface WatchResolverProps {
2
+ identifier: string;
3
+ }
4
+ /**
5
+ * WatchResolver - Resolves an identifier to either a brain name or run ID and starts watching.
6
+ *
7
+ * State machine handles all async operations via invoke.
8
+ * Resolution order:
9
+ * 1. Try to resolve as a brain name (fuzzy search)
10
+ * 2. If no brain matches, try as a run ID
11
+ * 3. If neither works, show an error
12
+ */
13
+ export declare const WatchResolver: ({ identifier }: WatchResolverProps) => import("react/jsx-runtime").JSX.Element | null;
14
+ export {};
15
+ //# sourceMappingURL=watch-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch-resolver.d.ts","sourceRoot":"","sources":["../../../src/components/watch-resolver.tsx"],"names":[],"mappings":"AAmRA,UAAU,kBAAkB;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,GAAI,gBAAgB,kBAAkB,mDA4F/D,CAAC"}
@@ -1,6 +1,8 @@
1
1
  interface WatchProps {
2
2
  runId: string;
3
+ manageScreenBuffer?: boolean;
4
+ footer?: string;
3
5
  }
4
- export declare const Watch: ({ runId }: WatchProps) => import("react/jsx-runtime").JSX.Element;
6
+ export declare const Watch: ({ runId, manageScreenBuffer, footer }: WatchProps) => import("react/jsx-runtime").JSX.Element;
5
7
  export {};
6
8
  //# sourceMappingURL=watch.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../../src/components/watch.tsx"],"names":[],"mappings":"AAyLA,UAAU,UAAU;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,KAAK,GAAI,WAAW,UAAU,4CAyI1C,CAAC"}
1
+ {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../../src/components/watch.tsx"],"names":[],"mappings":"AA4KA,UAAU,UAAU;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,KAAK,GAAI,uCAAoE,UAAU,4CA6KnG,CAAC"}
@@ -0,0 +1,37 @@
1
+ import type { CreateMachineOptions } from '@positronic/core';
2
+ /**
3
+ * React hook for brain execution state machine.
4
+ * Creates a fresh machine when `key` changes.
5
+ *
6
+ * @param key - When this value changes, a new machine is created (like React's key prop)
7
+ * @param options - Optional machine configuration
8
+ * @returns [current, send] - Current state and send function from useMachine
9
+ */
10
+ export declare function useBrainMachine(key?: unknown, options?: CreateMachineOptions): [{
11
+ name: import("robot3").AllStateKeys<{
12
+ idle: import("robot3").MachineState<string>;
13
+ running: import("robot3").MachineState<string>;
14
+ paused: import("robot3").MachineState<string>;
15
+ complete: import("robot3").MachineState<any>;
16
+ error: import("robot3").MachineState<string>;
17
+ cancelled: import("robot3").MachineState<any>;
18
+ }>;
19
+ value: import("robot3").MachineState<string>;
20
+ } & {
21
+ context: import("@positronic/core").BrainExecutionContext;
22
+ }, import("robot3").SendFunction<string>, import("robot3").Service<import("robot3").Machine<{
23
+ idle: import("robot3").MachineState<string>;
24
+ running: import("robot3").MachineState<string>;
25
+ paused: import("robot3").MachineState<string>;
26
+ complete: import("robot3").MachineState<any>;
27
+ error: import("robot3").MachineState<string>;
28
+ cancelled: import("robot3").MachineState<any>;
29
+ }, import("@positronic/core").BrainExecutionContext, import("robot3").AllStateKeys<{
30
+ idle: import("robot3").MachineState<string>;
31
+ running: import("robot3").MachineState<string>;
32
+ paused: import("robot3").MachineState<string>;
33
+ complete: import("robot3").MachineState<any>;
34
+ error: import("robot3").MachineState<string>;
35
+ cancelled: import("robot3").MachineState<any>;
36
+ }>, string>>];
37
+ //# sourceMappingURL=useBrainMachine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useBrainMachine.d.ts","sourceRoot":"","sources":["../../../src/hooks/useBrainMachine.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7D;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;cAI5E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@positronic/cli",
3
- "version": "0.0.50",
3
+ "version": "0.0.52",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -23,9 +23,9 @@
23
23
  "clean": "rm -rf tsconfig.tsbuildinfo dist node_modules"
24
24
  },
25
25
  "dependencies": {
26
- "@positronic/core": "^0.0.49",
27
- "@positronic/spec": "^0.0.49",
28
- "@positronic/template-new-project": "^0.0.49",
26
+ "@positronic/core": "^0.0.52",
27
+ "@positronic/spec": "^0.0.52",
28
+ "@positronic/template-new-project": "^0.0.52",
29
29
  "caz": "^2.0.0",
30
30
  "chokidar": "^3.6.0",
31
31
  "dotenv": "^16.4.7",
@@ -34,6 +34,7 @@
34
34
  "istextorbinary": "^9.5.0",
35
35
  "node-fetch": "^3.3.2",
36
36
  "react": "^18.3.1",
37
+ "react-robot": "^1.2.1",
37
38
  "yargs": "^17.7.2"
38
39
  },
39
40
  "devDependencies": {