@positronic/cli 0.0.2

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 (193) hide show
  1. package/dist/src/cli.js +739 -0
  2. package/dist/src/commands/backend.js +199 -0
  3. package/dist/src/commands/brain.js +446 -0
  4. package/dist/src/commands/brain.test.js +2936 -0
  5. package/dist/src/commands/helpers.js +1315 -0
  6. package/dist/src/commands/helpers.test.js +832 -0
  7. package/dist/src/commands/project-config-manager.js +197 -0
  8. package/dist/src/commands/project.js +130 -0
  9. package/dist/src/commands/project.test.js +1201 -0
  10. package/dist/src/commands/resources.js +272 -0
  11. package/dist/src/commands/resources.test.js +2511 -0
  12. package/dist/src/commands/schedule.js +73 -0
  13. package/dist/src/commands/schedule.test.js +1235 -0
  14. package/dist/src/commands/secret.js +87 -0
  15. package/dist/src/commands/secret.test.d.js +1 -0
  16. package/dist/src/commands/secret.test.js +761 -0
  17. package/dist/src/commands/server.js +816 -0
  18. package/dist/src/commands/server.test.js +1237 -0
  19. package/dist/src/commands/test-utils.js +737 -0
  20. package/dist/src/components/brain-history.js +169 -0
  21. package/dist/src/components/brain-list.js +108 -0
  22. package/dist/src/components/brain-rerun.js +313 -0
  23. package/dist/src/components/brain-show.js +65 -0
  24. package/dist/src/components/error.js +19 -0
  25. package/dist/src/components/project-add.js +95 -0
  26. package/dist/src/components/project-create.js +276 -0
  27. package/dist/src/components/project-list.js +88 -0
  28. package/dist/src/components/project-remove.js +91 -0
  29. package/dist/src/components/project-select.js +224 -0
  30. package/dist/src/components/project-show.js +41 -0
  31. package/dist/src/components/resource-clear.js +152 -0
  32. package/dist/src/components/resource-delete.js +189 -0
  33. package/dist/src/components/resource-list.js +174 -0
  34. package/dist/src/components/resource-sync.js +386 -0
  35. package/dist/src/components/resource-types.js +243 -0
  36. package/dist/src/components/resource-upload.js +366 -0
  37. package/dist/src/components/schedule-create.js +259 -0
  38. package/dist/src/components/schedule-delete.js +161 -0
  39. package/dist/src/components/schedule-list.js +176 -0
  40. package/dist/src/components/schedule-runs.js +103 -0
  41. package/dist/src/components/secret-bulk.js +262 -0
  42. package/dist/src/components/secret-create.js +199 -0
  43. package/dist/src/components/secret-delete.js +190 -0
  44. package/dist/src/components/secret-list.js +190 -0
  45. package/dist/src/components/secret-sync.js +303 -0
  46. package/dist/src/components/watch.js +184 -0
  47. package/dist/src/hooks/useApi.js +512 -0
  48. package/dist/src/positronic.js +33 -0
  49. package/dist/src/test/mock-api-client.js +371 -0
  50. package/dist/src/test/test-dev-server.js +1376 -0
  51. package/dist/types/cli.d.ts +9 -0
  52. package/dist/types/cli.d.ts.map +1 -0
  53. package/dist/types/commands/backend.d.ts +6 -0
  54. package/dist/types/commands/backend.d.ts.map +1 -0
  55. package/dist/types/commands/brain.d.ts +35 -0
  56. package/dist/types/commands/brain.d.ts.map +1 -0
  57. package/dist/types/commands/helpers.d.ts +55 -0
  58. package/dist/types/commands/helpers.d.ts.map +1 -0
  59. package/dist/types/commands/project-config-manager.d.ts +37 -0
  60. package/dist/types/commands/project-config-manager.d.ts.map +1 -0
  61. package/dist/types/commands/project.d.ts +55 -0
  62. package/dist/types/commands/project.d.ts.map +1 -0
  63. package/dist/types/commands/resources.d.ts +13 -0
  64. package/dist/types/commands/resources.d.ts.map +1 -0
  65. package/dist/types/commands/schedule.d.ts +27 -0
  66. package/dist/types/commands/schedule.d.ts.map +1 -0
  67. package/dist/types/commands/secret.d.ts +23 -0
  68. package/dist/types/commands/secret.d.ts.map +1 -0
  69. package/dist/types/commands/server.d.ts +12 -0
  70. package/dist/types/commands/server.d.ts.map +1 -0
  71. package/dist/types/commands/test-utils.d.ts +45 -0
  72. package/dist/types/commands/test-utils.d.ts.map +1 -0
  73. package/dist/types/components/brain-history.d.ts +7 -0
  74. package/dist/types/components/brain-history.d.ts.map +1 -0
  75. package/dist/types/components/brain-list.d.ts +2 -0
  76. package/dist/types/components/brain-list.d.ts.map +1 -0
  77. package/dist/types/components/brain-rerun.d.ts +9 -0
  78. package/dist/types/components/brain-rerun.d.ts.map +1 -0
  79. package/dist/types/components/brain-show.d.ts +6 -0
  80. package/dist/types/components/brain-show.d.ts.map +1 -0
  81. package/dist/types/components/error.d.ts +10 -0
  82. package/dist/types/components/error.d.ts.map +1 -0
  83. package/dist/types/components/project-add.d.ts +9 -0
  84. package/dist/types/components/project-add.d.ts.map +1 -0
  85. package/dist/types/components/project-create.d.ts +6 -0
  86. package/dist/types/components/project-create.d.ts.map +1 -0
  87. package/dist/types/components/project-list.d.ts +7 -0
  88. package/dist/types/components/project-list.d.ts.map +1 -0
  89. package/dist/types/components/project-remove.d.ts +8 -0
  90. package/dist/types/components/project-remove.d.ts.map +1 -0
  91. package/dist/types/components/project-select.d.ts +8 -0
  92. package/dist/types/components/project-select.d.ts.map +1 -0
  93. package/dist/types/components/project-show.d.ts +7 -0
  94. package/dist/types/components/project-show.d.ts.map +1 -0
  95. package/dist/types/components/resource-clear.d.ts +2 -0
  96. package/dist/types/components/resource-clear.d.ts.map +1 -0
  97. package/dist/types/components/resource-delete.d.ts +9 -0
  98. package/dist/types/components/resource-delete.d.ts.map +1 -0
  99. package/dist/types/components/resource-list.d.ts +2 -0
  100. package/dist/types/components/resource-list.d.ts.map +1 -0
  101. package/dist/types/components/resource-sync.d.ts +8 -0
  102. package/dist/types/components/resource-sync.d.ts.map +1 -0
  103. package/dist/types/components/resource-types.d.ts +7 -0
  104. package/dist/types/components/resource-types.d.ts.map +1 -0
  105. package/dist/types/components/resource-upload.d.ts +8 -0
  106. package/dist/types/components/resource-upload.d.ts.map +1 -0
  107. package/dist/types/components/schedule-create.d.ts +7 -0
  108. package/dist/types/components/schedule-create.d.ts.map +1 -0
  109. package/dist/types/components/schedule-delete.d.ts +7 -0
  110. package/dist/types/components/schedule-delete.d.ts.map +1 -0
  111. package/dist/types/components/schedule-list.d.ts +6 -0
  112. package/dist/types/components/schedule-list.d.ts.map +1 -0
  113. package/dist/types/components/schedule-runs.d.ts +8 -0
  114. package/dist/types/components/schedule-runs.d.ts.map +1 -0
  115. package/dist/types/components/secret-bulk.d.ts +8 -0
  116. package/dist/types/components/secret-bulk.d.ts.map +1 -0
  117. package/dist/types/components/secret-create.d.ts +9 -0
  118. package/dist/types/components/secret-create.d.ts.map +1 -0
  119. package/dist/types/components/secret-delete.d.ts +8 -0
  120. package/dist/types/components/secret-delete.d.ts.map +1 -0
  121. package/dist/types/components/secret-list.d.ts +7 -0
  122. package/dist/types/components/secret-list.d.ts.map +1 -0
  123. package/dist/types/components/secret-sync.d.ts +9 -0
  124. package/dist/types/components/secret-sync.d.ts.map +1 -0
  125. package/dist/types/components/watch.d.ts +7 -0
  126. package/dist/types/components/watch.d.ts.map +1 -0
  127. package/dist/types/hooks/useApi.d.ts +29 -0
  128. package/dist/types/hooks/useApi.d.ts.map +1 -0
  129. package/dist/types/positronic.d.ts +3 -0
  130. package/dist/types/positronic.d.ts.map +1 -0
  131. package/dist/types/test/mock-api-client.d.ts +25 -0
  132. package/dist/types/test/mock-api-client.d.ts.map +1 -0
  133. package/dist/types/test/test-dev-server.d.ts +129 -0
  134. package/dist/types/test/test-dev-server.d.ts.map +1 -0
  135. package/package.json +37 -0
  136. package/src/cli.ts +981 -0
  137. package/src/commands/backend.ts +63 -0
  138. package/src/commands/brain.test.ts +1004 -0
  139. package/src/commands/brain.ts +215 -0
  140. package/src/commands/helpers.test.ts +487 -0
  141. package/src/commands/helpers.ts +870 -0
  142. package/src/commands/project-config-manager.ts +152 -0
  143. package/src/commands/project.test.ts +502 -0
  144. package/src/commands/project.ts +109 -0
  145. package/src/commands/resources.test.ts +1052 -0
  146. package/src/commands/resources.ts +97 -0
  147. package/src/commands/schedule.test.ts +481 -0
  148. package/src/commands/schedule.ts +65 -0
  149. package/src/commands/secret.test.ts +210 -0
  150. package/src/commands/secret.ts +50 -0
  151. package/src/commands/server.test.ts +493 -0
  152. package/src/commands/server.ts +353 -0
  153. package/src/commands/test-utils.ts +324 -0
  154. package/src/components/brain-history.tsx +198 -0
  155. package/src/components/brain-list.tsx +105 -0
  156. package/src/components/brain-rerun.tsx +111 -0
  157. package/src/components/brain-show.tsx +92 -0
  158. package/src/components/error.tsx +24 -0
  159. package/src/components/project-add.tsx +59 -0
  160. package/src/components/project-create.tsx +83 -0
  161. package/src/components/project-list.tsx +83 -0
  162. package/src/components/project-remove.tsx +55 -0
  163. package/src/components/project-select.tsx +200 -0
  164. package/src/components/project-show.tsx +58 -0
  165. package/src/components/resource-clear.tsx +127 -0
  166. package/src/components/resource-delete.tsx +160 -0
  167. package/src/components/resource-list.tsx +177 -0
  168. package/src/components/resource-sync.tsx +170 -0
  169. package/src/components/resource-types.tsx +55 -0
  170. package/src/components/resource-upload.tsx +182 -0
  171. package/src/components/schedule-create.tsx +90 -0
  172. package/src/components/schedule-delete.tsx +116 -0
  173. package/src/components/schedule-list.tsx +186 -0
  174. package/src/components/schedule-runs.tsx +151 -0
  175. package/src/components/secret-bulk.tsx +79 -0
  176. package/src/components/secret-create.tsx +49 -0
  177. package/src/components/secret-delete.tsx +41 -0
  178. package/src/components/secret-list.tsx +41 -0
  179. package/src/components/watch.tsx +155 -0
  180. package/src/hooks/useApi.ts +183 -0
  181. package/src/positronic.ts +40 -0
  182. package/src/test/data/resources/config.json +1 -0
  183. package/src/test/data/resources/data/config.json +1 -0
  184. package/src/test/data/resources/data/logo.png +2 -0
  185. package/src/test/data/resources/docs/api.md +3 -0
  186. package/src/test/data/resources/docs/readme.md +3 -0
  187. package/src/test/data/resources/example.md +3 -0
  188. package/src/test/data/resources/file with spaces.txt +1 -0
  189. package/src/test/data/resources/readme.md +3 -0
  190. package/src/test/data/resources/test.txt +1 -0
  191. package/src/test/mock-api-client.ts +145 -0
  192. package/src/test/test-dev-server.ts +1003 -0
  193. package/tsconfig.json +11 -0
@@ -0,0 +1,2936 @@
1
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
2
+ try {
3
+ var info = gen[key](arg);
4
+ var value = info.value;
5
+ } catch (error) {
6
+ reject(error);
7
+ return;
8
+ }
9
+ if (info.done) {
10
+ resolve(value);
11
+ } else {
12
+ Promise.resolve(value).then(_next, _throw);
13
+ }
14
+ }
15
+ function _async_to_generator(fn) {
16
+ return function() {
17
+ var self = this, args = arguments;
18
+ return new Promise(function(resolve, reject) {
19
+ var gen = fn.apply(self, args);
20
+ function _next(value) {
21
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
22
+ }
23
+ function _throw(err) {
24
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
25
+ }
26
+ _next(undefined);
27
+ });
28
+ };
29
+ }
30
+ function _ts_generator(thisArg, body) {
31
+ var f, y, t, _ = {
32
+ label: 0,
33
+ sent: function() {
34
+ if (t[0] & 1) throw t[1];
35
+ return t[1];
36
+ },
37
+ trys: [],
38
+ ops: []
39
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
40
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
41
+ return this;
42
+ }), g;
43
+ function verb(n) {
44
+ return function(v) {
45
+ return step([
46
+ n,
47
+ v
48
+ ]);
49
+ };
50
+ }
51
+ function step(op) {
52
+ if (f) throw new TypeError("Generator is already executing.");
53
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
54
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
55
+ if (y = 0, t) op = [
56
+ op[0] & 2,
57
+ t.value
58
+ ];
59
+ switch(op[0]){
60
+ case 0:
61
+ case 1:
62
+ t = op;
63
+ break;
64
+ case 4:
65
+ _.label++;
66
+ return {
67
+ value: op[1],
68
+ done: false
69
+ };
70
+ case 5:
71
+ _.label++;
72
+ y = op[1];
73
+ op = [
74
+ 0
75
+ ];
76
+ continue;
77
+ case 7:
78
+ op = _.ops.pop();
79
+ _.trys.pop();
80
+ continue;
81
+ default:
82
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
83
+ _ = 0;
84
+ continue;
85
+ }
86
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
87
+ _.label = op[1];
88
+ break;
89
+ }
90
+ if (op[0] === 6 && _.label < t[1]) {
91
+ _.label = t[1];
92
+ t = op;
93
+ break;
94
+ }
95
+ if (t && _.label < t[2]) {
96
+ _.label = t[2];
97
+ _.ops.push(op);
98
+ break;
99
+ }
100
+ if (t[2]) _.ops.pop();
101
+ _.trys.pop();
102
+ continue;
103
+ }
104
+ op = body.call(thisArg, _);
105
+ } catch (e) {
106
+ op = [
107
+ 6,
108
+ e
109
+ ];
110
+ y = 0;
111
+ } finally{
112
+ f = t = 0;
113
+ }
114
+ if (op[0] & 5) throw op[1];
115
+ return {
116
+ value: op[0] ? op[1] : void 0,
117
+ done: true
118
+ };
119
+ }
120
+ }
121
+ import { describe, it, expect } from '@jest/globals';
122
+ import { createTestEnv, px } from './test-utils.js';
123
+ import nock from 'nock';
124
+ describe('CLI Integration: positronic brain commands', function() {
125
+ describe('brain run command', function() {
126
+ it('should successfully run a brain and return run ID', function() {
127
+ return _async_to_generator(function() {
128
+ var env, px, waitForOutput, isOutputRendered;
129
+ return _ts_generator(this, function(_state) {
130
+ switch(_state.label){
131
+ case 0:
132
+ return [
133
+ 4,
134
+ createTestEnv()
135
+ ];
136
+ case 1:
137
+ env = _state.sent();
138
+ return [
139
+ 4,
140
+ env.start()
141
+ ];
142
+ case 2:
143
+ px = _state.sent();
144
+ _state.label = 3;
145
+ case 3:
146
+ _state.trys.push([
147
+ 3,
148
+ ,
149
+ 6,
150
+ 8
151
+ ]);
152
+ return [
153
+ 4,
154
+ px([
155
+ 'run',
156
+ 'test-brain'
157
+ ])
158
+ ];
159
+ case 4:
160
+ waitForOutput = _state.sent().waitForOutput;
161
+ return [
162
+ 4,
163
+ waitForOutput(/Run ID: run-\d+/)
164
+ ];
165
+ case 5:
166
+ isOutputRendered = _state.sent();
167
+ expect(isOutputRendered).toBe(true);
168
+ return [
169
+ 3,
170
+ 8
171
+ ];
172
+ case 6:
173
+ return [
174
+ 4,
175
+ env.stopAndCleanup()
176
+ ];
177
+ case 7:
178
+ _state.sent();
179
+ return [
180
+ 7
181
+ ];
182
+ case 8:
183
+ return [
184
+ 2
185
+ ];
186
+ }
187
+ });
188
+ })();
189
+ });
190
+ it('should run a brain with watch option', function() {
191
+ return _async_to_generator(function() {
192
+ var env, px, _ref, waitForOutput, instance, isOutputRendered;
193
+ return _ts_generator(this, function(_state) {
194
+ switch(_state.label){
195
+ case 0:
196
+ return [
197
+ 4,
198
+ createTestEnv()
199
+ ];
200
+ case 1:
201
+ env = _state.sent();
202
+ return [
203
+ 4,
204
+ env.start()
205
+ ];
206
+ case 2:
207
+ px = _state.sent();
208
+ _state.label = 3;
209
+ case 3:
210
+ _state.trys.push([
211
+ 3,
212
+ ,
213
+ 6,
214
+ 8
215
+ ]);
216
+ return [
217
+ 4,
218
+ px([
219
+ 'run',
220
+ 'test-brain',
221
+ '--watch'
222
+ ])
223
+ ];
224
+ case 4:
225
+ _ref = _state.sent(), waitForOutput = _ref.waitForOutput, instance = _ref.instance;
226
+ return [
227
+ 4,
228
+ waitForOutput(/Connecting to watch service|Brain: test-brain/)
229
+ ];
230
+ case 5:
231
+ isOutputRendered = _state.sent();
232
+ expect(isOutputRendered).toBe(true);
233
+ // Unmount the component to trigger EventSource cleanup
234
+ instance.unmount();
235
+ return [
236
+ 3,
237
+ 8
238
+ ];
239
+ case 6:
240
+ return [
241
+ 4,
242
+ env.stopAndCleanup()
243
+ ];
244
+ case 7:
245
+ _state.sent();
246
+ return [
247
+ 7
248
+ ];
249
+ case 8:
250
+ return [
251
+ 2
252
+ ];
253
+ }
254
+ });
255
+ })();
256
+ });
257
+ it('should run a brain with short watch flag', function() {
258
+ return _async_to_generator(function() {
259
+ var env, px, _ref, waitForOutput, instance, isOutputRendered;
260
+ return _ts_generator(this, function(_state) {
261
+ switch(_state.label){
262
+ case 0:
263
+ return [
264
+ 4,
265
+ createTestEnv()
266
+ ];
267
+ case 1:
268
+ env = _state.sent();
269
+ return [
270
+ 4,
271
+ env.start()
272
+ ];
273
+ case 2:
274
+ px = _state.sent();
275
+ _state.label = 3;
276
+ case 3:
277
+ _state.trys.push([
278
+ 3,
279
+ ,
280
+ 6,
281
+ 8
282
+ ]);
283
+ return [
284
+ 4,
285
+ px([
286
+ 'run',
287
+ 'test-brain',
288
+ '-w'
289
+ ])
290
+ ];
291
+ case 4:
292
+ _ref = _state.sent(), waitForOutput = _ref.waitForOutput, instance = _ref.instance;
293
+ return [
294
+ 4,
295
+ waitForOutput(/Connecting to watch service|Brain: test-brain/)
296
+ ];
297
+ case 5:
298
+ isOutputRendered = _state.sent();
299
+ expect(isOutputRendered).toBe(true);
300
+ // Unmount the component to trigger EventSource cleanup
301
+ instance.unmount();
302
+ return [
303
+ 3,
304
+ 8
305
+ ];
306
+ case 6:
307
+ return [
308
+ 4,
309
+ env.stopAndCleanup()
310
+ ];
311
+ case 7:
312
+ _state.sent();
313
+ return [
314
+ 7
315
+ ];
316
+ case 8:
317
+ return [
318
+ 2
319
+ ];
320
+ }
321
+ });
322
+ })();
323
+ });
324
+ it('should handle brain not found (404) error with helpful message', function() {
325
+ return _async_to_generator(function() {
326
+ var env, px, waitForOutput, foundErrorTitle, foundErrorMessage, foundHelpText, calls, runCall;
327
+ return _ts_generator(this, function(_state) {
328
+ switch(_state.label){
329
+ case 0:
330
+ return [
331
+ 4,
332
+ createTestEnv()
333
+ ];
334
+ case 1:
335
+ env = _state.sent();
336
+ return [
337
+ 4,
338
+ env.start()
339
+ ];
340
+ case 2:
341
+ px = _state.sent();
342
+ _state.label = 3;
343
+ case 3:
344
+ _state.trys.push([
345
+ 3,
346
+ ,
347
+ 8,
348
+ 10
349
+ ]);
350
+ return [
351
+ 4,
352
+ px([
353
+ 'run',
354
+ 'non-existent-brain'
355
+ ])
356
+ ];
357
+ case 4:
358
+ waitForOutput = _state.sent().waitForOutput;
359
+ return [
360
+ 4,
361
+ waitForOutput(/Brain Not Found/i, 30)
362
+ ];
363
+ case 5:
364
+ foundErrorTitle = _state.sent();
365
+ expect(foundErrorTitle).toBe(true);
366
+ return [
367
+ 4,
368
+ waitForOutput(/Brain 'non-existent-brain' not found/i, 30)
369
+ ];
370
+ case 6:
371
+ foundErrorMessage = _state.sent();
372
+ expect(foundErrorMessage).toBe(true);
373
+ return [
374
+ 4,
375
+ waitForOutput(/brain name is spelled correctly/i, 30)
376
+ ];
377
+ case 7:
378
+ foundHelpText = _state.sent();
379
+ expect(foundHelpText).toBe(true);
380
+ // Verify the API was called
381
+ calls = env.server.getLogs();
382
+ runCall = calls.find(function(c) {
383
+ return c.method === 'createBrainRun';
384
+ });
385
+ expect(runCall).toBeDefined();
386
+ expect(runCall === null || runCall === void 0 ? void 0 : runCall.args[0]).toBe('non-existent-brain');
387
+ return [
388
+ 3,
389
+ 10
390
+ ];
391
+ case 8:
392
+ return [
393
+ 4,
394
+ env.stopAndCleanup()
395
+ ];
396
+ case 9:
397
+ _state.sent();
398
+ return [
399
+ 7
400
+ ];
401
+ case 10:
402
+ return [
403
+ 2
404
+ ];
405
+ }
406
+ });
407
+ })();
408
+ });
409
+ it('should handle API server error responses', function() {
410
+ return _async_to_generator(function() {
411
+ var env, px, port, originalExit, exitCalled;
412
+ return _ts_generator(this, function(_state) {
413
+ switch(_state.label){
414
+ case 0:
415
+ return [
416
+ 4,
417
+ createTestEnv()
418
+ ];
419
+ case 1:
420
+ env = _state.sent();
421
+ return [
422
+ 4,
423
+ env.start()
424
+ ];
425
+ case 2:
426
+ px = _state.sent();
427
+ _state.label = 3;
428
+ case 3:
429
+ _state.trys.push([
430
+ 3,
431
+ ,
432
+ 8,
433
+ 10
434
+ ]);
435
+ // Clear all existing nock interceptors to avoid conflicts
436
+ nock.cleanAll();
437
+ // Mock the server to return a 500 error
438
+ port = env.server.port;
439
+ nock("http://localhost:".concat(port)).post('/brains/runs').reply(500, 'Internal Server Error');
440
+ // Mock process.exit to prevent test from exiting
441
+ originalExit = process.exit;
442
+ exitCalled = false;
443
+ process.exit = function(code) {
444
+ exitCalled = true;
445
+ throw new Error("process.exit called with code ".concat(code));
446
+ };
447
+ _state.label = 4;
448
+ case 4:
449
+ _state.trys.push([
450
+ 4,
451
+ ,
452
+ 6,
453
+ 7
454
+ ]);
455
+ return [
456
+ 4,
457
+ expect(px([
458
+ 'run',
459
+ 'test-brain'
460
+ ])).rejects.toThrow('process.exit called with code 1')
461
+ ];
462
+ case 5:
463
+ _state.sent();
464
+ expect(exitCalled).toBe(true);
465
+ return [
466
+ 3,
467
+ 7
468
+ ];
469
+ case 6:
470
+ process.exit = originalExit;
471
+ return [
472
+ 7
473
+ ];
474
+ case 7:
475
+ return [
476
+ 3,
477
+ 10
478
+ ];
479
+ case 8:
480
+ return [
481
+ 4,
482
+ env.stopAndCleanup()
483
+ ];
484
+ case 9:
485
+ _state.sent();
486
+ return [
487
+ 7
488
+ ];
489
+ case 10:
490
+ return [
491
+ 2
492
+ ];
493
+ }
494
+ });
495
+ })();
496
+ });
497
+ it('should handle network connection errors (ECONNREFUSED)', function() {
498
+ return _async_to_generator(function() {
499
+ var env, px, port, originalExit, exitCalled;
500
+ return _ts_generator(this, function(_state) {
501
+ switch(_state.label){
502
+ case 0:
503
+ return [
504
+ 4,
505
+ createTestEnv()
506
+ ];
507
+ case 1:
508
+ env = _state.sent();
509
+ return [
510
+ 4,
511
+ env.start()
512
+ ];
513
+ case 2:
514
+ px = _state.sent();
515
+ _state.label = 3;
516
+ case 3:
517
+ _state.trys.push([
518
+ 3,
519
+ ,
520
+ 8,
521
+ 10
522
+ ]);
523
+ // Clear all existing nock interceptors to avoid conflicts
524
+ nock.cleanAll();
525
+ // Mock a connection refused error
526
+ port = env.server.port;
527
+ nock("http://localhost:".concat(port)).post('/brains/runs').replyWithError({
528
+ message: 'connect ECONNREFUSED',
529
+ code: 'ECONNREFUSED'
530
+ });
531
+ // Mock process.exit to prevent test from exiting
532
+ originalExit = process.exit;
533
+ exitCalled = false;
534
+ process.exit = function(code) {
535
+ exitCalled = true;
536
+ throw new Error("process.exit called with code ".concat(code));
537
+ };
538
+ _state.label = 4;
539
+ case 4:
540
+ _state.trys.push([
541
+ 4,
542
+ ,
543
+ 6,
544
+ 7
545
+ ]);
546
+ return [
547
+ 4,
548
+ expect(px([
549
+ 'run',
550
+ 'test-brain'
551
+ ])).rejects.toThrow('process.exit called with code 1')
552
+ ];
553
+ case 5:
554
+ _state.sent();
555
+ expect(exitCalled).toBe(true);
556
+ return [
557
+ 3,
558
+ 7
559
+ ];
560
+ case 6:
561
+ process.exit = originalExit;
562
+ return [
563
+ 7
564
+ ];
565
+ case 7:
566
+ return [
567
+ 3,
568
+ 10
569
+ ];
570
+ case 8:
571
+ return [
572
+ 4,
573
+ env.stopAndCleanup()
574
+ ];
575
+ case 9:
576
+ _state.sent();
577
+ return [
578
+ 7
579
+ ];
580
+ case 10:
581
+ return [
582
+ 2
583
+ ];
584
+ }
585
+ });
586
+ })();
587
+ });
588
+ it('should handle other network errors', function() {
589
+ return _async_to_generator(function() {
590
+ var env, px, port, originalExit, exitCalled;
591
+ return _ts_generator(this, function(_state) {
592
+ switch(_state.label){
593
+ case 0:
594
+ return [
595
+ 4,
596
+ createTestEnv()
597
+ ];
598
+ case 1:
599
+ env = _state.sent();
600
+ return [
601
+ 4,
602
+ env.start()
603
+ ];
604
+ case 2:
605
+ px = _state.sent();
606
+ _state.label = 3;
607
+ case 3:
608
+ _state.trys.push([
609
+ 3,
610
+ ,
611
+ 8,
612
+ 10
613
+ ]);
614
+ // Clear all existing nock interceptors to avoid conflicts
615
+ nock.cleanAll();
616
+ // Mock a different network error (without ECONNREFUSED code)
617
+ port = env.server.port;
618
+ nock("http://localhost:".concat(port)).post('/brains/runs').replyWithError({
619
+ message: 'Network timeout error occurred',
620
+ code: 'TIMEOUT'
621
+ });
622
+ // Mock process.exit to prevent test from exiting
623
+ originalExit = process.exit;
624
+ exitCalled = false;
625
+ process.exit = function(code) {
626
+ exitCalled = true;
627
+ throw new Error("process.exit called with code ".concat(code));
628
+ };
629
+ _state.label = 4;
630
+ case 4:
631
+ _state.trys.push([
632
+ 4,
633
+ ,
634
+ 6,
635
+ 7
636
+ ]);
637
+ return [
638
+ 4,
639
+ expect(px([
640
+ 'run',
641
+ 'test-brain'
642
+ ])).rejects.toThrow('process.exit called with code 1')
643
+ ];
644
+ case 5:
645
+ _state.sent();
646
+ expect(exitCalled).toBe(true);
647
+ return [
648
+ 3,
649
+ 7
650
+ ];
651
+ case 6:
652
+ process.exit = originalExit;
653
+ return [
654
+ 7
655
+ ];
656
+ case 7:
657
+ return [
658
+ 3,
659
+ 10
660
+ ];
661
+ case 8:
662
+ return [
663
+ 4,
664
+ env.stopAndCleanup()
665
+ ];
666
+ case 9:
667
+ _state.sent();
668
+ return [
669
+ 7
670
+ ];
671
+ case 10:
672
+ return [
673
+ 2
674
+ ];
675
+ }
676
+ });
677
+ })();
678
+ });
679
+ it('should handle network errors with specific error message', function() {
680
+ return _async_to_generator(function() {
681
+ var env, px, port, originalExit, exitCalled;
682
+ return _ts_generator(this, function(_state) {
683
+ switch(_state.label){
684
+ case 0:
685
+ return [
686
+ 4,
687
+ createTestEnv()
688
+ ];
689
+ case 1:
690
+ env = _state.sent();
691
+ return [
692
+ 4,
693
+ env.start()
694
+ ];
695
+ case 2:
696
+ px = _state.sent();
697
+ _state.label = 3;
698
+ case 3:
699
+ _state.trys.push([
700
+ 3,
701
+ ,
702
+ 8,
703
+ 10
704
+ ]);
705
+ // Clear all existing nock interceptors to avoid conflicts
706
+ nock.cleanAll();
707
+ // Mock a network error with a specific message (not ECONNREFUSED)
708
+ port = env.server.port;
709
+ nock("http://localhost:".concat(port)).post('/brains/runs').replyWithError(new Error('DNS resolution failed'));
710
+ // Mock process.exit to prevent test from exiting
711
+ originalExit = process.exit;
712
+ exitCalled = false;
713
+ process.exit = function(code) {
714
+ exitCalled = true;
715
+ throw new Error("process.exit called with code ".concat(code));
716
+ };
717
+ _state.label = 4;
718
+ case 4:
719
+ _state.trys.push([
720
+ 4,
721
+ ,
722
+ 6,
723
+ 7
724
+ ]);
725
+ return [
726
+ 4,
727
+ expect(px([
728
+ 'run',
729
+ 'test-brain'
730
+ ])).rejects.toThrow('process.exit called with code 1')
731
+ ];
732
+ case 5:
733
+ _state.sent();
734
+ expect(exitCalled).toBe(true);
735
+ return [
736
+ 3,
737
+ 7
738
+ ];
739
+ case 6:
740
+ process.exit = originalExit;
741
+ return [
742
+ 7
743
+ ];
744
+ case 7:
745
+ return [
746
+ 3,
747
+ 10
748
+ ];
749
+ case 8:
750
+ return [
751
+ 4,
752
+ env.stopAndCleanup()
753
+ ];
754
+ case 9:
755
+ _state.sent();
756
+ return [
757
+ 7
758
+ ];
759
+ case 10:
760
+ return [
761
+ 2
762
+ ];
763
+ }
764
+ });
765
+ })();
766
+ });
767
+ });
768
+ describe('brain watch command', function() {
769
+ it('should watch a brain run by run ID', function() {
770
+ return _async_to_generator(function() {
771
+ var env, px, _ref, waitForOutput, instance, isOutputRendered;
772
+ return _ts_generator(this, function(_state) {
773
+ switch(_state.label){
774
+ case 0:
775
+ return [
776
+ 4,
777
+ createTestEnv()
778
+ ];
779
+ case 1:
780
+ env = _state.sent();
781
+ return [
782
+ 4,
783
+ env.start()
784
+ ];
785
+ case 2:
786
+ px = _state.sent();
787
+ _state.label = 3;
788
+ case 3:
789
+ _state.trys.push([
790
+ 3,
791
+ ,
792
+ 6,
793
+ 8
794
+ ]);
795
+ return [
796
+ 4,
797
+ px([
798
+ 'watch',
799
+ '--run-id',
800
+ 'test-run-123'
801
+ ])
802
+ ];
803
+ case 4:
804
+ _ref = _state.sent(), waitForOutput = _ref.waitForOutput, instance = _ref.instance;
805
+ return [
806
+ 4,
807
+ waitForOutput(/Connecting to watch service|Brain: test-brain/)
808
+ ];
809
+ case 5:
810
+ isOutputRendered = _state.sent();
811
+ expect(isOutputRendered).toBe(true);
812
+ // Unmount the component to trigger EventSource cleanup
813
+ instance.unmount();
814
+ return [
815
+ 3,
816
+ 8
817
+ ];
818
+ case 6:
819
+ return [
820
+ 4,
821
+ env.stopAndCleanup()
822
+ ];
823
+ case 7:
824
+ _state.sent();
825
+ return [
826
+ 7
827
+ ];
828
+ case 8:
829
+ return [
830
+ 2
831
+ ];
832
+ }
833
+ });
834
+ })();
835
+ });
836
+ it('should watch a brain run by run ID using short flag', function() {
837
+ return _async_to_generator(function() {
838
+ var env, px, _ref, waitForOutput, instance, isOutputRendered;
839
+ return _ts_generator(this, function(_state) {
840
+ switch(_state.label){
841
+ case 0:
842
+ return [
843
+ 4,
844
+ createTestEnv()
845
+ ];
846
+ case 1:
847
+ env = _state.sent();
848
+ return [
849
+ 4,
850
+ env.start()
851
+ ];
852
+ case 2:
853
+ px = _state.sent();
854
+ _state.label = 3;
855
+ case 3:
856
+ _state.trys.push([
857
+ 3,
858
+ ,
859
+ 6,
860
+ 8
861
+ ]);
862
+ return [
863
+ 4,
864
+ px([
865
+ 'watch',
866
+ '--id',
867
+ 'test-run-456'
868
+ ])
869
+ ];
870
+ case 4:
871
+ _ref = _state.sent(), waitForOutput = _ref.waitForOutput, instance = _ref.instance;
872
+ return [
873
+ 4,
874
+ waitForOutput(/Connecting to watch service|Brain: test-brain/)
875
+ ];
876
+ case 5:
877
+ isOutputRendered = _state.sent();
878
+ expect(isOutputRendered).toBe(true);
879
+ // Unmount the component to trigger EventSource cleanup
880
+ instance.unmount();
881
+ return [
882
+ 3,
883
+ 8
884
+ ];
885
+ case 6:
886
+ return [
887
+ 4,
888
+ env.stopAndCleanup()
889
+ ];
890
+ case 7:
891
+ _state.sent();
892
+ return [
893
+ 7
894
+ ];
895
+ case 8:
896
+ return [
897
+ 2
898
+ ];
899
+ }
900
+ });
901
+ })();
902
+ });
903
+ it('should watch the single active run when watching by brain name', function() {
904
+ return _async_to_generator(function() {
905
+ var env, server, px, _ref, waitForOutput, instance, isOutputRendered, calls, activeRunsCall;
906
+ return _ts_generator(this, function(_state) {
907
+ switch(_state.label){
908
+ case 0:
909
+ return [
910
+ 4,
911
+ createTestEnv()
912
+ ];
913
+ case 1:
914
+ env = _state.sent();
915
+ server = env.server;
916
+ // Add a running brain run
917
+ server.addBrainRun({
918
+ brainRunId: 'run-active-123',
919
+ brainTitle: 'test brain',
920
+ type: 'START',
921
+ status: 'RUNNING',
922
+ createdAt: Date.now() - 60000,
923
+ startedAt: Date.now() - 60000
924
+ });
925
+ return [
926
+ 4,
927
+ env.start()
928
+ ];
929
+ case 2:
930
+ px = _state.sent();
931
+ _state.label = 3;
932
+ case 3:
933
+ _state.trys.push([
934
+ 3,
935
+ ,
936
+ 6,
937
+ 8
938
+ ]);
939
+ return [
940
+ 4,
941
+ px([
942
+ 'watch',
943
+ 'test-brain'
944
+ ])
945
+ ];
946
+ case 4:
947
+ _ref = _state.sent(), waitForOutput = _ref.waitForOutput, instance = _ref.instance;
948
+ return [
949
+ 4,
950
+ waitForOutput(/Connecting to watch service|Brain: test-brain/)
951
+ ];
952
+ case 5:
953
+ isOutputRendered = _state.sent();
954
+ expect(isOutputRendered).toBe(true);
955
+ // Verify API was called to get active runs
956
+ calls = server.getLogs();
957
+ activeRunsCall = calls.find(function(c) {
958
+ return c.method === 'getBrainActiveRuns';
959
+ });
960
+ expect(activeRunsCall).toBeDefined();
961
+ expect(activeRunsCall === null || activeRunsCall === void 0 ? void 0 : activeRunsCall.args[0]).toBe('test-brain');
962
+ // Unmount the component to trigger EventSource cleanup
963
+ instance.unmount();
964
+ return [
965
+ 3,
966
+ 8
967
+ ];
968
+ case 6:
969
+ return [
970
+ 4,
971
+ env.stopAndCleanup()
972
+ ];
973
+ case 7:
974
+ _state.sent();
975
+ return [
976
+ 7
977
+ ];
978
+ case 8:
979
+ return [
980
+ 2
981
+ ];
982
+ }
983
+ });
984
+ })();
985
+ });
986
+ it('should show error when no active runs found for brain name', function() {
987
+ return _async_to_generator(function() {
988
+ var env, px, waitForOutput, foundTitle, foundMessage, foundDetails, calls, activeRunsCall;
989
+ return _ts_generator(this, function(_state) {
990
+ switch(_state.label){
991
+ case 0:
992
+ return [
993
+ 4,
994
+ createTestEnv()
995
+ ];
996
+ case 1:
997
+ env = _state.sent();
998
+ return [
999
+ 4,
1000
+ env.start()
1001
+ ];
1002
+ case 2:
1003
+ px = _state.sent();
1004
+ _state.label = 3;
1005
+ case 3:
1006
+ _state.trys.push([
1007
+ 3,
1008
+ ,
1009
+ 8,
1010
+ 10
1011
+ ]);
1012
+ return [
1013
+ 4,
1014
+ px([
1015
+ 'watch',
1016
+ 'test-brain'
1017
+ ])
1018
+ ];
1019
+ case 4:
1020
+ waitForOutput = _state.sent().waitForOutput;
1021
+ return [
1022
+ 4,
1023
+ waitForOutput(/No Active Runs/i, 30)
1024
+ ];
1025
+ case 5:
1026
+ foundTitle = _state.sent();
1027
+ expect(foundTitle).toBe(true);
1028
+ return [
1029
+ 4,
1030
+ waitForOutput(/No currently running brain runs found for brain "test-brain"/i, 30)
1031
+ ];
1032
+ case 6:
1033
+ foundMessage = _state.sent();
1034
+ expect(foundMessage).toBe(true);
1035
+ return [
1036
+ 4,
1037
+ waitForOutput(/positronic run test-brain/i, 30)
1038
+ ];
1039
+ case 7:
1040
+ foundDetails = _state.sent();
1041
+ expect(foundDetails).toBe(true);
1042
+ // Verify API was called
1043
+ calls = env.server.getLogs();
1044
+ activeRunsCall = calls.find(function(c) {
1045
+ return c.method === 'getBrainActiveRuns';
1046
+ });
1047
+ expect(activeRunsCall).toBeDefined();
1048
+ return [
1049
+ 3,
1050
+ 10
1051
+ ];
1052
+ case 8:
1053
+ return [
1054
+ 4,
1055
+ env.stopAndCleanup()
1056
+ ];
1057
+ case 9:
1058
+ _state.sent();
1059
+ return [
1060
+ 7
1061
+ ];
1062
+ case 10:
1063
+ return [
1064
+ 2
1065
+ ];
1066
+ }
1067
+ });
1068
+ })();
1069
+ });
1070
+ it('should show error when multiple active runs found for brain name', function() {
1071
+ return _async_to_generator(function() {
1072
+ var env, server, px, waitForOutput, foundTitle, foundMessage, foundDetails;
1073
+ return _ts_generator(this, function(_state) {
1074
+ switch(_state.label){
1075
+ case 0:
1076
+ return [
1077
+ 4,
1078
+ createTestEnv()
1079
+ ];
1080
+ case 1:
1081
+ env = _state.sent();
1082
+ server = env.server;
1083
+ // Add multiple running brain runs
1084
+ server.addBrainRun({
1085
+ brainRunId: 'run-active-1',
1086
+ brainTitle: 'test brain',
1087
+ type: 'START',
1088
+ status: 'RUNNING',
1089
+ createdAt: Date.now() - 120000,
1090
+ startedAt: Date.now() - 120000
1091
+ });
1092
+ server.addBrainRun({
1093
+ brainRunId: 'run-active-2',
1094
+ brainTitle: 'test brain',
1095
+ type: 'START',
1096
+ status: 'RUNNING',
1097
+ createdAt: Date.now() - 60000,
1098
+ startedAt: Date.now() - 60000
1099
+ });
1100
+ return [
1101
+ 4,
1102
+ env.start()
1103
+ ];
1104
+ case 2:
1105
+ px = _state.sent();
1106
+ _state.label = 3;
1107
+ case 3:
1108
+ _state.trys.push([
1109
+ 3,
1110
+ ,
1111
+ 8,
1112
+ 10
1113
+ ]);
1114
+ return [
1115
+ 4,
1116
+ px([
1117
+ 'watch',
1118
+ 'test-brain'
1119
+ ])
1120
+ ];
1121
+ case 4:
1122
+ waitForOutput = _state.sent().waitForOutput;
1123
+ return [
1124
+ 4,
1125
+ waitForOutput(/Multiple Active Runs/i, 30)
1126
+ ];
1127
+ case 5:
1128
+ foundTitle = _state.sent();
1129
+ expect(foundTitle).toBe(true);
1130
+ return [
1131
+ 4,
1132
+ waitForOutput(/Found 2 active runs for brain "test-brain"/i, 30)
1133
+ ];
1134
+ case 6:
1135
+ foundMessage = _state.sent();
1136
+ expect(foundMessage).toBe(true);
1137
+ return [
1138
+ 4,
1139
+ waitForOutput(/positronic watch --run-id run-active-/i, 30)
1140
+ ];
1141
+ case 7:
1142
+ foundDetails = _state.sent();
1143
+ expect(foundDetails).toBe(true);
1144
+ return [
1145
+ 3,
1146
+ 10
1147
+ ];
1148
+ case 8:
1149
+ return [
1150
+ 4,
1151
+ env.stopAndCleanup()
1152
+ ];
1153
+ case 9:
1154
+ _state.sent();
1155
+ return [
1156
+ 7
1157
+ ];
1158
+ case 10:
1159
+ return [
1160
+ 2
1161
+ ];
1162
+ }
1163
+ });
1164
+ })();
1165
+ });
1166
+ it('should handle API errors when looking up active runs', function() {
1167
+ return _async_to_generator(function() {
1168
+ var env, px, port, waitForOutput, foundTitle, foundMessage, foundDetails;
1169
+ return _ts_generator(this, function(_state) {
1170
+ switch(_state.label){
1171
+ case 0:
1172
+ return [
1173
+ 4,
1174
+ createTestEnv()
1175
+ ];
1176
+ case 1:
1177
+ env = _state.sent();
1178
+ return [
1179
+ 4,
1180
+ env.start()
1181
+ ];
1182
+ case 2:
1183
+ px = _state.sent();
1184
+ _state.label = 3;
1185
+ case 3:
1186
+ _state.trys.push([
1187
+ 3,
1188
+ ,
1189
+ 8,
1190
+ 10
1191
+ ]);
1192
+ // Clear all existing nock interceptors to avoid conflicts
1193
+ nock.cleanAll();
1194
+ // Mock the server to return a 500 error for active-runs endpoint
1195
+ port = env.server.port;
1196
+ nock("http://localhost:".concat(port)).get(/^\/brains\/(.+)\/active-runs$/).reply(500, 'Internal Server Error');
1197
+ return [
1198
+ 4,
1199
+ px([
1200
+ 'watch',
1201
+ 'test-brain'
1202
+ ])
1203
+ ];
1204
+ case 4:
1205
+ waitForOutput = _state.sent().waitForOutput;
1206
+ return [
1207
+ 4,
1208
+ waitForOutput(/API Error/i, 30)
1209
+ ];
1210
+ case 5:
1211
+ foundTitle = _state.sent();
1212
+ expect(foundTitle).toBe(true);
1213
+ return [
1214
+ 4,
1215
+ waitForOutput(/Failed to get active runs for brain "test-brain"/i, 30)
1216
+ ];
1217
+ case 6:
1218
+ foundMessage = _state.sent();
1219
+ expect(foundMessage).toBe(true);
1220
+ return [
1221
+ 4,
1222
+ waitForOutput(/Server returned 500/i, 30)
1223
+ ];
1224
+ case 7:
1225
+ foundDetails = _state.sent();
1226
+ expect(foundDetails).toBe(true);
1227
+ return [
1228
+ 3,
1229
+ 10
1230
+ ];
1231
+ case 8:
1232
+ return [
1233
+ 4,
1234
+ env.stopAndCleanup()
1235
+ ];
1236
+ case 9:
1237
+ _state.sent();
1238
+ return [
1239
+ 7
1240
+ ];
1241
+ case 10:
1242
+ return [
1243
+ 2
1244
+ ];
1245
+ }
1246
+ });
1247
+ })();
1248
+ });
1249
+ it('should handle connection errors when looking up active runs', function() {
1250
+ return _async_to_generator(function() {
1251
+ var env, waitForOutput, foundTitle, foundMessage, foundDetails;
1252
+ return _ts_generator(this, function(_state) {
1253
+ switch(_state.label){
1254
+ case 0:
1255
+ return [
1256
+ 4,
1257
+ createTestEnv()
1258
+ ];
1259
+ case 1:
1260
+ env = _state.sent();
1261
+ _state.label = 2;
1262
+ case 2:
1263
+ _state.trys.push([
1264
+ 2,
1265
+ ,
1266
+ 7,
1267
+ 8
1268
+ ]);
1269
+ return [
1270
+ 4,
1271
+ px([
1272
+ 'watch',
1273
+ 'test-brain'
1274
+ ], {
1275
+ server: env.server
1276
+ })
1277
+ ];
1278
+ case 3:
1279
+ waitForOutput = _state.sent().waitForOutput;
1280
+ return [
1281
+ 4,
1282
+ waitForOutput(/Connection Error/i, 30)
1283
+ ];
1284
+ case 4:
1285
+ foundTitle = _state.sent();
1286
+ expect(foundTitle).toBe(true);
1287
+ return [
1288
+ 4,
1289
+ waitForOutput(/Error connecting to the local development server/i, 30)
1290
+ ];
1291
+ case 5:
1292
+ foundMessage = _state.sent();
1293
+ expect(foundMessage).toBe(true);
1294
+ return [
1295
+ 4,
1296
+ waitForOutput(/positronic server/i, 30)
1297
+ ];
1298
+ case 6:
1299
+ foundDetails = _state.sent();
1300
+ expect(foundDetails).toBe(true);
1301
+ return [
1302
+ 3,
1303
+ 8
1304
+ ];
1305
+ case 7:
1306
+ env.cleanup();
1307
+ return [
1308
+ 7
1309
+ ];
1310
+ case 8:
1311
+ return [
1312
+ 2
1313
+ ];
1314
+ }
1315
+ });
1316
+ })();
1317
+ });
1318
+ it('should show error when no run ID or brain name provided', function() {
1319
+ return _async_to_generator(function() {
1320
+ var env, px;
1321
+ return _ts_generator(this, function(_state) {
1322
+ switch(_state.label){
1323
+ case 0:
1324
+ return [
1325
+ 4,
1326
+ createTestEnv()
1327
+ ];
1328
+ case 1:
1329
+ env = _state.sent();
1330
+ return [
1331
+ 4,
1332
+ env.start()
1333
+ ];
1334
+ case 2:
1335
+ px = _state.sent();
1336
+ _state.label = 3;
1337
+ case 3:
1338
+ _state.trys.push([
1339
+ 3,
1340
+ ,
1341
+ 5,
1342
+ 7
1343
+ ]);
1344
+ // This will throw an error during yargs validation
1345
+ return [
1346
+ 4,
1347
+ expect(px([
1348
+ 'watch'
1349
+ ])).rejects.toThrow('You must provide either a brain name or a --run-id')
1350
+ ];
1351
+ case 4:
1352
+ _state.sent();
1353
+ return [
1354
+ 3,
1355
+ 7
1356
+ ];
1357
+ case 5:
1358
+ return [
1359
+ 4,
1360
+ env.stopAndCleanup()
1361
+ ];
1362
+ case 6:
1363
+ _state.sent();
1364
+ return [
1365
+ 7
1366
+ ];
1367
+ case 7:
1368
+ return [
1369
+ 2
1370
+ ];
1371
+ }
1372
+ });
1373
+ })();
1374
+ });
1375
+ it('should display all step statuses correctly', function() {
1376
+ return _async_to_generator(function() {
1377
+ var env, px, _ref, waitForOutput, instance, foundComplete, foundError, foundRunning, foundPending;
1378
+ return _ts_generator(this, function(_state) {
1379
+ switch(_state.label){
1380
+ case 0:
1381
+ return [
1382
+ 4,
1383
+ createTestEnv()
1384
+ ];
1385
+ case 1:
1386
+ env = _state.sent();
1387
+ return [
1388
+ 4,
1389
+ env.start()
1390
+ ];
1391
+ case 2:
1392
+ px = _state.sent();
1393
+ _state.label = 3;
1394
+ case 3:
1395
+ _state.trys.push([
1396
+ 3,
1397
+ ,
1398
+ 9,
1399
+ 11
1400
+ ]);
1401
+ return [
1402
+ 4,
1403
+ px([
1404
+ 'watch',
1405
+ '--run-id',
1406
+ 'test-multi-status'
1407
+ ])
1408
+ ];
1409
+ case 4:
1410
+ _ref = _state.sent(), waitForOutput = _ref.waitForOutput, instance = _ref.instance;
1411
+ return [
1412
+ 4,
1413
+ waitForOutput(/✔.*Complete Step/)
1414
+ ];
1415
+ case 5:
1416
+ foundComplete = _state.sent();
1417
+ expect(foundComplete).toBe(true);
1418
+ return [
1419
+ 4,
1420
+ waitForOutput(/•.*Error Step/)
1421
+ ];
1422
+ case 6:
1423
+ foundError = _state.sent();
1424
+ expect(foundError).toBe(true);
1425
+ return [
1426
+ 4,
1427
+ waitForOutput(/•.*Running Step/)
1428
+ ];
1429
+ case 7:
1430
+ foundRunning = _state.sent();
1431
+ expect(foundRunning).toBe(true);
1432
+ return [
1433
+ 4,
1434
+ waitForOutput(/•.*Pending Step/)
1435
+ ];
1436
+ case 8:
1437
+ foundPending = _state.sent();
1438
+ expect(foundPending).toBe(true);
1439
+ // Unmount the component to trigger EventSource cleanup
1440
+ instance.unmount();
1441
+ return [
1442
+ 3,
1443
+ 11
1444
+ ];
1445
+ case 9:
1446
+ return [
1447
+ 4,
1448
+ env.stopAndCleanup()
1449
+ ];
1450
+ case 10:
1451
+ _state.sent();
1452
+ return [
1453
+ 7
1454
+ ];
1455
+ case 11:
1456
+ return [
1457
+ 2
1458
+ ];
1459
+ }
1460
+ });
1461
+ })();
1462
+ });
1463
+ });
1464
+ describe('brain list command', function() {
1465
+ it('should list brains when no brains exist', function() {
1466
+ return _async_to_generator(function() {
1467
+ var env, px, waitForOutput, foundEmpty, calls, listCall;
1468
+ return _ts_generator(this, function(_state) {
1469
+ switch(_state.label){
1470
+ case 0:
1471
+ return [
1472
+ 4,
1473
+ createTestEnv()
1474
+ ];
1475
+ case 1:
1476
+ env = _state.sent();
1477
+ return [
1478
+ 4,
1479
+ env.start()
1480
+ ];
1481
+ case 2:
1482
+ px = _state.sent();
1483
+ _state.label = 3;
1484
+ case 3:
1485
+ _state.trys.push([
1486
+ 3,
1487
+ ,
1488
+ 6,
1489
+ 8
1490
+ ]);
1491
+ return [
1492
+ 4,
1493
+ px([
1494
+ 'list'
1495
+ ])
1496
+ ];
1497
+ case 4:
1498
+ waitForOutput = _state.sent().waitForOutput;
1499
+ return [
1500
+ 4,
1501
+ waitForOutput(/No brains found/i, 30)
1502
+ ];
1503
+ case 5:
1504
+ foundEmpty = _state.sent();
1505
+ expect(foundEmpty).toBe(true);
1506
+ // Verify API call was made
1507
+ calls = env.server.getLogs();
1508
+ listCall = calls.find(function(c) {
1509
+ return c.method === 'getBrains';
1510
+ });
1511
+ expect(listCall).toBeDefined();
1512
+ return [
1513
+ 3,
1514
+ 8
1515
+ ];
1516
+ case 6:
1517
+ return [
1518
+ 4,
1519
+ env.stopAndCleanup()
1520
+ ];
1521
+ case 7:
1522
+ _state.sent();
1523
+ return [
1524
+ 7
1525
+ ];
1526
+ case 8:
1527
+ return [
1528
+ 2
1529
+ ];
1530
+ }
1531
+ });
1532
+ })();
1533
+ });
1534
+ it('should list brains when brains exist', function() {
1535
+ return _async_to_generator(function() {
1536
+ var env, server, px, _ref, waitForOutput, instance, foundBrains, output, calls, listCall;
1537
+ return _ts_generator(this, function(_state) {
1538
+ switch(_state.label){
1539
+ case 0:
1540
+ return [
1541
+ 4,
1542
+ createTestEnv()
1543
+ ];
1544
+ case 1:
1545
+ env = _state.sent();
1546
+ server = env.server;
1547
+ // Add test brains before starting
1548
+ server.addBrain({
1549
+ name: 'daily-report',
1550
+ title: 'Daily Report Generator',
1551
+ description: 'Generates daily reports from various data sources',
1552
+ createdAt: Date.now() - 86400000,
1553
+ lastModified: Date.now() - 3600000
1554
+ });
1555
+ server.addBrain({
1556
+ name: 'data-processor',
1557
+ title: 'Data Processing Pipeline',
1558
+ description: 'Processes incoming data and transforms it',
1559
+ createdAt: Date.now() - 172800000,
1560
+ lastModified: Date.now() - 7200000
1561
+ });
1562
+ return [
1563
+ 4,
1564
+ env.start()
1565
+ ];
1566
+ case 2:
1567
+ px = _state.sent();
1568
+ _state.label = 3;
1569
+ case 3:
1570
+ _state.trys.push([
1571
+ 3,
1572
+ ,
1573
+ 6,
1574
+ 8
1575
+ ]);
1576
+ return [
1577
+ 4,
1578
+ px([
1579
+ 'list'
1580
+ ])
1581
+ ];
1582
+ case 4:
1583
+ _ref = _state.sent(), waitForOutput = _ref.waitForOutput, instance = _ref.instance;
1584
+ return [
1585
+ 4,
1586
+ waitForOutput(/daily-report/i, 30)
1587
+ ];
1588
+ case 5:
1589
+ foundBrains = _state.sent();
1590
+ expect(foundBrains).toBe(true);
1591
+ // Check that all data is shown
1592
+ output = instance.lastFrame() || '';
1593
+ expect(output).toContain('daily-report');
1594
+ expect(output).toContain('Daily Report Generator');
1595
+ expect(output).toContain('data-processor');
1596
+ expect(output).toContain('Data Processing Pipeline');
1597
+ // Verify API call
1598
+ calls = server.getLogs();
1599
+ listCall = calls.find(function(c) {
1600
+ return c.method === 'getBrains';
1601
+ });
1602
+ expect(listCall).toBeDefined();
1603
+ return [
1604
+ 3,
1605
+ 8
1606
+ ];
1607
+ case 6:
1608
+ return [
1609
+ 4,
1610
+ env.stopAndCleanup()
1611
+ ];
1612
+ case 7:
1613
+ _state.sent();
1614
+ return [
1615
+ 7
1616
+ ];
1617
+ case 8:
1618
+ return [
1619
+ 2
1620
+ ];
1621
+ }
1622
+ });
1623
+ })();
1624
+ });
1625
+ it('should handle API errors gracefully', function() {
1626
+ return _async_to_generator(function() {
1627
+ var env, waitForOutput, foundError;
1628
+ return _ts_generator(this, function(_state) {
1629
+ switch(_state.label){
1630
+ case 0:
1631
+ return [
1632
+ 4,
1633
+ createTestEnv()
1634
+ ];
1635
+ case 1:
1636
+ env = _state.sent();
1637
+ return [
1638
+ 4,
1639
+ px([
1640
+ 'list'
1641
+ ], {
1642
+ server: env.server
1643
+ })
1644
+ ];
1645
+ case 2:
1646
+ waitForOutput = _state.sent().waitForOutput;
1647
+ _state.label = 3;
1648
+ case 3:
1649
+ _state.trys.push([
1650
+ 3,
1651
+ ,
1652
+ 5,
1653
+ 6
1654
+ ]);
1655
+ return [
1656
+ 4,
1657
+ waitForOutput(/Error connecting to the local development server/i, 30)
1658
+ ];
1659
+ case 4:
1660
+ foundError = _state.sent();
1661
+ expect(foundError).toBe(true);
1662
+ return [
1663
+ 3,
1664
+ 6
1665
+ ];
1666
+ case 5:
1667
+ env.cleanup();
1668
+ return [
1669
+ 7
1670
+ ];
1671
+ case 6:
1672
+ return [
1673
+ 2
1674
+ ];
1675
+ }
1676
+ });
1677
+ })();
1678
+ });
1679
+ });
1680
+ describe('brain history command', function() {
1681
+ it('should show empty history when no runs exist', function() {
1682
+ return _async_to_generator(function() {
1683
+ var env, px, waitForOutput, foundMessage, calls, historyCall;
1684
+ return _ts_generator(this, function(_state) {
1685
+ switch(_state.label){
1686
+ case 0:
1687
+ return [
1688
+ 4,
1689
+ createTestEnv()
1690
+ ];
1691
+ case 1:
1692
+ env = _state.sent();
1693
+ return [
1694
+ 4,
1695
+ env.start()
1696
+ ];
1697
+ case 2:
1698
+ px = _state.sent();
1699
+ _state.label = 3;
1700
+ case 3:
1701
+ _state.trys.push([
1702
+ 3,
1703
+ ,
1704
+ 6,
1705
+ 8
1706
+ ]);
1707
+ return [
1708
+ 4,
1709
+ px([
1710
+ 'history',
1711
+ 'test-brain'
1712
+ ])
1713
+ ];
1714
+ case 4:
1715
+ waitForOutput = _state.sent().waitForOutput;
1716
+ return [
1717
+ 4,
1718
+ waitForOutput(/No run history found for brain: test-brain/i, 30)
1719
+ ];
1720
+ case 5:
1721
+ foundMessage = _state.sent();
1722
+ expect(foundMessage).toBe(true);
1723
+ // Verify API call was made
1724
+ calls = env.server.getLogs();
1725
+ historyCall = calls.find(function(c) {
1726
+ return c.method === 'getBrainHistory';
1727
+ });
1728
+ expect(historyCall).toBeDefined();
1729
+ expect(historyCall === null || historyCall === void 0 ? void 0 : historyCall.args[0]).toBe('test-brain');
1730
+ return [
1731
+ 3,
1732
+ 8
1733
+ ];
1734
+ case 6:
1735
+ return [
1736
+ 4,
1737
+ env.stopAndCleanup()
1738
+ ];
1739
+ case 7:
1740
+ _state.sent();
1741
+ return [
1742
+ 7
1743
+ ];
1744
+ case 8:
1745
+ return [
1746
+ 2
1747
+ ];
1748
+ }
1749
+ });
1750
+ })();
1751
+ });
1752
+ it('should show brain run history when runs exist', function() {
1753
+ return _async_to_generator(function() {
1754
+ var env, server, px, waitForOutput, foundHeader, foundRun1, foundRun2, foundComplete, foundError;
1755
+ return _ts_generator(this, function(_state) {
1756
+ switch(_state.label){
1757
+ case 0:
1758
+ return [
1759
+ 4,
1760
+ createTestEnv()
1761
+ ];
1762
+ case 1:
1763
+ env = _state.sent();
1764
+ server = env.server;
1765
+ // Add some brain runs to history
1766
+ server.addBrainRun({
1767
+ brainRunId: 'run-123',
1768
+ brainTitle: 'Test Brain',
1769
+ brainDescription: 'A test brain',
1770
+ type: 'START',
1771
+ status: 'COMPLETE',
1772
+ createdAt: Date.now() - 3600000,
1773
+ startedAt: Date.now() - 3600000,
1774
+ completedAt: Date.now() - 3540000
1775
+ });
1776
+ server.addBrainRun({
1777
+ brainRunId: 'run-456',
1778
+ brainTitle: 'Test Brain',
1779
+ type: 'START',
1780
+ status: 'ERROR',
1781
+ error: {
1782
+ message: 'Connection failed'
1783
+ },
1784
+ createdAt: Date.now() - 7200000,
1785
+ startedAt: Date.now() - 7200000
1786
+ });
1787
+ return [
1788
+ 4,
1789
+ env.start()
1790
+ ];
1791
+ case 2:
1792
+ px = _state.sent();
1793
+ _state.label = 3;
1794
+ case 3:
1795
+ _state.trys.push([
1796
+ 3,
1797
+ ,
1798
+ 10,
1799
+ 12
1800
+ ]);
1801
+ return [
1802
+ 4,
1803
+ px([
1804
+ 'history',
1805
+ 'test-brain'
1806
+ ])
1807
+ ];
1808
+ case 4:
1809
+ waitForOutput = _state.sent().waitForOutput;
1810
+ return [
1811
+ 4,
1812
+ waitForOutput(/Recent runs for brain "test-brain"/i, 30)
1813
+ ];
1814
+ case 5:
1815
+ foundHeader = _state.sent();
1816
+ expect(foundHeader).toBe(true);
1817
+ return [
1818
+ 4,
1819
+ waitForOutput(/run-123/i, 30)
1820
+ ];
1821
+ case 6:
1822
+ foundRun1 = _state.sent();
1823
+ expect(foundRun1).toBe(true);
1824
+ return [
1825
+ 4,
1826
+ waitForOutput(/run-456/i, 30)
1827
+ ];
1828
+ case 7:
1829
+ foundRun2 = _state.sent();
1830
+ expect(foundRun2).toBe(true);
1831
+ return [
1832
+ 4,
1833
+ waitForOutput(/COMPLETE/i, 30)
1834
+ ];
1835
+ case 8:
1836
+ foundComplete = _state.sent();
1837
+ expect(foundComplete).toBe(true);
1838
+ return [
1839
+ 4,
1840
+ waitForOutput(/ERROR/i, 30)
1841
+ ];
1842
+ case 9:
1843
+ foundError = _state.sent();
1844
+ expect(foundError).toBe(true);
1845
+ return [
1846
+ 3,
1847
+ 12
1848
+ ];
1849
+ case 10:
1850
+ return [
1851
+ 4,
1852
+ env.stopAndCleanup()
1853
+ ];
1854
+ case 11:
1855
+ _state.sent();
1856
+ return [
1857
+ 7
1858
+ ];
1859
+ case 12:
1860
+ return [
1861
+ 2
1862
+ ];
1863
+ }
1864
+ });
1865
+ })();
1866
+ });
1867
+ it('should respect custom limit parameter', function() {
1868
+ return _async_to_generator(function() {
1869
+ var env, px, waitForOutput, calls, historyCall;
1870
+ return _ts_generator(this, function(_state) {
1871
+ switch(_state.label){
1872
+ case 0:
1873
+ return [
1874
+ 4,
1875
+ createTestEnv()
1876
+ ];
1877
+ case 1:
1878
+ env = _state.sent();
1879
+ return [
1880
+ 4,
1881
+ env.start()
1882
+ ];
1883
+ case 2:
1884
+ px = _state.sent();
1885
+ _state.label = 3;
1886
+ case 3:
1887
+ _state.trys.push([
1888
+ 3,
1889
+ ,
1890
+ 6,
1891
+ 8
1892
+ ]);
1893
+ return [
1894
+ 4,
1895
+ px([
1896
+ 'history',
1897
+ 'test-brain',
1898
+ '--limit',
1899
+ '20'
1900
+ ])
1901
+ ];
1902
+ case 4:
1903
+ waitForOutput = _state.sent().waitForOutput;
1904
+ // Wait for the component to render
1905
+ return [
1906
+ 4,
1907
+ waitForOutput(/run history|Recent runs/i, 30)
1908
+ ];
1909
+ case 5:
1910
+ _state.sent();
1911
+ // Verify API was called with correct limit
1912
+ calls = env.server.getLogs();
1913
+ historyCall = calls.find(function(c) {
1914
+ return c.method === 'getBrainHistory';
1915
+ });
1916
+ expect(historyCall).toBeDefined();
1917
+ expect(historyCall === null || historyCall === void 0 ? void 0 : historyCall.args[1]).toBe(20);
1918
+ return [
1919
+ 3,
1920
+ 8
1921
+ ];
1922
+ case 6:
1923
+ return [
1924
+ 4,
1925
+ env.stopAndCleanup()
1926
+ ];
1927
+ case 7:
1928
+ _state.sent();
1929
+ return [
1930
+ 7
1931
+ ];
1932
+ case 8:
1933
+ return [
1934
+ 2
1935
+ ];
1936
+ }
1937
+ });
1938
+ })();
1939
+ });
1940
+ it('should show error details for failed runs', function() {
1941
+ return _async_to_generator(function() {
1942
+ var env, server, px, waitForOutput, foundErrors, foundErrorMsg;
1943
+ return _ts_generator(this, function(_state) {
1944
+ switch(_state.label){
1945
+ case 0:
1946
+ return [
1947
+ 4,
1948
+ createTestEnv()
1949
+ ];
1950
+ case 1:
1951
+ env = _state.sent();
1952
+ server = env.server;
1953
+ // Add a failed brain run
1954
+ server.addBrainRun({
1955
+ brainRunId: 'run-error',
1956
+ brainTitle: 'Test Brain',
1957
+ type: 'START',
1958
+ status: 'ERROR',
1959
+ error: 'Connection timeout',
1960
+ createdAt: Date.now() - 1800000,
1961
+ startedAt: Date.now() - 1800000
1962
+ });
1963
+ return [
1964
+ 4,
1965
+ env.start()
1966
+ ];
1967
+ case 2:
1968
+ px = _state.sent();
1969
+ _state.label = 3;
1970
+ case 3:
1971
+ _state.trys.push([
1972
+ 3,
1973
+ ,
1974
+ 7,
1975
+ 9
1976
+ ]);
1977
+ return [
1978
+ 4,
1979
+ px([
1980
+ 'history',
1981
+ 'test-brain'
1982
+ ])
1983
+ ];
1984
+ case 4:
1985
+ waitForOutput = _state.sent().waitForOutput;
1986
+ return [
1987
+ 4,
1988
+ waitForOutput(/Errors:/i, 30)
1989
+ ];
1990
+ case 5:
1991
+ foundErrors = _state.sent();
1992
+ expect(foundErrors).toBe(true);
1993
+ return [
1994
+ 4,
1995
+ waitForOutput(/Connection timeout/i, 30)
1996
+ ];
1997
+ case 6:
1998
+ foundErrorMsg = _state.sent();
1999
+ expect(foundErrorMsg).toBe(true);
2000
+ return [
2001
+ 3,
2002
+ 9
2003
+ ];
2004
+ case 7:
2005
+ return [
2006
+ 4,
2007
+ env.stopAndCleanup()
2008
+ ];
2009
+ case 8:
2010
+ _state.sent();
2011
+ return [
2012
+ 7
2013
+ ];
2014
+ case 9:
2015
+ return [
2016
+ 2
2017
+ ];
2018
+ }
2019
+ });
2020
+ })();
2021
+ });
2022
+ it('should handle server connection errors', function() {
2023
+ return _async_to_generator(function() {
2024
+ var env, waitForOutput, foundError;
2025
+ return _ts_generator(this, function(_state) {
2026
+ switch(_state.label){
2027
+ case 0:
2028
+ return [
2029
+ 4,
2030
+ createTestEnv()
2031
+ ];
2032
+ case 1:
2033
+ env = _state.sent();
2034
+ _state.label = 2;
2035
+ case 2:
2036
+ _state.trys.push([
2037
+ 2,
2038
+ ,
2039
+ 5,
2040
+ 6
2041
+ ]);
2042
+ return [
2043
+ 4,
2044
+ px([
2045
+ 'history',
2046
+ 'test-brain'
2047
+ ], {
2048
+ server: env.server
2049
+ })
2050
+ ];
2051
+ case 3:
2052
+ waitForOutput = _state.sent().waitForOutput;
2053
+ return [
2054
+ 4,
2055
+ waitForOutput(/Error connecting to the local development server/i, 30)
2056
+ ];
2057
+ case 4:
2058
+ foundError = _state.sent();
2059
+ expect(foundError).toBe(true);
2060
+ return [
2061
+ 3,
2062
+ 6
2063
+ ];
2064
+ case 5:
2065
+ env.cleanup();
2066
+ return [
2067
+ 7
2068
+ ];
2069
+ case 6:
2070
+ return [
2071
+ 2
2072
+ ];
2073
+ }
2074
+ });
2075
+ })();
2076
+ });
2077
+ it('should handle API server errors', function() {
2078
+ return _async_to_generator(function() {
2079
+ var env, px, port, waitForOutput, foundError;
2080
+ return _ts_generator(this, function(_state) {
2081
+ switch(_state.label){
2082
+ case 0:
2083
+ return [
2084
+ 4,
2085
+ createTestEnv()
2086
+ ];
2087
+ case 1:
2088
+ env = _state.sent();
2089
+ return [
2090
+ 4,
2091
+ env.start()
2092
+ ];
2093
+ case 2:
2094
+ px = _state.sent();
2095
+ _state.label = 3;
2096
+ case 3:
2097
+ _state.trys.push([
2098
+ 3,
2099
+ ,
2100
+ 6,
2101
+ 8
2102
+ ]);
2103
+ // Clear all existing nock interceptors to avoid conflicts
2104
+ nock.cleanAll();
2105
+ // Mock the server to return a 500 error
2106
+ port = env.server.port;
2107
+ nock("http://localhost:".concat(port)).get(/^\/brains\/(.+)\/history/).reply(500, 'Internal Server Error');
2108
+ return [
2109
+ 4,
2110
+ px([
2111
+ 'history',
2112
+ 'test-brain'
2113
+ ])
2114
+ ];
2115
+ case 4:
2116
+ waitForOutput = _state.sent().waitForOutput;
2117
+ return [
2118
+ 4,
2119
+ waitForOutput(/Error:|Failed|500/i, 30)
2120
+ ];
2121
+ case 5:
2122
+ foundError = _state.sent();
2123
+ expect(foundError).toBe(true);
2124
+ return [
2125
+ 3,
2126
+ 8
2127
+ ];
2128
+ case 6:
2129
+ return [
2130
+ 4,
2131
+ env.stopAndCleanup()
2132
+ ];
2133
+ case 7:
2134
+ _state.sent();
2135
+ return [
2136
+ 7
2137
+ ];
2138
+ case 8:
2139
+ return [
2140
+ 2
2141
+ ];
2142
+ }
2143
+ });
2144
+ })();
2145
+ });
2146
+ });
2147
+ describe('brain show command', function() {
2148
+ it('should show brain structure when brain exists', function() {
2149
+ return _async_to_generator(function() {
2150
+ var env, server, px, waitForOutput, foundTitle, foundDescription, foundSteps;
2151
+ return _ts_generator(this, function(_state) {
2152
+ switch(_state.label){
2153
+ case 0:
2154
+ return [
2155
+ 4,
2156
+ createTestEnv()
2157
+ ];
2158
+ case 1:
2159
+ env = _state.sent();
2160
+ server = env.server;
2161
+ // Add a brain to the test server with structure
2162
+ server.addBrain({
2163
+ name: 'test-brain',
2164
+ title: 'Test Brain',
2165
+ description: 'A test brain for unit testing',
2166
+ steps: [
2167
+ {
2168
+ type: 'step',
2169
+ title: 'Initialize'
2170
+ },
2171
+ {
2172
+ type: 'step',
2173
+ title: 'Process Data'
2174
+ },
2175
+ {
2176
+ type: 'brain',
2177
+ title: 'Nested Analysis',
2178
+ innerBrain: {
2179
+ title: 'Inner Brain',
2180
+ description: 'Performs nested analysis',
2181
+ steps: [
2182
+ {
2183
+ type: 'step',
2184
+ title: 'Analyze Subset'
2185
+ }
2186
+ ]
2187
+ }
2188
+ }
2189
+ ]
2190
+ });
2191
+ return [
2192
+ 4,
2193
+ env.start()
2194
+ ];
2195
+ case 2:
2196
+ px = _state.sent();
2197
+ _state.label = 3;
2198
+ case 3:
2199
+ _state.trys.push([
2200
+ 3,
2201
+ ,
2202
+ 8,
2203
+ 10
2204
+ ]);
2205
+ return [
2206
+ 4,
2207
+ px([
2208
+ 'show',
2209
+ 'test-brain'
2210
+ ])
2211
+ ];
2212
+ case 4:
2213
+ waitForOutput = _state.sent().waitForOutput;
2214
+ return [
2215
+ 4,
2216
+ waitForOutput(/Test Brain/, 30)
2217
+ ];
2218
+ case 5:
2219
+ foundTitle = _state.sent();
2220
+ expect(foundTitle).toBe(true);
2221
+ return [
2222
+ 4,
2223
+ waitForOutput(/A test brain for unit testing/, 30)
2224
+ ];
2225
+ case 6:
2226
+ foundDescription = _state.sent();
2227
+ expect(foundDescription).toBe(true);
2228
+ return [
2229
+ 4,
2230
+ waitForOutput(/• Initialize/, 30)
2231
+ ];
2232
+ case 7:
2233
+ foundSteps = _state.sent();
2234
+ expect(foundSteps).toBe(true);
2235
+ return [
2236
+ 3,
2237
+ 10
2238
+ ];
2239
+ case 8:
2240
+ return [
2241
+ 4,
2242
+ env.stopAndCleanup()
2243
+ ];
2244
+ case 9:
2245
+ _state.sent();
2246
+ return [
2247
+ 7
2248
+ ];
2249
+ case 10:
2250
+ return [
2251
+ 2
2252
+ ];
2253
+ }
2254
+ });
2255
+ })();
2256
+ });
2257
+ it('should show error when brain does not exist', function() {
2258
+ return _async_to_generator(function() {
2259
+ var env, px, waitForOutput, foundError;
2260
+ return _ts_generator(this, function(_state) {
2261
+ switch(_state.label){
2262
+ case 0:
2263
+ return [
2264
+ 4,
2265
+ createTestEnv()
2266
+ ];
2267
+ case 1:
2268
+ env = _state.sent();
2269
+ return [
2270
+ 4,
2271
+ env.start()
2272
+ ];
2273
+ case 2:
2274
+ px = _state.sent();
2275
+ _state.label = 3;
2276
+ case 3:
2277
+ _state.trys.push([
2278
+ 3,
2279
+ ,
2280
+ 6,
2281
+ 8
2282
+ ]);
2283
+ return [
2284
+ 4,
2285
+ px([
2286
+ 'show',
2287
+ 'non-existent-brain'
2288
+ ])
2289
+ ];
2290
+ case 4:
2291
+ waitForOutput = _state.sent().waitForOutput;
2292
+ return [
2293
+ 4,
2294
+ waitForOutput(/Brain 'non-existent-brain' not found/, 30)
2295
+ ];
2296
+ case 5:
2297
+ foundError = _state.sent();
2298
+ expect(foundError).toBe(true);
2299
+ return [
2300
+ 3,
2301
+ 8
2302
+ ];
2303
+ case 6:
2304
+ return [
2305
+ 4,
2306
+ env.stopAndCleanup()
2307
+ ];
2308
+ case 7:
2309
+ _state.sent();
2310
+ return [
2311
+ 7
2312
+ ];
2313
+ case 8:
2314
+ return [
2315
+ 2
2316
+ ];
2317
+ }
2318
+ });
2319
+ })();
2320
+ });
2321
+ });
2322
+ describe('brain rerun command', function() {
2323
+ it('should successfully rerun a brain without specific run ID', function() {
2324
+ return _async_to_generator(function() {
2325
+ var env, px, waitForOutput, foundSuccess, foundRunId, foundDescription, foundWatchSuggestion, calls, rerunCall;
2326
+ return _ts_generator(this, function(_state) {
2327
+ switch(_state.label){
2328
+ case 0:
2329
+ return [
2330
+ 4,
2331
+ createTestEnv()
2332
+ ];
2333
+ case 1:
2334
+ env = _state.sent();
2335
+ return [
2336
+ 4,
2337
+ env.start()
2338
+ ];
2339
+ case 2:
2340
+ px = _state.sent();
2341
+ _state.label = 3;
2342
+ case 3:
2343
+ _state.trys.push([
2344
+ 3,
2345
+ ,
2346
+ 9,
2347
+ 11
2348
+ ]);
2349
+ return [
2350
+ 4,
2351
+ px([
2352
+ 'rerun',
2353
+ 'test-brain'
2354
+ ])
2355
+ ];
2356
+ case 4:
2357
+ waitForOutput = _state.sent().waitForOutput;
2358
+ return [
2359
+ 4,
2360
+ waitForOutput(/Brain rerun started successfully/i, 30)
2361
+ ];
2362
+ case 5:
2363
+ foundSuccess = _state.sent();
2364
+ expect(foundSuccess).toBe(true);
2365
+ return [
2366
+ 4,
2367
+ waitForOutput(/New run ID:.*rerun-/i, 30)
2368
+ ];
2369
+ case 6:
2370
+ foundRunId = _state.sent();
2371
+ expect(foundRunId).toBe(true);
2372
+ return [
2373
+ 4,
2374
+ waitForOutput(/Rerunning brain "test-brain"/i, 30)
2375
+ ];
2376
+ case 7:
2377
+ foundDescription = _state.sent();
2378
+ expect(foundDescription).toBe(true);
2379
+ return [
2380
+ 4,
2381
+ waitForOutput(/Watch the run with: positronic watch --run-id/i, 30)
2382
+ ];
2383
+ case 8:
2384
+ foundWatchSuggestion = _state.sent();
2385
+ expect(foundWatchSuggestion).toBe(true);
2386
+ // Verify API call
2387
+ calls = env.server.getLogs();
2388
+ rerunCall = calls.find(function(c) {
2389
+ return c.method === 'rerunBrain';
2390
+ });
2391
+ expect(rerunCall).toBeDefined();
2392
+ expect(rerunCall === null || rerunCall === void 0 ? void 0 : rerunCall.args[0]).toBe('test-brain');
2393
+ expect(rerunCall === null || rerunCall === void 0 ? void 0 : rerunCall.args[1]).toBeUndefined(); // no runId
2394
+ return [
2395
+ 3,
2396
+ 11
2397
+ ];
2398
+ case 9:
2399
+ return [
2400
+ 4,
2401
+ env.stopAndCleanup()
2402
+ ];
2403
+ case 10:
2404
+ _state.sent();
2405
+ return [
2406
+ 7
2407
+ ];
2408
+ case 11:
2409
+ return [
2410
+ 2
2411
+ ];
2412
+ }
2413
+ });
2414
+ })();
2415
+ });
2416
+ it('should successfully rerun a brain with specific run ID', function() {
2417
+ return _async_to_generator(function() {
2418
+ var env, px, waitForOutput, foundSuccess, foundRunDetails, calls, rerunCall;
2419
+ return _ts_generator(this, function(_state) {
2420
+ switch(_state.label){
2421
+ case 0:
2422
+ return [
2423
+ 4,
2424
+ createTestEnv()
2425
+ ];
2426
+ case 1:
2427
+ env = _state.sent();
2428
+ return [
2429
+ 4,
2430
+ env.start()
2431
+ ];
2432
+ case 2:
2433
+ px = _state.sent();
2434
+ _state.label = 3;
2435
+ case 3:
2436
+ _state.trys.push([
2437
+ 3,
2438
+ ,
2439
+ 7,
2440
+ 9
2441
+ ]);
2442
+ return [
2443
+ 4,
2444
+ px([
2445
+ 'rerun',
2446
+ 'test-brain',
2447
+ 'run-123'
2448
+ ])
2449
+ ];
2450
+ case 4:
2451
+ waitForOutput = _state.sent().waitForOutput;
2452
+ return [
2453
+ 4,
2454
+ waitForOutput(/Brain rerun started successfully/i, 30)
2455
+ ];
2456
+ case 5:
2457
+ foundSuccess = _state.sent();
2458
+ expect(foundSuccess).toBe(true);
2459
+ return [
2460
+ 4,
2461
+ waitForOutput(/from run run-123/i, 30)
2462
+ ];
2463
+ case 6:
2464
+ foundRunDetails = _state.sent();
2465
+ expect(foundRunDetails).toBe(true);
2466
+ // Verify API call
2467
+ calls = env.server.getLogs();
2468
+ rerunCall = calls.find(function(c) {
2469
+ return c.method === 'rerunBrain';
2470
+ });
2471
+ expect(rerunCall).toBeDefined();
2472
+ expect(rerunCall === null || rerunCall === void 0 ? void 0 : rerunCall.args[0]).toBe('test-brain');
2473
+ expect(rerunCall === null || rerunCall === void 0 ? void 0 : rerunCall.args[1]).toBe('run-123');
2474
+ return [
2475
+ 3,
2476
+ 9
2477
+ ];
2478
+ case 7:
2479
+ return [
2480
+ 4,
2481
+ env.stopAndCleanup()
2482
+ ];
2483
+ case 8:
2484
+ _state.sent();
2485
+ return [
2486
+ 7
2487
+ ];
2488
+ case 9:
2489
+ return [
2490
+ 2
2491
+ ];
2492
+ }
2493
+ });
2494
+ })();
2495
+ });
2496
+ it('should successfully rerun a brain with step range options', function() {
2497
+ return _async_to_generator(function() {
2498
+ var env, px, waitForOutput, foundSuccess, foundStepRange, calls, rerunCall;
2499
+ return _ts_generator(this, function(_state) {
2500
+ switch(_state.label){
2501
+ case 0:
2502
+ return [
2503
+ 4,
2504
+ createTestEnv()
2505
+ ];
2506
+ case 1:
2507
+ env = _state.sent();
2508
+ return [
2509
+ 4,
2510
+ env.start()
2511
+ ];
2512
+ case 2:
2513
+ px = _state.sent();
2514
+ _state.label = 3;
2515
+ case 3:
2516
+ _state.trys.push([
2517
+ 3,
2518
+ ,
2519
+ 7,
2520
+ 9
2521
+ ]);
2522
+ return [
2523
+ 4,
2524
+ px([
2525
+ 'rerun',
2526
+ 'test-brain',
2527
+ '--starts-at',
2528
+ '3',
2529
+ '--stops-after',
2530
+ '5'
2531
+ ])
2532
+ ];
2533
+ case 4:
2534
+ waitForOutput = _state.sent().waitForOutput;
2535
+ return [
2536
+ 4,
2537
+ waitForOutput(/Brain rerun started successfully/i, 30)
2538
+ ];
2539
+ case 5:
2540
+ foundSuccess = _state.sent();
2541
+ expect(foundSuccess).toBe(true);
2542
+ return [
2543
+ 4,
2544
+ waitForOutput(/starting at step 3, stopping after step 5/i, 30)
2545
+ ];
2546
+ case 6:
2547
+ foundStepRange = _state.sent();
2548
+ expect(foundStepRange).toBe(true);
2549
+ // Verify API call
2550
+ calls = env.server.getLogs();
2551
+ rerunCall = calls.find(function(c) {
2552
+ return c.method === 'rerunBrain';
2553
+ });
2554
+ expect(rerunCall).toBeDefined();
2555
+ expect(rerunCall === null || rerunCall === void 0 ? void 0 : rerunCall.args[0]).toBe('test-brain');
2556
+ expect(rerunCall === null || rerunCall === void 0 ? void 0 : rerunCall.args[1]).toBeUndefined(); // no runId
2557
+ expect(rerunCall === null || rerunCall === void 0 ? void 0 : rerunCall.args[2]).toBe(3); // startsAt
2558
+ expect(rerunCall === null || rerunCall === void 0 ? void 0 : rerunCall.args[3]).toBe(5); // stopsAfter
2559
+ return [
2560
+ 3,
2561
+ 9
2562
+ ];
2563
+ case 7:
2564
+ return [
2565
+ 4,
2566
+ env.stopAndCleanup()
2567
+ ];
2568
+ case 8:
2569
+ _state.sent();
2570
+ return [
2571
+ 7
2572
+ ];
2573
+ case 9:
2574
+ return [
2575
+ 2
2576
+ ];
2577
+ }
2578
+ });
2579
+ })();
2580
+ });
2581
+ it('should handle brain not found error', function() {
2582
+ return _async_to_generator(function() {
2583
+ var env, px, waitForOutput, foundErrorTitle, foundErrorMessage, foundDetails;
2584
+ return _ts_generator(this, function(_state) {
2585
+ switch(_state.label){
2586
+ case 0:
2587
+ return [
2588
+ 4,
2589
+ createTestEnv()
2590
+ ];
2591
+ case 1:
2592
+ env = _state.sent();
2593
+ return [
2594
+ 4,
2595
+ env.start()
2596
+ ];
2597
+ case 2:
2598
+ px = _state.sent();
2599
+ _state.label = 3;
2600
+ case 3:
2601
+ _state.trys.push([
2602
+ 3,
2603
+ ,
2604
+ 8,
2605
+ 10
2606
+ ]);
2607
+ return [
2608
+ 4,
2609
+ px([
2610
+ 'rerun',
2611
+ 'non-existent-brain'
2612
+ ])
2613
+ ];
2614
+ case 4:
2615
+ waitForOutput = _state.sent().waitForOutput;
2616
+ return [
2617
+ 4,
2618
+ waitForOutput(/Brain Rerun Failed/i, 30)
2619
+ ];
2620
+ case 5:
2621
+ foundErrorTitle = _state.sent();
2622
+ expect(foundErrorTitle).toBe(true);
2623
+ return [
2624
+ 4,
2625
+ waitForOutput(/Brain 'non-existent-brain' not found/i, 30)
2626
+ ];
2627
+ case 6:
2628
+ foundErrorMessage = _state.sent();
2629
+ expect(foundErrorMessage).toBe(true);
2630
+ return [
2631
+ 4,
2632
+ waitForOutput(/positronic brain list/i, 30)
2633
+ ];
2634
+ case 7:
2635
+ foundDetails = _state.sent();
2636
+ expect(foundDetails).toBe(true);
2637
+ return [
2638
+ 3,
2639
+ 10
2640
+ ];
2641
+ case 8:
2642
+ return [
2643
+ 4,
2644
+ env.stopAndCleanup()
2645
+ ];
2646
+ case 9:
2647
+ _state.sent();
2648
+ return [
2649
+ 7
2650
+ ];
2651
+ case 10:
2652
+ return [
2653
+ 2
2654
+ ];
2655
+ }
2656
+ });
2657
+ })();
2658
+ });
2659
+ it('should handle run ID not found error', function() {
2660
+ return _async_to_generator(function() {
2661
+ var env, px, waitForOutput, foundErrorTitle, foundErrorMessage, foundDetails;
2662
+ return _ts_generator(this, function(_state) {
2663
+ switch(_state.label){
2664
+ case 0:
2665
+ return [
2666
+ 4,
2667
+ createTestEnv()
2668
+ ];
2669
+ case 1:
2670
+ env = _state.sent();
2671
+ return [
2672
+ 4,
2673
+ env.start()
2674
+ ];
2675
+ case 2:
2676
+ px = _state.sent();
2677
+ _state.label = 3;
2678
+ case 3:
2679
+ _state.trys.push([
2680
+ 3,
2681
+ ,
2682
+ 8,
2683
+ 10
2684
+ ]);
2685
+ return [
2686
+ 4,
2687
+ px([
2688
+ 'rerun',
2689
+ 'test-brain',
2690
+ 'non-existent-run'
2691
+ ])
2692
+ ];
2693
+ case 4:
2694
+ waitForOutput = _state.sent().waitForOutput;
2695
+ return [
2696
+ 4,
2697
+ waitForOutput(/Brain Rerun Failed/i, 30)
2698
+ ];
2699
+ case 5:
2700
+ foundErrorTitle = _state.sent();
2701
+ expect(foundErrorTitle).toBe(true);
2702
+ return [
2703
+ 4,
2704
+ waitForOutput(/Brain run 'non-existent-run' not found/i, 30)
2705
+ ];
2706
+ case 6:
2707
+ foundErrorMessage = _state.sent();
2708
+ expect(foundErrorMessage).toBe(true);
2709
+ return [
2710
+ 4,
2711
+ waitForOutput(/positronic brain history test-brain/i, 30)
2712
+ ];
2713
+ case 7:
2714
+ foundDetails = _state.sent();
2715
+ expect(foundDetails).toBe(true);
2716
+ return [
2717
+ 3,
2718
+ 10
2719
+ ];
2720
+ case 8:
2721
+ return [
2722
+ 4,
2723
+ env.stopAndCleanup()
2724
+ ];
2725
+ case 9:
2726
+ _state.sent();
2727
+ return [
2728
+ 7
2729
+ ];
2730
+ case 10:
2731
+ return [
2732
+ 2
2733
+ ];
2734
+ }
2735
+ });
2736
+ })();
2737
+ });
2738
+ it('should handle server connection errors', function() {
2739
+ return _async_to_generator(function() {
2740
+ var env, waitForOutput, foundErrorTitle, foundConnectionError;
2741
+ return _ts_generator(this, function(_state) {
2742
+ switch(_state.label){
2743
+ case 0:
2744
+ return [
2745
+ 4,
2746
+ createTestEnv()
2747
+ ];
2748
+ case 1:
2749
+ env = _state.sent();
2750
+ _state.label = 2;
2751
+ case 2:
2752
+ _state.trys.push([
2753
+ 2,
2754
+ ,
2755
+ 6,
2756
+ 7
2757
+ ]);
2758
+ return [
2759
+ 4,
2760
+ px([
2761
+ 'rerun',
2762
+ 'test-brain'
2763
+ ], {
2764
+ server: env.server
2765
+ })
2766
+ ];
2767
+ case 3:
2768
+ waitForOutput = _state.sent().waitForOutput;
2769
+ return [
2770
+ 4,
2771
+ waitForOutput(/Brain Rerun Failed/i, 30)
2772
+ ];
2773
+ case 4:
2774
+ foundErrorTitle = _state.sent();
2775
+ expect(foundErrorTitle).toBe(true);
2776
+ return [
2777
+ 4,
2778
+ waitForOutput(/Connection error/i, 30)
2779
+ ];
2780
+ case 5:
2781
+ foundConnectionError = _state.sent();
2782
+ expect(foundConnectionError).toBe(true);
2783
+ return [
2784
+ 3,
2785
+ 7
2786
+ ];
2787
+ case 6:
2788
+ env.cleanup();
2789
+ return [
2790
+ 7
2791
+ ];
2792
+ case 7:
2793
+ return [
2794
+ 2
2795
+ ];
2796
+ }
2797
+ });
2798
+ })();
2799
+ });
2800
+ it('should handle API server errors', function() {
2801
+ return _async_to_generator(function() {
2802
+ var env, px, port, waitForOutput, foundErrorTitle, foundServerError;
2803
+ return _ts_generator(this, function(_state) {
2804
+ switch(_state.label){
2805
+ case 0:
2806
+ return [
2807
+ 4,
2808
+ createTestEnv()
2809
+ ];
2810
+ case 1:
2811
+ env = _state.sent();
2812
+ return [
2813
+ 4,
2814
+ env.start()
2815
+ ];
2816
+ case 2:
2817
+ px = _state.sent();
2818
+ _state.label = 3;
2819
+ case 3:
2820
+ _state.trys.push([
2821
+ 3,
2822
+ ,
2823
+ 7,
2824
+ 9
2825
+ ]);
2826
+ // Clear all existing nock interceptors to avoid conflicts
2827
+ nock.cleanAll();
2828
+ // Mock the server to return a 500 error
2829
+ port = env.server.port;
2830
+ nock("http://localhost:".concat(port)).post('/brains/runs/rerun').reply(500, 'Internal Server Error');
2831
+ return [
2832
+ 4,
2833
+ px([
2834
+ 'rerun',
2835
+ 'test-brain'
2836
+ ])
2837
+ ];
2838
+ case 4:
2839
+ waitForOutput = _state.sent().waitForOutput;
2840
+ return [
2841
+ 4,
2842
+ waitForOutput(/Brain Rerun Failed/i, 30)
2843
+ ];
2844
+ case 5:
2845
+ foundErrorTitle = _state.sent();
2846
+ expect(foundErrorTitle).toBe(true);
2847
+ return [
2848
+ 4,
2849
+ waitForOutput(/Server returned 500/i, 30)
2850
+ ];
2851
+ case 6:
2852
+ foundServerError = _state.sent();
2853
+ expect(foundServerError).toBe(true);
2854
+ return [
2855
+ 3,
2856
+ 9
2857
+ ];
2858
+ case 7:
2859
+ return [
2860
+ 4,
2861
+ env.stopAndCleanup()
2862
+ ];
2863
+ case 8:
2864
+ _state.sent();
2865
+ return [
2866
+ 7
2867
+ ];
2868
+ case 9:
2869
+ return [
2870
+ 2
2871
+ ];
2872
+ }
2873
+ });
2874
+ })();
2875
+ });
2876
+ });
2877
+ describe('error handling', function() {
2878
+ it('should handle missing brain name for run command', function() {
2879
+ return _async_to_generator(function() {
2880
+ var env, px;
2881
+ return _ts_generator(this, function(_state) {
2882
+ switch(_state.label){
2883
+ case 0:
2884
+ return [
2885
+ 4,
2886
+ createTestEnv()
2887
+ ];
2888
+ case 1:
2889
+ env = _state.sent();
2890
+ return [
2891
+ 4,
2892
+ env.start()
2893
+ ];
2894
+ case 2:
2895
+ px = _state.sent();
2896
+ _state.label = 3;
2897
+ case 3:
2898
+ _state.trys.push([
2899
+ 3,
2900
+ ,
2901
+ 5,
2902
+ 7
2903
+ ]);
2904
+ // This will throw an error during yargs validation
2905
+ return [
2906
+ 4,
2907
+ expect(px([
2908
+ 'run'
2909
+ ])).rejects.toThrow('Not enough non-option arguments: got 0, need at least 1')
2910
+ ];
2911
+ case 4:
2912
+ _state.sent();
2913
+ return [
2914
+ 3,
2915
+ 7
2916
+ ];
2917
+ case 5:
2918
+ return [
2919
+ 4,
2920
+ env.stopAndCleanup()
2921
+ ];
2922
+ case 6:
2923
+ _state.sent();
2924
+ return [
2925
+ 7
2926
+ ];
2927
+ case 7:
2928
+ return [
2929
+ 2
2930
+ ];
2931
+ }
2932
+ });
2933
+ })();
2934
+ });
2935
+ });
2936
+ });