claude-flow-novice 2.15.1 → 2.15.2
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/cfn-extras/agents/google-sheets-specialist.md +614 -0
- package/.claude/commands/cfn/create-handoff.md +224 -0
- package/claude-assets/agents/cfn-dev-team/coordinators/handoff-coordinator.md +662 -0
- package/claude-assets/agents/cfn-dev-team/dev-ops/docker-specialist.md +29 -0
- package/claude-assets/cfn-extras/agents/google-sheets-specialist.md +614 -0
- package/claude-assets/commands/cfn/create-handoff.md +224 -0
- package/dist/agents/agent-loader.js +165 -146
- package/dist/agents/agent-loader.js.map +1 -1
- package/package.json +1 -1
- package/scripts/build-linux.sh +78 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Create session handoff documentation for team transitions or context resets (project)"
|
|
3
|
+
tags: ["handoff", "session-transition", "documentation", "context-preservation"]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Create Session Handoff Documentation
|
|
7
|
+
|
|
8
|
+
Generate comprehensive handoff documentation for transitioning work between sessions or teams.
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
/create-handoff [domain] [--duration=hours] [--focus="description"]
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Parameters
|
|
17
|
+
|
|
18
|
+
- `domain` (required): Work domain (e.g., docker, cfn-v3, testing, security)
|
|
19
|
+
- `--duration` (optional): Session duration in hours (default: 24)
|
|
20
|
+
- `--focus` (optional): Session focus description
|
|
21
|
+
|
|
22
|
+
## Examples
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Create handoff for Docker work
|
|
26
|
+
/create-handoff docker
|
|
27
|
+
|
|
28
|
+
# Create handoff with specific focus
|
|
29
|
+
/create-handoff cfn-v3 --focus="Loop 3 implementation and validation"
|
|
30
|
+
|
|
31
|
+
# Create handoff for longer session
|
|
32
|
+
/create-handoff security --duration=48 --focus="Security audit and remediation"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## What This Does
|
|
36
|
+
|
|
37
|
+
The handoff-coordinator agent will:
|
|
38
|
+
|
|
39
|
+
1. **Extract session context:**
|
|
40
|
+
- Git commits from specified duration
|
|
41
|
+
- Modified files with change summaries
|
|
42
|
+
- Key decisions and trade-offs
|
|
43
|
+
- Bugs fixed and issues deferred
|
|
44
|
+
|
|
45
|
+
2. **Generate structured handoff:**
|
|
46
|
+
- Executive summary (90-second read)
|
|
47
|
+
- Technical details with file changes
|
|
48
|
+
- Validation procedures and smoke tests
|
|
49
|
+
- Next steps with clear criteria
|
|
50
|
+
- Confidence scoring (0.0-1.0)
|
|
51
|
+
|
|
52
|
+
3. **Create quick reference:**
|
|
53
|
+
- 5-minute "resume work immediately" guide
|
|
54
|
+
- Critical context only
|
|
55
|
+
- Executable smoke test
|
|
56
|
+
|
|
57
|
+
4. **Output artifacts:**
|
|
58
|
+
- `planning/[domain]/handoff/SESSION_HANDOFF_[timestamp].md`
|
|
59
|
+
- `planning/[domain]/handoff/QUICK_START_[domain].md`
|
|
60
|
+
- Backlog entry (if work incomplete)
|
|
61
|
+
|
|
62
|
+
## When to Use This
|
|
63
|
+
|
|
64
|
+
**Use /create-handoff when:**
|
|
65
|
+
- ✅ Ending a multi-hour session with significant progress
|
|
66
|
+
- ✅ Transitioning work to another team
|
|
67
|
+
- ✅ Resetting context for a fresh session
|
|
68
|
+
- ✅ Documenting complex bug fixes or architectural decisions
|
|
69
|
+
- ✅ Creating checkpoints during long-running epics
|
|
70
|
+
|
|
71
|
+
**Don't use /create-handoff for:**
|
|
72
|
+
- ❌ Simple single-file edits
|
|
73
|
+
- ❌ Trivial bug fixes with no architectural impact
|
|
74
|
+
- ❌ Work that's already fully documented
|
|
75
|
+
- ❌ Sessions with no significant decisions or changes
|
|
76
|
+
|
|
77
|
+
## Output Structure
|
|
78
|
+
|
|
79
|
+
The generated handoff document includes:
|
|
80
|
+
|
|
81
|
+
### Executive Summary
|
|
82
|
+
- Session scope and objectives
|
|
83
|
+
- Key achievements
|
|
84
|
+
- Critical decisions
|
|
85
|
+
- Current state
|
|
86
|
+
|
|
87
|
+
### Work Completed
|
|
88
|
+
- Commits with hashes and messages
|
|
89
|
+
- Files changed with line counts
|
|
90
|
+
- Tests created/updated
|
|
91
|
+
- Documentation written
|
|
92
|
+
|
|
93
|
+
### Key Decisions
|
|
94
|
+
- Decision description
|
|
95
|
+
- Alternatives considered
|
|
96
|
+
- Trade-offs accepted
|
|
97
|
+
- Rationale and confidence
|
|
98
|
+
|
|
99
|
+
### Technical Details
|
|
100
|
+
- Root cause analyses
|
|
101
|
+
- Fix implementations
|
|
102
|
+
- Validation procedures
|
|
103
|
+
- Test results
|
|
104
|
+
|
|
105
|
+
### Current State
|
|
106
|
+
- What's working
|
|
107
|
+
- What needs attention
|
|
108
|
+
- What's blocked
|
|
109
|
+
- What's deferred
|
|
110
|
+
|
|
111
|
+
### Next Steps
|
|
112
|
+
- Immediate actions (today)
|
|
113
|
+
- Short-term goals (24-48 hours)
|
|
114
|
+
- Medium-term roadmap (next week)
|
|
115
|
+
|
|
116
|
+
### Validation Procedures
|
|
117
|
+
- Pre-handoff checklist
|
|
118
|
+
- Smoke test script
|
|
119
|
+
- Integration test
|
|
120
|
+
- Rollback procedure
|
|
121
|
+
|
|
122
|
+
### Confidence & Risk Assessment
|
|
123
|
+
- Component-level confidence scores
|
|
124
|
+
- Overall handoff confidence
|
|
125
|
+
- Risk classification (low/medium/high)
|
|
126
|
+
- Mitigation strategies
|
|
127
|
+
|
|
128
|
+
## Command Implementation
|
|
129
|
+
|
|
130
|
+
**YOU MUST IMMEDIATELY EXECUTE THE TASK TOOL AFTER READING THIS COMMAND.**
|
|
131
|
+
|
|
132
|
+
Do not just explain what would happen - actually spawn the agent.
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
// Extract parameters
|
|
136
|
+
const domain = args[0] || "general";
|
|
137
|
+
const duration = extractFlag(args, "--duration") || "24";
|
|
138
|
+
const focus = extractFlag(args, "--focus") || "Recent session work";
|
|
139
|
+
|
|
140
|
+
// Spawn handoff-coordinator agent
|
|
141
|
+
Task("handoff-coordinator", `
|
|
142
|
+
Create session handoff documentation for ${domain} domain.
|
|
143
|
+
|
|
144
|
+
Session context:
|
|
145
|
+
- Focus: ${focus}
|
|
146
|
+
- Duration: Last ${duration} hours
|
|
147
|
+
- Domain: ${domain}
|
|
148
|
+
|
|
149
|
+
Requirements:
|
|
150
|
+
- Extract git commits from last ${duration} hours
|
|
151
|
+
- Document all file changes with summaries
|
|
152
|
+
- Identify and document key decisions
|
|
153
|
+
- Create executable smoke test
|
|
154
|
+
- Include rollback procedure
|
|
155
|
+
- Generate quick start guide
|
|
156
|
+
|
|
157
|
+
Output location: planning/${domain}/handoff/
|
|
158
|
+
Target confidence: ≥0.90
|
|
159
|
+
|
|
160
|
+
Deliverables:
|
|
161
|
+
1. SESSION_HANDOFF_[timestamp].md (full handoff document)
|
|
162
|
+
2. QUICK_START_${domain}.md (5-minute resume guide)
|
|
163
|
+
3. Backlog entry (if work incomplete)
|
|
164
|
+
4. Smoke test script (executable validation)
|
|
165
|
+
`)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Success Criteria
|
|
169
|
+
|
|
170
|
+
The handoff is complete when:
|
|
171
|
+
|
|
172
|
+
- ✅ Handoff document follows template structure
|
|
173
|
+
- ✅ All commits referenced with valid hashes
|
|
174
|
+
- ✅ All file changes documented
|
|
175
|
+
- ✅ Key decisions include rationale
|
|
176
|
+
- ✅ Smoke test is executable
|
|
177
|
+
- ✅ Rollback procedure documented
|
|
178
|
+
- ✅ Confidence scores calculated
|
|
179
|
+
- ✅ Quick start guide created
|
|
180
|
+
- ✅ Overall confidence ≥0.90
|
|
181
|
+
|
|
182
|
+
## Related Commands
|
|
183
|
+
|
|
184
|
+
- `/cfn-loop-task` - Execute CFN Loop workflows
|
|
185
|
+
- `/github-commit` - Create git commits
|
|
186
|
+
- `/suggest-improvements` - Analyze codebase quality
|
|
187
|
+
|
|
188
|
+
## Anti-Patterns
|
|
189
|
+
|
|
190
|
+
**Don't do this:**
|
|
191
|
+
```bash
|
|
192
|
+
# ❌ Creating handoff without context
|
|
193
|
+
/create-handoff unknown
|
|
194
|
+
|
|
195
|
+
# ❌ Handoff for trivial work
|
|
196
|
+
/create-handoff typo-fix
|
|
197
|
+
|
|
198
|
+
# ❌ Handoff without domain
|
|
199
|
+
/create-handoff
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**Do this instead:**
|
|
203
|
+
```bash
|
|
204
|
+
# ✅ Clear domain and focus
|
|
205
|
+
/create-handoff docker --focus="Alpine Linux shell compatibility fix"
|
|
206
|
+
|
|
207
|
+
# ✅ Specific duration for multi-day work
|
|
208
|
+
/create-handoff cfn-v3 --duration=72 --focus="Three-loop validation implementation"
|
|
209
|
+
|
|
210
|
+
# ✅ Detailed context for complex work
|
|
211
|
+
/create-handoff security --focus="P1 vulnerability remediation and validation"
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Notes
|
|
215
|
+
|
|
216
|
+
- Handoff documents are stored in `planning/[domain]/handoff/`
|
|
217
|
+
- Git context is extracted automatically (no manual commit listing required)
|
|
218
|
+
- Smoke tests are generated as executable shell scripts
|
|
219
|
+
- Confidence scoring is calculated automatically
|
|
220
|
+
- Backlog entries are created only if work is incomplete
|
|
221
|
+
|
|
222
|
+
## Version History
|
|
223
|
+
|
|
224
|
+
- **v1.0 (2025-11-14):** Initial command creation with handoff-coordinator agent integration
|
|
@@ -1,12 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Dynamic Agent Loader - Reads agent definitions from .claude/agents/ directory
|
|
3
4
|
* Single source of truth for agent types in the system
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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");
|
|
8
141
|
// Legacy agent type mapping for backward compatibility
|
|
9
|
-
|
|
142
|
+
var LEGACY_AGENT_MAPPING = {
|
|
10
143
|
analyst: 'code-analyzer',
|
|
11
144
|
coordinator: 'hierarchical-coordinator',
|
|
12
145
|
optimizer: 'perf-analyzer',
|
|
@@ -17,38 +150,40 @@ const LEGACY_AGENT_MAPPING = {
|
|
|
17
150
|
};
|
|
18
151
|
/**
|
|
19
152
|
* Resolve legacy agent types to current equivalents
|
|
20
|
-
*/
|
|
153
|
+
*/ function resolveLegacyAgentType(legacyType) {
|
|
21
154
|
return LEGACY_AGENT_MAPPING[legacyType] || legacyType;
|
|
22
155
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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();
|
|
30
165
|
while(currentDir !== '/'){
|
|
31
|
-
|
|
32
|
-
if (existsSync(claudeAgentsPath)) {
|
|
166
|
+
var claudeAgentsPath = (0, node_path_1.resolve)(currentDir, '.claude', 'agents');
|
|
167
|
+
if ((0, node_fs_1.existsSync)(claudeAgentsPath)) {
|
|
33
168
|
return claudeAgentsPath;
|
|
34
169
|
}
|
|
35
|
-
currentDir = dirname(currentDir);
|
|
170
|
+
currentDir = (0, node_path_1.dirname)(currentDir);
|
|
36
171
|
}
|
|
37
|
-
return resolve(process.cwd(), '.claude', 'agents');
|
|
38
|
-
}
|
|
39
|
-
parseAgentFile(filePath) {
|
|
172
|
+
return (0, node_path_1.resolve)(process.cwd(), '.claude', 'agents');
|
|
173
|
+
};
|
|
174
|
+
AgentLoader.prototype.parseAgentFile = function(filePath) {
|
|
40
175
|
try {
|
|
41
|
-
|
|
42
|
-
|
|
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]*)$/);
|
|
43
178
|
if (!frontmatterMatch) {
|
|
44
|
-
console.warn(
|
|
179
|
+
console.warn("No frontmatter found in ".concat(filePath));
|
|
45
180
|
return null;
|
|
46
181
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
182
|
+
var yamlContent = frontmatterMatch[1], markdownContent = frontmatterMatch[2];
|
|
183
|
+
var frontmatter = (0, yaml_1.parse)(yamlContent);
|
|
184
|
+
var description = frontmatter.description;
|
|
50
185
|
if (!frontmatter.name || !description) {
|
|
51
|
-
console.warn(
|
|
186
|
+
console.warn("Missing required fields (name, description) in ".concat(filePath));
|
|
52
187
|
return null;
|
|
53
188
|
}
|
|
54
189
|
return {
|
|
@@ -69,129 +204,13 @@ export class AgentLoader {
|
|
|
69
204
|
content: markdownContent.trim()
|
|
70
205
|
};
|
|
71
206
|
} catch (error) {
|
|
72
|
-
console.error(
|
|
207
|
+
console.error("Error parsing agent file ".concat(filePath, ":"), error);
|
|
73
208
|
return null;
|
|
74
209
|
}
|
|
75
|
-
}
|
|
76
|
-
parseTools(frontmatter) {
|
|
77
|
-
|
|
210
|
+
};
|
|
211
|
+
AgentLoader.prototype.parseTools = function(frontmatter) {
|
|
212
|
+
var extractTools = function(input) {
|
|
78
213
|
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);
|
|
195
214
|
if (typeof input === 'string') {
|
|
196
215
|
return input.split(/[,\s]+/).map(function(t) {
|
|
197
216
|
return t.trim();
|