@covibes/zeroshot 5.3.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 (119) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +8 -385
  3. package/cli/index.js +108 -4615
  4. package/package.json +16 -125
  5. package/CHANGELOG.md +0 -537
  6. package/cli/commands/providers.js +0 -150
  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 -253
  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 -697
  14. package/cluster-templates/base-templates/single-worker.json +0 -63
  15. package/cluster-templates/base-templates/worker-validator.json +0 -152
  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 -212
  21. package/lib/id-detector.js +0 -53
  22. package/lib/provider-detection.js +0 -59
  23. package/lib/provider-names.js +0 -56
  24. package/lib/settings.js +0 -405
  25. package/lib/stream-json-parser.js +0 -10
  26. package/scripts/fix-node-pty-permissions.js +0 -75
  27. package/scripts/record-demo.sh +0 -279
  28. package/scripts/test-install.sh +0 -40
  29. package/scripts/validate-templates.js +0 -100
  30. package/src/agent/agent-config.js +0 -193
  31. package/src/agent/agent-context-builder.js +0 -335
  32. package/src/agent/agent-hook-executor.js +0 -402
  33. package/src/agent/agent-lifecycle.js +0 -683
  34. package/src/agent/agent-stuck-detector.js +0 -256
  35. package/src/agent/agent-task-executor.js +0 -1431
  36. package/src/agent/agent-trigger-evaluator.js +0 -67
  37. package/src/agent/output-extraction.js +0 -200
  38. package/src/agent/output-reformatter.js +0 -175
  39. package/src/agent/schema-utils.js +0 -111
  40. package/src/agent-wrapper.js +0 -570
  41. package/src/agents/git-pusher-agent.json +0 -20
  42. package/src/attach/attach-client.js +0 -438
  43. package/src/attach/attach-server.js +0 -543
  44. package/src/attach/index.js +0 -35
  45. package/src/attach/protocol.js +0 -220
  46. package/src/attach/ring-buffer.js +0 -121
  47. package/src/attach/socket-discovery.js +0 -267
  48. package/src/claude-task-runner.js +0 -523
  49. package/src/config-router.js +0 -80
  50. package/src/config-validator.js +0 -1660
  51. package/src/copy-worker.js +0 -43
  52. package/src/github.js +0 -139
  53. package/src/isolation-manager.js +0 -1381
  54. package/src/ledger.js +0 -614
  55. package/src/logic-engine.js +0 -223
  56. package/src/message-bus-bridge.js +0 -139
  57. package/src/message-bus.js +0 -249
  58. package/src/name-generator.js +0 -232
  59. package/src/orchestrator.js +0 -2519
  60. package/src/preflight.js +0 -485
  61. package/src/process-metrics.js +0 -566
  62. package/src/providers/anthropic/cli-builder.js +0 -45
  63. package/src/providers/anthropic/index.js +0 -134
  64. package/src/providers/anthropic/models.js +0 -23
  65. package/src/providers/anthropic/output-parser.js +0 -159
  66. package/src/providers/base-provider.js +0 -181
  67. package/src/providers/capabilities.js +0 -51
  68. package/src/providers/google/cli-builder.js +0 -55
  69. package/src/providers/google/index.js +0 -116
  70. package/src/providers/google/models.js +0 -24
  71. package/src/providers/google/output-parser.js +0 -92
  72. package/src/providers/index.js +0 -75
  73. package/src/providers/openai/cli-builder.js +0 -122
  74. package/src/providers/openai/index.js +0 -135
  75. package/src/providers/openai/models.js +0 -21
  76. package/src/providers/openai/output-parser.js +0 -129
  77. package/src/schemas/sub-cluster.js +0 -156
  78. package/src/status-footer.js +0 -980
  79. package/src/sub-cluster-wrapper.js +0 -560
  80. package/src/task-runner.js +0 -30
  81. package/src/template-resolver.js +0 -369
  82. package/src/tui/CHANGES.txt +0 -133
  83. package/src/tui/LAYOUT.md +0 -261
  84. package/src/tui/README.txt +0 -192
  85. package/src/tui/TWO-LEVEL-NAVIGATION.md +0 -186
  86. package/src/tui/data-poller.js +0 -325
  87. package/src/tui/demo.js +0 -208
  88. package/src/tui/formatters.js +0 -128
  89. package/src/tui/index.js +0 -193
  90. package/src/tui/keybindings.js +0 -383
  91. package/src/tui/layout.js +0 -334
  92. package/src/tui/renderer.js +0 -194
  93. package/task-lib/attachable-watcher.js +0 -272
  94. package/task-lib/claude-recovery.js +0 -119
  95. package/task-lib/commands/clean.js +0 -50
  96. package/task-lib/commands/get-log-path.js +0 -23
  97. package/task-lib/commands/kill.js +0 -32
  98. package/task-lib/commands/list.js +0 -105
  99. package/task-lib/commands/logs.js +0 -411
  100. package/task-lib/commands/resume.js +0 -42
  101. package/task-lib/commands/run.js +0 -57
  102. package/task-lib/commands/schedule.js +0 -105
  103. package/task-lib/commands/scheduler-cmd.js +0 -96
  104. package/task-lib/commands/schedules.js +0 -98
  105. package/task-lib/commands/status.js +0 -44
  106. package/task-lib/commands/unschedule.js +0 -16
  107. package/task-lib/completion.js +0 -9
  108. package/task-lib/config.js +0 -10
  109. package/task-lib/name-generator.js +0 -230
  110. package/task-lib/package.json +0 -3
  111. package/task-lib/runner.js +0 -144
  112. package/task-lib/scheduler.js +0 -252
  113. package/task-lib/store.js +0 -230
  114. package/task-lib/tui/formatters.js +0 -166
  115. package/task-lib/tui/index.js +0 -197
  116. package/task-lib/tui/layout.js +0 -111
  117. package/task-lib/tui/renderer.js +0 -119
  118. package/task-lib/tui.js +0 -384
  119. package/task-lib/watcher.js +0 -188
@@ -1,75 +0,0 @@
1
- /**
2
- * Message formatting utilities for CLI output
3
- * Extracted from index.js to reduce complexity
4
- */
5
-
6
- const chalk = require('chalk');
7
-
8
- /**
9
- * Get color for sender based on consistent hashing
10
- * @param {string} sender - Sender name
11
- * @returns {Function} Chalk color function
12
- */
13
- function getColorForSender(sender) {
14
- const colors = [chalk.cyan, chalk.magenta, chalk.yellow, chalk.green, chalk.blue];
15
- let hash = 0;
16
- for (let i = 0; i < sender.length; i++) {
17
- hash = (hash << 5) - hash + sender.charCodeAt(i);
18
- hash = hash & hash;
19
- }
20
- return colors[Math.abs(hash) % colors.length];
21
- }
22
-
23
- /**
24
- * Build message prefix with timestamp, sender, and optional cluster ID
25
- * @param {Object} msg - Message object
26
- * @param {boolean} showClusterId - Whether to show cluster ID
27
- * @param {boolean} isActive - Whether cluster is active
28
- * @returns {string} Formatted prefix
29
- */
30
- function buildMessagePrefix(msg, showClusterId, isActive) {
31
- const color = isActive ? getColorForSender(msg.sender) : chalk.dim;
32
-
33
- let senderLabel = msg.sender;
34
- if (showClusterId && msg.cluster_id) {
35
- senderLabel = `${msg.cluster_id}/${msg.sender}`;
36
- }
37
-
38
- const modelSuffix = msg.sender_model ? chalk.dim(` [${msg.sender_model}]`) : '';
39
- return color(`${senderLabel.padEnd(showClusterId ? 25 : 15)} |`) + modelSuffix;
40
- }
41
-
42
- /**
43
- * Build cluster prefix for watch mode
44
- * @param {string} clusterId - Cluster ID
45
- * @param {boolean} isActive - Whether cluster is active
46
- * @returns {string} Formatted prefix
47
- */
48
- function buildClusterPrefix(clusterId, isActive) {
49
- return isActive
50
- ? chalk.white(`${clusterId.padEnd(20)} |`)
51
- : chalk.dim(`${clusterId.padEnd(20)} |`);
52
- }
53
-
54
- /**
55
- * Parse and normalize data fields (handles string JSON)
56
- * @param {string|Array} data - Data to parse
57
- * @returns {Array} Parsed array
58
- */
59
- function parseDataField(data) {
60
- if (typeof data === 'string') {
61
- try {
62
- return JSON.parse(data);
63
- } catch {
64
- return [];
65
- }
66
- }
67
- return Array.isArray(data) ? data : [];
68
- }
69
-
70
- module.exports = {
71
- getColorForSender,
72
- buildMessagePrefix,
73
- buildClusterPrefix,
74
- parseDataField,
75
- };
@@ -1,253 +0,0 @@
1
- /**
2
- * Normal mode message formatters
3
- * Full-detail message display for non-watch mode
4
- *
5
- * All functions accept an optional `print` parameter for output routing.
6
- * When StatusFooter is active, pass safePrint to avoid terminal garbling.
7
- */
8
-
9
- const chalk = require('chalk');
10
-
11
- /**
12
- * Format AGENT_LIFECYCLE events
13
- * @param {Object} msg - Message object
14
- * @param {string} prefix - Formatted message prefix
15
- * @param {Function} [print=console.log] - Print function for output
16
- * @returns {boolean} True if message was handled
17
- */
18
- function formatAgentLifecycle(msg, prefix, print = console.log) {
19
- const data = msg.content?.data;
20
- const event = data?.event;
21
-
22
- let icon, eventText;
23
- switch (event) {
24
- case 'STARTED':
25
- icon = chalk.green('▶');
26
- const triggers = data.triggers?.join(', ') || 'none';
27
- eventText = `started (listening for: ${chalk.dim(triggers)})`;
28
- break;
29
- case 'TASK_STARTED':
30
- icon = chalk.yellow('⚡');
31
- eventText = `${chalk.cyan(data.triggeredBy)} → task #${data.iteration} (${chalk.dim(data.model)})`;
32
- break;
33
- case 'TASK_COMPLETED':
34
- icon = chalk.green('✓');
35
- eventText = `task #${data.iteration} completed`;
36
- break;
37
- default:
38
- icon = chalk.dim('•');
39
- eventText = event || 'unknown event';
40
- }
41
-
42
- print(`${prefix} ${icon} ${eventText}`);
43
- return true;
44
- }
45
-
46
- /**
47
- * Format AGENT_ERROR events
48
- * @param {Object} msg - Message object
49
- * @param {string} prefix - Formatted message prefix
50
- * @param {string} timestamp - Formatted timestamp
51
- * @param {Function} [print=console.log] - Print function for output
52
- * @returns {boolean} True if message was handled
53
- */
54
- function formatAgentError(msg, prefix, timestamp, print = console.log) {
55
- print(''); // Blank line before error
56
- print(chalk.bold.red(`${'─'.repeat(60)}`));
57
- print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold.red('🔴 AGENT ERROR')}`);
58
-
59
- if (msg.content?.text) {
60
- print(`${prefix} ${chalk.red(msg.content.text)}`);
61
- }
62
-
63
- if (msg.content?.data?.stack) {
64
- const stackLines = msg.content.data.stack.split('\n').slice(0, 5);
65
- for (const line of stackLines) {
66
- if (line.trim()) {
67
- print(`${prefix} ${chalk.dim(line)}`);
68
- }
69
- }
70
- }
71
-
72
- print(chalk.bold.red(`${'─'.repeat(60)}`));
73
- return true;
74
- }
75
-
76
- /**
77
- * Format ISSUE_OPENED events
78
- * @param {Object} msg - Message object
79
- * @param {string} prefix - Formatted message prefix
80
- * @param {string} timestamp - Formatted timestamp
81
- * @param {Set} shownNewTaskForCluster - Set tracking shown tasks
82
- * @param {Function} [print=console.log] - Print function for output
83
- * @returns {boolean} True if message was handled
84
- */
85
- function formatIssueOpened(msg, prefix, timestamp, shownNewTaskForCluster, print = console.log) {
86
- // Skip duplicate - conductor re-publishes after spawning agents
87
- if (shownNewTaskForCluster.has(msg.cluster_id)) {
88
- return true;
89
- }
90
- shownNewTaskForCluster.add(msg.cluster_id);
91
-
92
- print(''); // Blank line before new task
93
- print(chalk.bold.blue(`${'─'.repeat(60)}`));
94
- print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold.blue('📋 NEW TASK')}`);
95
-
96
- if (msg.content?.text) {
97
- const lines = msg.content.text.split('\n').slice(0, 3);
98
- for (const line of lines) {
99
- if (line.trim() && line.trim() !== '# Manual Input') {
100
- print(`${prefix} ${chalk.white(line)}`);
101
- }
102
- }
103
- }
104
-
105
- print(chalk.bold.blue(`${'─'.repeat(60)}`));
106
- return true;
107
- }
108
-
109
- /**
110
- * Format IMPLEMENTATION_READY events
111
- * @param {Object} msg - Message object
112
- * @param {string} prefix - Formatted message prefix
113
- * @param {string} timestamp - Formatted timestamp
114
- * @param {Function} [print=console.log] - Print function for output
115
- * @returns {boolean} True if message was handled
116
- */
117
- function formatImplementationReady(msg, prefix, timestamp, print = console.log) {
118
- print(
119
- `${prefix} ${chalk.gray(timestamp)} ${chalk.bold.yellow('✅ IMPLEMENTATION READY')}`
120
- );
121
-
122
- if (msg.content?.data?.commit) {
123
- print(
124
- `${prefix} ${chalk.gray('Commit:')} ${chalk.cyan(msg.content.data.commit.substring(0, 8))}`
125
- );
126
- }
127
-
128
- return true;
129
- }
130
-
131
- /**
132
- * Format VALIDATION_RESULT events
133
- * @param {Object} msg - Message object
134
- * @param {string} prefix - Formatted message prefix
135
- * @param {string} timestamp - Formatted timestamp
136
- * @param {Function} [print=console.log] - Print function for output
137
- * @returns {boolean} True if message was handled
138
- */
139
- function formatValidationResult(msg, prefix, timestamp, print = console.log) {
140
- const data = msg.content?.data || {};
141
- const approved = data.approved === true || data.approved === 'true';
142
- const status = approved ? chalk.bold.green('✓ APPROVED') : chalk.bold.red('✗ REJECTED');
143
-
144
- print(`${prefix} ${chalk.gray(timestamp)} ${status}`);
145
-
146
- // Show summary if present and not a template variable
147
- if (msg.content?.text && !msg.content.text.includes('{{')) {
148
- print(`${prefix} ${msg.content.text.substring(0, 100)}`);
149
- }
150
-
151
- // Show full JSON data structure
152
- print(
153
- `${prefix} ${chalk.dim(JSON.stringify(data, null, 2).split('\n').join(`\n${prefix} `))}`
154
- );
155
-
156
- return true;
157
- }
158
-
159
- /**
160
- * Format CLUSTER_COMPLETE events
161
- * @param {Object} msg - Message object
162
- * @param {string} prefix - Formatted message prefix
163
- * @param {string} timestamp - Formatted timestamp
164
- * @param {Function} [print=console.log] - Print function for output
165
- * @returns {boolean} True if message was handled
166
- */
167
- function formatClusterComplete(msg, prefix, timestamp, print = console.log) {
168
- print(''); // Blank line
169
- print(chalk.bold.green(`${'═'.repeat(60)}`));
170
- print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold.green('🎉 CLUSTER COMPLETE')}`);
171
- if (msg.content?.data?.reason) {
172
- print(`${prefix} ${chalk.green(msg.content.data.reason)}`);
173
- }
174
- print(chalk.bold.green(`${'═'.repeat(60)}`));
175
- return true;
176
- }
177
-
178
- /**
179
- * Format CLUSTER_FAILED events
180
- * @param {Object} msg - Message object
181
- * @param {string} prefix - Formatted message prefix
182
- * @param {string} timestamp - Formatted timestamp
183
- * @param {Function} [print=console.log] - Print function for output
184
- * @returns {boolean} True if message was handled
185
- */
186
- function formatClusterFailed(msg, prefix, timestamp, print = console.log) {
187
- print(''); // Blank line
188
- print(chalk.bold.red(`${'═'.repeat(60)}`));
189
- print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold.red('❌ CLUSTER FAILED')}`);
190
- if (msg.content?.text) {
191
- print(`${prefix} ${chalk.red(msg.content.text)}`);
192
- }
193
- if (msg.content?.data?.reason) {
194
- print(`${prefix} ${chalk.red(msg.content.data.reason)}`);
195
- }
196
- print(chalk.bold.red(`${'═'.repeat(60)}`));
197
- return true;
198
- }
199
-
200
- /**
201
- * Format PR_CREATED events
202
- * @param {Object} msg - Message object
203
- * @param {string} prefix - Formatted message prefix
204
- * @param {string} timestamp - Formatted timestamp
205
- * @param {Function} [print=console.log] - Print function for output
206
- * @returns {boolean} True if message was handled
207
- */
208
- function formatPrCreated(msg, prefix, timestamp, print = console.log) {
209
- const prNumber = msg.content?.data?.pr_number || '';
210
- const prUrl = msg.content?.data?.pr_url || '';
211
-
212
- print(''); // Blank line before PR notification
213
- print(chalk.bold.green(`${'─'.repeat(60)}`));
214
- print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold.green('🎉 PULL REQUEST CREATED')}`);
215
-
216
- if (prNumber) {
217
- print(`${prefix} ${chalk.gray('PR:')} ${chalk.cyan(`#${prNumber}`)}`);
218
- }
219
- if (prUrl) {
220
- print(`${prefix} ${chalk.gray('URL:')} ${chalk.blue(prUrl)}`);
221
- }
222
-
223
- print(chalk.bold.green(`${'─'.repeat(60)}`));
224
- return true;
225
- }
226
-
227
- /**
228
- * Format generic messages (fallback)
229
- * @param {Object} msg - Message object
230
- * @param {string} prefix - Formatted message prefix
231
- * @param {string} timestamp - Formatted timestamp
232
- * @param {Function} [print=console.log] - Print function for output
233
- * @returns {boolean} True if message was handled
234
- */
235
- function formatGenericMessage(msg, prefix, timestamp, print = console.log) {
236
- print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold(msg.topic)}`);
237
- if (msg.content?.text) {
238
- print(`${prefix} ${msg.content.text}`);
239
- }
240
- return true;
241
- }
242
-
243
- module.exports = {
244
- formatAgentLifecycle,
245
- formatAgentError,
246
- formatIssueOpened,
247
- formatImplementationReady,
248
- formatValidationResult,
249
- formatPrCreated,
250
- formatClusterComplete,
251
- formatClusterFailed,
252
- formatGenericMessage,
253
- };
@@ -1,181 +0,0 @@
1
- /**
2
- * Watch mode message formatters
3
- * Simplified, high-level event display for zeroshot watch command
4
- */
5
-
6
- const chalk = require('chalk');
7
- const { buildClusterPrefix, getColorForSender, parseDataField } = require('./message-formatter-utils');
8
-
9
- /**
10
- * Format AGENT_ERROR for watch mode
11
- * @param {Object} msg - Message object
12
- * @param {string} clusterPrefix - Formatted cluster prefix
13
- */
14
- function formatAgentError(msg, clusterPrefix) {
15
- const errorMsg = `${msg.sender} ${chalk.bold.red('ERROR')}`;
16
- console.log(`${clusterPrefix} ${errorMsg}`);
17
- if (msg.content?.text) {
18
- console.log(`${clusterPrefix} ${chalk.red(msg.content.text)}`);
19
- }
20
- }
21
-
22
- /**
23
- * Format ISSUE_OPENED for watch mode
24
- * @param {Object} msg - Message object
25
- * @param {string} clusterPrefix - Formatted cluster prefix
26
- */
27
- function formatIssueOpened(msg, clusterPrefix) {
28
- const issueNum = msg.content?.data?.issue_number || '';
29
- const title = msg.content?.data?.title || '';
30
- const prompt = msg.content?.data?.prompt || msg.content?.text || '';
31
-
32
- const taskDesc = title === 'Manual Input' && prompt ? prompt : title;
33
- const truncatedDesc =
34
- taskDesc && taskDesc.length > 60 ? taskDesc.substring(0, 60) + '...' : taskDesc;
35
-
36
- const eventText = `Started ${issueNum ? `#${issueNum}` : 'task'}${truncatedDesc ? chalk.dim(` - ${truncatedDesc}`) : ''}`;
37
- console.log(`${clusterPrefix} ${eventText}`);
38
- }
39
-
40
- /**
41
- * Format IMPLEMENTATION_READY for watch mode
42
- * @param {Object} msg - Message object
43
- * @param {string} clusterPrefix - Formatted cluster prefix
44
- */
45
- function formatImplementationReady(msg, clusterPrefix) {
46
- const agentColor = getColorForSender(msg.sender);
47
- const agentName = agentColor(msg.sender);
48
- const eventText = `${agentName} completed implementation`;
49
- console.log(`${clusterPrefix} ${eventText}`);
50
- }
51
-
52
- /**
53
- * Format VALIDATION_RESULT for watch mode
54
- * @param {Object} msg - Message object
55
- * @param {string} clusterPrefix - Formatted cluster prefix
56
- */
57
- function formatValidationResult(msg, clusterPrefix) {
58
- const agentColor = getColorForSender(msg.sender);
59
- const agentName = agentColor(msg.sender);
60
- const data = msg.content?.data;
61
- const approved = data?.approved === 'true' || data?.approved === true;
62
- const status = approved ? chalk.green('APPROVED') : chalk.red('REJECTED');
63
-
64
- let eventText = `${agentName} ${status}`;
65
- if (data?.summary && !approved) {
66
- eventText += chalk.dim(` - ${data.summary}`);
67
- }
68
- console.log(`${clusterPrefix} ${eventText}`);
69
-
70
- if (!approved) {
71
- printRejectionDetails(data, clusterPrefix);
72
- }
73
- }
74
-
75
- /**
76
- * Print rejection details (errors/issues)
77
- * @param {Object} data - Validation data
78
- * @param {string} clusterPrefix - Formatted cluster prefix
79
- */
80
- function printRejectionDetails(data, clusterPrefix) {
81
- const errors = parseDataField(data.errors);
82
- const issues = parseDataField(data.issues);
83
-
84
- if (errors.length > 0) {
85
- const errorsCharCount = JSON.stringify(errors).length;
86
- console.log(
87
- `${clusterPrefix} ${chalk.red('•')} ${errors.length} error${errors.length > 1 ? 's' : ''} (${errorsCharCount} chars)`
88
- );
89
- }
90
-
91
- if (issues.length > 0) {
92
- const issuesCharCount = JSON.stringify(issues).length;
93
- console.log(
94
- `${clusterPrefix} ${chalk.yellow('•')} ${issues.length} issue${issues.length > 1 ? 's' : ''} (${issuesCharCount} chars)`
95
- );
96
- }
97
- }
98
-
99
- /**
100
- * Format PR_CREATED for watch mode
101
- * @param {Object} msg - Message object
102
- * @param {string} clusterPrefix - Formatted cluster prefix
103
- */
104
- function formatPrCreated(msg, clusterPrefix) {
105
- const agentColor = getColorForSender(msg.sender);
106
- const agentName = agentColor(msg.sender);
107
- const prNum = msg.content?.data?.pr_number || '';
108
- const eventText = `${agentName} created PR${prNum ? ` #${prNum}` : ''}`;
109
- console.log(`${clusterPrefix} ${eventText}`);
110
- }
111
-
112
- /**
113
- * Format PR_MERGED for watch mode
114
- * @param {Object} msg - Message object
115
- * @param {string} clusterPrefix - Formatted cluster prefix
116
- */
117
- function formatPrMerged(msg, clusterPrefix) {
118
- const agentColor = getColorForSender(msg.sender);
119
- const agentName = agentColor(msg.sender);
120
- const eventText = `${agentName} merged PR`;
121
- console.log(`${clusterPrefix} ${eventText}`);
122
- }
123
-
124
- /**
125
- * Format unknown topic for watch mode (fallback)
126
- * @param {Object} msg - Message object
127
- * @param {string} clusterPrefix - Formatted cluster prefix
128
- */
129
- function formatUnknownTopic(msg, clusterPrefix) {
130
- const agentColor = getColorForSender(msg.sender);
131
- const agentName = agentColor(msg.sender);
132
- const eventText = `${agentName} ${msg.topic.toLowerCase().replace(/_/g, ' ')}`;
133
- console.log(`${clusterPrefix} ${eventText}`);
134
- }
135
-
136
- /**
137
- * Main watch mode formatter
138
- * @param {Object} msg - Message object
139
- * @param {boolean} isActive - Whether cluster is active
140
- * @returns {boolean} True if message was handled
141
- */
142
- function formatWatchMode(msg, isActive) {
143
- // Skip low-level topics (too noisy for watch mode)
144
- if (msg.topic === 'AGENT_OUTPUT' || msg.topic === 'AGENT_LIFECYCLE') {
145
- return true;
146
- }
147
-
148
- // Clear status line, print message, will be redrawn by status interval
149
- process.stdout.write('\r' + ' '.repeat(120) + '\r');
150
-
151
- const clusterPrefix = buildClusterPrefix(msg.cluster_id, isActive);
152
-
153
- switch (msg.topic) {
154
- case 'AGENT_ERROR':
155
- formatAgentError(msg, clusterPrefix);
156
- break;
157
- case 'ISSUE_OPENED':
158
- formatIssueOpened(msg, clusterPrefix);
159
- break;
160
- case 'IMPLEMENTATION_READY':
161
- formatImplementationReady(msg, clusterPrefix);
162
- break;
163
- case 'VALIDATION_RESULT':
164
- formatValidationResult(msg, clusterPrefix);
165
- break;
166
- case 'PR_CREATED':
167
- formatPrCreated(msg, clusterPrefix);
168
- break;
169
- case 'PR_MERGED':
170
- formatPrMerged(msg, clusterPrefix);
171
- break;
172
- default:
173
- formatUnknownTopic(msg, clusterPrefix);
174
- }
175
-
176
- return true;
177
- }
178
-
179
- module.exports = {
180
- formatWatchMode,
181
- };