@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,169 @@
1
+ import React from 'react';
2
+ import { Text, Box } from 'ink';
3
+ import { useApiGet } from '../hooks/useApi.js';
4
+ import { ErrorComponent } from './error.js';
5
+ // Helper to format dates
6
+ var formatDate = function(timestamp) {
7
+ var date = new Date(timestamp);
8
+ return date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
9
+ };
10
+ // Helper to format relative time
11
+ var formatRelativeTime = function(timestamp) {
12
+ var now = Date.now();
13
+ var diffMs = now - timestamp;
14
+ var diffMins = Math.floor(diffMs / (1000 * 60));
15
+ var diffHours = Math.floor(diffMs / (1000 * 60 * 60));
16
+ var diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
17
+ if (diffMins < 1) {
18
+ return 'just now';
19
+ } else if (diffMins < 60) {
20
+ return "".concat(diffMins, " min ago");
21
+ } else if (diffHours < 24) {
22
+ return "".concat(diffHours, " hr ago");
23
+ } else {
24
+ return "".concat(diffDays, " day").concat(diffDays === 1 ? '' : 's', " ago");
25
+ }
26
+ };
27
+ // Helper to format duration
28
+ var formatDuration = function(startMs, endMs) {
29
+ var durationMs = endMs - startMs;
30
+ var seconds = Math.floor(durationMs / 1000);
31
+ var minutes = Math.floor(seconds / 60);
32
+ if (seconds < 60) {
33
+ return "".concat(seconds, "s");
34
+ } else {
35
+ var remainingSeconds = seconds % 60;
36
+ return "".concat(minutes, "m ").concat(remainingSeconds, "s");
37
+ }
38
+ };
39
+ // Helper to get status color
40
+ var getStatusColor = function(status) {
41
+ switch(status){
42
+ case 'COMPLETE':
43
+ return 'green';
44
+ case 'ERROR':
45
+ return 'red';
46
+ case 'RUNNING':
47
+ return 'yellow';
48
+ default:
49
+ return 'gray';
50
+ }
51
+ };
52
+ // Helper to pad text to column width
53
+ var padRight = function(text, width) {
54
+ return text + ' '.repeat(Math.max(0, width - text.length));
55
+ };
56
+ // Helper to truncate text
57
+ var truncate = function(text, maxWidth) {
58
+ if (text.length <= maxWidth) return text;
59
+ return text.substring(0, maxWidth - 3) + '...';
60
+ };
61
+ export var BrainHistory = function(param) {
62
+ var brainName = param.brainName, limit = param.limit;
63
+ var url = "/brains/".concat(encodeURIComponent(brainName), "/history?limit=").concat(limit);
64
+ var _useApiGet = useApiGet(url), data = _useApiGet.data, loading = _useApiGet.loading, error = _useApiGet.error;
65
+ if (error) {
66
+ return /*#__PURE__*/ React.createElement(ErrorComponent, {
67
+ error: error
68
+ });
69
+ }
70
+ if (loading) {
71
+ return /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, null, "\uD83E\uDDE0 Loading brain history..."));
72
+ }
73
+ if (!data || data.runs.length === 0) {
74
+ return /*#__PURE__*/ React.createElement(Box, {
75
+ flexDirection: "column"
76
+ }, /*#__PURE__*/ React.createElement(Text, null, "No run history found for brain: ", brainName), /*#__PURE__*/ React.createElement(Box, {
77
+ marginTop: 1
78
+ }, /*#__PURE__*/ React.createElement(Text, {
79
+ dimColor: true
80
+ }, 'Tip: Run this brain with "px run ', brainName, '" to create history')));
81
+ }
82
+ // Define column widths
83
+ var columns = {
84
+ runId: {
85
+ header: 'Run ID',
86
+ width: 38
87
+ },
88
+ status: {
89
+ header: 'Status',
90
+ width: 10
91
+ },
92
+ type: {
93
+ header: 'Type',
94
+ width: 10
95
+ },
96
+ when: {
97
+ header: 'When',
98
+ width: 12
99
+ },
100
+ duration: {
101
+ header: 'Duration',
102
+ width: 10
103
+ },
104
+ startedAt: {
105
+ header: 'Started At',
106
+ width: 20
107
+ }
108
+ };
109
+ return /*#__PURE__*/ React.createElement(Box, {
110
+ flexDirection: "column",
111
+ paddingTop: 1,
112
+ paddingBottom: 1
113
+ }, /*#__PURE__*/ React.createElement(Text, {
114
+ bold: true
115
+ }, 'Recent runs for brain "', brainName, '" (', data.runs.length, " shown):"), /*#__PURE__*/ React.createElement(Box, {
116
+ marginTop: 1,
117
+ flexDirection: "column"
118
+ }, /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, {
119
+ bold: true,
120
+ color: "cyan"
121
+ }, padRight(columns.runId.header, columns.runId.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, {
122
+ bold: true,
123
+ color: "cyan"
124
+ }, padRight(columns.status.header, columns.status.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, {
125
+ bold: true,
126
+ color: "cyan"
127
+ }, padRight(columns.type.header, columns.type.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, {
128
+ bold: true,
129
+ color: "cyan"
130
+ }, padRight(columns.when.header, columns.when.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, {
131
+ bold: true,
132
+ color: "cyan"
133
+ }, padRight(columns.duration.header, columns.duration.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, {
134
+ bold: true,
135
+ color: "cyan"
136
+ }, padRight(columns.startedAt.header, columns.startedAt.width))), /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, {
137
+ dimColor: true
138
+ }, '─'.repeat(112))), data.runs.map(function(run) {
139
+ var duration = run.startedAt && run.completedAt ? formatDuration(run.startedAt, run.completedAt) : run.status === 'RUNNING' ? 'Running...' : 'N/A';
140
+ return /*#__PURE__*/ React.createElement(Box, {
141
+ key: run.brainRunId
142
+ }, /*#__PURE__*/ React.createElement(Text, null, padRight(truncate(run.brainRunId, columns.runId.width), columns.runId.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, {
143
+ color: getStatusColor(run.status)
144
+ }, padRight(run.status, columns.status.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, null, padRight(run.type || 'N/A', columns.type.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, {
145
+ dimColor: true
146
+ }, padRight(formatRelativeTime(run.createdAt), columns.when.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, null, padRight(duration, columns.duration.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, {
147
+ dimColor: true
148
+ }, padRight(run.startedAt ? formatDate(run.startedAt) : 'N/A', columns.startedAt.width)));
149
+ }), data.runs.filter(function(r) {
150
+ return r.status === 'ERROR' && r.error;
151
+ }).length > 0 && /*#__PURE__*/ React.createElement(Box, {
152
+ flexDirection: "column",
153
+ marginTop: 1
154
+ }, /*#__PURE__*/ React.createElement(Text, {
155
+ bold: true,
156
+ color: "red"
157
+ }, "Errors:"), data.runs.filter(function(r) {
158
+ return r.status === 'ERROR' && r.error;
159
+ }).map(function(run) {
160
+ return /*#__PURE__*/ React.createElement(Box, {
161
+ key: run.brainRunId,
162
+ marginLeft: 2
163
+ }, /*#__PURE__*/ React.createElement(Text, {
164
+ dimColor: true
165
+ }, run.brainRunId, ": "), /*#__PURE__*/ React.createElement(Text, {
166
+ color: "red"
167
+ }, typeof run.error === 'string' ? run.error : JSON.stringify(run.error)));
168
+ }))));
169
+ };
@@ -0,0 +1,108 @@
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 } from 'ink';
28
+ import { ErrorComponent } from './error.js';
29
+ import { useApiGet } from '../hooks/useApi.js';
30
+ // Helper to truncate text to fit column width
31
+ var truncate = function(text, maxWidth) {
32
+ if (text.length <= maxWidth) return text;
33
+ return text.substring(0, maxWidth - 3) + '...';
34
+ };
35
+ // Helper to pad text to column width
36
+ var padRight = function(text, width) {
37
+ return text + ' '.repeat(Math.max(0, width - text.length));
38
+ };
39
+ export var BrainList = function() {
40
+ var _useApiGet = useApiGet('/brains'), data = _useApiGet.data, loading = _useApiGet.loading, error = _useApiGet.error;
41
+ if (error) {
42
+ return /*#__PURE__*/ React.createElement(ErrorComponent, {
43
+ error: error
44
+ });
45
+ }
46
+ if (loading) {
47
+ return /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, null, "\uD83E\uDDE0 Loading brains..."));
48
+ }
49
+ if (!data || data.brains.length === 0) {
50
+ return /*#__PURE__*/ React.createElement(Box, {
51
+ flexDirection: "column"
52
+ }, /*#__PURE__*/ React.createElement(Text, null, "No brains found."), /*#__PURE__*/ React.createElement(Box, {
53
+ marginTop: 1
54
+ }, /*#__PURE__*/ React.createElement(Text, {
55
+ dimColor: true
56
+ }, 'Tip: Create a brain with "px brain new <name>" or add .ts files to the brains/ directory')));
57
+ }
58
+ // Sort brains alphabetically by name
59
+ var sortedBrains = _to_consumable_array(data.brains).sort(function(a, b) {
60
+ return a.name.localeCompare(b.name);
61
+ });
62
+ // Define column widths
63
+ var columns = {
64
+ name: {
65
+ header: 'Name',
66
+ width: 25
67
+ },
68
+ title: {
69
+ header: 'Title',
70
+ width: 35
71
+ },
72
+ description: {
73
+ header: 'Description',
74
+ width: 50
75
+ }
76
+ };
77
+ // Calculate total width for separator
78
+ var totalWidth = Object.values(columns).reduce(function(sum, col) {
79
+ return sum + col.width + 2;
80
+ }, 0) - 2;
81
+ return /*#__PURE__*/ React.createElement(Box, {
82
+ flexDirection: "column",
83
+ paddingTop: 1,
84
+ paddingBottom: 1
85
+ }, /*#__PURE__*/ React.createElement(Text, {
86
+ bold: true
87
+ }, "Found ", data.count, " brain", data.count === 1 ? '' : 's', ":"), /*#__PURE__*/ React.createElement(Box, {
88
+ marginTop: 1,
89
+ flexDirection: "column"
90
+ }, /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, {
91
+ bold: true,
92
+ color: "cyan"
93
+ }, padRight(columns.name.header, columns.name.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, {
94
+ bold: true,
95
+ color: "cyan"
96
+ }, padRight(columns.title.header, columns.title.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, {
97
+ bold: true,
98
+ color: "cyan"
99
+ }, padRight(columns.description.header, columns.description.width))), /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, {
100
+ dimColor: true
101
+ }, '─'.repeat(totalWidth))), sortedBrains.map(function(brain) {
102
+ return /*#__PURE__*/ React.createElement(Box, {
103
+ key: brain.name
104
+ }, /*#__PURE__*/ React.createElement(Text, null, padRight(truncate(brain.name, columns.name.width), columns.name.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, null, padRight(truncate(brain.title, columns.title.width), columns.title.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, {
105
+ dimColor: true
106
+ }, padRight(truncate(brain.description, columns.description.width), columns.description.width)));
107
+ })));
108
+ };
@@ -0,0 +1,313 @@
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 asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
10
+ try {
11
+ var info = gen[key](arg);
12
+ var value = info.value;
13
+ } catch (error) {
14
+ reject(error);
15
+ return;
16
+ }
17
+ if (info.done) {
18
+ resolve(value);
19
+ } else {
20
+ Promise.resolve(value).then(_next, _throw);
21
+ }
22
+ }
23
+ function _async_to_generator(fn) {
24
+ return function() {
25
+ var self = this, args = arguments;
26
+ return new Promise(function(resolve, reject) {
27
+ var gen = fn.apply(self, args);
28
+ function _next(value) {
29
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
30
+ }
31
+ function _throw(err) {
32
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
33
+ }
34
+ _next(undefined);
35
+ });
36
+ };
37
+ }
38
+ function _iterable_to_array_limit(arr, i) {
39
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
40
+ if (_i == null) return;
41
+ var _arr = [];
42
+ var _n = true;
43
+ var _d = false;
44
+ var _s, _e;
45
+ try {
46
+ for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
47
+ _arr.push(_s.value);
48
+ if (i && _arr.length === i) break;
49
+ }
50
+ } catch (err) {
51
+ _d = true;
52
+ _e = err;
53
+ } finally{
54
+ try {
55
+ if (!_n && _i["return"] != null) _i["return"]();
56
+ } finally{
57
+ if (_d) throw _e;
58
+ }
59
+ }
60
+ return _arr;
61
+ }
62
+ function _non_iterable_rest() {
63
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
64
+ }
65
+ function _sliced_to_array(arr, i) {
66
+ return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
67
+ }
68
+ function _unsupported_iterable_to_array(o, minLen) {
69
+ if (!o) return;
70
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
71
+ var n = Object.prototype.toString.call(o).slice(8, -1);
72
+ if (n === "Object" && o.constructor) n = o.constructor.name;
73
+ if (n === "Map" || n === "Set") return Array.from(n);
74
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
75
+ }
76
+ function _ts_generator(thisArg, body) {
77
+ var f, y, t, _ = {
78
+ label: 0,
79
+ sent: function() {
80
+ if (t[0] & 1) throw t[1];
81
+ return t[1];
82
+ },
83
+ trys: [],
84
+ ops: []
85
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
86
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
87
+ return this;
88
+ }), g;
89
+ function verb(n) {
90
+ return function(v) {
91
+ return step([
92
+ n,
93
+ v
94
+ ]);
95
+ };
96
+ }
97
+ function step(op) {
98
+ if (f) throw new TypeError("Generator is already executing.");
99
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
100
+ 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;
101
+ if (y = 0, t) op = [
102
+ op[0] & 2,
103
+ t.value
104
+ ];
105
+ switch(op[0]){
106
+ case 0:
107
+ case 1:
108
+ t = op;
109
+ break;
110
+ case 4:
111
+ _.label++;
112
+ return {
113
+ value: op[1],
114
+ done: false
115
+ };
116
+ case 5:
117
+ _.label++;
118
+ y = op[1];
119
+ op = [
120
+ 0
121
+ ];
122
+ continue;
123
+ case 7:
124
+ op = _.ops.pop();
125
+ _.trys.pop();
126
+ continue;
127
+ default:
128
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
129
+ _ = 0;
130
+ continue;
131
+ }
132
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
133
+ _.label = op[1];
134
+ break;
135
+ }
136
+ if (op[0] === 6 && _.label < t[1]) {
137
+ _.label = t[1];
138
+ t = op;
139
+ break;
140
+ }
141
+ if (t && _.label < t[2]) {
142
+ _.label = t[2];
143
+ _.ops.push(op);
144
+ break;
145
+ }
146
+ if (t[2]) _.ops.pop();
147
+ _.trys.pop();
148
+ continue;
149
+ }
150
+ op = body.call(thisArg, _);
151
+ } catch (e) {
152
+ op = [
153
+ 6,
154
+ e
155
+ ];
156
+ y = 0;
157
+ } finally{
158
+ f = t = 0;
159
+ }
160
+ if (op[0] & 5) throw op[1];
161
+ return {
162
+ value: op[0] ? op[1] : void 0,
163
+ done: true
164
+ };
165
+ }
166
+ }
167
+ import React, { useState, useEffect } from 'react';
168
+ import { Text, Box } from 'ink';
169
+ import { apiClient } from '../commands/helpers.js';
170
+ import { ErrorComponent } from './error.js';
171
+ export var BrainRerun = function(param) {
172
+ var brainName = param.brainName, runId = param.runId, startsAt = param.startsAt, stopsAfter = param.stopsAfter;
173
+ var _useState = _sliced_to_array(useState(true), 2), isLoading = _useState[0], setIsLoading = _useState[1];
174
+ var _useState1 = _sliced_to_array(useState(null), 2), error = _useState1[0], setError = _useState1[1];
175
+ var _useState2 = _sliced_to_array(useState(null), 2), newRunId = _useState2[0], setNewRunId = _useState2[1];
176
+ useEffect(function() {
177
+ var rerunBrain = function() {
178
+ return _async_to_generator(function() {
179
+ var body, response, result, errorData, errorText, err;
180
+ return _ts_generator(this, function(_state) {
181
+ switch(_state.label){
182
+ case 0:
183
+ _state.trys.push([
184
+ 0,
185
+ 8,
186
+ 9,
187
+ 10
188
+ ]);
189
+ body = {
190
+ brainName: brainName
191
+ };
192
+ if (runId) body.runId = runId;
193
+ if (startsAt !== undefined) body.startsAt = startsAt;
194
+ if (stopsAfter !== undefined) body.stopsAfter = stopsAfter;
195
+ return [
196
+ 4,
197
+ apiClient.fetch('/brains/runs/rerun', {
198
+ method: 'POST',
199
+ headers: {
200
+ 'Content-Type': 'application/json'
201
+ },
202
+ body: JSON.stringify(body)
203
+ })
204
+ ];
205
+ case 1:
206
+ response = _state.sent();
207
+ if (!(response.status === 201)) return [
208
+ 3,
209
+ 3
210
+ ];
211
+ return [
212
+ 4,
213
+ response.json()
214
+ ];
215
+ case 2:
216
+ result = _state.sent();
217
+ setNewRunId(result.brainRunId);
218
+ return [
219
+ 3,
220
+ 7
221
+ ];
222
+ case 3:
223
+ if (!(response.status === 404)) return [
224
+ 3,
225
+ 5
226
+ ];
227
+ return [
228
+ 4,
229
+ response.json()
230
+ ];
231
+ case 4:
232
+ errorData = _state.sent();
233
+ setError(errorData.error || "Brain or run not found");
234
+ return [
235
+ 3,
236
+ 7
237
+ ];
238
+ case 5:
239
+ return [
240
+ 4,
241
+ response.text()
242
+ ];
243
+ case 6:
244
+ errorText = _state.sent();
245
+ setError("Server returned ".concat(response.status, ": ").concat(errorText));
246
+ _state.label = 7;
247
+ case 7:
248
+ return [
249
+ 3,
250
+ 10
251
+ ];
252
+ case 8:
253
+ err = _state.sent();
254
+ setError("Connection error: ".concat(err.message));
255
+ return [
256
+ 3,
257
+ 10
258
+ ];
259
+ case 9:
260
+ setIsLoading(false);
261
+ return [
262
+ 7
263
+ ];
264
+ case 10:
265
+ return [
266
+ 2
267
+ ];
268
+ }
269
+ });
270
+ })();
271
+ };
272
+ rerunBrain();
273
+ }, [
274
+ brainName,
275
+ runId,
276
+ startsAt,
277
+ stopsAfter
278
+ ]);
279
+ if (isLoading) {
280
+ return /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, null, "\uD83D\uDD04 Starting brain rerun..."));
281
+ }
282
+ if (error) {
283
+ var errorDetails = runId ? 'Make sure the brain "'.concat(brainName, '" and run ID "').concat(runId, '" exist.\nYou can list brain history with: positronic brain history ').concat(brainName) : 'Make sure the brain "'.concat(brainName, '" exists.\nYou can list available brains with: positronic brain list');
284
+ return /*#__PURE__*/ React.createElement(ErrorComponent, {
285
+ error: {
286
+ title: 'Brain Rerun Failed',
287
+ message: error,
288
+ details: errorDetails
289
+ }
290
+ });
291
+ }
292
+ if (newRunId) {
293
+ var runDetails = runId ? " from run ".concat(runId) : '';
294
+ var rangeDetails = startsAt || stopsAfter ? " (".concat(startsAt ? "starting at step ".concat(startsAt) : '').concat(startsAt && stopsAfter ? ', ' : '').concat(stopsAfter ? "stopping after step ".concat(stopsAfter) : '', ")") : '';
295
+ return /*#__PURE__*/ React.createElement(Box, {
296
+ flexDirection: "column"
297
+ }, /*#__PURE__*/ React.createElement(Text, {
298
+ bold: true,
299
+ color: "green"
300
+ }, "✅ Brain rerun started successfully!"), /*#__PURE__*/ React.createElement(Text, null, "New run ID: ", /*#__PURE__*/ React.createElement(Text, {
301
+ bold: true
302
+ }, newRunId)), /*#__PURE__*/ React.createElement(Text, {
303
+ dimColor: true
304
+ }, 'Rerunning brain "', brainName, '"', runDetails, rangeDetails), /*#__PURE__*/ React.createElement(Box, {
305
+ marginTop: 1
306
+ }, /*#__PURE__*/ React.createElement(Text, {
307
+ dimColor: true
308
+ }, "Watch the run with: positronic watch --run-id ", newRunId)));
309
+ }
310
+ return /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, {
311
+ color: "red"
312
+ }, "❌ Unexpected error occurred"));
313
+ };
@@ -0,0 +1,65 @@
1
+ import React from 'react';
2
+ import { Text, Box } from 'ink';
3
+ import { useApiGet } from '../hooks/useApi.js';
4
+ import { ErrorComponent } from './error.js';
5
+ var StepDisplay = function(param) {
6
+ var step = param.step, _param_indent = param.indent, indent = _param_indent === void 0 ? 0 : _param_indent;
7
+ var indentStr = ' '.repeat(indent);
8
+ if (step.type === 'step') {
9
+ return /*#__PURE__*/ React.createElement(Text, null, indentStr, "• ", step.title);
10
+ } else {
11
+ var _step_innerBrain;
12
+ // Nested brain
13
+ return /*#__PURE__*/ React.createElement(Box, {
14
+ flexDirection: "column"
15
+ }, /*#__PURE__*/ React.createElement(Text, null, indentStr, "▸ ", step.title, " ", /*#__PURE__*/ React.createElement(Text, {
16
+ dimColor: true
17
+ }, "(nested brain)")), (_step_innerBrain = step.innerBrain) === null || _step_innerBrain === void 0 ? void 0 : _step_innerBrain.steps.map(function(innerStep, idx) {
18
+ return /*#__PURE__*/ React.createElement(StepDisplay, {
19
+ key: idx,
20
+ step: innerStep,
21
+ indent: indent + 1
22
+ });
23
+ }));
24
+ }
25
+ };
26
+ export var BrainShow = function(param) {
27
+ var brainName = param.brainName;
28
+ var _useApiGet = useApiGet("/brains/".concat(encodeURIComponent(brainName))), data = _useApiGet.data, loading = _useApiGet.loading, error = _useApiGet.error;
29
+ if (loading) {
30
+ return /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, null, "\uD83E\uDDE0 Loading brain details..."));
31
+ }
32
+ if (error) {
33
+ return /*#__PURE__*/ React.createElement(ErrorComponent, {
34
+ error: error
35
+ });
36
+ }
37
+ if (!data) {
38
+ return /*#__PURE__*/ React.createElement(Box, {
39
+ flexDirection: "column"
40
+ }, /*#__PURE__*/ React.createElement(Text, {
41
+ color: "red"
42
+ }, "Brain '", brainName, "' not found"));
43
+ }
44
+ return /*#__PURE__*/ React.createElement(Box, {
45
+ flexDirection: "column",
46
+ gap: 1
47
+ }, /*#__PURE__*/ React.createElement(Text, {
48
+ bold: true,
49
+ underline: true
50
+ }, data.title), data.description && /*#__PURE__*/ React.createElement(Text, {
51
+ dimColor: true
52
+ }, data.description), /*#__PURE__*/ React.createElement(Box, {
53
+ flexDirection: "column"
54
+ }, /*#__PURE__*/ React.createElement(Text, {
55
+ bold: true
56
+ }, "Steps:"), /*#__PURE__*/ React.createElement(Box, {
57
+ flexDirection: "column",
58
+ marginLeft: 1
59
+ }, data.steps.map(function(step, idx) {
60
+ return /*#__PURE__*/ React.createElement(StepDisplay, {
61
+ key: idx,
62
+ step: step
63
+ });
64
+ }))));
65
+ };
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import { Box, Text } from 'ink';
3
+ export var ErrorComponent = function(param) {
4
+ var error = param.error;
5
+ return /*#__PURE__*/ React.createElement(Box, {
6
+ flexDirection: "column"
7
+ }, /*#__PURE__*/ React.createElement(Text, {
8
+ color: "red",
9
+ bold: true
10
+ }, "❌ ", error.title), /*#__PURE__*/ React.createElement(Box, {
11
+ paddingLeft: 2,
12
+ flexDirection: "column"
13
+ }, /*#__PURE__*/ React.createElement(Text, {
14
+ color: "red"
15
+ }, error.message), error.details && /*#__PURE__*/ React.createElement(Text, {
16
+ color: "red",
17
+ dimColor: true
18
+ }, error.details)));
19
+ };