coverme-scanner 1.0.23 → 1.0.25
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/.claude/commands/coverme.md +38 -4
- package/dist/cli/index.js +67 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +9 -0
- package/dist/cli/init.js.map +1 -1
- package/dist/templates/agents.example.json +16 -0
- package/dist/templates/agents.schema.json +75 -0
- package/package.json +1 -1
- package/src/cli/index.ts +78 -1
- package/src/cli/init.ts +9 -0
- package/src/templates/agents.example.json +16 -0
- package/src/templates/agents.schema.json +75 -0
|
@@ -18,12 +18,43 @@ Execute ALL phases automatically. Do NOT stop until the HTML report is open.
|
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
-
## Phase
|
|
21
|
+
## Phase 0: Load Custom Agents (if exists)
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
**FIRST**, check if `.coverme/agents.json` exists:
|
|
24
|
+
```bash
|
|
25
|
+
cat .coverme/agents.json 2>/dev/null || echo "NO_CUSTOM_AGENTS"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
If the file exists, it will look like this:
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"agents": [
|
|
32
|
+
{ "name": "John", "task": "Check .env files for secrets" },
|
|
33
|
+
{ "name": "Sarah", "task": "Find regex patterns vulnerable to ReDoS" }
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
For EACH custom agent, launch it in Phase 1 alongside the built-in agents. The agent should:
|
|
39
|
+
1. Do what the `task` says
|
|
40
|
+
2. Output findings with ID prefix based on the agent name (e.g., JOHN-001, SARAH-001)
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Phase 1: Discovery (10+ parallel agents)
|
|
45
|
+
|
|
46
|
+
Launch ALL built-in agents + custom discovery agents IN PARALLEL using the Task tool with `run_in_background: true`:
|
|
24
47
|
|
|
25
48
|
**IMPORTANT**: Set `run_in_background: true` on ALL Task tool calls to run agents in parallel without blocking.
|
|
26
49
|
|
|
50
|
+
### Custom Agents (from .coverme/agents.json)
|
|
51
|
+
If custom agents were loaded in Phase 0, launch each one as a Task with their specific task.
|
|
52
|
+
|
|
53
|
+
Example: If agents.json has `{"name": "John", "task": "Check .env files"}`, launch:
|
|
54
|
+
```
|
|
55
|
+
Task: "John: Check .env files for secrets and sensitive configuration. Output findings as JSON with id prefix JOHN-XXX"
|
|
56
|
+
```
|
|
57
|
+
|
|
27
58
|
### Agent 1: Security Scanner (Core)
|
|
28
59
|
```
|
|
29
60
|
Scan for OWASP Top 10 and common vulnerabilities:
|
|
@@ -427,11 +458,14 @@ Output JSON: [{id: "TEST-XXX", title, severity, category: "testing", file, line,
|
|
|
427
458
|
|
|
428
459
|
---
|
|
429
460
|
|
|
430
|
-
## Phase 2: Cross-Validation (3 parallel validators)
|
|
461
|
+
## Phase 2: Cross-Validation (3+ parallel validators)
|
|
431
462
|
|
|
432
463
|
Wait for all Phase 1 background agents to complete using `AgentOutputTool`.
|
|
433
464
|
|
|
434
|
-
Then launch 3 validators IN PARALLEL with `run_in_background: true`:
|
|
465
|
+
Then launch 3 built-in validators + custom validation agents IN PARALLEL with `run_in_background: true`:
|
|
466
|
+
|
|
467
|
+
### Custom Validators (from .coverme/agents.json)
|
|
468
|
+
If custom agents with `"phase": "validation"` were loaded in Phase 0, launch them here in parallel with the built-in validators.
|
|
435
469
|
|
|
436
470
|
### Validator A: False Positive Hunter
|
|
437
471
|
```
|
package/dist/cli/index.js
CHANGED
|
@@ -38,5 +38,72 @@ program
|
|
|
38
38
|
.action(async (jsonFile, options) => {
|
|
39
39
|
await (0, index_js_1.generateReport)(jsonFile, options.output, options.format || 'pdf');
|
|
40
40
|
});
|
|
41
|
+
// Agent management commands
|
|
42
|
+
const agentCmd = program
|
|
43
|
+
.command('agent')
|
|
44
|
+
.description('Manage custom agents');
|
|
45
|
+
agentCmd
|
|
46
|
+
.command('add')
|
|
47
|
+
.description('Add a new custom agent')
|
|
48
|
+
.argument('<name>', 'Agent name (e.g., "John")')
|
|
49
|
+
.argument('<task>', 'What the agent should do')
|
|
50
|
+
.action((name, task) => {
|
|
51
|
+
const covermeDir = (0, path_1.join)(process.cwd(), '.coverme');
|
|
52
|
+
const agentsPath = (0, path_1.join)(covermeDir, 'agents.json');
|
|
53
|
+
if (!(0, fs_1.existsSync)(covermeDir)) {
|
|
54
|
+
(0, fs_1.mkdirSync)(covermeDir, { recursive: true });
|
|
55
|
+
}
|
|
56
|
+
let agents = { agents: [] };
|
|
57
|
+
if ((0, fs_1.existsSync)(agentsPath)) {
|
|
58
|
+
agents = JSON.parse((0, fs_1.readFileSync)(agentsPath, 'utf-8'));
|
|
59
|
+
if (!agents.agents)
|
|
60
|
+
agents.agents = [];
|
|
61
|
+
}
|
|
62
|
+
agents.agents.push({ name, task });
|
|
63
|
+
(0, fs_1.writeFileSync)(agentsPath, JSON.stringify(agents, null, 2));
|
|
64
|
+
console.log(`Added agent "${name}"`);
|
|
65
|
+
console.log(`Task: ${task}`);
|
|
66
|
+
});
|
|
67
|
+
agentCmd
|
|
68
|
+
.command('list')
|
|
69
|
+
.description('List all custom agents')
|
|
70
|
+
.action(() => {
|
|
71
|
+
const agentsPath = (0, path_1.join)(process.cwd(), '.coverme', 'agents.json');
|
|
72
|
+
if (!(0, fs_1.existsSync)(agentsPath)) {
|
|
73
|
+
console.log('No custom agents. Add one with: coverme agent add "John" "Check .env files for secrets"');
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const agents = JSON.parse((0, fs_1.readFileSync)(agentsPath, 'utf-8'));
|
|
77
|
+
if (!agents.agents || agents.agents.length === 0) {
|
|
78
|
+
console.log('No custom agents. Add one with: coverme agent add "John" "Check .env files for secrets"');
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
console.log('\nCustom Agents:\n');
|
|
82
|
+
agents.agents.forEach((agent, i) => {
|
|
83
|
+
console.log(` ${i + 1}. ${agent.name}`);
|
|
84
|
+
console.log(` Task: ${agent.task}`);
|
|
85
|
+
console.log('');
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
agentCmd
|
|
89
|
+
.command('remove')
|
|
90
|
+
.description('Remove a custom agent')
|
|
91
|
+
.argument('<name>', 'Agent name to remove')
|
|
92
|
+
.action((name) => {
|
|
93
|
+
const agentsPath = (0, path_1.join)(process.cwd(), '.coverme', 'agents.json');
|
|
94
|
+
if (!(0, fs_1.existsSync)(agentsPath)) {
|
|
95
|
+
console.error('No agents.json found');
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const agents = JSON.parse((0, fs_1.readFileSync)(agentsPath, 'utf-8'));
|
|
99
|
+
const idx = agents.agents.findIndex((a) => a.name.toLowerCase() === name.toLowerCase());
|
|
100
|
+
if (idx === -1) {
|
|
101
|
+
console.error(`Agent "${name}" not found`);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const removed = agents.agents.splice(idx, 1)[0];
|
|
105
|
+
(0, fs_1.writeFileSync)(agentsPath, JSON.stringify(agents, null, 2));
|
|
106
|
+
console.log(`Removed agent "${removed.name}"`);
|
|
107
|
+
});
|
|
41
108
|
program.parse();
|
|
42
109
|
//# sourceMappingURL=index.js.map
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,uCAAiC;AACjC,uCAAiC;AACjC,iDAAoD;AACpD,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/init.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAIA,UAAU,WAAW;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAihBD,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAIA,UAAU,WAAW;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAihBD,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAwI9D"}
|
package/dist/cli/init.js
CHANGED
|
@@ -675,6 +675,15 @@ Reports saved to: .coverme/
|
|
|
675
675
|
- report_YYYY-MM-DD_HH-MM-SS.html
|
|
676
676
|
- scan_YYYY-MM-DD_HH-MM-SS.json
|
|
677
677
|
|
|
678
|
+
Custom Agents:
|
|
679
|
+
Add your own experts to the scan:
|
|
680
|
+
|
|
681
|
+
coverme agent add "John" "Check all .env files for exposed secrets"
|
|
682
|
+
coverme agent add "Sarah" "Find regex patterns vulnerable to ReDoS"
|
|
683
|
+
|
|
684
|
+
List agents: coverme agent list
|
|
685
|
+
Remove agent: coverme agent remove "John"
|
|
686
|
+
|
|
678
687
|
The .coverme/ folder is automatically added to .gitignore
|
|
679
688
|
|
|
680
689
|
================================================================================
|
package/dist/cli/init.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuhBA,
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agents": [
|
|
3
|
+
{
|
|
4
|
+
"name": "John",
|
|
5
|
+
"task": "Check all .env files and environment variables for exposed secrets, API keys, and sensitive configuration"
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
"name": "Sarah",
|
|
9
|
+
"task": "Find all regex patterns in the code and check if any are vulnerable to ReDoS attacks"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"name": "DevOps Expert",
|
|
13
|
+
"task": "Review Dockerfile, docker-compose, and Kubernetes configs for security misconfigurations"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "CoverMe Custom Agents Configuration",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"properties": {
|
|
6
|
+
"customAgents": {
|
|
7
|
+
"type": "array",
|
|
8
|
+
"description": "List of custom agents to add to the scan",
|
|
9
|
+
"items": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"required": ["id", "name", "phase", "prompt"],
|
|
12
|
+
"properties": {
|
|
13
|
+
"id": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "Unique identifier for the agent (lowercase, no spaces)",
|
|
16
|
+
"pattern": "^[a-z][a-z0-9-]*$"
|
|
17
|
+
},
|
|
18
|
+
"name": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"description": "Display name for the agent"
|
|
21
|
+
},
|
|
22
|
+
"phase": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"enum": ["discovery", "validation", "consensus"],
|
|
25
|
+
"description": "Which phase this agent runs in"
|
|
26
|
+
},
|
|
27
|
+
"priority": {
|
|
28
|
+
"type": "integer",
|
|
29
|
+
"minimum": 1,
|
|
30
|
+
"maximum": 10,
|
|
31
|
+
"default": 5,
|
|
32
|
+
"description": "Priority within phase (1=first, 10=last)"
|
|
33
|
+
},
|
|
34
|
+
"idPrefix": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"pattern": "^[A-Z]{2,6}$",
|
|
37
|
+
"description": "Prefix for finding IDs (e.g., 'DROR' -> DROR-001)"
|
|
38
|
+
},
|
|
39
|
+
"prompt": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"description": "The prompt/instructions for this agent"
|
|
42
|
+
},
|
|
43
|
+
"enabled": {
|
|
44
|
+
"type": "boolean",
|
|
45
|
+
"default": true,
|
|
46
|
+
"description": "Whether this agent is active"
|
|
47
|
+
},
|
|
48
|
+
"timeout": {
|
|
49
|
+
"type": "integer",
|
|
50
|
+
"default": 120000,
|
|
51
|
+
"description": "Timeout in milliseconds"
|
|
52
|
+
},
|
|
53
|
+
"runInBackground": {
|
|
54
|
+
"type": "boolean",
|
|
55
|
+
"default": true,
|
|
56
|
+
"description": "Run this agent in background"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"settings": {
|
|
62
|
+
"type": "object",
|
|
63
|
+
"properties": {
|
|
64
|
+
"runCustomAgentsInParallel": {
|
|
65
|
+
"type": "boolean",
|
|
66
|
+
"default": true
|
|
67
|
+
},
|
|
68
|
+
"customAgentTimeout": {
|
|
69
|
+
"type": "integer",
|
|
70
|
+
"default": 120000
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
package/package.json
CHANGED
package/src/cli/index.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { Command } from 'commander';
|
|
|
4
4
|
import { init } from './init.js';
|
|
5
5
|
import { scan } from './scan.js';
|
|
6
6
|
import { generateReport } from '../report/index.js';
|
|
7
|
-
import { readFileSync } from 'fs';
|
|
7
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync } from 'fs';
|
|
8
8
|
import { join } from 'path';
|
|
9
9
|
|
|
10
10
|
const pkg = JSON.parse(readFileSync(join(__dirname, '..', '..', 'package.json'), 'utf-8'));
|
|
@@ -44,4 +44,81 @@ program
|
|
|
44
44
|
await generateReport(jsonFile, options.output, options.format || 'pdf');
|
|
45
45
|
});
|
|
46
46
|
|
|
47
|
+
// Agent management commands
|
|
48
|
+
const agentCmd = program
|
|
49
|
+
.command('agent')
|
|
50
|
+
.description('Manage custom agents');
|
|
51
|
+
|
|
52
|
+
agentCmd
|
|
53
|
+
.command('add')
|
|
54
|
+
.description('Add a new custom agent')
|
|
55
|
+
.argument('<name>', 'Agent name (e.g., "John")')
|
|
56
|
+
.argument('<task>', 'What the agent should do')
|
|
57
|
+
.action((name: string, task: string) => {
|
|
58
|
+
const covermeDir = join(process.cwd(), '.coverme');
|
|
59
|
+
const agentsPath = join(covermeDir, 'agents.json');
|
|
60
|
+
|
|
61
|
+
if (!existsSync(covermeDir)) {
|
|
62
|
+
mkdirSync(covermeDir, { recursive: true });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
let agents: any = { agents: [] };
|
|
66
|
+
if (existsSync(agentsPath)) {
|
|
67
|
+
agents = JSON.parse(readFileSync(agentsPath, 'utf-8'));
|
|
68
|
+
if (!agents.agents) agents.agents = [];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
agents.agents.push({ name, task });
|
|
72
|
+
writeFileSync(agentsPath, JSON.stringify(agents, null, 2));
|
|
73
|
+
console.log(`Added agent "${name}"`);
|
|
74
|
+
console.log(`Task: ${task}`);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
agentCmd
|
|
78
|
+
.command('list')
|
|
79
|
+
.description('List all custom agents')
|
|
80
|
+
.action(() => {
|
|
81
|
+
const agentsPath = join(process.cwd(), '.coverme', 'agents.json');
|
|
82
|
+
if (!existsSync(agentsPath)) {
|
|
83
|
+
console.log('No custom agents. Add one with: coverme agent add "John" "Check .env files for secrets"');
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const agents = JSON.parse(readFileSync(agentsPath, 'utf-8'));
|
|
88
|
+
if (!agents.agents || agents.agents.length === 0) {
|
|
89
|
+
console.log('No custom agents. Add one with: coverme agent add "John" "Check .env files for secrets"');
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
console.log('\nCustom Agents:\n');
|
|
94
|
+
agents.agents.forEach((agent: any, i: number) => {
|
|
95
|
+
console.log(` ${i + 1}. ${agent.name}`);
|
|
96
|
+
console.log(` Task: ${agent.task}`);
|
|
97
|
+
console.log('');
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
agentCmd
|
|
102
|
+
.command('remove')
|
|
103
|
+
.description('Remove a custom agent')
|
|
104
|
+
.argument('<name>', 'Agent name to remove')
|
|
105
|
+
.action((name: string) => {
|
|
106
|
+
const agentsPath = join(process.cwd(), '.coverme', 'agents.json');
|
|
107
|
+
if (!existsSync(agentsPath)) {
|
|
108
|
+
console.error('No agents.json found');
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const agents = JSON.parse(readFileSync(agentsPath, 'utf-8'));
|
|
113
|
+
const idx = agents.agents.findIndex((a: any) => a.name.toLowerCase() === name.toLowerCase());
|
|
114
|
+
if (idx === -1) {
|
|
115
|
+
console.error(`Agent "${name}" not found`);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const removed = agents.agents.splice(idx, 1)[0];
|
|
120
|
+
writeFileSync(agentsPath, JSON.stringify(agents, null, 2));
|
|
121
|
+
console.log(`Removed agent "${removed.name}"`);
|
|
122
|
+
});
|
|
123
|
+
|
|
47
124
|
program.parse();
|
package/src/cli/init.ts
CHANGED
|
@@ -656,6 +656,15 @@ Reports saved to: .coverme/
|
|
|
656
656
|
- report_YYYY-MM-DD_HH-MM-SS.html
|
|
657
657
|
- scan_YYYY-MM-DD_HH-MM-SS.json
|
|
658
658
|
|
|
659
|
+
Custom Agents:
|
|
660
|
+
Add your own experts to the scan:
|
|
661
|
+
|
|
662
|
+
coverme agent add "John" "Check all .env files for exposed secrets"
|
|
663
|
+
coverme agent add "Sarah" "Find regex patterns vulnerable to ReDoS"
|
|
664
|
+
|
|
665
|
+
List agents: coverme agent list
|
|
666
|
+
Remove agent: coverme agent remove "John"
|
|
667
|
+
|
|
659
668
|
The .coverme/ folder is automatically added to .gitignore
|
|
660
669
|
|
|
661
670
|
================================================================================
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agents": [
|
|
3
|
+
{
|
|
4
|
+
"name": "John",
|
|
5
|
+
"task": "Check all .env files and environment variables for exposed secrets, API keys, and sensitive configuration"
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
"name": "Sarah",
|
|
9
|
+
"task": "Find all regex patterns in the code and check if any are vulnerable to ReDoS attacks"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"name": "DevOps Expert",
|
|
13
|
+
"task": "Review Dockerfile, docker-compose, and Kubernetes configs for security misconfigurations"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "CoverMe Custom Agents Configuration",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"properties": {
|
|
6
|
+
"customAgents": {
|
|
7
|
+
"type": "array",
|
|
8
|
+
"description": "List of custom agents to add to the scan",
|
|
9
|
+
"items": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"required": ["id", "name", "phase", "prompt"],
|
|
12
|
+
"properties": {
|
|
13
|
+
"id": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "Unique identifier for the agent (lowercase, no spaces)",
|
|
16
|
+
"pattern": "^[a-z][a-z0-9-]*$"
|
|
17
|
+
},
|
|
18
|
+
"name": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"description": "Display name for the agent"
|
|
21
|
+
},
|
|
22
|
+
"phase": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"enum": ["discovery", "validation", "consensus"],
|
|
25
|
+
"description": "Which phase this agent runs in"
|
|
26
|
+
},
|
|
27
|
+
"priority": {
|
|
28
|
+
"type": "integer",
|
|
29
|
+
"minimum": 1,
|
|
30
|
+
"maximum": 10,
|
|
31
|
+
"default": 5,
|
|
32
|
+
"description": "Priority within phase (1=first, 10=last)"
|
|
33
|
+
},
|
|
34
|
+
"idPrefix": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"pattern": "^[A-Z]{2,6}$",
|
|
37
|
+
"description": "Prefix for finding IDs (e.g., 'DROR' -> DROR-001)"
|
|
38
|
+
},
|
|
39
|
+
"prompt": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"description": "The prompt/instructions for this agent"
|
|
42
|
+
},
|
|
43
|
+
"enabled": {
|
|
44
|
+
"type": "boolean",
|
|
45
|
+
"default": true,
|
|
46
|
+
"description": "Whether this agent is active"
|
|
47
|
+
},
|
|
48
|
+
"timeout": {
|
|
49
|
+
"type": "integer",
|
|
50
|
+
"default": 120000,
|
|
51
|
+
"description": "Timeout in milliseconds"
|
|
52
|
+
},
|
|
53
|
+
"runInBackground": {
|
|
54
|
+
"type": "boolean",
|
|
55
|
+
"default": true,
|
|
56
|
+
"description": "Run this agent in background"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"settings": {
|
|
62
|
+
"type": "object",
|
|
63
|
+
"properties": {
|
|
64
|
+
"runCustomAgentsInParallel": {
|
|
65
|
+
"type": "boolean",
|
|
66
|
+
"default": true
|
|
67
|
+
},
|
|
68
|
+
"customAgentTimeout": {
|
|
69
|
+
"type": "integer",
|
|
70
|
+
"default": 120000
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|