@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
package/task-lib/tui.js DELETED
@@ -1,384 +0,0 @@
1
- /**
2
- * Task TUI - Interactive task viewer
3
- *
4
- * Features:
5
- * - List all tasks
6
- * - Navigate with arrow keys
7
- * - Press Enter to view logs
8
- * - Press Esc to go back to list
9
- */
10
-
11
- import blessed from 'blessed';
12
- import { loadTasks } from './store.js';
13
- import { isProcessRunning } from './runner.js';
14
- import fs from 'fs';
15
- import path from 'path';
16
- import os from 'os';
17
-
18
- // Parse a single log line from JSON stream format
19
- function parseLogLine(line) {
20
- let trimmed = line.trim();
21
-
22
- // Strip timestamp prefix if present: [1234567890]{...} -> {...}
23
- const timestampMatch = trimmed.match(/^\[\d+\](.*)$/);
24
- if (timestampMatch) {
25
- trimmed = timestampMatch[1];
26
- }
27
-
28
- // Keep non-JSON lines
29
- if (!trimmed.startsWith('{')) {
30
- return trimmed ? trimmed + '\n' : '';
31
- }
32
-
33
- // Parse JSON and extract relevant info
34
- try {
35
- const event = JSON.parse(trimmed);
36
-
37
- // Extract text from content_block_delta
38
- if (event.type === 'stream_event' && event.event?.type === 'content_block_delta') {
39
- return event.event?.delta?.text || '';
40
- }
41
- // Extract tool use info
42
- else if (event.type === 'stream_event' && event.event?.type === 'content_block_start') {
43
- const block = event.event?.content_block;
44
- if (block?.type === 'tool_use' && block?.name) {
45
- return `\n[Tool: ${block.name}]\n`;
46
- }
47
- }
48
- // Extract assistant messages
49
- else if (event.type === 'assistant' && event.message?.content) {
50
- let output = '';
51
- for (const content of event.message.content) {
52
- if (content.type === 'text') {
53
- output += content.text;
54
- }
55
- }
56
- return output;
57
- }
58
- // Extract final result
59
- else if (event.type === 'result') {
60
- if (event.is_error) {
61
- return `\n[ERROR] ${event.result || 'Unknown error'}\n`;
62
- }
63
- }
64
- } catch {
65
- // Not JSON or parse error - skip
66
- }
67
-
68
- return '';
69
- }
70
-
71
- class TaskTUI {
72
- constructor(options = {}) {
73
- this.tasks = [];
74
- this.selectedIndex = 0;
75
- this.viewMode = 'list'; // 'list' or 'detail'
76
- this.selectedTask = null;
77
- this.initialScrollDone = false;
78
- this.refreshRate = options.refreshRate || 1000;
79
- }
80
-
81
- start() {
82
- // Create screen
83
- this.screen = blessed.screen({
84
- smartCSR: true,
85
- title: 'Vibe Task Watch',
86
- dockBorders: true,
87
- fullUnicode: true,
88
- });
89
-
90
- // Create main list view
91
- this.listBox = blessed.list({
92
- parent: this.screen,
93
- top: 0,
94
- left: 0,
95
- width: '100%',
96
- height: '100%-2',
97
- keys: true,
98
- vi: true,
99
- mouse: true,
100
- border: {
101
- type: 'line',
102
- },
103
- style: {
104
- selected: {
105
- bg: 'blue',
106
- fg: 'white',
107
- bold: true,
108
- },
109
- border: {
110
- fg: 'cyan',
111
- },
112
- },
113
- tags: true,
114
- });
115
-
116
- // Create detail view (hidden initially)
117
- this.detailBox = blessed.box({
118
- parent: this.screen,
119
- top: 0,
120
- left: 0,
121
- width: '100%',
122
- height: '100%-2',
123
- border: {
124
- type: 'line',
125
- },
126
- style: {
127
- border: {
128
- fg: 'cyan',
129
- },
130
- },
131
- scrollable: true,
132
- alwaysScroll: true,
133
- keys: true,
134
- vi: true,
135
- mouse: true,
136
- scrollbar: {
137
- ch: '│',
138
- style: {
139
- bg: 'cyan',
140
- },
141
- },
142
- tags: false,
143
- hidden: true,
144
- });
145
-
146
- // Status bar
147
- this.statusBar = blessed.box({
148
- parent: this.screen,
149
- bottom: 0,
150
- left: 0,
151
- width: '100%',
152
- height: 2,
153
- content: '',
154
- tags: true,
155
- style: {
156
- bg: 'blue',
157
- fg: 'white',
158
- },
159
- });
160
-
161
- // Setup keybindings
162
- this.setupKeybindings();
163
-
164
- // Initial render
165
- this.refreshData();
166
- this.render();
167
-
168
- // Start polling
169
- this.pollInterval = setInterval(() => {
170
- this.refreshData();
171
- this.render();
172
- }, this.refreshRate);
173
-
174
- // Render screen
175
- this.screen.render();
176
-
177
- // Focus on list after layout is established
178
- this.listBox.focus();
179
- }
180
-
181
- setupKeybindings() {
182
- // Quit
183
- this.screen.key(['q', 'C-c'], () => {
184
- if (this.pollInterval) {
185
- clearInterval(this.pollInterval);
186
- }
187
- process.exit(0);
188
- });
189
-
190
- // Enter - view details
191
- this.listBox.key(['enter', 'space'], () => {
192
- if (this.tasks.length > 0) {
193
- this.selectedTask = this.tasks[this.selectedIndex];
194
- this.viewMode = 'detail';
195
- this.initialScrollDone = false;
196
- this.listBox.hide();
197
- this.detailBox.show();
198
- this.screen.render();
199
- setImmediate(() => {
200
- this.detailBox.focus();
201
- this.render();
202
- });
203
- }
204
- });
205
-
206
- // Escape - back to list
207
- this.screen.key(['escape'], () => {
208
- if (this.viewMode === 'detail') {
209
- this.viewMode = 'list';
210
- this.detailBox.hide();
211
- this.listBox.show();
212
- this.screen.render();
213
- setImmediate(() => {
214
- this.listBox.focus();
215
- this.render();
216
- });
217
- }
218
- });
219
-
220
- // Arrow keys for list
221
- this.listBox.key(['up', 'k'], () => {
222
- if (this.selectedIndex > 0) {
223
- this.selectedIndex--;
224
- this.listBox.select(this.selectedIndex);
225
- this.render();
226
- }
227
- });
228
-
229
- this.listBox.key(['down', 'j'], () => {
230
- if (this.selectedIndex < this.tasks.length - 1) {
231
- this.selectedIndex++;
232
- this.listBox.select(this.selectedIndex);
233
- this.render();
234
- }
235
- });
236
-
237
- // Scroll in detail view
238
- this.detailBox.key(['up', 'k'], () => {
239
- this.detailBox.scroll(-1);
240
- this.screen.render();
241
- });
242
-
243
- this.detailBox.key(['down', 'j'], () => {
244
- this.detailBox.scroll(1);
245
- this.screen.render();
246
- });
247
-
248
- this.detailBox.key(['pageup', 'u'], () => {
249
- this.detailBox.scroll(-10);
250
- this.screen.render();
251
- });
252
-
253
- this.detailBox.key(['pagedown', 'd'], () => {
254
- this.detailBox.scroll(10);
255
- this.screen.render();
256
- });
257
- }
258
-
259
- refreshData() {
260
- const tasks = loadTasks();
261
- this.tasks = Object.values(tasks);
262
-
263
- // Sort by creation date, newest first
264
- this.tasks.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
265
-
266
- // Verify running status
267
- for (const task of this.tasks) {
268
- if (task.status === 'running' && !isProcessRunning(task.pid)) {
269
- task.status = 'stale';
270
- }
271
- }
272
- }
273
-
274
- render() {
275
- if (this.viewMode === 'list') {
276
- this.renderList();
277
- } else {
278
- this.renderDetail();
279
- }
280
- }
281
-
282
- renderList() {
283
- const items = this.tasks.map((task) => {
284
- const statusIcon =
285
- {
286
- running: '{green-fg}●{/}',
287
- completed: '{green-fg}●{/}',
288
- failed: '{red-fg}●{/}',
289
- stale: '{yellow-fg}●{/}',
290
- }[task.status] || '{gray-fg}●{/}';
291
-
292
- const age = this.getAge(task.createdAt);
293
- const cwd = task.cwd.replace(os.homedir(), '~');
294
-
295
- return `${statusIcon} {cyan-fg}${task.id.padEnd(25)}{/} {gray-fg}${task.status.padEnd(10)} ${age.padEnd(10)} ${cwd}{/}`;
296
- });
297
-
298
- this.listBox.setItems(items);
299
- this.listBox.setLabel(
300
- ` Tasks (${this.tasks.length}) - ↑↓ navigate, Enter to view logs, q to quit `
301
- );
302
-
303
- // Update status bar
304
- if (this.tasks.length > 0) {
305
- const task = this.tasks[this.selectedIndex];
306
- this.statusBar.setContent(
307
- ` Selected: {cyan-fg}${task.id}{/} | Status: ${this.getStatusColor(task.status)} | Press Enter to view logs`
308
- );
309
- } else {
310
- this.statusBar.setContent(' No tasks found');
311
- }
312
-
313
- this.screen.render();
314
- }
315
-
316
- renderDetail() {
317
- if (!this.selectedTask) return;
318
-
319
- const task = this.selectedTask;
320
-
321
- // Load and parse log file
322
- const logPath = path.join(os.homedir(), '.claude-zeroshot', 'logs', `${task.id}.log`);
323
- let content = '';
324
-
325
- if (fs.existsSync(logPath)) {
326
- try {
327
- const rawContent = fs.readFileSync(logPath, 'utf8');
328
- const lines = rawContent.split('\n');
329
-
330
- // Parse JSON stream and extract human-readable content
331
- for (const line of lines) {
332
- const parsed = parseLogLine(line);
333
- if (parsed) content += parsed;
334
- }
335
-
336
- // Strip ANSI codes for clean display
337
- // eslint-disable-next-line no-control-regex
338
- content = content.replace(/\x1b\[[0-9;]*m/g, '');
339
- } catch (error) {
340
- content = `Error reading log: ${error.message}`;
341
- }
342
- } else {
343
- content = 'No log file found';
344
- }
345
-
346
- this.detailBox.setContent(content);
347
- this.detailBox.setLabel(` ${task.id} | ${task.status} | ↑↓ scroll, Esc back, q quit `);
348
-
349
- // Update status bar
350
- this.statusBar.setContent(` ${task.id} | Esc to go back`);
351
-
352
- // Scroll to bottom only on first view
353
- if (!this.initialScrollDone) {
354
- this.detailBox.setScrollPerc(100);
355
- this.initialScrollDone = true;
356
- }
357
-
358
- this.screen.render();
359
- }
360
-
361
- getAge(dateStr) {
362
- const diff = Date.now() - new Date(dateStr).getTime();
363
- const mins = Math.floor(diff / 60000);
364
- const hours = Math.floor(mins / 60);
365
- const days = Math.floor(hours / 24);
366
-
367
- if (days > 0) return `${days}d ago`;
368
- if (hours > 0) return `${hours}h ago`;
369
- if (mins > 0) return `${mins}m ago`;
370
- return 'just now';
371
- }
372
-
373
- getStatusColor(status) {
374
- const colors = {
375
- running: '{green-fg}running{/}',
376
- completed: '{green-fg}completed{/}',
377
- failed: '{red-fg}failed{/}',
378
- stale: '{yellow-fg}stale{/}',
379
- };
380
- return colors[status] || status;
381
- }
382
- }
383
-
384
- export default TaskTUI;
@@ -1,188 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Watcher process - spawns and monitors a CLI process
5
- * Runs detached from parent, updates task status on completion
6
- */
7
-
8
- import { spawn } from 'child_process';
9
- import { appendFileSync } from 'fs';
10
- import { updateTask } from './store.js';
11
- import { detectStreamingModeError, recoverStructuredOutput } from './claude-recovery.js';
12
- import { createRequire } from 'module';
13
-
14
- const require = createRequire(import.meta.url);
15
- const { normalizeProviderName } = require('../lib/provider-names');
16
-
17
- const [, , taskId, cwd, logFile, argsJson, configJson] = process.argv;
18
- const args = JSON.parse(argsJson);
19
- const config = configJson ? JSON.parse(configJson) : {};
20
-
21
- function log(msg) {
22
- appendFileSync(logFile, msg);
23
- }
24
-
25
- const providerName = normalizeProviderName(config.provider || 'claude');
26
- const enableRecovery = providerName === 'claude';
27
-
28
- const env = { ...process.env, ...(config.env || {}) };
29
- const command = config.command || 'claude';
30
- const finalArgs = [...args];
31
-
32
- const child = spawn(command, finalArgs, {
33
- cwd,
34
- env,
35
- stdio: ['ignore', 'pipe', 'pipe'],
36
- });
37
-
38
- updateTask(taskId, { pid: child.pid });
39
-
40
- const silentJsonMode =
41
- config.outputFormat === 'json' && config.jsonSchema && config.silentJsonOutput && enableRecovery;
42
-
43
- let finalResultJson = null;
44
- let streamingModeError = null;
45
-
46
- let stdoutBuffer = '';
47
-
48
- child.stdout.on('data', (data) => {
49
- const chunk = data.toString();
50
- const timestamp = Date.now();
51
-
52
- if (silentJsonMode) {
53
- stdoutBuffer += chunk;
54
- const lines = stdoutBuffer.split('\n');
55
- stdoutBuffer = lines.pop() || '';
56
-
57
- for (const line of lines) {
58
- if (!line.trim()) continue;
59
- if (enableRecovery) {
60
- const detectedError = detectStreamingModeError(line);
61
- if (detectedError) {
62
- streamingModeError = { ...detectedError, timestamp };
63
- continue;
64
- }
65
- }
66
- try {
67
- const json = JSON.parse(line);
68
- if (json.structured_output) {
69
- finalResultJson = line;
70
- }
71
- } catch {
72
- // Not JSON, skip
73
- }
74
- }
75
- } else {
76
- stdoutBuffer += chunk;
77
- const lines = stdoutBuffer.split('\n');
78
- stdoutBuffer = lines.pop() || '';
79
-
80
- for (const line of lines) {
81
- if (enableRecovery) {
82
- const detectedError = detectStreamingModeError(line);
83
- if (detectedError) {
84
- streamingModeError = { ...detectedError, timestamp };
85
- continue;
86
- }
87
- }
88
- log(`[${timestamp}]${line}\n`);
89
- }
90
- }
91
- });
92
-
93
- let stderrBuffer = '';
94
-
95
- child.stderr.on('data', (data) => {
96
- const chunk = data.toString();
97
- const timestamp = Date.now();
98
-
99
- stderrBuffer += chunk;
100
- const lines = stderrBuffer.split('\n');
101
- stderrBuffer = lines.pop() || '';
102
-
103
- for (const line of lines) {
104
- log(`[${timestamp}]${line}\n`);
105
- }
106
- });
107
-
108
- child.on('close', async (code, signal) => {
109
- const timestamp = Date.now();
110
-
111
- if (stdoutBuffer.trim()) {
112
- if (enableRecovery) {
113
- const detectedError = detectStreamingModeError(stdoutBuffer);
114
- if (detectedError) {
115
- streamingModeError = { ...detectedError, timestamp };
116
- } else if (silentJsonMode) {
117
- try {
118
- const json = JSON.parse(stdoutBuffer);
119
- if (json.structured_output) {
120
- finalResultJson = stdoutBuffer;
121
- }
122
- } catch {
123
- // Not valid JSON
124
- }
125
- } else {
126
- log(`[${timestamp}]${stdoutBuffer}\n`);
127
- }
128
- } else if (!silentJsonMode) {
129
- log(`[${timestamp}]${stdoutBuffer}\n`);
130
- }
131
- }
132
-
133
- if (stderrBuffer.trim()) {
134
- log(`[${timestamp}]${stderrBuffer}\n`);
135
- }
136
-
137
- let recovered = null;
138
- if (enableRecovery && code !== 0 && streamingModeError?.sessionId) {
139
- recovered = recoverStructuredOutput(streamingModeError.sessionId);
140
- if (recovered?.payload) {
141
- const recoveredLine = JSON.stringify(recovered.payload);
142
- if (silentJsonMode) {
143
- finalResultJson = recoveredLine;
144
- } else {
145
- log(`[${timestamp}]${recoveredLine}\n`);
146
- }
147
- } else if (streamingModeError.line) {
148
- if (silentJsonMode) {
149
- log(streamingModeError.line + '\n');
150
- } else {
151
- log(`[${streamingModeError.timestamp}]${streamingModeError.line}\n`);
152
- }
153
- }
154
- }
155
-
156
- if (silentJsonMode && finalResultJson) {
157
- log(finalResultJson + '\n');
158
- }
159
-
160
- if (config.outputFormat !== 'json') {
161
- log(`\n${'='.repeat(50)}\n`);
162
- log(`Finished: ${new Date().toISOString()}\n`);
163
- log(`Exit code: ${code}, Signal: ${signal}\n`);
164
- }
165
-
166
- const resolvedCode = recovered?.payload ? 0 : code;
167
- const status = resolvedCode === 0 ? 'completed' : 'failed';
168
- try {
169
- await updateTask(taskId, {
170
- status,
171
- exitCode: resolvedCode,
172
- error: resolvedCode === 0 ? null : signal ? `Killed by ${signal}` : null,
173
- });
174
- } catch (updateError) {
175
- log(`[${Date.now()}][ERROR] Failed to update task status: ${updateError.message}\n`);
176
- }
177
- process.exit(0);
178
- });
179
-
180
- child.on('error', async (err) => {
181
- log(`\nError: ${err.message}\n`);
182
- try {
183
- await updateTask(taskId, { status: 'failed', error: err.message });
184
- } catch (updateError) {
185
- log(`[${Date.now()}][ERROR] Failed to update task status: ${updateError.message}\n`);
186
- }
187
- process.exit(1);
188
- });