@covibes/zeroshot 5.2.1 → 5.4.0
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.
- package/CHANGELOG.md +174 -189
- package/README.md +226 -195
- package/cli/commands/providers.js +149 -0
- package/cli/index.js +3145 -2366
- package/cli/lib/first-run.js +40 -3
- package/cli/message-formatters-normal.js +28 -6
- package/cluster-templates/base-templates/debug-workflow.json +24 -78
- package/cluster-templates/base-templates/full-workflow.json +99 -316
- package/cluster-templates/base-templates/single-worker.json +23 -15
- package/cluster-templates/base-templates/worker-validator.json +105 -36
- package/cluster-templates/conductor-bootstrap.json +9 -7
- package/lib/docker-config.js +14 -1
- package/lib/git-remote-utils.js +165 -0
- package/lib/id-detector.js +10 -7
- package/lib/provider-defaults.js +62 -0
- package/lib/provider-detection.js +59 -0
- package/lib/provider-names.js +57 -0
- package/lib/settings/claude-auth.js +78 -0
- package/lib/settings.js +298 -15
- package/lib/stream-json-parser.js +4 -238
- package/package.json +27 -6
- package/scripts/setup-merge-queue.sh +170 -0
- package/scripts/validate-templates.js +100 -0
- package/src/agent/agent-config.js +140 -63
- package/src/agent/agent-context-builder.js +336 -165
- package/src/agent/agent-hook-executor.js +337 -67
- package/src/agent/agent-lifecycle.js +386 -287
- package/src/agent/agent-stuck-detector.js +7 -7
- package/src/agent/agent-task-executor.js +944 -683
- package/src/agent/output-extraction.js +217 -0
- package/src/agent/output-reformatter.js +175 -0
- package/src/agent/schema-utils.js +146 -0
- package/src/agent-wrapper.js +112 -31
- package/src/agents/git-pusher-template.js +285 -0
- package/src/claude-task-runner.js +145 -44
- package/src/config-router.js +13 -13
- package/src/config-validator.js +1049 -563
- package/src/input-helpers.js +65 -0
- package/src/isolation-manager.js +499 -320
- package/src/issue-providers/README.md +305 -0
- package/src/issue-providers/azure-devops-provider.js +273 -0
- package/src/issue-providers/base-provider.js +232 -0
- package/src/issue-providers/github-provider.js +179 -0
- package/src/issue-providers/gitlab-provider.js +241 -0
- package/src/issue-providers/index.js +196 -0
- package/src/issue-providers/jira-provider.js +239 -0
- package/src/ledger.js +50 -11
- package/src/lib/safe-exec.js +88 -0
- package/src/orchestrator.js +1348 -757
- package/src/preflight.js +306 -149
- package/src/process-metrics.js +98 -56
- package/src/providers/anthropic/cli-builder.js +73 -0
- package/src/providers/anthropic/index.js +204 -0
- package/src/providers/anthropic/models.js +23 -0
- package/src/providers/anthropic/output-parser.js +177 -0
- package/src/providers/base-provider.js +251 -0
- package/src/providers/capabilities.js +60 -0
- package/src/providers/google/cli-builder.js +55 -0
- package/src/providers/google/index.js +116 -0
- package/src/providers/google/models.js +24 -0
- package/src/providers/google/output-parser.js +101 -0
- package/src/providers/index.js +91 -0
- package/src/providers/openai/cli-builder.js +133 -0
- package/src/providers/openai/index.js +136 -0
- package/src/providers/openai/models.js +21 -0
- package/src/providers/openai/output-parser.js +143 -0
- package/src/providers/opencode/cli-builder.js +42 -0
- package/src/providers/opencode/index.js +103 -0
- package/src/providers/opencode/models.js +55 -0
- package/src/providers/opencode/output-parser.js +122 -0
- package/src/schemas/sub-cluster.js +68 -39
- package/src/status-footer.js +94 -48
- package/src/sub-cluster-wrapper.js +92 -36
- package/src/task-runner.js +8 -6
- package/src/template-resolver.js +12 -9
- package/src/tui/data-poller.js +123 -99
- package/src/tui/formatters.js +4 -3
- package/src/tui/keybindings.js +259 -318
- package/src/tui/layout.js +20 -3
- package/src/tui/renderer.js +11 -21
- package/task-lib/attachable-watcher.js +150 -111
- package/task-lib/claude-recovery.js +156 -0
- package/task-lib/commands/episodes.js +105 -0
- package/task-lib/commands/list.js +3 -3
- package/task-lib/commands/logs.js +231 -189
- package/task-lib/commands/resume.js +3 -2
- package/task-lib/commands/run.js +12 -3
- package/task-lib/commands/schedules.js +111 -61
- package/task-lib/config.js +0 -2
- package/task-lib/runner.js +128 -50
- package/task-lib/scheduler.js +3 -3
- package/task-lib/store.js +464 -152
- package/task-lib/tui/formatters.js +94 -45
- package/task-lib/tui/renderer.js +13 -3
- package/task-lib/tui.js +73 -32
- package/task-lib/watcher.js +157 -100
- package/src/agents/git-pusher-agent.json +0 -20
- package/src/github.js +0 -103
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
* - maxModel ceiling enforcement at config time
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
const { loadSettings, validateModelAgainstMax } = require('../../lib/settings');
|
|
12
|
+
const { loadSettings, validateModelAgainstMax, VALID_MODELS } = require('../../lib/settings');
|
|
13
|
+
|
|
14
|
+
const VALID_LEVELS = ['level1', 'level2', 'level3'];
|
|
13
15
|
|
|
14
16
|
// Default max iterations (high limit - let the user decide when to give up)
|
|
15
17
|
const DEFAULT_MAX_ITERATIONS = 100;
|
|
@@ -25,21 +27,13 @@ const DEFAULT_TIMEOUT = 0;
|
|
|
25
27
|
const DEFAULT_STALE_DURATION_MS = 30 * 60 * 1000; // 30 minutes before triggering analysis
|
|
26
28
|
const DEFAULT_LIVENESS_CHECK_ENABLED = true; // Safe with multi-indicator detection
|
|
27
29
|
|
|
28
|
-
|
|
29
|
-
* Validate and normalize agent configuration
|
|
30
|
-
* @param {Object} config - Raw agent configuration
|
|
31
|
-
* @param {Object} options - Agent wrapper options
|
|
32
|
-
* @returns {Object} Normalized configuration
|
|
33
|
-
*/
|
|
34
|
-
function validateAgentConfig(config, options = {}) {
|
|
30
|
+
function applyOutputDefaults(config) {
|
|
35
31
|
// CRITICAL: Enforce JSON schema output by default to prevent parse failures and crashes
|
|
36
|
-
// Agents MUST return structured output so hooks can safely use {{result.*}} templates
|
|
37
32
|
if (!config.outputFormat) {
|
|
38
33
|
config.outputFormat = 'json';
|
|
39
34
|
}
|
|
40
35
|
|
|
41
36
|
// If outputFormat is json but no schema defined, use a minimal default schema
|
|
42
|
-
// This prevents uncaught exceptions when parsing agent output
|
|
43
37
|
if (config.outputFormat === 'json' && !config.jsonSchema) {
|
|
44
38
|
config.jsonSchema = {
|
|
45
39
|
type: 'object',
|
|
@@ -56,99 +50,135 @@ function validateAgentConfig(config, options = {}) {
|
|
|
56
50
|
required: ['summary', 'result'],
|
|
57
51
|
};
|
|
58
52
|
}
|
|
53
|
+
}
|
|
59
54
|
|
|
60
|
-
|
|
61
|
-
// If no model specified, model is null - _selectModel() will use maxModel as default
|
|
62
|
-
let modelConfig;
|
|
55
|
+
function buildModelConfig(config) {
|
|
63
56
|
if (config.modelRules) {
|
|
64
|
-
|
|
65
|
-
} else {
|
|
66
|
-
modelConfig = { type: 'static', model: config.model || null };
|
|
57
|
+
return { type: 'rules', rules: config.modelRules };
|
|
67
58
|
}
|
|
59
|
+
return {
|
|
60
|
+
type: 'static',
|
|
61
|
+
model: config.model || null,
|
|
62
|
+
modelLevel: config.modelLevel || null,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
68
65
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
66
|
+
function applyStrictSchemaDefault(config, settings) {
|
|
67
|
+
if (config.strictSchema === undefined) {
|
|
68
|
+
config.strictSchema = settings.strictSchema !== false; // Default true if not set
|
|
69
|
+
}
|
|
70
|
+
}
|
|
73
71
|
|
|
74
|
-
|
|
75
|
-
|
|
72
|
+
function validateStaticModelConfig(configId, modelConfig, maxModel, minModel) {
|
|
73
|
+
if (modelConfig.model && VALID_MODELS.includes(modelConfig.model)) {
|
|
76
74
|
try {
|
|
77
|
-
validateModelAgainstMax(modelConfig.model, maxModel);
|
|
75
|
+
validateModelAgainstMax(modelConfig.model, maxModel, minModel);
|
|
78
76
|
} catch (error) {
|
|
79
|
-
throw new Error(`Agent "${
|
|
77
|
+
throw new Error(`Agent "${configId}": ${error.message}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (modelConfig.modelLevel && !VALID_LEVELS.includes(modelConfig.modelLevel)) {
|
|
82
|
+
throw new Error(
|
|
83
|
+
`Agent "${configId}": invalid modelLevel "${modelConfig.modelLevel}". ` +
|
|
84
|
+
`Valid: ${VALID_LEVELS.join(', ')}`
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function validateModelRule(configId, rule, maxModel, minModel) {
|
|
90
|
+
if (rule.model && VALID_MODELS.includes(rule.model)) {
|
|
91
|
+
try {
|
|
92
|
+
validateModelAgainstMax(rule.model, maxModel, minModel);
|
|
93
|
+
} catch {
|
|
94
|
+
throw new Error(
|
|
95
|
+
`Agent "${configId}": modelRule "${rule.iterations}" requests "${rule.model}" ` +
|
|
96
|
+
`but maxModel is "${maxModel}"${minModel ? ` and minModel is "${minModel}"` : ''}. ` +
|
|
97
|
+
`Either adjust the rule's model or change maxModel/minModel settings.`
|
|
98
|
+
);
|
|
80
99
|
}
|
|
81
|
-
}
|
|
82
|
-
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (rule.modelLevel && !VALID_LEVELS.includes(rule.modelLevel)) {
|
|
103
|
+
throw new Error(
|
|
104
|
+
`Agent "${configId}": modelRule "${rule.iterations}" has invalid modelLevel ` +
|
|
105
|
+
`"${rule.modelLevel}". Valid: ${VALID_LEVELS.join(', ')}`
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function validateModelConfig(config, modelConfig, maxModel, minModel) {
|
|
111
|
+
if (modelConfig.type === 'static') {
|
|
112
|
+
validateStaticModelConfig(config.id, modelConfig, maxModel, minModel);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (modelConfig.type === 'rules') {
|
|
83
117
|
for (const rule of modelConfig.rules) {
|
|
84
|
-
|
|
85
|
-
try {
|
|
86
|
-
validateModelAgainstMax(rule.model, maxModel);
|
|
87
|
-
} catch {
|
|
88
|
-
throw new Error(
|
|
89
|
-
`Agent "${config.id}": modelRule "${rule.iterations}" requests "${rule.model}" ` +
|
|
90
|
-
`but maxModel is "${maxModel}". Either lower the rule's model or raise maxModel.`
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
118
|
+
validateModelRule(config.id, rule, maxModel, minModel);
|
|
94
119
|
}
|
|
95
120
|
}
|
|
121
|
+
}
|
|
96
122
|
|
|
97
|
-
|
|
98
|
-
// Formats:
|
|
99
|
-
// prompt: "string" -> static
|
|
100
|
-
// prompt: { system: "string" } -> static
|
|
101
|
-
// prompt: { initial: "...", subsequent: "..." } -> iteration 1 vs 2+
|
|
102
|
-
// prompt: { iterations: [...] } -> full control
|
|
103
|
-
let promptConfig = null;
|
|
123
|
+
function buildPromptConfig(config) {
|
|
104
124
|
if (config.prompt?.iterations) {
|
|
105
|
-
|
|
106
|
-
}
|
|
125
|
+
return { type: 'rules', rules: config.prompt.iterations };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (config.prompt?.initial || config.prompt?.subsequent) {
|
|
107
129
|
const rules = [];
|
|
108
130
|
if (config.prompt.initial) rules.push({ match: '1', system: config.prompt.initial });
|
|
109
131
|
if (config.prompt.subsequent) rules.push({ match: '2+', system: config.prompt.subsequent });
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
132
|
+
return { type: 'rules', rules };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (typeof config.prompt === 'string') {
|
|
136
|
+
return { type: 'static', system: config.prompt };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (config.prompt?.system) {
|
|
140
|
+
return { type: 'static', system: config.prompt.system };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (config.prompt) {
|
|
116
144
|
throw new Error(`Agent "${config.id}": invalid prompt format`);
|
|
117
145
|
}
|
|
118
146
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function normalizeTimeout(config) {
|
|
122
151
|
if (config.timeout === undefined || config.timeout === null || config.timeout === '') {
|
|
123
152
|
config.timeout = DEFAULT_TIMEOUT;
|
|
124
153
|
} else {
|
|
125
|
-
// Coerce to number (handles string "0" from template resolution)
|
|
126
154
|
config.timeout = Number(config.timeout);
|
|
127
155
|
}
|
|
156
|
+
|
|
128
157
|
if (!Number.isFinite(config.timeout) || config.timeout < 0) {
|
|
129
158
|
throw new Error(
|
|
130
159
|
`Agent "${config.id}": timeout must be a non-negative number (got ${config.timeout}).`
|
|
131
160
|
);
|
|
132
161
|
}
|
|
133
162
|
|
|
134
|
-
|
|
135
|
-
|
|
163
|
+
return config.timeout;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function buildNormalizedConfig(config, modelConfig, promptConfig) {
|
|
167
|
+
return {
|
|
136
168
|
...config,
|
|
137
169
|
modelConfig,
|
|
138
170
|
promptConfig,
|
|
139
171
|
maxIterations: config.maxIterations || DEFAULT_MAX_ITERATIONS,
|
|
140
|
-
timeout: config.timeout,
|
|
172
|
+
timeout: config.timeout,
|
|
141
173
|
staleDuration: config.staleDuration || DEFAULT_STALE_DURATION_MS,
|
|
142
|
-
enableLivenessCheck: config.enableLivenessCheck ?? DEFAULT_LIVENESS_CHECK_ENABLED,
|
|
174
|
+
enableLivenessCheck: config.enableLivenessCheck ?? DEFAULT_LIVENESS_CHECK_ENABLED,
|
|
143
175
|
};
|
|
176
|
+
}
|
|
144
177
|
|
|
145
|
-
|
|
146
|
-
// Check if this agent executes tasks (vs orchestrator agents that only publish messages)
|
|
178
|
+
function assertTestModeSafety(config, options) {
|
|
147
179
|
const executesTask = config.triggers?.some(
|
|
148
180
|
(trigger) => !trigger.action || trigger.action === 'execute_task'
|
|
149
181
|
);
|
|
150
|
-
|
|
151
|
-
// Accept either mockSpawnFn OR taskRunner as valid mock sources
|
|
152
182
|
const hasMock = options.mockSpawnFn || options.taskRunner;
|
|
153
183
|
|
|
154
184
|
if (options.testMode && !hasMock && executesTask) {
|
|
@@ -157,6 +187,53 @@ function validateAgentConfig(config, options = {}) {
|
|
|
157
187
|
`This would cause real Claude API calls. ABORTING.`
|
|
158
188
|
);
|
|
159
189
|
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Validate and normalize agent configuration
|
|
194
|
+
* @param {Object} config - Raw agent configuration
|
|
195
|
+
* @param {Object} options - Agent wrapper options
|
|
196
|
+
* @returns {Object} Normalized configuration
|
|
197
|
+
*/
|
|
198
|
+
function validateAgentConfig(config, options = {}) {
|
|
199
|
+
applyOutputDefaults(config);
|
|
200
|
+
|
|
201
|
+
// Model configuration: support both static model and dynamic rules
|
|
202
|
+
// If no model specified, model is null - _selectModel() will use provider defaults
|
|
203
|
+
const modelConfig = buildModelConfig(config);
|
|
204
|
+
|
|
205
|
+
// COST CEILING/FLOOR ENFORCEMENT: Validate model(s) against maxModel and minModel at config time
|
|
206
|
+
// Catches violations EARLY (config load) instead of at runtime (iteration N)
|
|
207
|
+
const settings = loadSettings();
|
|
208
|
+
const maxModel = settings.maxModel || 'sonnet';
|
|
209
|
+
const minModel = settings.minModel || null;
|
|
210
|
+
|
|
211
|
+
// STRICT SCHEMA PROPAGATION: Issue #52 fix
|
|
212
|
+
// If agent config doesn't explicitly set strictSchema, inherit from global settings
|
|
213
|
+
// This allows `zeroshot settings set strictSchema false` to actually affect agents
|
|
214
|
+
// Default behavior: strictSchema=true (reliable JSON output, no streaming)
|
|
215
|
+
applyStrictSchemaDefault(config, settings);
|
|
216
|
+
validateModelConfig(config, modelConfig, maxModel, minModel);
|
|
217
|
+
|
|
218
|
+
// Prompt configuration: support static prompt OR iteration-based rules
|
|
219
|
+
// Formats:
|
|
220
|
+
// prompt: "string" -> static
|
|
221
|
+
// prompt: { system: "string" } -> static
|
|
222
|
+
// prompt: { initial: "...", subsequent: "..." } -> iteration 1 vs 2+
|
|
223
|
+
// prompt: { iterations: [...] } -> full control
|
|
224
|
+
const promptConfig = buildPromptConfig(config);
|
|
225
|
+
|
|
226
|
+
// Default timeout to 0 (no timeout) if not specified
|
|
227
|
+
// Use positive number for timeout in milliseconds
|
|
228
|
+
// ROBUST: Handle undefined, null, AND string values from template resolution
|
|
229
|
+
normalizeTimeout(config);
|
|
230
|
+
|
|
231
|
+
// Build normalized config
|
|
232
|
+
const normalizedConfig = buildNormalizedConfig(config, modelConfig, promptConfig);
|
|
233
|
+
|
|
234
|
+
// SAFETY: In test mode, verify mock is provided for agents that execute tasks
|
|
235
|
+
// Check if this agent executes tasks (vs orchestrator agents that only publish messages)
|
|
236
|
+
assertTestModeSafety(config, options);
|
|
160
237
|
|
|
161
238
|
return normalizedConfig;
|
|
162
239
|
}
|