@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,543 +0,0 @@
1
- /**
2
- * AttachServer - PTY process manager with socket server for attach/detach
3
- *
4
- * Lifecycle:
5
- * 1. Created when task/agent spawns
6
- * 2. Spawns command via node-pty
7
- * 3. Listens on Unix socket for client connections
8
- * 4. Buffers output in ring buffer (for late-joining clients)
9
- * 5. Broadcasts output to all connected clients
10
- * 6. Cleans up when process exits
11
- *
12
- * Features:
13
- * - Multi-client support (multiple terminals can attach)
14
- * - Output history replay on attach
15
- * - Signal forwarding (SIGINT, SIGTERM)
16
- * - Window resize support
17
- * - Graceful cleanup on exit
18
- */
19
-
20
- const net = require('net');
21
- const fs = require('fs');
22
- const path = require('path');
23
- const EventEmitter = require('events');
24
-
25
- const RingBuffer = require('./ring-buffer');
26
- const protocol = require('./protocol');
27
- const { cleanupStaleSocket } = require('./socket-discovery');
28
-
29
- // FAIL FAST: Check for node-pty at module load time, not at spawn time
30
- let pty;
31
- try {
32
- pty = require('node-pty');
33
- } catch (e) {
34
- throw new Error(
35
- `AttachServer: node-pty not installed. Run: npm install node-pty\n` +
36
- `Original error: ${e.message}`
37
- );
38
- }
39
-
40
- // Default output buffer size: 1MB
41
- const DEFAULT_BUFFER_SIZE = 1024 * 1024;
42
-
43
- class AttachServer extends EventEmitter {
44
- /**
45
- * @param {object} options
46
- * @param {string} options.id - Task or agent ID
47
- * @param {string} options.socketPath - Unix socket path
48
- * @param {string} options.command - Command to spawn
49
- * @param {string[]} options.args - Command arguments
50
- * @param {string} [options.cwd] - Working directory
51
- * @param {object} [options.env] - Environment variables
52
- * @param {number} [options.cols] - Terminal columns (default 120)
53
- * @param {number} [options.rows] - Terminal rows (default 30)
54
- * @param {number} [options.bufferSize] - Output buffer size (default 1MB)
55
- */
56
- constructor(options) {
57
- super();
58
-
59
- if (!options.id) throw new Error('AttachServer: id is required');
60
- if (!options.socketPath) throw new Error('AttachServer: socketPath is required');
61
- if (!options.command) throw new Error('AttachServer: command is required');
62
-
63
- this.id = options.id;
64
- this.socketPath = options.socketPath;
65
- this.command = options.command;
66
- this.args = options.args || [];
67
- this.cwd = options.cwd || process.cwd();
68
- this.env = options.env || process.env;
69
- this.cols = options.cols || 120;
70
- this.rows = options.rows || 30;
71
-
72
- this.outputBuffer = new RingBuffer(options.bufferSize || DEFAULT_BUFFER_SIZE);
73
- this.clients = new Map(); // clientId -> { socket, decoder }
74
- this.pty = null;
75
- this.server = null;
76
- this.state = 'stopped'; // stopped, starting, running, exiting, exited
77
- this.exitCode = null;
78
- this.exitSignal = null;
79
- this.pid = null;
80
-
81
- // Bind cleanup handlers
82
- this._onProcessExit = this._onProcessExit.bind(this);
83
- this._onServerError = this._onServerError.bind(this);
84
- }
85
-
86
- /**
87
- * Start the PTY process and socket server
88
- * @returns {Promise<void>}
89
- */
90
- async start() {
91
- if (this.state !== 'stopped') {
92
- throw new Error(`AttachServer: Cannot start from state '${this.state}'`);
93
- }
94
-
95
- this.state = 'starting';
96
-
97
- // Ensure socket directory exists
98
- const socketDir = path.dirname(this.socketPath);
99
- if (!fs.existsSync(socketDir)) {
100
- fs.mkdirSync(socketDir, { recursive: true });
101
- }
102
-
103
- // Clean up stale socket if exists
104
- await cleanupStaleSocket(this.socketPath);
105
-
106
- // Check if socket is still in use (another process)
107
- if (fs.existsSync(this.socketPath)) {
108
- throw new Error(`AttachServer: Socket already in use: ${this.socketPath}`);
109
- }
110
-
111
- // Start socket server FIRST (so clients can connect immediately)
112
- await this._startServer();
113
-
114
- // Spawn PTY process
115
- await this._spawnPty();
116
-
117
- this.state = 'running';
118
- this.emit('start', { id: this.id, pid: this.pid });
119
- }
120
-
121
- /**
122
- * Stop the server and kill the PTY process
123
- * @param {string} [signal='SIGTERM'] - Signal to send
124
- * @returns {Promise<void>}
125
- */
126
- async stop(signal = 'SIGTERM') {
127
- if (this.state !== 'running') {
128
- return;
129
- }
130
-
131
- this.state = 'exiting';
132
-
133
- // Kill PTY process
134
- if (this.pty) {
135
- try {
136
- this.pty.kill(signal);
137
- } catch {
138
- // Process may already be dead
139
- }
140
- }
141
-
142
- // Wait for process to exit (with timeout)
143
- await new Promise((resolve) => {
144
- const timeout = setTimeout(() => {
145
- // Force kill if still running
146
- if (this.pty) {
147
- try {
148
- this.pty.kill('SIGKILL');
149
- } catch {
150
- // Ignore
151
- }
152
- }
153
- resolve();
154
- }, 5000);
155
-
156
- const checkExit = () => {
157
- if (this.state === 'exited') {
158
- clearTimeout(timeout);
159
- resolve();
160
- } else {
161
- setTimeout(checkExit, 100);
162
- }
163
- };
164
- checkExit();
165
- });
166
-
167
- await this._cleanup();
168
- }
169
-
170
- /**
171
- * Send a signal to the PTY process
172
- * @param {string} signal - Signal name (SIGINT, SIGTERM, etc.)
173
- */
174
- sendSignal(signal) {
175
- if (!this.pty || this.state !== 'running') {
176
- return false;
177
- }
178
-
179
- try {
180
- this.pty.kill(signal);
181
- return true;
182
- } catch {
183
- return false;
184
- }
185
- }
186
-
187
- /**
188
- * Resize the PTY
189
- * @param {number} cols - Columns
190
- * @param {number} rows - Rows
191
- */
192
- resize(cols, rows) {
193
- if (!this.pty || this.state !== 'running') {
194
- return;
195
- }
196
-
197
- this.cols = cols;
198
- this.rows = rows;
199
-
200
- try {
201
- this.pty.resize(cols, rows);
202
- } catch {
203
- // Ignore resize errors
204
- }
205
- }
206
-
207
- /**
208
- * Write to PTY stdin (for future interactive mode)
209
- * @param {Buffer|string} data - Data to write
210
- */
211
- write(data) {
212
- if (!this.pty || this.state !== 'running') {
213
- return false;
214
- }
215
-
216
- try {
217
- this.pty.write(data);
218
- return true;
219
- } catch {
220
- return false;
221
- }
222
- }
223
-
224
- /**
225
- * Get current server state
226
- * @returns {object}
227
- */
228
- getState() {
229
- return {
230
- id: this.id,
231
- state: this.state,
232
- pid: this.pid,
233
- exitCode: this.exitCode,
234
- exitSignal: this.exitSignal,
235
- clientCount: this.clients.size,
236
- bufferSize: this.outputBuffer.getSize(),
237
- };
238
- }
239
-
240
- // ─────────────────────────────────────────────────────────────────
241
- // Private methods
242
- // ─────────────────────────────────────────────────────────────────
243
-
244
- /**
245
- * Start the Unix socket server
246
- * @private
247
- */
248
- _startServer() {
249
- return new Promise((resolve, reject) => {
250
- this.server = net.createServer((socket) => {
251
- this._handleClientConnection(socket);
252
- });
253
-
254
- this.server.on('error', this._onServerError);
255
-
256
- this.server.listen(this.socketPath, () => {
257
- // Set socket permissions (owner read/write only)
258
- try {
259
- fs.chmodSync(this.socketPath, 0o600);
260
- } catch {
261
- // Ignore permission errors
262
- }
263
- resolve();
264
- });
265
-
266
- this.server.on('error', (err) => {
267
- if (this.state === 'starting') {
268
- reject(err);
269
- }
270
- });
271
- });
272
- }
273
-
274
- /**
275
- * Spawn the PTY process
276
- * @private
277
- */
278
- _spawnPty() {
279
- this.pty = pty.spawn(this.command, this.args, {
280
- name: 'xterm-256color',
281
- cols: this.cols,
282
- rows: this.rows,
283
- cwd: this.cwd,
284
- env: this.env,
285
- });
286
-
287
- this.pid = this.pty.pid;
288
-
289
- // Handle PTY output
290
- this.pty.onData((data) => {
291
- this._handlePtyOutput(data);
292
- });
293
-
294
- // Handle PTY exit
295
- this.pty.onExit(({ exitCode, signal }) => {
296
- this._onProcessExit(exitCode, signal);
297
- });
298
- }
299
-
300
- /**
301
- * Handle PTY output
302
- * @private
303
- */
304
- _handlePtyOutput(data) {
305
- // Buffer output for late-joining clients
306
- this.outputBuffer.write(data);
307
-
308
- // Broadcast to all connected clients
309
- const message = protocol.encode(protocol.createOutputMessage(data));
310
-
311
- for (const [clientId, client] of this.clients) {
312
- try {
313
- client.socket.write(message);
314
- } catch {
315
- // Client disconnected, will be cleaned up
316
- this._removeClient(clientId);
317
- }
318
- }
319
-
320
- // Emit for local listeners (e.g., logging)
321
- this.emit('output', data);
322
- }
323
-
324
- /**
325
- * Handle new client connection
326
- * @private
327
- */
328
- _handleClientConnection(socket) {
329
- const decoder = new protocol.MessageDecoder();
330
- let clientId = null;
331
-
332
- socket.on('data', (data) => {
333
- try {
334
- const messages = decoder.feed(data);
335
- for (const msg of messages) {
336
- this._handleClientMessage(socket, msg, (id) => {
337
- clientId = id;
338
- });
339
- }
340
- } catch (e) {
341
- // Protocol error, close connection
342
- this._sendError(socket, `Protocol error: ${e.message}`);
343
- socket.end();
344
- }
345
- });
346
-
347
- socket.on('close', () => {
348
- if (clientId) {
349
- this._removeClient(clientId);
350
- }
351
- });
352
-
353
- socket.on('error', () => {
354
- if (clientId) {
355
- this._removeClient(clientId);
356
- }
357
- });
358
- }
359
-
360
- /**
361
- * Handle message from client
362
- * @private
363
- */
364
- _handleClientMessage(socket, message, setClientId) {
365
- switch (message.type) {
366
- case protocol.MessageType.ATTACH: {
367
- const { clientId, cols, rows } = message;
368
- if (!clientId) {
369
- this._sendError(socket, 'ATTACH requires clientId');
370
- return;
371
- }
372
-
373
- // Register client
374
- this.clients.set(clientId, {
375
- socket,
376
- decoder: new protocol.MessageDecoder(),
377
- });
378
- setClientId(clientId);
379
-
380
- // Send history (buffered output)
381
- const history = this.outputBuffer.read();
382
- if (history.length > 0) {
383
- socket.write(protocol.encode(protocol.createHistoryMessage(history)));
384
- }
385
-
386
- // Send current state
387
- socket.write(protocol.encode(protocol.createStateMessage(this.getState())));
388
-
389
- // Resize PTY to client dimensions (if provided)
390
- if (cols && rows) {
391
- this.resize(cols, rows);
392
- }
393
-
394
- this.emit('clientAttach', { clientId });
395
- break;
396
- }
397
-
398
- case protocol.MessageType.DETACH: {
399
- const { clientId } = message;
400
- this._removeClient(clientId);
401
- socket.end();
402
- break;
403
- }
404
-
405
- case protocol.MessageType.RESIZE: {
406
- const { cols, rows } = message;
407
- if (cols && rows) {
408
- this.resize(cols, rows);
409
- }
410
- break;
411
- }
412
-
413
- case protocol.MessageType.SIGNAL: {
414
- const { signal } = message;
415
- this.sendSignal(signal);
416
- break;
417
- }
418
-
419
- case protocol.MessageType.STDIN: {
420
- // Future interactive mode
421
- const data = protocol.decodeData(message);
422
- if (data) {
423
- this.write(data);
424
- }
425
- break;
426
- }
427
-
428
- default:
429
- this._sendError(socket, `Unknown message type: ${message.type}`);
430
- }
431
- }
432
-
433
- /**
434
- * Remove a client
435
- * @private
436
- */
437
- _removeClient(clientId) {
438
- const client = this.clients.get(clientId);
439
- if (client) {
440
- this.clients.delete(clientId);
441
- this.emit('clientDetach', { clientId });
442
- }
443
- }
444
-
445
- /**
446
- * Send error message to client
447
- * @private
448
- */
449
- _sendError(socket, message) {
450
- try {
451
- socket.write(protocol.encode(protocol.createErrorMessage(message)));
452
- } catch {
453
- // Client disconnected
454
- }
455
- }
456
-
457
- /**
458
- * Handle PTY process exit
459
- * @private
460
- */
461
- _onProcessExit(exitCode, signal) {
462
- this.exitCode = exitCode;
463
- this.exitSignal = signal;
464
- this.state = 'exited';
465
-
466
- // Notify all clients
467
- const exitMessage = protocol.encode(protocol.createExitMessage(exitCode, signal));
468
-
469
- for (const [, client] of this.clients) {
470
- try {
471
- client.socket.write(exitMessage);
472
- client.socket.end();
473
- } catch {
474
- // Client already disconnected
475
- }
476
- }
477
-
478
- this.emit('exit', { exitCode, signal });
479
-
480
- // Clean up after short delay (allow clients to receive exit message)
481
- setTimeout(() => {
482
- this._cleanup();
483
- }, 500);
484
- }
485
-
486
- /**
487
- * Handle server error
488
- * @private
489
- */
490
- _onServerError(err) {
491
- this.emit('error', err);
492
- }
493
-
494
- /**
495
- * Clean up resources
496
- * @private
497
- */
498
- async _cleanup() {
499
- // Close all client connections
500
- for (const [, client] of this.clients) {
501
- try {
502
- client.socket.destroy();
503
- } catch {
504
- // Ignore
505
- }
506
- }
507
- this.clients.clear();
508
-
509
- // Close server
510
- if (this.server) {
511
- await new Promise((resolve) => {
512
- this.server.close(() => resolve());
513
- });
514
- this.server = null;
515
- }
516
-
517
- // Remove socket file
518
- if (fs.existsSync(this.socketPath)) {
519
- try {
520
- fs.unlinkSync(this.socketPath);
521
- } catch {
522
- // Ignore
523
- }
524
- }
525
-
526
- // Clean up empty parent directory for cluster sockets
527
- const socketDir = path.dirname(this.socketPath);
528
- if (socketDir.includes('cluster-')) {
529
- try {
530
- const files = fs.readdirSync(socketDir);
531
- if (files.length === 0) {
532
- fs.rmdirSync(socketDir);
533
- }
534
- } catch {
535
- // Ignore
536
- }
537
- }
538
-
539
- this.emit('cleanup');
540
- }
541
- }
542
-
543
- module.exports = AttachServer;
@@ -1,35 +0,0 @@
1
- /**
2
- * Attach/Detach System - tmux-style session management for zeroshot tasks and clusters
3
- *
4
- * Usage:
5
- * const { AttachServer, AttachClient, socketDiscovery } = require('./attach');
6
- *
7
- * // Server side (in watcher.js or agent-wrapper.js)
8
- * const server = new AttachServer({
9
- * id: 'task-xxx',
10
- * socketPath: socketDiscovery.getTaskSocketPath('task-xxx'),
11
- * command: 'claude',
12
- * args: ['--print', '--output-format', 'stream-json', prompt],
13
- * });
14
- * await server.start();
15
- *
16
- * // Client side (in CLI attach command)
17
- * const client = new AttachClient({
18
- * socketPath: socketDiscovery.getTaskSocketPath('task-xxx'),
19
- * });
20
- * await client.connect();
21
- */
22
-
23
- const AttachServer = require('./attach-server');
24
- const AttachClient = require('./attach-client');
25
- const RingBuffer = require('./ring-buffer');
26
- const protocol = require('./protocol');
27
- const socketDiscovery = require('./socket-discovery');
28
-
29
- module.exports = {
30
- AttachServer,
31
- AttachClient,
32
- RingBuffer,
33
- protocol,
34
- socketDiscovery,
35
- };