@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,369 +0,0 @@
1
- /**
2
- * TemplateResolver - Resolves parameterized cluster templates
3
- *
4
- * Takes a base template with {{param}} placeholders and resolves them
5
- * with provided parameter values. Pure data transformation, no magic.
6
- *
7
- * Resolution rules:
8
- * 1. Load base template JSON
9
- * 2. Deep clone
10
- * 3. Walk all values, replace {{param}} with params[param]
11
- * 4. Handle conditional agents via "condition" field
12
- * 5. Fail hard if any {{param}} remains unresolved
13
- */
14
-
15
- const fs = require('fs');
16
- const path = require('path');
17
-
18
- class TemplateResolver {
19
- /**
20
- * @param {string} templatesDir
21
- */
22
- constructor(templatesDir) {
23
- this.templatesDir = templatesDir;
24
- this.baseTemplatesDir = path.join(templatesDir, 'base-templates');
25
- }
26
-
27
- /**
28
- * Resolve a template with parameters
29
- * @param {string} baseName - Name of base template (without .json)
30
- * @param {Object} params - Parameter values to substitute
31
- * @returns {Object} Resolved cluster config
32
- */
33
- resolve(baseName, params) {
34
- // Load base template
35
- const templatePath = path.join(this.baseTemplatesDir, `${baseName}.json`);
36
- if (!fs.existsSync(templatePath)) {
37
- throw new Error(`Base template not found: ${baseName} (looked in ${templatePath})`);
38
- }
39
-
40
- const templateJson = fs.readFileSync(templatePath, 'utf8');
41
- const template = JSON.parse(templateJson);
42
-
43
- // Validate required params
44
- this._validateParams(template, params);
45
-
46
- // Apply defaults for missing params (e.g., timeout: 0)
47
- const paramsWithDefaults = this._applyDefaults(template, params);
48
-
49
- // Deep clone and resolve
50
- const resolved = this._resolveObject(JSON.parse(JSON.stringify(template)), paramsWithDefaults);
51
-
52
- // Filter out conditional agents that don't meet their condition
53
- if (resolved.agents) {
54
- resolved.agents = resolved.agents.filter((/** @type {any} */ agent) => {
55
- if (!agent.condition) return true;
56
- const conditionMet = this._evaluateCondition(agent.condition, params);
57
- delete agent.condition; // Remove condition field from final output
58
- return conditionMet;
59
- });
60
- }
61
-
62
- // Verify no unresolved placeholders remain
63
- this._verifyResolved(resolved);
64
-
65
- // Remove params schema from output (it's metadata, not config)
66
- delete resolved.params;
67
-
68
- return resolved;
69
- }
70
-
71
- /**
72
- * Validate that required params are provided
73
- * @private
74
- * @param {any} template
75
- * @param {any} params
76
- */
77
- _validateParams(template, params) {
78
- if (!template.params) return;
79
-
80
- const missing = [];
81
- for (const [name, schema] of Object.entries(template.params)) {
82
- if (params[name] === undefined && schema.default === undefined) {
83
- missing.push(name);
84
- }
85
- }
86
-
87
- if (missing.length > 0) {
88
- throw new Error(`Missing required params: ${missing.join(', ')}`);
89
- }
90
- }
91
-
92
- /**
93
- * Apply template defaults for any missing params
94
- * @private
95
- * @param {any} template
96
- * @param {any} params
97
- * @returns {any} params with defaults applied
98
- */
99
- _applyDefaults(template, params) {
100
- if (!template.params) return params;
101
-
102
- const result = { ...params };
103
- for (const [name, schema] of Object.entries(template.params)) {
104
- if (result[name] === undefined && schema.default !== undefined) {
105
- result[name] = schema.default;
106
- }
107
- }
108
- return result;
109
- }
110
-
111
- /**
112
- * Recursively resolve placeholders in an object
113
- * @private
114
- * @param {any} obj
115
- * @param {any} params
116
- * @returns {any}
117
- */
118
- _resolveObject(obj, params) {
119
- if (obj === null || obj === undefined) {
120
- return obj;
121
- }
122
-
123
- if (typeof obj === 'string') {
124
- return this._resolveString(obj, params);
125
- }
126
-
127
- if (Array.isArray(obj)) {
128
- return obj.map((item) => this._resolveObject(item, params));
129
- }
130
-
131
- if (typeof obj === 'object') {
132
- /** @type {any} */
133
- const result = {};
134
- for (const [key, value] of Object.entries(obj)) {
135
- result[key] = this._resolveObject(value, params);
136
- }
137
- return result;
138
- }
139
-
140
- return obj;
141
- }
142
-
143
- /**
144
- * Resolve placeholders in a string
145
- * Supports: {{param}} and {{#if condition}}...{{/if}}
146
- * @private
147
- * @param {any} str
148
- * @param {any} params
149
- * @returns {any}
150
- */
151
- _resolveString(str, params) {
152
- // Handle simple {{param}} substitutions
153
- let result = str.replace(
154
- /\{\{(\w+)\}\}/g,
155
- (/** @type {any} */ _match, /** @type {any} */ paramName) => {
156
- if (params[paramName] !== undefined) {
157
- return params[paramName];
158
- }
159
- // Return match unchanged if param not found (will be caught by verify)
160
- return _match;
161
- }
162
- );
163
-
164
- // Handle {{#if condition}}...{{/if}} blocks
165
- result = result.replace(
166
- /\{\{#if\s+([^}]+)\}\}([\s\S]*?)\{\{\/if\}\}/g,
167
- (/** @type {any} */ _match, /** @type {any} */ condition, /** @type {any} */ content) => {
168
- const conditionMet = this._evaluateCondition(condition, params);
169
- return conditionMet ? content : '';
170
- }
171
- );
172
-
173
- // Clean up multiple newlines from removed conditionals
174
- result = result.replace(/\n{3,}/g, '\n\n');
175
-
176
- return result;
177
- }
178
-
179
- /**
180
- * Evaluate a simple condition expression
181
- * Supports: param == 'value', param != 'value', {{param}} >= N
182
- * @private
183
- * @param {any} condition
184
- * @param {any} params
185
- * @returns {boolean}
186
- */
187
- _evaluateCondition(condition, params) {
188
- // Replace {{param}} with actual values first
189
- let expr = condition.trim();
190
-
191
- // Replace {{param}} placeholders
192
- expr = expr.replace(
193
- /\{\{(\w+)\}\}/g,
194
- (/** @type {any} */ _match, /** @type {any} */ paramName) => {
195
- const value = params[paramName];
196
- if (value === undefined) return 'undefined';
197
- if (typeof value === 'string') return `"${value}"`;
198
- return String(value);
199
- }
200
- );
201
-
202
- // Replace bare param names
203
- for (const [name, value] of Object.entries(params)) {
204
- const regex = new RegExp(`\\b${name}\\b`, 'g');
205
- if (typeof value === 'string') {
206
- expr = expr.replace(regex, `"${value}"`);
207
- } else {
208
- expr = expr.replace(regex, String(value));
209
- }
210
- }
211
-
212
- try {
213
- // Parse and evaluate simple comparison expressions without eval
214
- return this._evaluateSimpleExpression(expr);
215
- } catch {
216
- console.error(`Failed to evaluate condition: ${condition} (resolved: ${expr})`);
217
- return false;
218
- }
219
- }
220
-
221
- /**
222
- * Evaluate simple comparison expressions without eval
223
- * Supports: ==, !=, <, >, <=, >=, &&, ||
224
- * @private
225
- * @param {string} expr
226
- * @returns {boolean}
227
- */
228
- _evaluateSimpleExpression(expr) {
229
- // Handle logical operators (&&, ||) by splitting and recursing
230
- if (expr.includes('||')) {
231
- const parts = expr.split('||');
232
- return parts.some((part) => this._evaluateSimpleExpression(part.trim()));
233
- }
234
- if (expr.includes('&&')) {
235
- const parts = expr.split('&&');
236
- return parts.every((part) => this._evaluateSimpleExpression(part.trim()));
237
- }
238
-
239
- // Handle comparison operators
240
- const comparisonOps = ['==', '!=', '<=', '>=', '<', '>'];
241
- for (const op of comparisonOps) {
242
- if (expr.includes(op)) {
243
- const [left, right] = expr.split(op).map((s) => s.trim());
244
- const leftVal = this._parseValue(left);
245
- const rightVal = this._parseValue(right);
246
-
247
- switch (op) {
248
- case '==':
249
- return leftVal === rightVal;
250
- case '!=':
251
- return leftVal !== rightVal;
252
- case '<':
253
- return leftVal < rightVal;
254
- case '>':
255
- return leftVal > rightVal;
256
- case '<=':
257
- return leftVal <= rightVal;
258
- case '>=':
259
- return leftVal >= rightVal;
260
- }
261
- }
262
- }
263
-
264
- // If no operator found, treat as boolean literal or truthy value
265
- return this._parseValue(expr) ? true : false;
266
- }
267
-
268
- /**
269
- * Parse a value from string (number, boolean, string literal)
270
- * @private
271
- * @param {string} str
272
- * @returns {any}
273
- */
274
- _parseValue(str) {
275
- str = str.trim();
276
-
277
- // String literals (single or double quotes)
278
- if ((str.startsWith('"') && str.endsWith('"')) || (str.startsWith("'") && str.endsWith("'"))) {
279
- return str.slice(1, -1);
280
- }
281
-
282
- // Boolean literals
283
- if (str === 'true') return true;
284
- if (str === 'false') return false;
285
- if (str === 'undefined' || str === 'null') return undefined;
286
-
287
- // Numbers
288
- if (/^-?\d+(\.\d+)?$/.test(str)) {
289
- return parseFloat(str);
290
- }
291
-
292
- // Return as-is for other cases
293
- return str;
294
- }
295
-
296
- /**
297
- * Verify no unresolved placeholders remain
298
- * @private
299
- * @param {any} obj
300
- */
301
- _verifyResolved(obj) {
302
- const unresolved = this._findUnresolved(obj);
303
- if (unresolved.length > 0) {
304
- throw new Error(`Unresolved template placeholders: ${unresolved.join(', ')}`);
305
- }
306
- }
307
-
308
- /**
309
- * Find all unresolved {{param}} placeholders
310
- * @private
311
- * @param {any} obj
312
- * @param {string} pathPrefix
313
- * @returns {string[]}
314
- */
315
- _findUnresolved(obj, pathPrefix = '') {
316
- const unresolved = [];
317
-
318
- if (typeof obj === 'string') {
319
- const matches = obj.match(/\{\{(\w+)\}\}/g);
320
- if (matches) {
321
- unresolved.push(...matches.map((m) => `${pathPrefix}: ${m}`));
322
- }
323
- } else if (Array.isArray(obj)) {
324
- obj.forEach((item, i) => {
325
- unresolved.push(...this._findUnresolved(item, `${pathPrefix}[${i}]`));
326
- });
327
- } else if (obj && typeof obj === 'object') {
328
- for (const [key, value] of Object.entries(obj)) {
329
- unresolved.push(...this._findUnresolved(value, `${pathPrefix}.${key}`));
330
- }
331
- }
332
-
333
- return unresolved;
334
- }
335
-
336
- /**
337
- * List available base templates
338
- * @returns {string[]}
339
- */
340
- listTemplates() {
341
- if (!fs.existsSync(this.baseTemplatesDir)) {
342
- return [];
343
- }
344
- return fs
345
- .readdirSync(this.baseTemplatesDir)
346
- .filter((f) => f.endsWith('.json'))
347
- .map((f) => f.replace('.json', ''));
348
- }
349
-
350
- /**
351
- * Get template metadata (name, description, params)
352
- * @param {any} baseName
353
- * @returns {any}
354
- */
355
- getTemplateInfo(baseName) {
356
- const templatePath = path.join(this.baseTemplatesDir, `${baseName}.json`);
357
- if (!fs.existsSync(templatePath)) {
358
- return null;
359
- }
360
- const template = JSON.parse(fs.readFileSync(templatePath, 'utf8'));
361
- return {
362
- name: template.name,
363
- description: template.description,
364
- params: template.params || {},
365
- };
366
- }
367
- }
368
-
369
- module.exports = TemplateResolver;
@@ -1,133 +0,0 @@
1
- TUI Performance & UX Improvements
2
- ==================================
3
-
4
- ## New Features
5
-
6
- ### 4. Two-Level Navigation 🎯
7
- **Feature:** Completely separate layouts for overview vs detail
8
- **Implementation:**
9
- - Overview mode: ONLY shows clusters table + stats (agents/logs hidden)
10
- - Detail mode: ONLY shows agents + logs (clusters/stats hidden)
11
- - Enter key to drill into detail, Escape to return
12
- - Help text updates dynamically based on current view
13
- - Widgets physically shown/hidden (not just empty data)
14
-
15
- ## Fixed Issues
16
-
17
- ### 1. Slow Startup ⚡
18
- **Problem:** TUI took 5-10 seconds to start due to synchronous cluster loading
19
- **Solution:**
20
- - Deferred initial polls by 50-100ms to let UI render first
21
- - Shows "Loading..." message immediately
22
- - Lazy-loads cluster ledgers only when needed
23
- - Startup now instant (<100ms)
24
-
25
- ### 2. Default Filter 🎯
26
- **Problem:** Showed all clusters (including stopped) by default
27
- **Solution:**
28
- - Changed default filter from "all" to "running"
29
- - User only sees active clusters
30
- - Can still use `--filter all` to see everything
31
-
32
- ### 3. Cluster Selection 📍
33
- **Problem:** Agents and logs weren't properly filtered by selected cluster
34
- **Solution:**
35
- - Renderer now tracks selectedClusterId
36
- - Agents shown are for the selected cluster only
37
- - Logs filtered to show only messages from selected cluster
38
- - Messages cleared when switching between clusters
39
- - Navigate with ↑↓ or jk keys
40
-
41
- ## Performance Improvements
42
-
43
- **Before:**
44
- - Startup: 5-10 seconds
45
- - All clusters loaded synchronously
46
- - All ledgers opened on startup
47
- - Unfiltered logs from all clusters
48
-
49
- **After:**
50
- - Startup: <100ms instant
51
- - Clusters loaded async after UI renders
52
- - Ledgers lazy-loaded when needed
53
- - Logs filtered to selected cluster only
54
-
55
- ## Usage
56
-
57
- ```bash
58
- # Shows only running clusters (default)
59
- vibe watch
60
-
61
- # Show all clusters (including stopped)
62
- vibe watch --filter all
63
-
64
- # Show only stopped clusters
65
- vibe watch --filter stopped
66
- ```
67
-
68
- ## Keyboard Navigation
69
-
70
- ### Two-Level Navigation
71
- - **Overview Mode** (default): ONLY clusters + stats visible
72
- - Large clusters table (16 rows) with system stats sidebar
73
- - No agents or logs shown
74
- - `↑` / `k` - Select previous cluster
75
- - `↓` / `j` - Select next cluster
76
- - `Enter` - Switch to detail view for selected cluster
77
-
78
- - **Detail Mode**: ONLY agents + logs visible
79
- - Full-width agents table (9 rows)
80
- - Full-width live logs (9 rows)
81
- - Clusters table and stats hidden
82
- - `Escape` - Switch back to overview mode
83
-
84
- Agents and logs auto-update in real-time when in detail view
85
-
86
- ## Technical Changes
87
-
88
- ### data-poller.js
89
- - Line 45-53: Deferred initial polls with setTimeout
90
- - Line 196-208: Added lazy loading for cluster ledgers
91
- - Line 201-203: Check if ledger DB exists before loading
92
-
93
- ### index.js (TUI)
94
- - Line 21: Changed default filter to 'running'
95
- - Line 34-36: Added viewMode state ('overview' or 'detail') and detailClusterId
96
- - Line 48-49: Show "Loading..." message on startup
97
- - Line 107-119: Conditional rendering - agents only shown in detail view
98
- - Line 130-137: Conditional rendering for resource_stats case
99
-
100
- ### keybindings.js
101
- - Line 14-37: Enter key handler to switch to detail view
102
- - Line 39-59: Escape key handler to switch to overview view
103
- - Line 22, 45: Clear messages when switching views
104
- - Line 29-34: Detail mode - hide clusters/stats, show agents/logs
105
- - Line 52-57: Overview mode - show clusters/stats, hide agents/logs
106
- - Line 24-27, 47-50: Update help text based on view mode
107
-
108
- ### layout.js
109
- - Line 36: Expanded clusters table to 16 rows (from 6)
110
- - Line 66: Expanded stats box to 16 rows (from 6)
111
- - Line 85: Repositioned agent table to row 0, 9 rows, full width
112
- - Line 119: Repositioned logs to row 9, 9 rows, full width
113
- - Line 165-167: Initially hide agent table and logs (overview mode default)
114
-
115
- ### cli/index.js
116
- - Line 1161: Changed default filter to 'running' in CLI option
117
-
118
- ## Testing
119
-
120
- Run integration tests:
121
- ```bash
122
- node tests/tui-integration.test.js # Basic TUI startup and data loading
123
- node tests/tui-navigation-test.js # Two-level navigation functionality
124
- ```
125
-
126
- Expected: All tests pass, TUI starts instantly
127
-
128
- ## Notes
129
-
130
- - Messages are cluster-scoped (only show for selected cluster)
131
- - Selection persists across refreshes
132
- - Empty clusters (no agents) still show in list
133
- - Logs clear when switching clusters to avoid confusion