@covibes/zeroshot 5.4.0 → 5.4.1

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 (136) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +8 -465
  3. package/cli/index.js +101 -5231
  4. package/package.json +16 -130
  5. package/CHANGELOG.md +0 -537
  6. package/cli/commands/providers.js +0 -149
  7. package/cli/lib/first-run.js +0 -211
  8. package/cli/lib/update-checker.js +0 -281
  9. package/cli/message-formatter-utils.js +0 -75
  10. package/cli/message-formatters-normal.js +0 -275
  11. package/cli/message-formatters-watch.js +0 -181
  12. package/cluster-templates/base-templates/debug-workflow.json +0 -375
  13. package/cluster-templates/base-templates/full-workflow.json +0 -581
  14. package/cluster-templates/base-templates/single-worker.json +0 -63
  15. package/cluster-templates/base-templates/worker-validator.json +0 -208
  16. package/cluster-templates/conductor-bootstrap.json +0 -124
  17. package/docker/zeroshot-cluster/Dockerfile +0 -152
  18. package/docker/zeroshot-cluster/pre-baked-deps.json +0 -28
  19. package/lib/completion.js +0 -174
  20. package/lib/docker-config.js +0 -220
  21. package/lib/git-remote-utils.js +0 -165
  22. package/lib/id-detector.js +0 -56
  23. package/lib/provider-defaults.js +0 -62
  24. package/lib/provider-detection.js +0 -59
  25. package/lib/provider-names.js +0 -57
  26. package/lib/settings/claude-auth.js +0 -78
  27. package/lib/settings.js +0 -503
  28. package/lib/stream-json-parser.js +0 -10
  29. package/scripts/fix-node-pty-permissions.js +0 -75
  30. package/scripts/record-demo.sh +0 -279
  31. package/scripts/setup-merge-queue.sh +0 -170
  32. package/scripts/test-install.sh +0 -40
  33. package/scripts/validate-templates.js +0 -100
  34. package/src/agent/agent-config.js +0 -246
  35. package/src/agent/agent-context-builder.js +0 -444
  36. package/src/agent/agent-hook-executor.js +0 -599
  37. package/src/agent/agent-lifecycle.js +0 -743
  38. package/src/agent/agent-stuck-detector.js +0 -256
  39. package/src/agent/agent-task-executor.js +0 -1690
  40. package/src/agent/agent-trigger-evaluator.js +0 -67
  41. package/src/agent/output-extraction.js +0 -217
  42. package/src/agent/output-reformatter.js +0 -175
  43. package/src/agent/schema-utils.js +0 -146
  44. package/src/agent-wrapper.js +0 -579
  45. package/src/agents/git-pusher-template.js +0 -285
  46. package/src/attach/attach-client.js +0 -438
  47. package/src/attach/attach-server.js +0 -543
  48. package/src/attach/index.js +0 -35
  49. package/src/attach/protocol.js +0 -220
  50. package/src/attach/ring-buffer.js +0 -121
  51. package/src/attach/socket-discovery.js +0 -267
  52. package/src/claude-task-runner.js +0 -574
  53. package/src/config-router.js +0 -80
  54. package/src/config-validator.js +0 -1925
  55. package/src/copy-worker.js +0 -43
  56. package/src/input-helpers.js +0 -65
  57. package/src/isolation-manager.js +0 -1471
  58. package/src/issue-providers/README.md +0 -305
  59. package/src/issue-providers/azure-devops-provider.js +0 -273
  60. package/src/issue-providers/base-provider.js +0 -232
  61. package/src/issue-providers/github-provider.js +0 -179
  62. package/src/issue-providers/gitlab-provider.js +0 -241
  63. package/src/issue-providers/index.js +0 -196
  64. package/src/issue-providers/jira-provider.js +0 -239
  65. package/src/ledger.js +0 -631
  66. package/src/lib/safe-exec.js +0 -88
  67. package/src/logic-engine.js +0 -223
  68. package/src/message-bus-bridge.js +0 -139
  69. package/src/message-bus.js +0 -249
  70. package/src/name-generator.js +0 -232
  71. package/src/orchestrator.js +0 -2815
  72. package/src/preflight.js +0 -639
  73. package/src/process-metrics.js +0 -608
  74. package/src/providers/anthropic/cli-builder.js +0 -73
  75. package/src/providers/anthropic/index.js +0 -204
  76. package/src/providers/anthropic/models.js +0 -23
  77. package/src/providers/anthropic/output-parser.js +0 -177
  78. package/src/providers/base-provider.js +0 -251
  79. package/src/providers/capabilities.js +0 -60
  80. package/src/providers/google/cli-builder.js +0 -55
  81. package/src/providers/google/index.js +0 -116
  82. package/src/providers/google/models.js +0 -24
  83. package/src/providers/google/output-parser.js +0 -101
  84. package/src/providers/index.js +0 -91
  85. package/src/providers/openai/cli-builder.js +0 -133
  86. package/src/providers/openai/index.js +0 -136
  87. package/src/providers/openai/models.js +0 -21
  88. package/src/providers/openai/output-parser.js +0 -143
  89. package/src/providers/opencode/cli-builder.js +0 -42
  90. package/src/providers/opencode/index.js +0 -103
  91. package/src/providers/opencode/models.js +0 -55
  92. package/src/providers/opencode/output-parser.js +0 -122
  93. package/src/schemas/sub-cluster.js +0 -185
  94. package/src/status-footer.js +0 -1026
  95. package/src/sub-cluster-wrapper.js +0 -601
  96. package/src/task-runner.js +0 -30
  97. package/src/template-resolver.js +0 -372
  98. package/src/tui/CHANGES.txt +0 -133
  99. package/src/tui/LAYOUT.md +0 -261
  100. package/src/tui/README.txt +0 -192
  101. package/src/tui/TWO-LEVEL-NAVIGATION.md +0 -186
  102. package/src/tui/data-poller.js +0 -349
  103. package/src/tui/demo.js +0 -208
  104. package/src/tui/formatters.js +0 -129
  105. package/src/tui/index.js +0 -193
  106. package/src/tui/keybindings.js +0 -324
  107. package/src/tui/layout.js +0 -334
  108. package/src/tui/renderer.js +0 -184
  109. package/task-lib/attachable-watcher.js +0 -309
  110. package/task-lib/claude-recovery.js +0 -156
  111. package/task-lib/commands/clean.js +0 -50
  112. package/task-lib/commands/episodes.js +0 -105
  113. package/task-lib/commands/get-log-path.js +0 -23
  114. package/task-lib/commands/kill.js +0 -32
  115. package/task-lib/commands/list.js +0 -105
  116. package/task-lib/commands/logs.js +0 -453
  117. package/task-lib/commands/resume.js +0 -42
  118. package/task-lib/commands/run.js +0 -57
  119. package/task-lib/commands/schedule.js +0 -105
  120. package/task-lib/commands/scheduler-cmd.js +0 -96
  121. package/task-lib/commands/schedules.js +0 -148
  122. package/task-lib/commands/status.js +0 -44
  123. package/task-lib/commands/unschedule.js +0 -16
  124. package/task-lib/completion.js +0 -9
  125. package/task-lib/config.js +0 -8
  126. package/task-lib/name-generator.js +0 -230
  127. package/task-lib/package.json +0 -3
  128. package/task-lib/runner.js +0 -201
  129. package/task-lib/scheduler.js +0 -252
  130. package/task-lib/store.js +0 -529
  131. package/task-lib/tui/formatters.js +0 -215
  132. package/task-lib/tui/index.js +0 -197
  133. package/task-lib/tui/layout.js +0 -111
  134. package/task-lib/tui/renderer.js +0 -129
  135. package/task-lib/tui.js +0 -425
  136. package/task-lib/watcher.js +0 -226
package/src/tui/layout.js DELETED
@@ -1,334 +0,0 @@
1
- /**
2
- * TUI Dashboard Layout
3
- * Creates a blessed-contrib grid with multiple widgets for cluster monitoring
4
- *
5
- * Layout Grid (20 rows x 12 columns):
6
- * - Rows 0-5: Clusters Table (cols 0-7) | System Stats (cols 8-11)
7
- * - Rows 6-11: Agents Table (cols 0-11)
8
- * - Rows 12-17: Live Logs (cols 0-11)
9
- * - Rows 18-19: Help Bar (cols 0-11)
10
- */
11
-
12
- const blessed = require('blessed');
13
- const contrib = require('blessed-contrib');
14
-
15
- /**
16
- * Create main TUI layout with grid-based widget organization
17
- * @param {blessed.screen} screen - Blessed screen instance
18
- * @returns {object} Layout object containing all widgets
19
- */
20
- function createLayout(screen) {
21
- // Create 20x12 grid for responsive layout
22
- const grid = new contrib.grid({ rows: 20, cols: 12, screen });
23
-
24
- // ============================================================
25
- // OVERVIEW MODE LAYOUT:
26
- // - Clusters Table (0-16 rows, 8 cols) - LARGE
27
- // - System Stats (0-6 rows, 4 cols)
28
- // - Help Bar (18-20 rows, 12 cols)
29
- //
30
- // DETAIL MODE LAYOUT:
31
- // - Agents Table (0-9 rows, 12 cols)
32
- // - Logs (9-18 rows, 12 cols)
33
- // - Help Bar (18-20 rows, 12 cols)
34
- // ============================================================
35
-
36
- const clustersTable = grid.set(0, 0, 15, 8, contrib.table, {
37
- keys: true,
38
- fg: 'white',
39
- selectedFg: 'black',
40
- selectedBg: 'cyan',
41
- interactive: true,
42
- label: ' Clusters ',
43
- border: { type: 'line', fg: 'cyan' },
44
- columnSpacing: 2,
45
- columnWidth: [15, 12, 8, 10, 8],
46
- style: {
47
- header: {
48
- fg: 'cyan',
49
- bold: true,
50
- },
51
- cell: {
52
- selected: {
53
- fg: 'black',
54
- bg: 'cyan',
55
- },
56
- },
57
- },
58
- });
59
-
60
- // Set initial columns for clusters table
61
- clustersTable.setData({
62
- headers: ['ID', 'Status', 'Agents', 'Config', 'Uptime'],
63
- data: [],
64
- });
65
-
66
- const statsBox = grid.set(0, 8, 15, 4, blessed.box, {
67
- label: ' System Stats ',
68
- content: '',
69
- tags: true,
70
- border: { type: 'line', fg: 'cyan' },
71
- style: {
72
- border: { fg: 'cyan' },
73
- label: { fg: 'cyan' },
74
- },
75
- padding: {
76
- left: 2,
77
- right: 2,
78
- },
79
- });
80
-
81
- // ============================================================
82
- // AGENTS TABLE (Detail mode only - 9 rows x 12 cols full width)
83
- // ============================================================
84
-
85
- const agentTable = grid.set(0, 0, 9, 12, contrib.table, {
86
- keys: true,
87
- fg: 'white',
88
- selectedFg: 'black',
89
- selectedBg: 'cyan',
90
- interactive: true,
91
- label: ' Agents ',
92
- border: { type: 'line', fg: 'cyan' },
93
- columnSpacing: 1,
94
- columnWidth: [12, 15, 12, 8, 8, 10, 10],
95
- style: {
96
- header: {
97
- fg: 'cyan',
98
- bold: true,
99
- },
100
- cell: {
101
- selected: {
102
- fg: 'black',
103
- bg: 'cyan',
104
- },
105
- },
106
- },
107
- });
108
-
109
- // Set initial columns for agents table
110
- agentTable.setData({
111
- headers: ['Cluster ID', 'Agent ID', 'Role', 'Status', 'Iter', 'CPU', 'Memory'],
112
- data: [],
113
- });
114
-
115
- // ============================================================
116
- // LOGS (Detail mode only - 9 rows x 12 cols full width)
117
- // ============================================================
118
-
119
- const logsBox = grid.set(9, 0, 9, 12, contrib.log, {
120
- fg: 'white',
121
- label: ' Live Logs ',
122
- border: { type: 'line', fg: 'cyan' },
123
- tags: true,
124
- style: {
125
- border: { fg: 'cyan' },
126
- label: { fg: 'cyan' },
127
- text: { fg: 'white' },
128
- },
129
- scrollable: true,
130
- mouse: true,
131
- keyable: true,
132
- });
133
-
134
- // ============================================================
135
- // WARNING BAR (experimental notice)
136
- // ============================================================
137
-
138
- const warningBar = grid.set(15, 0, 2, 12, blessed.box, {
139
- content: '{yellow-fg}⚠ Watch TUI is experimental{/}',
140
- tags: true,
141
- border: { type: 'line', fg: 'yellow' },
142
- style: {
143
- border: { fg: 'yellow' },
144
- },
145
- padding: {
146
- left: 1,
147
- },
148
- });
149
-
150
- // ============================================================
151
- // HELP BAR (2 rows x 12 cols):
152
- // - Keyboard shortcuts and commands
153
- // ============================================================
154
-
155
- const helpBar = grid.set(17, 0, 3, 12, blessed.box, {
156
- label: ' Help ',
157
- content:
158
- '{cyan-fg}[Enter]{/} View ' +
159
- '{cyan-fg}[↑/↓]{/} Navigate ' +
160
- '{cyan-fg}[K]{/} Kill ' +
161
- '{cyan-fg}[s]{/} Stop ' +
162
- '{cyan-fg}[l]{/} Logs ' +
163
- '{cyan-fg}[r]{/} Refresh ' +
164
- '{cyan-fg}[q]{/} Quit',
165
- tags: true,
166
- border: { type: 'line', fg: 'cyan' },
167
- style: {
168
- border: { fg: 'cyan' },
169
- label: { fg: 'cyan' },
170
- text: { fg: 'white' },
171
- },
172
- padding: {
173
- left: 1,
174
- right: 1,
175
- },
176
- });
177
-
178
- // Focus on clusters table by default
179
- clustersTable.focus();
180
-
181
- // Initially hide agent table and logs (overview mode)
182
- agentTable.hide();
183
- logsBox.hide();
184
-
185
- // ============================================================
186
- // Widget Navigation
187
- // ============================================================
188
-
189
- const widgets = [clustersTable, agentTable, logsBox];
190
- let currentFocus = 0;
191
-
192
- /**
193
- * Cycle focus to next widget (Tab key)
194
- */
195
- screen.key(['tab'], () => {
196
- currentFocus = (currentFocus + 1) % widgets.length;
197
- widgets[currentFocus].focus();
198
- });
199
-
200
- /**
201
- * Cycle focus to previous widget (Shift+Tab)
202
- */
203
- screen.key(['shift-tab'], () => {
204
- currentFocus = (currentFocus - 1 + widgets.length) % widgets.length;
205
- widgets[currentFocus].focus();
206
- });
207
-
208
- // ============================================================
209
- // Return all widgets for external access
210
- // ============================================================
211
-
212
- return {
213
- screen,
214
- grid,
215
- clustersTable,
216
- statsBox,
217
- agentTable,
218
- logsBox,
219
- warningBar,
220
- helpBar,
221
- widgets,
222
- focus: (widgetIndex) => {
223
- if (widgetIndex >= 0 && widgetIndex < widgets.length) {
224
- currentFocus = widgetIndex;
225
- widgets[widgetIndex].focus();
226
- }
227
- },
228
- getCurrentFocus: () => currentFocus,
229
- };
230
- }
231
-
232
- /**
233
- * Update clusters table with current cluster data
234
- * @param {object} clustersTable - Clusters table widget
235
- * @param {array} clusters - Array of cluster objects with properties: id, status, agentCount, config, uptime
236
- */
237
- function updateClustersTable(clustersTable, clusters) {
238
- const data = clusters.map((cluster) => [
239
- cluster.id || 'N/A',
240
- cluster.status || 'unknown',
241
- String(cluster.agentCount || 0),
242
- cluster.config || 'N/A',
243
- cluster.uptime || '0s',
244
- ]);
245
-
246
- clustersTable.setData({
247
- headers: ['ID', 'Status', 'Agents', 'Config', 'Uptime'],
248
- data,
249
- });
250
- }
251
-
252
- /**
253
- * Update agents table with current agent data
254
- * @param {object} agentTable - Agents table widget
255
- * @param {array} agents - Array of agent objects
256
- */
257
- function updateAgentsTable(agentTable, agents) {
258
- const data = agents.map((agent) => [
259
- agent.clusterId || 'N/A',
260
- agent.id || 'N/A',
261
- agent.role || 'worker',
262
- agent.status || 'idle',
263
- String(agent.iteration || 0),
264
- agent.cpu || '0.0%',
265
- agent.memory || '0 MB',
266
- ]);
267
-
268
- agentTable.setData({
269
- headers: ['Cluster ID', 'Agent ID', 'Role', 'Status', 'Iter', 'CPU', 'Memory'],
270
- data,
271
- });
272
- }
273
-
274
- /**
275
- * Update system stats box with current metrics
276
- * @param {object} statsBox - Stats box widget
277
- * @param {object} stats - Object with properties: totalMemory, usedMemory, totalCPU, activeClusters, totalAgents
278
- */
279
- function updateStatsBox(statsBox, stats) {
280
- const content =
281
- `{cyan-fg}Active Clusters:{/}\n` +
282
- ` {white-fg}${stats.activeClusters || 0}{/}\n\n` +
283
- `{cyan-fg}Total Agents:{/}\n` +
284
- ` {white-fg}${stats.totalAgents || 0}{/}\n\n` +
285
- `{cyan-fg}System Memory:{/}\n` +
286
- ` {white-fg}${stats.usedMemory || '0 MB'}{/}\n` +
287
- ` {gray-fg}/ ${stats.totalMemory || '0 MB'}{/}\n\n` +
288
- `{cyan-fg}System CPU:{/}\n` +
289
- ` {white-fg}${stats.totalCPU || '0.0%'}{/}`;
290
-
291
- statsBox.setContent(content);
292
- }
293
-
294
- /**
295
- * Add log entry to logs widget
296
- * @param {object} logsBox - Logs box widget
297
- * @param {string} message - Log message
298
- * @param {string} level - Log level (info, warn, error, debug)
299
- */
300
- function addLogEntry(logsBox, message, level = 'info') {
301
- const timestamp = new Date().toLocaleTimeString();
302
- const levelColor = {
303
- info: 'white-fg',
304
- warn: 'yellow-fg',
305
- error: 'red-fg',
306
- debug: 'gray-fg',
307
- };
308
-
309
- const color = levelColor[level] || 'white-fg';
310
- const logMessage = `{${color}}[${timestamp}]{/} ${message}`;
311
-
312
- logsBox.log(logMessage);
313
- }
314
-
315
- /**
316
- * Clear logs widget by resetting content
317
- * @param {object} logsBox - Logs box widget
318
- */
319
- function clearLogs(logsBox) {
320
- // Log widget doesn't have clearData, so we destroy and recreate
321
- // Or use native content clearing
322
- if (logsBox._logLines) {
323
- logsBox._logLines = [];
324
- }
325
- }
326
-
327
- module.exports = {
328
- createLayout,
329
- updateClustersTable,
330
- updateAgentsTable,
331
- updateStatsBox,
332
- addLogEntry,
333
- clearLogs,
334
- };
@@ -1,184 +0,0 @@
1
- /**
2
- * TUI Screen Renderer
3
- * Transforms polled data into widget updates using formatters and layout widgets
4
- */
5
-
6
- const { formatTimestamp, formatBytes, formatCPU, stateIcon, truncate } = require('./formatters');
7
-
8
- class Renderer {
9
- /**
10
- * Create renderer instance
11
- * @param {object} widgets - Widget objects from layout.js
12
- * @param {object} screen - Blessed screen instance
13
- */
14
- constructor(widgets, screen) {
15
- if (!widgets) {
16
- throw new Error('Renderer requires widgets object from layout');
17
- }
18
- if (!screen) {
19
- throw new Error('Renderer requires screen instance');
20
- }
21
-
22
- this.widgets = widgets;
23
- this.screen = screen;
24
- this.selectedClusterId = null;
25
- }
26
-
27
- /**
28
- * Set the currently selected cluster ID
29
- * @param {string|null} id - Cluster ID to select
30
- */
31
- setSelectedCluster(id) {
32
- this.selectedClusterId = id;
33
- }
34
-
35
- /**
36
- * Render clusters table with state icons and uptime
37
- * @param {Array} clusters - Array of cluster objects
38
- */
39
- renderClustersTable(clusters) {
40
- const clusterList = !clusters || !Array.isArray(clusters) ? [] : clusters;
41
-
42
- const data = clusterList.map((c) => {
43
- if (!c) return ['', '', '', ''];
44
-
45
- const icon = stateIcon(c.state || 'unknown');
46
- const uptime =
47
- c.state === 'running' && c.createdAt ? formatTimestamp(Date.now() - c.createdAt) : '-';
48
- const clusterId = truncate(c.id || '', 18);
49
- const state = (c.state || 'unknown').toUpperCase();
50
- const agentCount = `${c.agentCount || 0} agents`;
51
-
52
- return [`${icon} ${clusterId}`, state, agentCount, uptime];
53
- });
54
-
55
- if (this.widgets.clustersTable && this.widgets.clustersTable.setData) {
56
- this.widgets.clustersTable.setData({
57
- headers: ['ID', 'State', 'Agents', 'Uptime'],
58
- data,
59
- });
60
- }
61
- }
62
-
63
- /**
64
- * Render system statistics box with aggregate metrics
65
- * @param {Array} clusters - Array of cluster objects
66
- * @param {Map} resourceStats - Map of PID -> {cpu, memory}
67
- */
68
- renderSystemStats(clusters, resourceStats) {
69
- const clusterList = !clusters || !Array.isArray(clusters) ? [] : clusters;
70
- const statsMap = !resourceStats || !(resourceStats instanceof Map) ? new Map() : resourceStats;
71
-
72
- // Calculate aggregate stats
73
- const activeClusters = clusterList.filter((c) => c && c.state === 'running').length;
74
- const totalAgents = clusterList.reduce((sum, c) => sum + (c?.agentCount || 0), 0);
75
-
76
- // Calculate average CPU and memory from resource stats
77
- let totalCpu = 0;
78
- let totalMemory = 0;
79
- let statCount = 0;
80
-
81
- statsMap.forEach((stat) => {
82
- if (stat && typeof stat.cpu === 'number' && typeof stat.memory === 'number') {
83
- totalCpu += stat.cpu;
84
- totalMemory += stat.memory;
85
- statCount++;
86
- }
87
- });
88
-
89
- const avgCpu = statCount > 0 ? totalCpu / statCount : 0;
90
- const avgMemory = statCount > 0 ? totalMemory / statCount : 0;
91
-
92
- // Format output with blessed color tags
93
- const statsText = [
94
- '{cyan-fg}Active Clusters:{/} ' + activeClusters,
95
- '{cyan-fg}Total Agents:{/} ' + totalAgents,
96
- '{cyan-fg}Avg CPU:{/} ' + formatCPU(avgCpu),
97
- '{cyan-fg}Avg Memory:{/} ' + formatBytes(avgMemory),
98
- ].join('\n');
99
-
100
- if (this.widgets.statsBox && this.widgets.statsBox.setContent) {
101
- this.widgets.statsBox.setContent(statsText);
102
- }
103
- }
104
-
105
- /**
106
- * Render agent table for selected cluster
107
- * @param {Array} agents - Array of agent objects
108
- * @param {Map} resourceStats - Map of PID -> {cpu, memory}
109
- */
110
- renderAgentTable(agents, resourceStats) {
111
- if (!this.selectedClusterId) {
112
- // No cluster selected, show empty table
113
- if (this.widgets.agentTable && this.widgets.agentTable.setData) {
114
- this.widgets.agentTable.setData({
115
- headers: ['Agent', 'Role', 'State', 'Iter', 'CPU%', 'Mem'],
116
- data: [],
117
- });
118
- }
119
- return;
120
- }
121
-
122
- const agentList = !agents || !Array.isArray(agents) ? [] : agents;
123
- const statsMap = !resourceStats || !(resourceStats instanceof Map) ? new Map() : resourceStats;
124
-
125
- const data = agentList.map((a) => {
126
- if (!a) return ['', '', '', '', '', ''];
127
-
128
- const pid = a.pid;
129
- const stats = statsMap.get(pid) || { cpu: 0, memory: 0 };
130
-
131
- const agentId = truncate(a.id || '', 12);
132
- const role = truncate(a.role || '', 12);
133
- const state = a.state || 'unknown';
134
- const iteration = `${a.iteration || 0}/${a.maxIterations || 0}`;
135
- const cpu = formatCPU(stats.cpu);
136
- const memory = formatBytes(stats.memory);
137
-
138
- return [agentId, role, state, iteration, cpu, memory];
139
- });
140
-
141
- if (this.widgets.agentTable && this.widgets.agentTable.setData) {
142
- this.widgets.agentTable.setData({
143
- headers: ['Agent', 'Role', 'State', 'Iter', 'CPU%', 'Mem'],
144
- data,
145
- });
146
- }
147
- }
148
-
149
- /**
150
- * Render log messages to log widget
151
- * @param {Array} messages - Array of message objects
152
- */
153
- renderLogs(messages) {
154
- if (!messages || !Array.isArray(messages)) {
155
- return;
156
- }
157
-
158
- if (!this.widgets.logsBox || !this.widgets.logsBox.log) {
159
- return;
160
- }
161
-
162
- messages.forEach((msg) => {
163
- if (!msg) return;
164
-
165
- const timestamp = msg.timestamp || Date.now();
166
- const time = new Date(timestamp).toLocaleTimeString();
167
- const sender = truncate(msg.sender || 'unknown', 15);
168
- const text = truncate(msg.content?.text || '', 60);
169
-
170
- this.widgets.logsBox.log(`[${time}] ${sender}: ${text}`);
171
- });
172
- }
173
-
174
- /**
175
- * Trigger screen render to update display
176
- */
177
- render() {
178
- if (this.screen && this.screen.render) {
179
- this.screen.render();
180
- }
181
- }
182
- }
183
-
184
- module.exports = Renderer;