@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
@@ -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
- };