claude-flow-novice 2.14.16 → 2.14.17

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.
@@ -15,7 +15,7 @@ Execute CFN Loop using CLI spawning for maximum cost savings (95-98% vs Task too
15
15
  ## What is CLI Mode?
16
16
 
17
17
  **CLI Mode Architecture v3.0 (Enhanced):**
18
- - Main Chat spawns **single coordinator agent** via Task()
18
+ - Main Chat spawns **single coordinator agent**
19
19
  - Enhanced coordinator spawns **all workers via CLI** with protocol compliance
20
20
  - CLI agents use **Z.ai custom routing** (when enabled)
21
21
  - **Real-time monitoring** with automatic recovery from stuck agents
@@ -77,23 +77,121 @@ Savings: 64% with custom routing, 95-98% vs all-Task
77
77
  | Standard | ≥0.75 | ≥0.90 | 10 | 3-4 | Production features |
78
78
  | Enterprise | ≥0.85 | ≥0.95 | 15 | 5 | Security, compliance, critical systems |
79
79
 
80
- ## 🚨 CRITICAL EXECUTION INSTRUCTIONS
80
+ ## How CLI Mode Works
81
81
 
82
- **YOU ARE MAIN CHAT. YOU SPAWN ONLY THE cfn-v3-coordinator AGENT.**
82
+ 1. **Main Chat** spawns a single `cfn-v3-coordinator` agent
83
+ 2. **Coordinator** orchestrates the entire CFN Loop workflow
84
+ 3. **Loop 3** agents implement the solution and validate against quality gates
85
+ 4. **Loop 2** agents review and provide validation feedback
86
+ 5. **Product Owner** makes the final decision on deliverables
87
+ 6. **Background execution** with Redis coordination for scalability
83
88
 
84
- **DO NOT spawn Loop 3 agents (backend-dev, researcher, etc.)**
85
- **DO NOT spawn Loop 2 agents (reviewer, tester, etc.)**
86
- **DO NOT spawn product-owner**
89
+ The coordinator handles all agent spawning internally using optimized CLI processes.
87
90
 
88
- The coordinator handles ALL agent spawning internally via enhanced CLI mode v3.0.
91
+ ## CLI Mode Benefits
92
+
93
+ **Cost Savings:**
94
+ - 64% savings with Z.ai routing vs all-Anthropic
95
+ - 95-98% savings vs Task tool spawning
96
+ - Scales linearly with iterations (Task mode scales exponentially)
97
+
98
+ **Production Features v3.0:**
99
+ - Background execution (no timeout issues)
100
+ - Redis state persistence (crash recovery)
101
+ - Zero-token waiting (BLPOP blocks without API calls)
102
+ - Web portal visibility (http://localhost:3000)
103
+ - **Enhanced monitoring**: Real-time agent progress tracking
104
+ - **Automatic recovery**: Dead process cleanup and agent restart
105
+ - **Protocol compliance**: Prevents "consensus on vapor" anti-patterns
106
+ - **Progress visibility**: Detailed reports with timestamps and health status
107
+
108
+ **Performance:**
109
+ - Parallel agent spawning (no sequential bottleneck)
110
+ - Instant wake-up (<100ms latency)
111
+ - Scalable (10+ agents, indefinite cycles)
112
+
113
+ ## When to Use CLI Mode
114
+
115
+ **Use CLI Mode for:**
116
+ - ✅ Production features
117
+ - ✅ Long-running tasks (>10 min)
118
+ - ✅ Multi-iteration workflows
119
+ - ✅ Cost-sensitive projects
120
+ - ✅ Background execution
121
+
122
+ **Use Task Mode for:**
123
+ - Debugging (full visibility needed)
124
+ - Learning CFN Loop workflow
125
+ - Short prototypes (<5 min)
126
+ - Single-iteration tasks
127
+
128
+ ## Troubleshooting
129
+
130
+ **Custom routing not working:**
131
+ ```bash
132
+ /switch-api status # Check current provider
133
+ /switch-api zai # Enable Z.ai routing
134
+ ```
135
+
136
+ **Coordinator timeout:**
137
+ - Expected for long tasks (>10 min)
138
+ - Check web portal for progress: http://localhost:3000
139
+ - Query Redis: `redis-cli HGETALL "cfn_loop:task:$TASK_ID:context"`
140
+
141
+ **No deliverables created:**
142
+ - Orchestrator validates deliverables before PROCEED
143
+ - Will force ITERATE if git diff shows zero changes
144
+ - Check coordinator output for validation failures
145
+
146
+ **Web Portal Access:**
147
+ - Monitor real-time agent progress at http://localhost:3000
148
+ - View detailed execution logs and health status
149
+ - Track iteration progress and confidence scores
150
+
151
+ ## Usage Examples
152
+
153
+ **Simple API Development:**
154
+ ```bash
155
+ /cfn-loop-cli "Build REST API with user authentication"
156
+ ```
157
+
158
+ **Complex Feature with High Quality Requirements:**
159
+ ```bash
160
+ /cfn-loop-cli "Implement payment processing with PCI compliance" --mode=enterprise --max-iterations=15
161
+ ```
162
+
163
+ **Quick Prototype:**
164
+ ```bash
165
+ /cfn-loop-cli "Build MVP landing page" --mode=mvp
166
+ ```
167
+
168
+ **Infrastructure Deployment:**
169
+ ```bash
170
+ /cfn-loop-cli "Set up CI/CD pipeline for microservices"
171
+ ```
172
+
173
+ ## Related Commands
174
+
175
+ - **Task Mode**: `/cfn-loop-task` (debugging, full visibility)
176
+ - **Frontend**: `/cfn-loop-frontend` (visual iteration workflow)
177
+ - **Documentation**: `/cfn-loop-document` (generate docs)
178
+
179
+ ## Related Documentation
180
+
181
+ - Task Mode Guide: `.claude/commands/cfn/CFN_LOOP_TASK_MODE.md`
182
+ - Coordinator Parameters: `.claude/commands/cfn/CFN_COORDINATOR_PARAMETERS.md`
183
+ - Redis Coordination: `.claude/skills/cfn-redis-coordination/SKILL.md`
184
+ - Orchestration: `.claude/skills/cfn-loop-orchestration/SKILL.md`
89
185
 
90
186
  ---
91
187
 
92
- ### Execute This Task() Call:
188
+ ## 🚨 EXECUTION INSTRUCTIONS (Internal Use)
189
+
190
+ **Main Chat: Execute this Task() call after slash command processing:**
93
191
 
94
192
  ```javascript
95
193
  Task("cfn-v3-coordinator", `
96
- CFN LOOP CLI MODE - ENHANCED PRODUCTION EXECUTION v3.0
194
+ CFN LOOP CLI MODE v3.0 - PRODUCTION EXECUTION WITH ENHANCED MONITORING
97
195
 
98
196
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
99
197
  TASK SPECIFICATION
@@ -103,6 +201,8 @@ Task("cfn-v3-coordinator", `
103
201
  Task ID: cfn-cli-$(date +%s%N | tail -c 7)-${RANDOM}
104
202
  Mode: ${mode.toUpperCase()}
105
203
 
204
+ Enhanced Monitoring: Real-time agent tracking, automatic recovery, protocol compliance
205
+
106
206
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
107
207
  SUCCESS CRITERIA
108
208
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
@@ -129,6 +229,7 @@ Task("cfn-v3-coordinator", `
129
229
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
130
230
 
131
231
  Mode: ${mode.toUpperCase()}
232
+ Enhanced Features: Real-time monitoring, automatic recovery, protocol compliance
132
233
 
133
234
  Loop 3 Agents (Implementation) - SELECT BASED ON TASK:
134
235
  Examples:
@@ -145,10 +246,10 @@ Task("cfn-v3-coordinator", `
145
246
  Product Owner: product-owner
146
247
 
147
248
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
148
- ENHANCED EXECUTION INSTRUCTIONS v3.0
249
+ EXECUTION INSTRUCTIONS (Enhanced v3.0)
149
250
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
150
251
 
151
- 1. INVOKE ENHANCED ORCHESTRATOR (CLI spawning v3.0):
252
+ 1. INVOKE ENHANCED ORCHESTRATOR (CLI spawning with monitoring):
152
253
 
153
254
  TASK_ID="cfn-cli-$(date +%s%N | tail -c 7)-${RANDOM}"
154
255
  MODE="${mode}"
@@ -164,16 +265,15 @@ Task("cfn-v3-coordinator", `
164
265
  --max-iterations ${maxIterations}
165
266
 
166
267
  2. ENHANCED ORCHESTRATOR HANDLES v3.0:
167
- - **Real-time monitoring** with automatic stuck agent recovery
168
- - **Process health checking** and dead process cleanup
169
- - **Protocol compliance** preventing "consensus on vapor" anti-patterns
170
- - **Progress visibility** with detailed timestamped reports
171
- - Spawns all agents via enhanced CLI (background)
172
- - Loop 3: Gate check (≥threshold) → PASS/ITERATE
173
- - Loop 2: Consensus check (≥threshold) COMPLETE/ITERATE
174
- - Product Owner: PROCEED/ITERATE/ABORT decision
175
- - Git commit/push on PROCEED
176
- - Returns structured result to Main Chat
268
+ - Spawns all agents via CLI (background) with protocol compliance
269
+ - Real-time agent progress monitoring and stuck detection
270
+ - Automatic recovery from dead processes
271
+ - Enhanced context validation prevents "consensus on vapor"
272
+ - Loop 3: Gate check (≥threshold) → PASS/ITERATE with health verification
273
+ - Loop 2: Consensus check (≥threshold) → COMPLETE/ITERATE
274
+ - Product Owner: PROCEED/ITERATE/ABORT decision with deliverable validation
275
+ - Git commit/push on PROCEED
276
+ - Returns structured result to Main Chat
177
277
 
178
278
  3. RETURN STRUCTURED RESULT:
179
279
  {
@@ -186,90 +286,26 @@ Task("cfn-v3-coordinator", `
186
286
  "pending": [...]
187
287
  },
188
288
  "deliverables": [...],
289
+ "enhancedMonitoring": {
290
+ "agentHealth": "healthy|recovered",
291
+ "processRecovery": true,
292
+ "protocolCompliance": true
293
+ },
189
294
  "recommendations": [...]
190
295
  }
191
296
 
192
297
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
193
- CRITICAL RULES
298
+ CRITICAL ENHANCED RULES v3.0
194
299
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
195
300
 
196
- - DO NOT spawn agents with Task() - orchestrator uses enhanced CLI
197
- - ALL agents run in background via npx claude-flow-novice
198
- - USE Redis BLPOP for loop dependencies
199
- - AGENTS use Z.ai routing automatically (when enabled)
200
- - ORCHESTRATOR provides real-time monitoring and recovery
201
- - RETURN structured result when complete
301
+ - USE enhanced orchestration script with real-time monitoring
302
+ - ALL agents run in background via npx claude-flow-novice (enhanced v3.0)
303
+ - USE Redis BLPOP for loop dependencies (zero-token coordination)
304
+ - AGENTS use Z.ai routing automatically (when enabled)
305
+ - ENFORCE protocol compliance (prevent "consensus on vapor")
306
+ - MONITOR agent health and auto-recover stuck processes
307
+ - ✅ RETURN structured result with enhanced monitoring data
202
308
  `, "cfn-v3-coordinator")
203
309
  ```
204
310
 
205
- ## CLI Mode Benefits
206
-
207
- **Cost Savings:**
208
- - 64% savings with Z.ai routing vs all-Anthropic
209
- - 95-98% savings vs Task tool spawning
210
- - Scales linearly with iterations (Task mode scales exponentially)
211
-
212
- **Production Features v3.0:**
213
- - Background execution (no timeout issues)
214
- - Redis state persistence (crash recovery)
215
- - Zero-token waiting (BLPOP blocks without API calls)
216
- - Web portal visibility (http://localhost:3000)
217
- - **Enhanced monitoring**: Real-time agent progress tracking
218
- - **Automatic recovery**: Dead process cleanup and agent restart
219
- - **Protocol compliance**: Prevents "consensus on vapor" anti-patterns
220
- - **Progress visibility**: Detailed reports with timestamps and health status
221
-
222
- **Performance:**
223
- - Parallel agent spawning (no sequential bottleneck)
224
- - Instant wake-up (<100ms latency)
225
- - Scalable (10+ agents, indefinite cycles)
226
-
227
- ## When to Use CLI Mode
228
-
229
- **Use CLI Mode for:**
230
- - ✅ Production features
231
- - ✅ Long-running tasks (>10 min)
232
- - ✅ Multi-iteration workflows
233
- - ✅ Cost-sensitive projects
234
- - ✅ Background execution
235
-
236
- **Use Task Mode for:**
237
- - Debugging (full visibility needed)
238
- - Learning CFN Loop workflow
239
- - Short prototypes (<5 min)
240
- - Single-iteration tasks
241
-
242
- ## Troubleshooting
243
-
244
- **Custom routing not working:**
245
- ```bash
246
- /switch-api status # Check current provider
247
- /switch-api zai # Enable Z.ai routing
248
- ```
249
-
250
- **Coordinator timeout:**
251
- - Expected for long tasks (>10 min)
252
- - Check web portal for progress: http://localhost:3000
253
- - Query Redis: `redis-cli HGETALL "cfn_loop:task:$TASK_ID:context"`
254
-
255
- **No deliverables created:**
256
- - Orchestrator validates deliverables before PROCEED
257
- - Will force ITERATE if git diff shows zero changes
258
- - Check coordinator output for validation failures
259
-
260
- ## Related Commands
261
-
262
- - **Task Mode**: `/cfn-loop-task` (debugging, full visibility)
263
- - **Frontend**: `/cfn-loop-frontend` (visual iteration workflow)
264
- - **Documentation**: `/cfn-loop-document` (generate docs)
265
-
266
- ## Related Documentation
267
-
268
- - Task Mode Guide: `.claude/commands/cfn/CFN_LOOP_TASK_MODE.md`
269
- - Coordinator Parameters: `.claude/commands/cfn/CFN_COORDINATOR_PARAMETERS.md`
270
- - Redis Coordination: `.claude/skills/cfn-redis-coordination/SKILL.md`
271
- - Orchestration: `.claude/skills/cfn-loop-orchestration/SKILL.md`
272
-
273
- ---
274
-
275
- **Version:** 1.0.0 (2025-10-31) - CLI mode: production execution, cost-optimized, background processing
311
+ **Version:** 3.0.0 (2025-11-05) - Enhanced CLI mode: production execution with real-time monitoring, automatic recovery, and protocol compliance
@@ -1,145 +1,12 @@
1
- "use strict";
2
1
  /**
3
2
  * Dynamic Agent Loader - Reads agent definitions from .claude/agents/ directory
4
3
  * Single source of truth for agent types in the system
5
- */ var __awaiter = this && this.__awaiter || function(thisArg, _arguments, P, generator) {
6
- function adopt(value) {
7
- return value instanceof P ? value : new P(function(resolve) {
8
- resolve(value);
9
- });
10
- }
11
- return new (P || (P = Promise))(function(resolve, reject) {
12
- function fulfilled(value) {
13
- try {
14
- step(generator.next(value));
15
- } catch (e) {
16
- reject(e);
17
- }
18
- }
19
- function rejected(value) {
20
- try {
21
- step(generator["throw"](value));
22
- } catch (e) {
23
- reject(e);
24
- }
25
- }
26
- function step(result) {
27
- result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
28
- }
29
- step((generator = generator.apply(thisArg, _arguments || [])).next());
30
- });
31
- };
32
- var __generator = this && this.__generator || function(thisArg, body) {
33
- var _ = {
34
- label: 0,
35
- sent: function() {
36
- if (t[0] & 1) throw t[1];
37
- return t[1];
38
- },
39
- trys: [],
40
- ops: []
41
- }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
42
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
43
- return this;
44
- }), g;
45
- function verb(n) {
46
- return function(v) {
47
- return step([
48
- n,
49
- v
50
- ]);
51
- };
52
- }
53
- function step(op) {
54
- if (f) throw new TypeError("Generator is already executing.");
55
- while(g && (g = 0, op[0] && (_ = 0)), _)try {
56
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
57
- if (y = 0, t) op = [
58
- op[0] & 2,
59
- t.value
60
- ];
61
- switch(op[0]){
62
- case 0:
63
- case 1:
64
- t = op;
65
- break;
66
- case 4:
67
- _.label++;
68
- return {
69
- value: op[1],
70
- done: false
71
- };
72
- case 5:
73
- _.label++;
74
- y = op[1];
75
- op = [
76
- 0
77
- ];
78
- continue;
79
- case 7:
80
- op = _.ops.pop();
81
- _.trys.pop();
82
- continue;
83
- default:
84
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
85
- _ = 0;
86
- continue;
87
- }
88
- if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
89
- _.label = op[1];
90
- break;
91
- }
92
- if (op[0] === 6 && _.label < t[1]) {
93
- _.label = t[1];
94
- t = op;
95
- break;
96
- }
97
- if (t && _.label < t[2]) {
98
- _.label = t[2];
99
- _.ops.push(op);
100
- break;
101
- }
102
- if (t[2]) _.ops.pop();
103
- _.trys.pop();
104
- continue;
105
- }
106
- op = body.call(thisArg, _);
107
- } catch (e) {
108
- op = [
109
- 6,
110
- e
111
- ];
112
- y = 0;
113
- } finally{
114
- f = t = 0;
115
- }
116
- if (op[0] & 5) throw op[1];
117
- return {
118
- value: op[0] ? op[1] : void 0,
119
- done: true
120
- };
121
- }
122
- };
123
- var __spreadArray = this && this.__spreadArray || function(to, from, pack) {
124
- if (pack || arguments.length === 2) for(var i = 0, l = from.length, ar; i < l; i++){
125
- if (ar || !(i in from)) {
126
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
127
- ar[i] = from[i];
128
- }
129
- }
130
- return to.concat(ar || Array.prototype.slice.call(from));
131
- };
132
- Object.defineProperty(exports, "__esModule", {
133
- value: true
134
- });
135
- exports.refreshAgents = exports.getAgentsByCategory = exports.isValidAgentType = exports.searchAgents = exports.getAgentCategories = exports.getAllAgents = exports.getAgent = exports.getAvailableAgentTypes = exports.agentLoader = exports.AgentLoader = void 0;
136
- exports.resolveLegacyAgentType = resolveLegacyAgentType;
137
- var node_fs_1 = require("node:fs");
138
- var glob_1 = require("glob");
139
- var node_path_1 = require("node:path");
140
- var yaml_1 = require("yaml");
4
+ */ import { readFileSync, existsSync } from 'node:fs';
5
+ import { glob } from 'glob';
6
+ import { resolve, dirname } from 'node:path';
7
+ import { parse as parseYaml } from 'yaml';
141
8
  // Legacy agent type mapping for backward compatibility
142
- var LEGACY_AGENT_MAPPING = {
9
+ const LEGACY_AGENT_MAPPING = {
143
10
  analyst: 'code-analyzer',
144
11
  coordinator: 'hierarchical-coordinator',
145
12
  optimizer: 'perf-analyzer',
@@ -150,40 +17,38 @@ var LEGACY_AGENT_MAPPING = {
150
17
  };
151
18
  /**
152
19
  * Resolve legacy agent types to current equivalents
153
- */ function resolveLegacyAgentType(legacyType) {
20
+ */ export function resolveLegacyAgentType(legacyType) {
154
21
  return LEGACY_AGENT_MAPPING[legacyType] || legacyType;
155
22
  }
156
- var AgentLoader = /** @class */ function() {
157
- function AgentLoader() {
158
- this.agentCache = new Map();
159
- this.categoriesCache = [];
160
- this.lastLoadTime = 0;
161
- this.CACHE_EXPIRY = 60000; // 1 minute cache
162
- }
163
- AgentLoader.prototype.getAgentsDirectory = function() {
164
- var currentDir = process.cwd();
23
+ export class AgentLoader {
24
+ agentCache = new Map();
25
+ categoriesCache = [];
26
+ lastLoadTime = 0;
27
+ CACHE_EXPIRY = 60_000;
28
+ getAgentsDirectory() {
29
+ let currentDir = process.cwd();
165
30
  while(currentDir !== '/'){
166
- var claudeAgentsPath = (0, node_path_1.resolve)(currentDir, '.claude', 'agents');
167
- if ((0, node_fs_1.existsSync)(claudeAgentsPath)) {
31
+ const claudeAgentsPath = resolve(currentDir, '.claude', 'agents');
32
+ if (existsSync(claudeAgentsPath)) {
168
33
  return claudeAgentsPath;
169
34
  }
170
- currentDir = (0, node_path_1.dirname)(currentDir);
35
+ currentDir = dirname(currentDir);
171
36
  }
172
- return (0, node_path_1.resolve)(process.cwd(), '.claude', 'agents');
173
- };
174
- AgentLoader.prototype.parseAgentFile = function(filePath) {
37
+ return resolve(process.cwd(), '.claude', 'agents');
38
+ }
39
+ parseAgentFile(filePath) {
175
40
  try {
176
- var content = (0, node_fs_1.readFileSync)(filePath, 'utf-8');
177
- var frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);
41
+ const content = readFileSync(filePath, 'utf-8');
42
+ const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);
178
43
  if (!frontmatterMatch) {
179
- console.warn("No frontmatter found in ".concat(filePath));
44
+ console.warn(`No frontmatter found in ${filePath}`);
180
45
  return null;
181
46
  }
182
- var yamlContent = frontmatterMatch[1], markdownContent = frontmatterMatch[2];
183
- var frontmatter = (0, yaml_1.parse)(yamlContent);
184
- var description = frontmatter.description;
47
+ const [, yamlContent, markdownContent] = frontmatterMatch;
48
+ const frontmatter = parseYaml(yamlContent);
49
+ const description = frontmatter.description;
185
50
  if (!frontmatter.name || !description) {
186
- console.warn("Missing required fields (name, description) in ".concat(filePath));
51
+ console.warn(`Missing required fields (name, description) in ${filePath}`);
187
52
  return null;
188
53
  }
189
54
  return {
@@ -204,13 +69,129 @@ var AgentLoader = /** @class */ function() {
204
69
  content: markdownContent.trim()
205
70
  };
206
71
  } catch (error) {
207
- console.error("Error parsing agent file ".concat(filePath, ":"), error);
72
+ console.error(`Error parsing agent file ${filePath}:`, error);
208
73
  return null;
209
74
  }
210
- };
211
- AgentLoader.prototype.parseTools = function(frontmatter) {
212
- var extractTools = function(input) {
75
+ }
76
+ parseTools(frontmatter) {
77
+ const extractTools = (input)=>{
213
78
  if (Array.isArray(input)) return input.map(String);
79
+ if (typeof input === 'string') {
80
+ return input.split(/[,\s]+/).map((t)=>t.trim()).filter((t)=>t.length > 0);
81
+ }
82
+ return [];
83
+ };
84
+ // Safely handle tools and capabilities.tools
85
+ const toolsFromFrontmatter = frontmatter.tools ? extractTools(frontmatter.tools) : [];
86
+ const toolsFromCapabilities = frontmatter.capabilities && typeof frontmatter.capabilities === 'object' ? extractTools(Object(frontmatter.capabilities).tools) : [];
87
+ return [
88
+ ...toolsFromFrontmatter,
89
+ ...toolsFromCapabilities
90
+ ];
91
+ }
92
+ async loadAgents() {
93
+ const agentsDir = this.getAgentsDirectory();
94
+ if (!existsSync(agentsDir)) {
95
+ console.warn(`Agents directory not found: ${agentsDir}`);
96
+ return;
97
+ }
98
+ const agentFiles = await new Promise((resolve, reject)=>{
99
+ glob('**/*.md', {
100
+ cwd: agentsDir,
101
+ ignore: [
102
+ '**/README.md',
103
+ '**/MIGRATION_SUMMARY.md'
104
+ ],
105
+ absolute: true
106
+ }, (err, matches)=>{
107
+ if (err) reject(err);
108
+ else resolve(matches);
109
+ });
110
+ });
111
+ this.agentCache.clear();
112
+ this.categoriesCache = [];
113
+ const categoryMap = new Map();
114
+ for (const filePath of agentFiles){
115
+ const agent = this.parseAgentFile(filePath);
116
+ if (agent) {
117
+ this.agentCache.set(agent.name, agent);
118
+ const relativePath = filePath.replace(agentsDir, '');
119
+ const pathParts = relativePath.split('/');
120
+ const category = pathParts[1] || 'uncategorized';
121
+ if (!categoryMap.has(category)) {
122
+ categoryMap.set(category, []);
123
+ }
124
+ categoryMap.get(category).push(agent);
125
+ }
126
+ }
127
+ this.categoriesCache = Array.from(categoryMap.entries()).map(([name, agents])=>({
128
+ name,
129
+ agents: agents.sort((a, b)=>a.name.localeCompare(b.name))
130
+ }));
131
+ this.lastLoadTime = Date.now();
132
+ }
133
+ // Rest of the methods remain similar to the original implementation
134
+ needsRefresh() {
135
+ return Date.now() - this.lastLoadTime > this.CACHE_EXPIRY;
136
+ }
137
+ async ensureLoaded() {
138
+ if (this.agentCache.size === 0 || this.needsRefresh()) {
139
+ await this.loadAgents();
140
+ }
141
+ }
142
+ async getAvailableAgentTypes() {
143
+ await this.ensureLoaded();
144
+ const currentTypes = Array.from(this.agentCache.keys());
145
+ const legacyTypes = Object.keys(LEGACY_AGENT_MAPPING);
146
+ return Array.from(new Set([
147
+ ...currentTypes,
148
+ ...legacyTypes
149
+ ])).sort();
150
+ }
151
+ async getAgent(name) {
152
+ await this.ensureLoaded();
153
+ return this.agentCache.get(name) || this.agentCache.get(resolveLegacyAgentType(name)) || null;
154
+ }
155
+ async getAllAgents() {
156
+ await this.ensureLoaded();
157
+ return Array.from(this.agentCache.values()).sort((a, b)=>a.name.localeCompare(b.name));
158
+ }
159
+ async getAgentCategories() {
160
+ await this.ensureLoaded();
161
+ return this.categoriesCache;
162
+ }
163
+ async searchAgents(query) {
164
+ await this.ensureLoaded();
165
+ const lowerQuery = query.toLowerCase();
166
+ return Array.from(this.agentCache.values()).filter((agent)=>agent.name.toLowerCase().includes(lowerQuery) || agent.description.toLowerCase().includes(lowerQuery) || agent.capabilities?.some((cap)=>cap.toLowerCase().includes(lowerQuery)));
167
+ }
168
+ async isValidAgentType(name) {
169
+ await this.ensureLoaded();
170
+ return this.agentCache.has(name) || this.agentCache.has(resolveLegacyAgentType(name));
171
+ }
172
+ async getAgentsByCategory(category) {
173
+ const categories = await this.getAgentCategories();
174
+ const found = categories.find((cat)=>cat.name === category);
175
+ return found?.agents || [];
176
+ }
177
+ async refresh() {
178
+ this.lastLoadTime = 0;
179
+ await this.loadAgents();
180
+ }
181
+ }
182
+ // Singleton instance
183
+ export const agentLoader = new AgentLoader();
184
+ // Convenience exports for use in other modules
185
+ export const getAvailableAgentTypes = ()=>agentLoader.getAvailableAgentTypes();
186
+ export const getAgent = (name)=>agentLoader.getAgent(name);
187
+ export const getAllAgents = ()=>agentLoader.getAllAgents();
188
+ export const getAgentCategories = ()=>agentLoader.getAgentCategories();
189
+ export const searchAgents = (query)=>agentLoader.searchAgents(query);
190
+ export const isValidAgentType = (name)=>agentLoader.isValidAgentType(name);
191
+ export const getAgentsByCategory = (category)=>agentLoader.getAgentsByCategory(category);
192
+ export const refreshAgents = ()=>agentLoader.refresh();
193
+
194
+ //# sourceMappingURL=agent-loader.js.map.isArray(input)) return input.map(String);
214
195
  if (typeof input === 'string') {
215
196
  return input.split(/[,\s]+/).map(function(t) {
216
197
  return t.trim();