@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
@@ -0,0 +1,364 @@
1
+ function _array_like_to_array(arr, len) {
2
+ if (len == null || len > arr.length) len = arr.length;
3
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
4
+ return arr2;
5
+ }
6
+ function _array_without_holes(arr) {
7
+ if (Array.isArray(arr)) return _array_like_to_array(arr);
8
+ }
9
+ function _iterable_to_array(iter) {
10
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
11
+ }
12
+ function _non_iterable_spread() {
13
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
14
+ }
15
+ function _to_consumable_array(arr) {
16
+ return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
17
+ }
18
+ function _unsupported_iterable_to_array(o, minLen) {
19
+ if (!o) return;
20
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
21
+ var n = Object.prototype.toString.call(o).slice(8, -1);
22
+ if (n === "Object" && o.constructor) n = o.constructor.name;
23
+ if (n === "Map" || n === "Set") return Array.from(n);
24
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
25
+ }
26
+ import React from 'react';
27
+ import { Text, Box, useStdout, useInput } from 'ink';
28
+ import { BRAIN_EVENTS } from '@positronic/core';
29
+ function formatFullTimestamp(timestamp) {
30
+ return timestamp.toLocaleTimeString('en-US', {
31
+ hour: '2-digit',
32
+ minute: '2-digit',
33
+ second: '2-digit',
34
+ hour12: false
35
+ });
36
+ }
37
+ function formatValue(value) {
38
+ if (typeof value === 'string') return value;
39
+ return JSON.stringify(value, null, 2);
40
+ }
41
+ function getStatusIcon(status) {
42
+ switch(status){
43
+ case 'complete':
44
+ return '✓';
45
+ case 'running':
46
+ return '•';
47
+ case 'error':
48
+ return '✗';
49
+ default:
50
+ return '○';
51
+ }
52
+ }
53
+ function getEventSymbol(event) {
54
+ switch(event.type){
55
+ case BRAIN_EVENTS.START:
56
+ return {
57
+ symbol: '[>]',
58
+ color: 'yellow'
59
+ };
60
+ case BRAIN_EVENTS.COMPLETE:
61
+ return {
62
+ symbol: '[ok]',
63
+ color: 'green'
64
+ };
65
+ case BRAIN_EVENTS.ERROR:
66
+ return {
67
+ symbol: '[!!]',
68
+ color: 'red'
69
+ };
70
+ case BRAIN_EVENTS.CANCELLED:
71
+ return {
72
+ symbol: '[x]',
73
+ color: 'red'
74
+ };
75
+ case BRAIN_EVENTS.STEP_START:
76
+ return {
77
+ symbol: '[.]',
78
+ color: 'yellow'
79
+ };
80
+ case BRAIN_EVENTS.STEP_COMPLETE:
81
+ return {
82
+ symbol: '[+]',
83
+ color: 'green'
84
+ };
85
+ case BRAIN_EVENTS.STEP_RETRY:
86
+ return {
87
+ symbol: '[?]',
88
+ color: 'yellow'
89
+ };
90
+ case BRAIN_EVENTS.STEP_STATUS:
91
+ return {
92
+ symbol: '[-]',
93
+ color: 'gray'
94
+ };
95
+ case BRAIN_EVENTS.WEBHOOK:
96
+ return {
97
+ symbol: '[~]',
98
+ color: 'cyan'
99
+ };
100
+ case BRAIN_EVENTS.WEBHOOK_RESPONSE:
101
+ return {
102
+ symbol: '[<]',
103
+ color: 'cyan'
104
+ };
105
+ case BRAIN_EVENTS.AGENT_START:
106
+ return {
107
+ symbol: '[A]',
108
+ color: 'yellow'
109
+ };
110
+ case BRAIN_EVENTS.AGENT_ITERATION:
111
+ return {
112
+ symbol: '[#]',
113
+ color: 'gray'
114
+ };
115
+ case BRAIN_EVENTS.AGENT_TOOL_CALL:
116
+ return {
117
+ symbol: '[T]',
118
+ color: 'white'
119
+ };
120
+ case BRAIN_EVENTS.AGENT_TOOL_RESULT:
121
+ return {
122
+ symbol: '[R]',
123
+ color: 'white'
124
+ };
125
+ case BRAIN_EVENTS.AGENT_ASSISTANT_MESSAGE:
126
+ return {
127
+ symbol: '[M]',
128
+ color: 'white'
129
+ };
130
+ case BRAIN_EVENTS.AGENT_COMPLETE:
131
+ return {
132
+ symbol: '[A]',
133
+ color: 'green'
134
+ };
135
+ case BRAIN_EVENTS.AGENT_TOKEN_LIMIT:
136
+ return {
137
+ symbol: '[!]',
138
+ color: 'red'
139
+ };
140
+ case BRAIN_EVENTS.AGENT_ITERATION_LIMIT:
141
+ return {
142
+ symbol: '[!]',
143
+ color: 'red'
144
+ };
145
+ case BRAIN_EVENTS.AGENT_WEBHOOK:
146
+ return {
147
+ symbol: '[W]',
148
+ color: 'cyan'
149
+ };
150
+ default:
151
+ return {
152
+ symbol: '[?]',
153
+ color: 'gray'
154
+ };
155
+ }
156
+ }
157
+ function getEventDetailContent(event) {
158
+ switch(event.type){
159
+ case BRAIN_EVENTS.AGENT_TOOL_CALL:
160
+ return [
161
+ "Tool: ".concat(event.toolName),
162
+ "Tool Call ID: ".concat(event.toolCallId),
163
+ "Step: ".concat(event.stepTitle),
164
+ '',
165
+ 'Input:',
166
+ JSON.stringify(event.input, null, 2)
167
+ ].join('\n');
168
+ case BRAIN_EVENTS.AGENT_TOOL_RESULT:
169
+ return [
170
+ "Tool: ".concat(event.toolName),
171
+ "Tool Call ID: ".concat(event.toolCallId),
172
+ "Step: ".concat(event.stepTitle),
173
+ '',
174
+ 'Result:',
175
+ formatValue(event.result)
176
+ ].join('\n');
177
+ case BRAIN_EVENTS.ERROR:
178
+ return [
179
+ "Brain: ".concat(event.brainTitle),
180
+ '',
181
+ "Error: ".concat(event.error.name),
182
+ "Message: ".concat(event.error.message),
183
+ '',
184
+ 'Stack Trace:',
185
+ event.error.stack || '(no stack trace)'
186
+ ].join('\n');
187
+ case BRAIN_EVENTS.AGENT_COMPLETE:
188
+ return [
189
+ "Step: ".concat(event.stepTitle),
190
+ "Terminal Tool: ".concat(event.terminalToolName),
191
+ "Total Iterations: ".concat(event.totalIterations),
192
+ "Total Tokens: ".concat(event.totalTokens.toLocaleString()),
193
+ '',
194
+ 'Result:',
195
+ JSON.stringify(event.result, null, 2)
196
+ ].join('\n');
197
+ case BRAIN_EVENTS.AGENT_ITERATION:
198
+ return [
199
+ "Step: ".concat(event.stepTitle),
200
+ "Iteration: ".concat(event.iteration),
201
+ "Tokens This Iteration: ".concat(event.tokensThisIteration.toLocaleString()),
202
+ "Total Tokens So Far: ".concat(event.totalTokens.toLocaleString())
203
+ ].join('\n');
204
+ case BRAIN_EVENTS.STEP_COMPLETE:
205
+ return [
206
+ "Step: ".concat(event.stepTitle),
207
+ "Step ID: ".concat(event.stepId),
208
+ '',
209
+ 'State Patch:',
210
+ JSON.stringify(event.patch, null, 2)
211
+ ].join('\n');
212
+ case BRAIN_EVENTS.AGENT_START:
213
+ return [
214
+ "Step: ".concat(event.stepTitle),
215
+ "Step ID: ".concat(event.stepId),
216
+ '',
217
+ 'Tools:'
218
+ ].concat(_to_consumable_array(event.tools && event.tools.length > 0 ? event.tools.map(function(t) {
219
+ return " • ".concat(t);
220
+ }) : [
221
+ ' (none)'
222
+ ]), [
223
+ '',
224
+ 'Prompt:',
225
+ event.prompt
226
+ ], _to_consumable_array(event.system ? [
227
+ '',
228
+ 'System Prompt:',
229
+ event.system
230
+ ] : [])).join('\n');
231
+ case BRAIN_EVENTS.START:
232
+ return [
233
+ "Brain: ".concat(event.brainTitle)
234
+ ].concat(_to_consumable_array(event.brainDescription ? [
235
+ "Description: ".concat(event.brainDescription)
236
+ ] : []), [
237
+ "Run ID: ".concat(event.brainRunId),
238
+ '',
239
+ 'Options:',
240
+ JSON.stringify(event.options, null, 2)
241
+ ]).join('\n');
242
+ case BRAIN_EVENTS.AGENT_TOKEN_LIMIT:
243
+ return [
244
+ "Step: ".concat(event.stepTitle),
245
+ "Total Tokens: ".concat(event.totalTokens.toLocaleString()),
246
+ "Max Tokens: ".concat(event.maxTokens.toLocaleString()),
247
+ '',
248
+ 'Token limit exceeded. Agent stopped.'
249
+ ].join('\n');
250
+ case BRAIN_EVENTS.AGENT_ITERATION_LIMIT:
251
+ return [
252
+ "Step: ".concat(event.stepTitle),
253
+ "Iteration: ".concat(event.iteration),
254
+ "Max Iterations: ".concat(event.maxIterations),
255
+ "Total Tokens: ".concat(event.totalTokens.toLocaleString()),
256
+ '',
257
+ 'Iteration limit reached. Agent stopped.'
258
+ ].join('\n');
259
+ case BRAIN_EVENTS.STEP_STATUS:
260
+ return [
261
+ 'Steps:'
262
+ ].concat(_to_consumable_array(event.steps.map(function(s) {
263
+ return " ".concat(getStatusIcon(s.status), " ").concat(s.title);
264
+ }))).join('\n');
265
+ case BRAIN_EVENTS.AGENT_ASSISTANT_MESSAGE:
266
+ return [
267
+ "Step: ".concat(event.stepTitle),
268
+ '',
269
+ 'Message:',
270
+ event.content
271
+ ].join('\n');
272
+ case BRAIN_EVENTS.STEP_START:
273
+ return [
274
+ "Step: ".concat(event.stepTitle),
275
+ "Step ID: ".concat(event.stepId)
276
+ ].join('\n');
277
+ case BRAIN_EVENTS.STEP_RETRY:
278
+ return [
279
+ "Step: ".concat(event.stepTitle),
280
+ "Step ID: ".concat(event.stepId),
281
+ "Attempt: ".concat(event.attempt)
282
+ ].join('\n');
283
+ case BRAIN_EVENTS.COMPLETE:
284
+ return [
285
+ "Brain: ".concat(event.brainTitle),
286
+ '',
287
+ 'Brain completed successfully.'
288
+ ].join('\n');
289
+ case BRAIN_EVENTS.CANCELLED:
290
+ return [
291
+ "Brain: ".concat(event.brainTitle),
292
+ '',
293
+ 'Brain was cancelled.'
294
+ ].join('\n');
295
+ case BRAIN_EVENTS.WEBHOOK:
296
+ return [
297
+ 'Waiting for webhook response...',
298
+ '',
299
+ 'Wait For:',
300
+ JSON.stringify(event.waitFor, null, 2)
301
+ ].join('\n');
302
+ case BRAIN_EVENTS.WEBHOOK_RESPONSE:
303
+ return [
304
+ 'Webhook Response:',
305
+ JSON.stringify(event.response, null, 2)
306
+ ].join('\n');
307
+ case BRAIN_EVENTS.AGENT_WEBHOOK:
308
+ return [
309
+ "Step: ".concat(event.stepTitle),
310
+ "Tool: ".concat(event.toolName),
311
+ "Tool Call ID: ".concat(event.toolCallId),
312
+ '',
313
+ 'Agent waiting for webhook response...'
314
+ ].join('\n');
315
+ default:
316
+ // Show all fields for any event type
317
+ return JSON.stringify(event, null, 2);
318
+ }
319
+ }
320
+ export var EventDetail = function(param) {
321
+ var stored = param.stored, scrollOffset = param.scrollOffset, onScrollChange = param.onScrollChange, _param_isActive = param.isActive, isActive = _param_isActive === void 0 ? true : _param_isActive;
322
+ var stdout = useStdout().stdout;
323
+ var terminalHeight = (stdout === null || stdout === void 0 ? void 0 : stdout.rows) || 24;
324
+ var maxLines = Math.max(5, terminalHeight - 8);
325
+ var content = getEventDetailContent(stored.event);
326
+ var lines = content.split('\n');
327
+ var totalLines = lines.length;
328
+ var maxScroll = Math.max(0, totalLines - maxLines);
329
+ // Handle scrolling
330
+ useInput(function(input, key) {
331
+ if (!isActive) return;
332
+ if (key.upArrow || input === 'k') {
333
+ onScrollChange(Math.max(0, scrollOffset - 1));
334
+ } else if (key.downArrow || input === 'j') {
335
+ onScrollChange(Math.min(maxScroll, scrollOffset + 1));
336
+ }
337
+ }, {
338
+ isActive: isActive
339
+ });
340
+ var visibleLines = lines.slice(scrollOffset, scrollOffset + maxLines);
341
+ var _getEventSymbol = getEventSymbol(stored.event), symbol = _getEventSymbol.symbol, color = _getEventSymbol.color;
342
+ return /*#__PURE__*/ React.createElement(Box, {
343
+ flexDirection: "column"
344
+ }, /*#__PURE__*/ React.createElement(Box, {
345
+ marginBottom: 1
346
+ }, /*#__PURE__*/ React.createElement(Text, {
347
+ color: color
348
+ }, symbol, " "), /*#__PURE__*/ React.createElement(Text, {
349
+ bold: true
350
+ }, stored.event.type), /*#__PURE__*/ React.createElement(Text, {
351
+ dimColor: true
352
+ }, " • ", formatFullTimestamp(stored.timestamp))), /*#__PURE__*/ React.createElement(Box, {
353
+ flexDirection: "column",
354
+ marginLeft: 2
355
+ }, visibleLines.map(function(line, i) {
356
+ return /*#__PURE__*/ React.createElement(Text, {
357
+ key: scrollOffset + i
358
+ }, line);
359
+ })), totalLines > maxLines && /*#__PURE__*/ React.createElement(Box, {
360
+ marginTop: 1
361
+ }, /*#__PURE__*/ React.createElement(Text, {
362
+ dimColor: true
363
+ }, "Lines ", scrollOffset + 1, "-", Math.min(scrollOffset + maxLines, totalLines), " of ", totalLines)));
364
+ };
@@ -1,6 +1,53 @@
1
- import React from 'react';
2
- import { Text, Box, useStdout } from 'ink';
1
+ function _array_like_to_array(arr, len) {
2
+ if (len == null || len > arr.length) len = arr.length;
3
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
4
+ return arr2;
5
+ }
6
+ function _array_with_holes(arr) {
7
+ if (Array.isArray(arr)) return arr;
8
+ }
9
+ function _iterable_to_array_limit(arr, i) {
10
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
11
+ if (_i == null) return;
12
+ var _arr = [];
13
+ var _n = true;
14
+ var _d = false;
15
+ var _s, _e;
16
+ try {
17
+ for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
18
+ _arr.push(_s.value);
19
+ if (i && _arr.length === i) break;
20
+ }
21
+ } catch (err) {
22
+ _d = true;
23
+ _e = err;
24
+ } finally{
25
+ try {
26
+ if (!_n && _i["return"] != null) _i["return"]();
27
+ } finally{
28
+ if (_d) throw _e;
29
+ }
30
+ }
31
+ return _arr;
32
+ }
33
+ function _non_iterable_rest() {
34
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
35
+ }
36
+ function _sliced_to_array(arr, i) {
37
+ return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
38
+ }
39
+ function _unsupported_iterable_to_array(o, minLen) {
40
+ if (!o) return;
41
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
42
+ var n = Object.prototype.toString.call(o).slice(8, -1);
43
+ if (n === "Object" && o.constructor) n = o.constructor.name;
44
+ if (n === "Map" || n === "Set") return Array.from(n);
45
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
46
+ }
47
+ import React, { useState, useEffect } from 'react';
48
+ import { Text, Box, useStdout, useInput } from 'ink';
3
49
  import { BRAIN_EVENTS } from '@positronic/core';
50
+ import { EventDetail } from './event-detail.js';
4
51
  // Format relative timestamp
5
52
  function formatTimestamp(timestamp) {
6
53
  var now = Date.now();
@@ -32,12 +79,6 @@ function formatEvent(event) {
32
79
  text: 'Brain started: "'.concat(event.brainTitle, '"'),
33
80
  color: 'yellow'
34
81
  };
35
- case BRAIN_EVENTS.RESTART:
36
- return {
37
- symbol: '[>>]',
38
- text: 'Brain restarted: "'.concat(event.brainTitle, '"'),
39
- color: 'yellow'
40
- };
41
82
  case BRAIN_EVENTS.COMPLETE:
42
83
  return {
43
84
  symbol: '[ok]',
@@ -102,7 +143,8 @@ function formatEvent(event) {
102
143
  return {
103
144
  symbol: '[#]',
104
145
  text: "Agent iteration ".concat(event.iteration),
105
- color: 'gray'
146
+ color: 'gray',
147
+ tokens: event.tokensThisIteration
106
148
  };
107
149
  case BRAIN_EVENTS.AGENT_TOOL_CALL:
108
150
  return {
@@ -125,14 +167,23 @@ function formatEvent(event) {
125
167
  case BRAIN_EVENTS.AGENT_COMPLETE:
126
168
  return {
127
169
  symbol: '[A]',
128
- text: 'Agent completed: "'.concat(event.terminalToolName, '" (').concat(event.totalIterations, " iterations)"),
129
- color: 'green'
170
+ text: 'Agent completed: "'.concat(event.terminalToolName, '" (').concat(event.totalIterations, " iter)"),
171
+ color: 'green',
172
+ tokens: event.totalTokens
130
173
  };
131
174
  case BRAIN_EVENTS.AGENT_TOKEN_LIMIT:
132
175
  return {
133
176
  symbol: '[!]',
134
177
  text: "Token limit reached: ".concat(event.totalTokens, "/").concat(event.maxTokens),
135
- color: 'red'
178
+ color: 'red',
179
+ tokens: event.totalTokens
180
+ };
181
+ case BRAIN_EVENTS.AGENT_ITERATION_LIMIT:
182
+ return {
183
+ symbol: '[!]',
184
+ text: "Iteration limit reached: ".concat(event.iteration, "/").concat(event.maxIterations),
185
+ color: 'red',
186
+ tokens: event.totalTokens
136
187
  };
137
188
  case BRAIN_EVENTS.AGENT_WEBHOOK:
138
189
  return {
@@ -140,6 +191,24 @@ function formatEvent(event) {
140
191
  text: "Agent webhook: ".concat(event.toolName),
141
192
  color: 'cyan'
142
193
  };
194
+ case BRAIN_EVENTS.AGENT_RAW_RESPONSE_MESSAGE:
195
+ return {
196
+ symbol: '[~]',
197
+ text: "Agent response (iteration ".concat(event.iteration, ")"),
198
+ color: 'gray'
199
+ };
200
+ case BRAIN_EVENTS.PAUSED:
201
+ return {
202
+ symbol: '[||]',
203
+ text: 'Brain paused: "'.concat(event.brainTitle, '"'),
204
+ color: 'cyan'
205
+ };
206
+ case BRAIN_EVENTS.RESUMED:
207
+ return {
208
+ symbol: '[>]',
209
+ text: 'Brain resumed: "'.concat(event.brainTitle, '"'),
210
+ color: 'green'
211
+ };
143
212
  default:
144
213
  return {
145
214
  symbol: '[?]',
@@ -148,36 +217,163 @@ function formatEvent(event) {
148
217
  };
149
218
  }
150
219
  }
220
+ // Calculate visible window with selection support
221
+ function calculateVisibleWindow(eventsLength, selectedIndex, maxVisible) {
222
+ if (selectedIndex === null) {
223
+ // Auto-scroll: show most recent
224
+ return {
225
+ start: Math.max(0, eventsLength - maxVisible),
226
+ end: eventsLength
227
+ };
228
+ }
229
+ // Keep selection centered when possible
230
+ var half = Math.floor(maxVisible / 2);
231
+ var start = Math.max(0, selectedIndex - half);
232
+ var end = Math.min(eventsLength, start + maxVisible);
233
+ // Adjust if we hit the end
234
+ if (end === eventsLength) {
235
+ start = Math.max(0, end - maxVisible);
236
+ }
237
+ return {
238
+ start: start,
239
+ end: end
240
+ };
241
+ }
151
242
  var EventLine = function(param) {
152
- var stored = param.stored;
153
- var _formatEvent = formatEvent(stored.event), symbol = _formatEvent.symbol, text = _formatEvent.text, color = _formatEvent.color;
243
+ var stored = param.stored, isSelected = param.isSelected;
244
+ var _formatEvent = formatEvent(stored.event), symbol = _formatEvent.symbol, text = _formatEvent.text, color = _formatEvent.color, tokens = _formatEvent.tokens;
154
245
  var timestamp = formatTimestamp(stored.timestamp);
155
246
  return /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, {
247
+ color: isSelected ? 'cyan' : undefined
248
+ }, isSelected ? '› ' : ' '), /*#__PURE__*/ React.createElement(Text, {
156
249
  dimColor: true
157
250
  }, timestamp.padEnd(12), " "), /*#__PURE__*/ React.createElement(Text, {
158
- color: color
159
- }, symbol, " "), /*#__PURE__*/ React.createElement(Text, null, text));
251
+ color: isSelected ? 'cyan' : color
252
+ }, symbol, " "), /*#__PURE__*/ React.createElement(Text, {
253
+ color: isSelected ? 'cyan' : undefined
254
+ }, text), tokens !== undefined && /*#__PURE__*/ React.createElement(Text, {
255
+ dimColor: true
256
+ }, " (", tokens.toLocaleString(), " tokens)"));
160
257
  };
161
258
  export var EventsView = function(param) {
162
- var events = param.events;
259
+ var events = param.events, _param_totalTokens = param.totalTokens, totalTokens = _param_totalTokens === void 0 ? 0 : _param_totalTokens, _param_isActive = param.isActive, isActive = _param_isActive === void 0 ? true : _param_isActive, onModeChange = param.onModeChange, onViewState = param.onViewState, controlledSelectedIndex = param.selectedIndex, onSelectedIndexChange = param.onSelectedIndexChange;
163
260
  var stdout = useStdout().stdout;
164
261
  var terminalHeight = (stdout === null || stdout === void 0 ? void 0 : stdout.rows) || 24;
165
- // Reserve lines for header, footer, margins
166
- var maxVisible = Math.max(5, terminalHeight - 6);
167
- // Show most recent events at bottom (scrolling up)
168
- var visibleEvents = events.slice(-maxVisible);
262
+ // Reserve lines for header, footer, margins, token total
263
+ var maxVisible = Math.max(5, terminalHeight - 8);
264
+ var _useState = _sliced_to_array(useState('list'), 2), mode = _useState[0], setMode = _useState[1];
265
+ var _useState1 = _sliced_to_array(useState(null), 2), internalSelectedIndex = _useState1[0], setInternalSelectedIndex = _useState1[1];
266
+ var _useState2 = _sliced_to_array(useState(0), 2), scrollOffset = _useState2[0], setScrollOffset = _useState2[1];
267
+ // Use controlled value if provided, otherwise use internal state
268
+ var isControlled = controlledSelectedIndex !== undefined;
269
+ var selectedIndex = isControlled ? controlledSelectedIndex : internalSelectedIndex;
270
+ var setSelectedIndex = function(index) {
271
+ if (isControlled) {
272
+ onSelectedIndexChange === null || onSelectedIndexChange === void 0 ? void 0 : onSelectedIndexChange(index);
273
+ } else {
274
+ setInternalSelectedIndex(index);
275
+ }
276
+ };
277
+ // Notify parent of mode changes
278
+ useEffect(function() {
279
+ if (onModeChange) {
280
+ if (mode === 'detail') {
281
+ onModeChange('detail');
282
+ } else if (selectedIndex !== null) {
283
+ onModeChange('navigating');
284
+ } else {
285
+ onModeChange('auto');
286
+ }
287
+ }
288
+ }, [
289
+ mode,
290
+ selectedIndex,
291
+ onModeChange
292
+ ]);
293
+ // Keep selection valid when events change
294
+ useEffect(function() {
295
+ if (selectedIndex !== null && events.length > 0) {
296
+ if (selectedIndex >= events.length) {
297
+ setSelectedIndex(events.length - 1);
298
+ }
299
+ }
300
+ }, [
301
+ events.length,
302
+ selectedIndex
303
+ ]);
304
+ // Keyboard handling
305
+ useInput(function(input, key) {
306
+ if (!isActive) return;
307
+ if (mode === 'list') {
308
+ if (key.upArrow || input === 'k') {
309
+ if (selectedIndex === null) {
310
+ // First navigation: start from last event
311
+ if (events.length > 0) {
312
+ setSelectedIndex(events.length - 1);
313
+ }
314
+ } else if (selectedIndex > 0) {
315
+ setSelectedIndex(selectedIndex - 1);
316
+ }
317
+ } else if (key.downArrow || input === 'j') {
318
+ if (selectedIndex === null) {
319
+ if (events.length > 0) {
320
+ setSelectedIndex(events.length - 1);
321
+ }
322
+ } else if (selectedIndex < events.length - 1) {
323
+ setSelectedIndex(selectedIndex + 1);
324
+ }
325
+ } else if (key.return && selectedIndex !== null && events.length > 0) {
326
+ setMode('detail');
327
+ setScrollOffset(0);
328
+ } else if (input === 's' && selectedIndex !== null && onViewState) {
329
+ // View state at selected event
330
+ onViewState(selectedIndex);
331
+ } else if (key.escape && selectedIndex !== null) {
332
+ // Return to auto-scroll mode
333
+ setSelectedIndex(null);
334
+ }
335
+ } else if (mode === 'detail') {
336
+ // Escape or 'b' to go back to list
337
+ if (key.escape || input === 'b') {
338
+ setMode('list');
339
+ }
340
+ }
341
+ }, {
342
+ isActive: isActive
343
+ });
344
+ // Detail view
345
+ if (mode === 'detail' && selectedIndex !== null && events[selectedIndex]) {
346
+ return /*#__PURE__*/ React.createElement(EventDetail, {
347
+ stored: events[selectedIndex],
348
+ scrollOffset: scrollOffset,
349
+ onScrollChange: setScrollOffset,
350
+ isActive: isActive
351
+ });
352
+ }
353
+ // List view
354
+ var _calculateVisibleWindow = calculateVisibleWindow(events.length, selectedIndex, maxVisible), start = _calculateVisibleWindow.start, end = _calculateVisibleWindow.end;
355
+ var visibleEvents = events.slice(start, end);
169
356
  return /*#__PURE__*/ React.createElement(Box, {
170
357
  flexDirection: "column"
171
358
  }, /*#__PURE__*/ React.createElement(Box, {
172
359
  marginBottom: 1
173
360
  }, /*#__PURE__*/ React.createElement(Text, {
174
361
  bold: true
175
- }, "Events (", events.length, " total)")), visibleEvents.length === 0 ? /*#__PURE__*/ React.createElement(Text, {
362
+ }, "Events (", events.length, " total)"), selectedIndex !== null && /*#__PURE__*/ React.createElement(Text, {
363
+ dimColor: true
364
+ }, " • Selected: ", selectedIndex + 1)), visibleEvents.length === 0 ? /*#__PURE__*/ React.createElement(Text, {
176
365
  dimColor: true
177
366
  }, "Waiting for events...") : visibleEvents.map(function(stored, index) {
178
367
  return /*#__PURE__*/ React.createElement(EventLine, {
179
- key: index,
180
- stored: stored
368
+ key: start + index,
369
+ stored: stored,
370
+ isSelected: selectedIndex === start + index
181
371
  });
182
- }));
372
+ }), totalTokens > 0 && /*#__PURE__*/ React.createElement(Box, {
373
+ marginTop: 1
374
+ }, /*#__PURE__*/ React.createElement(Text, {
375
+ dimColor: true
376
+ }, "Total tokens: "), /*#__PURE__*/ React.createElement(Text, {
377
+ bold: true
378
+ }, totalTokens.toLocaleString())));
183
379
  };