claude-flow-novice 2.14.15 → 2.14.16
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/cfn-loop-cli.md +113 -42
- package/claude-assets/commands/cfn-loop-cli.md +113 -42
- package/dist/agent/skill-mcp-selector.js +459 -0
- package/dist/agent/skill-mcp-selector.js.map +1 -0
- package/dist/cli/agent-token-manager.js +382 -0
- package/dist/cli/agent-token-manager.js.map +1 -0
- package/dist/cli/config-manager.js +91 -109
- package/dist/cli/config-manager.js.map +1 -1
- package/dist/mcp/auth-middleware.js +367 -0
- package/dist/mcp/auth-middleware.js.map +1 -0
- package/dist/mcp/playwright-mcp-server-auth.js +515 -0
- package/dist/mcp/playwright-mcp-server-auth.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Agent Token Management CLI
|
|
4
|
+
* Generate, register, and manage agent tokens for MCP authentication
|
|
5
|
+
*/ const crypto = require('crypto');
|
|
6
|
+
const Redis = require('redis');
|
|
7
|
+
const fs = require('fs').promises;
|
|
8
|
+
const path = require('path');
|
|
9
|
+
let AgentTokenManager = class AgentTokenManager {
|
|
10
|
+
constructor(options = {}){
|
|
11
|
+
this.redisUrl = options.redisUrl || process.env.MCP_REDIS_URL || 'redis://localhost:6379';
|
|
12
|
+
this.redis = null;
|
|
13
|
+
this.agentConfigPath = options.agentConfigPath || './config/agent-whitelist.json';
|
|
14
|
+
this.defaultExpiry = options.defaultExpiry || '24h';
|
|
15
|
+
}
|
|
16
|
+
async initialize() {
|
|
17
|
+
try {
|
|
18
|
+
this.redis = Redis.createClient({
|
|
19
|
+
url: this.redisUrl
|
|
20
|
+
});
|
|
21
|
+
await this.redis.connect();
|
|
22
|
+
console.log('Connected to Redis for token management');
|
|
23
|
+
} catch (error) {
|
|
24
|
+
console.error('Failed to connect to Redis:', error);
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async loadAgentConfig() {
|
|
29
|
+
try {
|
|
30
|
+
const configPath = path.resolve(this.agentConfigPath);
|
|
31
|
+
const config = await fs.readFile(configPath, 'utf8');
|
|
32
|
+
return JSON.parse(config);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.error('Failed to load agent config:', error);
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
generateToken() {
|
|
39
|
+
return crypto.randomBytes(32).toString('hex');
|
|
40
|
+
}
|
|
41
|
+
parseExpiry(expiry) {
|
|
42
|
+
if (typeof expiry === 'number') {
|
|
43
|
+
return expiry;
|
|
44
|
+
}
|
|
45
|
+
const match = expiry.match(/^(\d+)([smhd])$/);
|
|
46
|
+
if (!match) {
|
|
47
|
+
return 86400; // Default to 24 hours
|
|
48
|
+
}
|
|
49
|
+
const value = parseInt(match[1]);
|
|
50
|
+
const unit = match[2];
|
|
51
|
+
const multipliers = {
|
|
52
|
+
s: 1,
|
|
53
|
+
m: 60,
|
|
54
|
+
h: 3600,
|
|
55
|
+
d: 86400
|
|
56
|
+
};
|
|
57
|
+
return value * (multipliers[unit] || 86400);
|
|
58
|
+
}
|
|
59
|
+
async registerAgentToken(agentType, options = {}) {
|
|
60
|
+
try {
|
|
61
|
+
const config = await this.loadAgentConfig();
|
|
62
|
+
const agentConfig = config.agents.find((a)=>a.type === agentType);
|
|
63
|
+
if (!agentConfig) {
|
|
64
|
+
throw new Error(`Unknown agent type: ${agentType}. Available types: ${config.agents.map((a)=>a.type).join(', ')}`);
|
|
65
|
+
}
|
|
66
|
+
const token = this.generateToken();
|
|
67
|
+
const expiresIn = options.expiresIn || this.defaultExpiry;
|
|
68
|
+
const expiresAt = Date.now() + this.parseExpiry(expiresIn) * 1000;
|
|
69
|
+
const tokenData = {
|
|
70
|
+
token,
|
|
71
|
+
agentType,
|
|
72
|
+
displayName: agentConfig.displayName,
|
|
73
|
+
skills: agentConfig.skills,
|
|
74
|
+
allowedMcpServers: agentConfig.allowedMcpServers,
|
|
75
|
+
resourceLimits: agentConfig.resourceLimits,
|
|
76
|
+
expiresAt,
|
|
77
|
+
createdAt: Date.now(),
|
|
78
|
+
createdBy: options.createdBy || 'cli',
|
|
79
|
+
description: options.description || `Token for ${agentConfig.displayName}`
|
|
80
|
+
};
|
|
81
|
+
// Store in Redis
|
|
82
|
+
const key = `mcp:agent:${agentType}:${token}`;
|
|
83
|
+
const value = JSON.stringify(tokenData);
|
|
84
|
+
const ttlSeconds = this.parseExpiry(expiresIn);
|
|
85
|
+
await this.redis.setEx(key, ttlSeconds, value);
|
|
86
|
+
console.log(`✅ Token registered successfully!`);
|
|
87
|
+
console.log(` Agent Type: ${agentConfig.displayName} (${agentType})`);
|
|
88
|
+
console.log(` Token: ${token}`);
|
|
89
|
+
console.log(` Skills: ${agentConfig.skills.join(', ')}`);
|
|
90
|
+
console.log(` Allowed MCP Servers: ${agentConfig.allowedMcpServers.join(', ')}`);
|
|
91
|
+
console.log(` Expires: ${new Date(expiresAt).toISOString()}`);
|
|
92
|
+
console.log(` Memory Limit: ${agentConfig.resourceLimits.maxMemoryMB}MB`);
|
|
93
|
+
console.log(` Rate Limit: ${agentConfig.resourceLimits.maxRequestsPerMinute}/min`);
|
|
94
|
+
return tokenData;
|
|
95
|
+
} catch (error) {
|
|
96
|
+
console.error('❌ Failed to register token:', error.message);
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async listActiveTokens(agentType = null) {
|
|
101
|
+
try {
|
|
102
|
+
const pattern = agentType ? `mcp:agent:${agentType}:*` : 'mcp:agent:*';
|
|
103
|
+
const keys = await this.redis.keys(pattern);
|
|
104
|
+
const tokens = [];
|
|
105
|
+
for (const key of keys){
|
|
106
|
+
const value = await this.redis.get(key);
|
|
107
|
+
if (value) {
|
|
108
|
+
const tokenData = JSON.parse(value);
|
|
109
|
+
tokens.push({
|
|
110
|
+
...tokenData,
|
|
111
|
+
key,
|
|
112
|
+
status: tokenData.expiresAt > Date.now() ? 'active' : 'expired'
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (tokens.length === 0) {
|
|
117
|
+
console.log('No active tokens found');
|
|
118
|
+
return [];
|
|
119
|
+
}
|
|
120
|
+
console.log(`\nActive Tokens (${tokens.length}):\n`);
|
|
121
|
+
console.log('Agent Type | Token | Expires At | Status');
|
|
122
|
+
console.log('-------------------|------------------------------------|------------------------------|--------');
|
|
123
|
+
for (const token of tokens){
|
|
124
|
+
const expiresAt = new Date(token.expiresAt).toISOString();
|
|
125
|
+
const tokenShort = token.token.substring(0, 32);
|
|
126
|
+
console.log(`${token.agentType.padEnd(17)} | ${tokenShort} | ${expiresAt} | ${token.status}`);
|
|
127
|
+
}
|
|
128
|
+
return tokens;
|
|
129
|
+
} catch (error) {
|
|
130
|
+
console.error('❌ Failed to list tokens:', error.message);
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async revokeToken(agentType, token) {
|
|
135
|
+
try {
|
|
136
|
+
const key = `mcp:agent:${agentType}:${token}`;
|
|
137
|
+
const exists = await this.redis.exists(key);
|
|
138
|
+
if (!exists) {
|
|
139
|
+
throw new Error(`Token not found for agent ${agentType}`);
|
|
140
|
+
}
|
|
141
|
+
await this.redis.del(key);
|
|
142
|
+
console.log(`✅ Token revoked successfully for agent ${agentType}`);
|
|
143
|
+
console.log(` Token: ${token}`);
|
|
144
|
+
} catch (error) {
|
|
145
|
+
console.error('❌ Failed to revoke token:', error.message);
|
|
146
|
+
throw error;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
async revokeAllTokens(agentType = null) {
|
|
150
|
+
try {
|
|
151
|
+
const pattern = agentType ? `mcp:agent:${agentType}:*` : 'mcp:agent:*';
|
|
152
|
+
const keys = await this.redis.keys(pattern);
|
|
153
|
+
if (keys.length === 0) {
|
|
154
|
+
console.log('No tokens found to revoke');
|
|
155
|
+
return 0;
|
|
156
|
+
}
|
|
157
|
+
await this.redis.del(keys);
|
|
158
|
+
console.log(`✅ Revoked ${keys.length} tokens${agentType ? ` for agent ${agentType}` : ''}`);
|
|
159
|
+
return keys.length;
|
|
160
|
+
} catch (error) {
|
|
161
|
+
console.error('❌ Failed to revoke tokens:', error.message);
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
async validateToken(agentType, token) {
|
|
166
|
+
try {
|
|
167
|
+
const key = `mcp:agent:${agentType}:${token}`;
|
|
168
|
+
const value = await this.redis.get(key);
|
|
169
|
+
if (!value) {
|
|
170
|
+
return {
|
|
171
|
+
valid: false,
|
|
172
|
+
reason: 'Token not found'
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
const tokenData = JSON.parse(value);
|
|
176
|
+
if (Date.now() > tokenData.expiresAt) {
|
|
177
|
+
await this.redis.del(key);
|
|
178
|
+
return {
|
|
179
|
+
valid: false,
|
|
180
|
+
reason: 'Token expired'
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
valid: true,
|
|
185
|
+
tokenData
|
|
186
|
+
};
|
|
187
|
+
} catch (error) {
|
|
188
|
+
return {
|
|
189
|
+
valid: false,
|
|
190
|
+
reason: error.message
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
async getAgentInfo(agentType) {
|
|
195
|
+
try {
|
|
196
|
+
const config = await this.loadAgentConfig();
|
|
197
|
+
const agentConfig = config.agents.find((a)=>a.type === agentType);
|
|
198
|
+
if (!agentConfig) {
|
|
199
|
+
throw new Error(`Unknown agent type: ${agentType}`);
|
|
200
|
+
}
|
|
201
|
+
console.log(`\nAgent Information: ${agentConfig.displayName}`);
|
|
202
|
+
console.log('='.repeat(50));
|
|
203
|
+
console.log(`Type: ${agentConfig.type}`);
|
|
204
|
+
console.log(`Skills: ${agentConfig.skills.join(', ')}`);
|
|
205
|
+
console.log(`Allowed MCP Servers: ${agentConfig.allowedMcpServers.join(', ')}`);
|
|
206
|
+
console.log(`Memory Limit: ${agentConfig.resourceLimits.maxMemoryMB}MB`);
|
|
207
|
+
console.log(`Rate Limit: ${agentConfig.resourceLimits.maxRequestsPerMinute}/min`);
|
|
208
|
+
console.log(`Max Concurrent: ${agentConfig.resourceLimits.maxConcurrentRequests}`);
|
|
209
|
+
console.log(`Description: ${agentConfig.description}`);
|
|
210
|
+
return agentConfig;
|
|
211
|
+
} catch (error) {
|
|
212
|
+
console.error('❌ Failed to get agent info:', error.message);
|
|
213
|
+
throw error;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
async listAgentTypes() {
|
|
217
|
+
try {
|
|
218
|
+
const config = await this.loadAgentConfig();
|
|
219
|
+
console.log(`\nAvailable Agent Types (${config.agents.length}):\n`);
|
|
220
|
+
console.log('Agent Type | Display Name | Skills Count');
|
|
221
|
+
console.log('------------------------|--------------------------------|-------------');
|
|
222
|
+
for (const agent of config.agents){
|
|
223
|
+
const type = agent.type.padEnd(22);
|
|
224
|
+
const name = agent.displayName.padEnd(32);
|
|
225
|
+
const skills = agent.skills.length;
|
|
226
|
+
console.log(`${type} | ${name} | ${skills}`);
|
|
227
|
+
}
|
|
228
|
+
return config.agents.map((a)=>a.type);
|
|
229
|
+
} catch (error) {
|
|
230
|
+
console.error('❌ Failed to list agent types:', error.message);
|
|
231
|
+
throw error;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
async shutdown() {
|
|
235
|
+
if (this.redis) {
|
|
236
|
+
await this.redis.quit();
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
// CLI interface
|
|
241
|
+
async function main() {
|
|
242
|
+
const args = process.argv.slice(2);
|
|
243
|
+
const command = args[0];
|
|
244
|
+
if (!command) {
|
|
245
|
+
console.log(`
|
|
246
|
+
Agent Token Management CLI
|
|
247
|
+
|
|
248
|
+
Usage: node agent-token-manager.js <command> [options]
|
|
249
|
+
|
|
250
|
+
Commands:
|
|
251
|
+
register <agent-type> [options] Register a new token for an agent
|
|
252
|
+
list [agent-type] List active tokens
|
|
253
|
+
revoke <agent-type> <token> Revoke a specific token
|
|
254
|
+
revoke-all [agent-type] Revoke all tokens (optionally for specific agent)
|
|
255
|
+
validate <agent-type> <token> Validate a token
|
|
256
|
+
info <agent-type> Show agent information
|
|
257
|
+
types List available agent types
|
|
258
|
+
|
|
259
|
+
Options for 'register' command:
|
|
260
|
+
--expires-in <duration> Token expiry (e.g., 1h, 30m, 7d) [default: 24h]
|
|
261
|
+
--description <text> Token description
|
|
262
|
+
--created-by <identifier> Creator identifier
|
|
263
|
+
|
|
264
|
+
Examples:
|
|
265
|
+
# Register token for frontend engineer
|
|
266
|
+
node agent-token-manager.js register react-frontend-engineer
|
|
267
|
+
|
|
268
|
+
# Register token with custom expiry
|
|
269
|
+
node agent-token-manager.js register backend-developer --expires-in 2h
|
|
270
|
+
|
|
271
|
+
# List all active tokens
|
|
272
|
+
node agent-token-manager.js list
|
|
273
|
+
|
|
274
|
+
# List tokens for specific agent
|
|
275
|
+
node agent-token-manager.js list react-frontend-engineer
|
|
276
|
+
|
|
277
|
+
# Revoke a specific token
|
|
278
|
+
node agent-token-manager.js revoke react-frontend-engineer abc123...
|
|
279
|
+
|
|
280
|
+
# Get agent information
|
|
281
|
+
node agent-token-manager.js info security-specialist
|
|
282
|
+
`);
|
|
283
|
+
process.exit(0);
|
|
284
|
+
}
|
|
285
|
+
const tokenManager = new AgentTokenManager();
|
|
286
|
+
try {
|
|
287
|
+
await tokenManager.initialize();
|
|
288
|
+
switch(command){
|
|
289
|
+
case 'register':
|
|
290
|
+
{
|
|
291
|
+
const agentType = args[1];
|
|
292
|
+
if (!agentType) {
|
|
293
|
+
throw new Error('Agent type is required for register command');
|
|
294
|
+
}
|
|
295
|
+
const options = {};
|
|
296
|
+
for(let i = 2; i < args.length; i++){
|
|
297
|
+
if (args[i] === '--expires-in') {
|
|
298
|
+
options.expiresIn = args[++i];
|
|
299
|
+
} else if (args[i] === '--description') {
|
|
300
|
+
options.description = args[++i];
|
|
301
|
+
} else if (args[i] === '--created-by') {
|
|
302
|
+
options.createdBy = args[++i];
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
await tokenManager.registerAgentToken(agentType, options);
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
case 'list':
|
|
309
|
+
{
|
|
310
|
+
const agentType = args[1];
|
|
311
|
+
await tokenManager.listActiveTokens(agentType);
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
case 'revoke':
|
|
315
|
+
{
|
|
316
|
+
const agentType = args[1];
|
|
317
|
+
const token = args[2];
|
|
318
|
+
if (!agentType || !token) {
|
|
319
|
+
throw new Error('Agent type and token are required for revoke command');
|
|
320
|
+
}
|
|
321
|
+
await tokenManager.revokeToken(agentType, token);
|
|
322
|
+
break;
|
|
323
|
+
}
|
|
324
|
+
case 'revoke-all':
|
|
325
|
+
{
|
|
326
|
+
const agentType = args[1];
|
|
327
|
+
const count = await tokenManager.revokeAllTokens(agentType);
|
|
328
|
+
console.log(`Revoked ${count} tokens`);
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
case 'validate':
|
|
332
|
+
{
|
|
333
|
+
const agentType = args[1];
|
|
334
|
+
const token = args[2];
|
|
335
|
+
if (!agentType || !token) {
|
|
336
|
+
throw new Error('Agent type and token are required for validate command');
|
|
337
|
+
}
|
|
338
|
+
const result = await tokenManager.validateToken(agentType, token);
|
|
339
|
+
if (result.valid) {
|
|
340
|
+
console.log('✅ Token is valid');
|
|
341
|
+
console.log(` Agent Type: ${result.tokenData.agentType}`);
|
|
342
|
+
console.log(` Skills: ${result.tokenData.skills.join(', ')}`);
|
|
343
|
+
console.log(` Expires: ${new Date(result.tokenData.expiresAt).toISOString()}`);
|
|
344
|
+
} else {
|
|
345
|
+
console.log('❌ Token is invalid');
|
|
346
|
+
console.log(` Reason: ${result.reason}`);
|
|
347
|
+
}
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
case 'info':
|
|
351
|
+
{
|
|
352
|
+
const agentType = args[1];
|
|
353
|
+
if (!agentType) {
|
|
354
|
+
throw new Error('Agent type is required for info command');
|
|
355
|
+
}
|
|
356
|
+
await tokenManager.getAgentInfo(agentType);
|
|
357
|
+
break;
|
|
358
|
+
}
|
|
359
|
+
case 'types':
|
|
360
|
+
{
|
|
361
|
+
await tokenManager.listAgentTypes();
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
default:
|
|
365
|
+
throw new Error(`Unknown command: ${command}`);
|
|
366
|
+
}
|
|
367
|
+
} catch (error) {
|
|
368
|
+
console.error('❌ Error:', error.message);
|
|
369
|
+
process.exit(1);
|
|
370
|
+
} finally{
|
|
371
|
+
await tokenManager.shutdown();
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
if (require.main === module) {
|
|
375
|
+
main().catch((error)=>{
|
|
376
|
+
console.error('Fatal error:', error);
|
|
377
|
+
process.exit(1);
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
module.exports = AgentTokenManager;
|
|
381
|
+
|
|
382
|
+
//# sourceMappingURL=agent-token-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cli/agent-token-manager.js"],"sourcesContent":["#!/usr/bin/env node\r\n\r\n/**\r\n * Agent Token Management CLI\r\n * Generate, register, and manage agent tokens for MCP authentication\r\n */\r\n\r\nconst crypto = require('crypto');\r\nconst Redis = require('redis');\r\nconst fs = require('fs').promises;\r\nconst path = require('path');\r\n\r\nclass AgentTokenManager {\r\n constructor(options = {}) {\r\n this.redisUrl = options.redisUrl || process.env.MCP_REDIS_URL || 'redis://localhost:6379';\r\n this.redis = null;\r\n this.agentConfigPath = options.agentConfigPath || './config/agent-whitelist.json';\r\n this.defaultExpiry = options.defaultExpiry || '24h';\r\n }\r\n\r\n async initialize() {\r\n try {\r\n this.redis = Redis.createClient({ url: this.redisUrl });\r\n await this.redis.connect();\r\n console.log('Connected to Redis for token management');\r\n } catch (error) {\r\n console.error('Failed to connect to Redis:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n async loadAgentConfig() {\r\n try {\r\n const configPath = path.resolve(this.agentConfigPath);\r\n const config = await fs.readFile(configPath, 'utf8');\r\n return JSON.parse(config);\r\n } catch (error) {\r\n console.error('Failed to load agent config:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n generateToken() {\r\n return crypto.randomBytes(32).toString('hex');\r\n }\r\n\r\n parseExpiry(expiry) {\r\n if (typeof expiry === 'number') {\r\n return expiry;\r\n }\r\n\r\n const match = expiry.match(/^(\\d+)([smhd])$/);\r\n if (!match) {\r\n return 86400; // Default to 24 hours\r\n }\r\n\r\n const value = parseInt(match[1]);\r\n const unit = match[2];\r\n const multipliers = { s: 1, m: 60, h: 3600, d: 86400 };\r\n\r\n return value * (multipliers[unit] || 86400);\r\n }\r\n\r\n async registerAgentToken(agentType, options = {}) {\r\n try {\r\n const config = await this.loadAgentConfig();\r\n const agentConfig = config.agents.find(a => a.type === agentType);\r\n\r\n if (!agentConfig) {\r\n throw new Error(`Unknown agent type: ${agentType}. Available types: ${config.agents.map(a => a.type).join(', ')}`);\r\n }\r\n\r\n const token = this.generateToken();\r\n const expiresIn = options.expiresIn || this.defaultExpiry;\r\n const expiresAt = Date.now() + (this.parseExpiry(expiresIn) * 1000);\r\n\r\n const tokenData = {\r\n token,\r\n agentType,\r\n displayName: agentConfig.displayName,\r\n skills: agentConfig.skills,\r\n allowedMcpServers: agentConfig.allowedMcpServers,\r\n resourceLimits: agentConfig.resourceLimits,\r\n expiresAt,\r\n createdAt: Date.now(),\r\n createdBy: options.createdBy || 'cli',\r\n description: options.description || `Token for ${agentConfig.displayName}`\r\n };\r\n\r\n // Store in Redis\r\n const key = `mcp:agent:${agentType}:${token}`;\r\n const value = JSON.stringify(tokenData);\r\n const ttlSeconds = this.parseExpiry(expiresIn);\r\n\r\n await this.redis.setEx(key, ttlSeconds, value);\r\n\r\n console.log(`✅ Token registered successfully!`);\r\n console.log(` Agent Type: ${agentConfig.displayName} (${agentType})`);\r\n console.log(` Token: ${token}`);\r\n console.log(` Skills: ${agentConfig.skills.join(', ')}`);\r\n console.log(` Allowed MCP Servers: ${agentConfig.allowedMcpServers.join(', ')}`);\r\n console.log(` Expires: ${new Date(expiresAt).toISOString()}`);\r\n console.log(` Memory Limit: ${agentConfig.resourceLimits.maxMemoryMB}MB`);\r\n console.log(` Rate Limit: ${agentConfig.resourceLimits.maxRequestsPerMinute}/min`);\r\n\r\n return tokenData;\r\n\r\n } catch (error) {\r\n console.error('❌ Failed to register token:', error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n async listActiveTokens(agentType = null) {\r\n try {\r\n const pattern = agentType ? `mcp:agent:${agentType}:*` : 'mcp:agent:*';\r\n const keys = await this.redis.keys(pattern);\r\n const tokens = [];\r\n\r\n for (const key of keys) {\r\n const value = await this.redis.get(key);\r\n if (value) {\r\n const tokenData = JSON.parse(value);\r\n tokens.push({\r\n ...tokenData,\r\n key,\r\n status: tokenData.expiresAt > Date.now() ? 'active' : 'expired'\r\n });\r\n }\r\n }\r\n\r\n if (tokens.length === 0) {\r\n console.log('No active tokens found');\r\n return [];\r\n }\r\n\r\n console.log(`\\nActive Tokens (${tokens.length}):\\n`);\r\n console.log('Agent Type | Token | Expires At | Status');\r\n console.log('-------------------|------------------------------------|------------------------------|--------');\r\n\r\n for (const token of tokens) {\r\n const expiresAt = new Date(token.expiresAt).toISOString();\r\n const tokenShort = token.token.substring(0, 32);\r\n console.log(`${token.agentType.padEnd(17)} | ${tokenShort} | ${expiresAt} | ${token.status}`);\r\n }\r\n\r\n return tokens;\r\n\r\n } catch (error) {\r\n console.error('❌ Failed to list tokens:', error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n async revokeToken(agentType, token) {\r\n try {\r\n const key = `mcp:agent:${agentType}:${token}`;\r\n const exists = await this.redis.exists(key);\r\n\r\n if (!exists) {\r\n throw new Error(`Token not found for agent ${agentType}`);\r\n }\r\n\r\n await this.redis.del(key);\r\n console.log(`✅ Token revoked successfully for agent ${agentType}`);\r\n console.log(` Token: ${token}`);\r\n\r\n } catch (error) {\r\n console.error('❌ Failed to revoke token:', error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n async revokeAllTokens(agentType = null) {\r\n try {\r\n const pattern = agentType ? `mcp:agent:${agentType}:*` : 'mcp:agent:*';\r\n const keys = await this.redis.keys(pattern);\r\n\r\n if (keys.length === 0) {\r\n console.log('No tokens found to revoke');\r\n return 0;\r\n }\r\n\r\n await this.redis.del(keys);\r\n console.log(`✅ Revoked ${keys.length} tokens${agentType ? ` for agent ${agentType}` : ''}`);\r\n return keys.length;\r\n\r\n } catch (error) {\r\n console.error('❌ Failed to revoke tokens:', error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n async validateToken(agentType, token) {\r\n try {\r\n const key = `mcp:agent:${agentType}:${token}`;\r\n const value = await this.redis.get(key);\r\n\r\n if (!value) {\r\n return { valid: false, reason: 'Token not found' };\r\n }\r\n\r\n const tokenData = JSON.parse(value);\r\n\r\n if (Date.now() > tokenData.expiresAt) {\r\n await this.redis.del(key);\r\n return { valid: false, reason: 'Token expired' };\r\n }\r\n\r\n return {\r\n valid: true,\r\n tokenData\r\n };\r\n\r\n } catch (error) {\r\n return { valid: false, reason: error.message };\r\n }\r\n }\r\n\r\n async getAgentInfo(agentType) {\r\n try {\r\n const config = await this.loadAgentConfig();\r\n const agentConfig = config.agents.find(a => a.type === agentType);\r\n\r\n if (!agentConfig) {\r\n throw new Error(`Unknown agent type: ${agentType}`);\r\n }\r\n\r\n console.log(`\\nAgent Information: ${agentConfig.displayName}`);\r\n console.log('='.repeat(50));\r\n console.log(`Type: ${agentConfig.type}`);\r\n console.log(`Skills: ${agentConfig.skills.join(', ')}`);\r\n console.log(`Allowed MCP Servers: ${agentConfig.allowedMcpServers.join(', ')}`);\r\n console.log(`Memory Limit: ${agentConfig.resourceLimits.maxMemoryMB}MB`);\r\n console.log(`Rate Limit: ${agentConfig.resourceLimits.maxRequestsPerMinute}/min`);\r\n console.log(`Max Concurrent: ${agentConfig.resourceLimits.maxConcurrentRequests}`);\r\n console.log(`Description: ${agentConfig.description}`);\r\n\r\n return agentConfig;\r\n\r\n } catch (error) {\r\n console.error('❌ Failed to get agent info:', error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n async listAgentTypes() {\r\n try {\r\n const config = await this.loadAgentConfig();\r\n\r\n console.log(`\\nAvailable Agent Types (${config.agents.length}):\\n`);\r\n console.log('Agent Type | Display Name | Skills Count');\r\n console.log('------------------------|--------------------------------|-------------');\r\n\r\n for (const agent of config.agents) {\r\n const type = agent.type.padEnd(22);\r\n const name = agent.displayName.padEnd(32);\r\n const skills = agent.skills.length;\r\n console.log(`${type} | ${name} | ${skills}`);\r\n }\r\n\r\n return config.agents.map(a => a.type);\r\n\r\n } catch (error) {\r\n console.error('❌ Failed to list agent types:', error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n async shutdown() {\r\n if (this.redis) {\r\n await this.redis.quit();\r\n }\r\n }\r\n}\r\n\r\n// CLI interface\r\nasync function main() {\r\n const args = process.argv.slice(2);\r\n const command = args[0];\r\n\r\n if (!command) {\r\n console.log(`\r\nAgent Token Management CLI\r\n\r\nUsage: node agent-token-manager.js <command> [options]\r\n\r\nCommands:\r\n register <agent-type> [options] Register a new token for an agent\r\n list [agent-type] List active tokens\r\n revoke <agent-type> <token> Revoke a specific token\r\n revoke-all [agent-type] Revoke all tokens (optionally for specific agent)\r\n validate <agent-type> <token> Validate a token\r\n info <agent-type> Show agent information\r\n types List available agent types\r\n\r\nOptions for 'register' command:\r\n --expires-in <duration> Token expiry (e.g., 1h, 30m, 7d) [default: 24h]\r\n --description <text> Token description\r\n --created-by <identifier> Creator identifier\r\n\r\nExamples:\r\n # Register token for frontend engineer\r\n node agent-token-manager.js register react-frontend-engineer\r\n\r\n # Register token with custom expiry\r\n node agent-token-manager.js register backend-developer --expires-in 2h\r\n\r\n # List all active tokens\r\n node agent-token-manager.js list\r\n\r\n # List tokens for specific agent\r\n node agent-token-manager.js list react-frontend-engineer\r\n\r\n # Revoke a specific token\r\n node agent-token-manager.js revoke react-frontend-engineer abc123...\r\n\r\n # Get agent information\r\n node agent-token-manager.js info security-specialist\r\n`);\r\n process.exit(0);\r\n }\r\n\r\n const tokenManager = new AgentTokenManager();\r\n\r\n try {\r\n await tokenManager.initialize();\r\n\r\n switch (command) {\r\n case 'register': {\r\n const agentType = args[1];\r\n if (!agentType) {\r\n throw new Error('Agent type is required for register command');\r\n }\r\n\r\n const options = {};\r\n for (let i = 2; i < args.length; i++) {\r\n if (args[i] === '--expires-in') {\r\n options.expiresIn = args[++i];\r\n } else if (args[i] === '--description') {\r\n options.description = args[++i];\r\n } else if (args[i] === '--created-by') {\r\n options.createdBy = args[++i];\r\n }\r\n }\r\n\r\n await tokenManager.registerAgentToken(agentType, options);\r\n break;\r\n }\r\n\r\n case 'list': {\r\n const agentType = args[1];\r\n await tokenManager.listActiveTokens(agentType);\r\n break;\r\n }\r\n\r\n case 'revoke': {\r\n const agentType = args[1];\r\n const token = args[2];\r\n if (!agentType || !token) {\r\n throw new Error('Agent type and token are required for revoke command');\r\n }\r\n await tokenManager.revokeToken(agentType, token);\r\n break;\r\n }\r\n\r\n case 'revoke-all': {\r\n const agentType = args[1];\r\n const count = await tokenManager.revokeAllTokens(agentType);\r\n console.log(`Revoked ${count} tokens`);\r\n break;\r\n }\r\n\r\n case 'validate': {\r\n const agentType = args[1];\r\n const token = args[2];\r\n if (!agentType || !token) {\r\n throw new Error('Agent type and token are required for validate command');\r\n }\r\n\r\n const result = await tokenManager.validateToken(agentType, token);\r\n if (result.valid) {\r\n console.log('✅ Token is valid');\r\n console.log(` Agent Type: ${result.tokenData.agentType}`);\r\n console.log(` Skills: ${result.tokenData.skills.join(', ')}`);\r\n console.log(` Expires: ${new Date(result.tokenData.expiresAt).toISOString()}`);\r\n } else {\r\n console.log('❌ Token is invalid');\r\n console.log(` Reason: ${result.reason}`);\r\n }\r\n break;\r\n }\r\n\r\n case 'info': {\r\n const agentType = args[1];\r\n if (!agentType) {\r\n throw new Error('Agent type is required for info command');\r\n }\r\n await tokenManager.getAgentInfo(agentType);\r\n break;\r\n }\r\n\r\n case 'types': {\r\n await tokenManager.listAgentTypes();\r\n break;\r\n }\r\n\r\n default:\r\n throw new Error(`Unknown command: ${command}`);\r\n }\r\n\r\n } catch (error) {\r\n console.error('❌ Error:', error.message);\r\n process.exit(1);\r\n } finally {\r\n await tokenManager.shutdown();\r\n }\r\n}\r\n\r\nif (require.main === module) {\r\n main().catch(error => {\r\n console.error('Fatal error:', error);\r\n process.exit(1);\r\n });\r\n}\r\n\r\nmodule.exports = AgentTokenManager;"],"names":["crypto","require","Redis","fs","promises","path","AgentTokenManager","options","redisUrl","process","env","MCP_REDIS_URL","redis","agentConfigPath","defaultExpiry","initialize","createClient","url","connect","console","log","error","loadAgentConfig","configPath","resolve","config","readFile","JSON","parse","generateToken","randomBytes","toString","parseExpiry","expiry","match","value","parseInt","unit","multipliers","s","m","h","d","registerAgentToken","agentType","agentConfig","agents","find","a","type","Error","map","join","token","expiresIn","expiresAt","Date","now","tokenData","displayName","skills","allowedMcpServers","resourceLimits","createdAt","createdBy","description","key","stringify","ttlSeconds","setEx","toISOString","maxMemoryMB","maxRequestsPerMinute","message","listActiveTokens","pattern","keys","tokens","get","push","status","length","tokenShort","substring","padEnd","revokeToken","exists","del","revokeAllTokens","validateToken","valid","reason","getAgentInfo","repeat","maxConcurrentRequests","listAgentTypes","agent","name","shutdown","quit","main","args","argv","slice","command","exit","tokenManager","i","count","result","module","catch","exports"],"mappings":"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"}
|
|
@@ -1,118 +1,100 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import * as fs from "fs/promises";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import Ajv from "ajv";
|
|
4
|
+
import * as lodash from "lodash";
|
|
5
|
+
let ConfigManager = class ConfigManager {
|
|
6
|
+
static _instance = null;
|
|
7
|
+
configPath;
|
|
8
|
+
schemaPath;
|
|
9
|
+
ajv;
|
|
10
|
+
constructor(){
|
|
11
|
+
this.configPath = path.join(process.env.HOME || "", ".claude-flow-config.json");
|
|
12
|
+
this.schemaPath = path.join(__dirname, "../../.claude/skills/config-management/config.json");
|
|
13
|
+
this.ajv = new Ajv();
|
|
7
14
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
step(generator.next(value));
|
|
12
|
-
} catch (e) {
|
|
13
|
-
reject(e);
|
|
14
|
-
}
|
|
15
|
+
static getInstance() {
|
|
16
|
+
if (!ConfigManager._instance) {
|
|
17
|
+
ConfigManager._instance = new ConfigManager();
|
|
15
18
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
return ConfigManager._instance;
|
|
20
|
+
}
|
|
21
|
+
async readConfig() {
|
|
22
|
+
try {
|
|
23
|
+
const configContent = await fs.readFile(this.configPath, "utf-8");
|
|
24
|
+
return JSON.parse(configContent);
|
|
25
|
+
} catch (error) {
|
|
26
|
+
// If config doesn't exist, create from schema
|
|
27
|
+
return this.resetToDefaults();
|
|
22
28
|
}
|
|
23
|
-
|
|
24
|
-
|
|
29
|
+
}
|
|
30
|
+
async writeConfig(config) {
|
|
31
|
+
const schemaContent = await fs.readFile(this.schemaPath, "utf-8");
|
|
32
|
+
const schema = JSON.parse(schemaContent);
|
|
33
|
+
const validate = this.ajv.compile(schema);
|
|
34
|
+
if (!validate(config)) {
|
|
35
|
+
throw new Error("Invalid configuration: " + this.ajv.errorsText(validate.errors));
|
|
25
36
|
}
|
|
26
|
-
|
|
27
|
-
});
|
|
28
|
-
};
|
|
29
|
-
var __generator = this && this.__generator || function(thisArg, body) {
|
|
30
|
-
var _ = {
|
|
31
|
-
label: 0,
|
|
32
|
-
sent: function() {
|
|
33
|
-
if (t[0] & 1) throw t[1];
|
|
34
|
-
return t[1];
|
|
35
|
-
},
|
|
36
|
-
trys: [],
|
|
37
|
-
ops: []
|
|
38
|
-
}, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
39
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
|
|
40
|
-
return this;
|
|
41
|
-
}), g;
|
|
42
|
-
function verb(n) {
|
|
43
|
-
return function(v) {
|
|
44
|
-
return step([
|
|
45
|
-
n,
|
|
46
|
-
v
|
|
47
|
-
]);
|
|
48
|
-
};
|
|
37
|
+
await fs.writeFile(this.configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
49
38
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
];
|
|
58
|
-
switch(op[0]){
|
|
59
|
-
case 0:
|
|
60
|
-
case 1:
|
|
61
|
-
t = op;
|
|
62
|
-
break;
|
|
63
|
-
case 4:
|
|
64
|
-
_.label++;
|
|
65
|
-
return {
|
|
66
|
-
value: op[1],
|
|
67
|
-
done: false
|
|
68
|
-
};
|
|
69
|
-
case 5:
|
|
70
|
-
_.label++;
|
|
71
|
-
y = op[1];
|
|
72
|
-
op = [
|
|
73
|
-
0
|
|
74
|
-
];
|
|
75
|
-
continue;
|
|
76
|
-
case 7:
|
|
77
|
-
op = _.ops.pop();
|
|
78
|
-
_.trys.pop();
|
|
79
|
-
continue;
|
|
80
|
-
default:
|
|
81
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
82
|
-
_ = 0;
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
85
|
-
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
|
|
86
|
-
_.label = op[1];
|
|
87
|
-
break;
|
|
88
|
-
}
|
|
89
|
-
if (op[0] === 6 && _.label < t[1]) {
|
|
90
|
-
_.label = t[1];
|
|
91
|
-
t = op;
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
94
|
-
if (t && _.label < t[2]) {
|
|
95
|
-
_.label = t[2];
|
|
96
|
-
_.ops.push(op);
|
|
97
|
-
break;
|
|
98
|
-
}
|
|
99
|
-
if (t[2]) _.ops.pop();
|
|
100
|
-
_.trys.pop();
|
|
101
|
-
continue;
|
|
102
|
-
}
|
|
103
|
-
op = body.call(thisArg, _);
|
|
104
|
-
} catch (e) {
|
|
105
|
-
op = [
|
|
106
|
-
6,
|
|
107
|
-
e
|
|
108
|
-
];
|
|
109
|
-
y = 0;
|
|
110
|
-
} finally{
|
|
111
|
-
f = t = 0;
|
|
39
|
+
async getValue(keyPath) {
|
|
40
|
+
const config = await this.readConfig();
|
|
41
|
+
const value = lodash.get(config, keyPath);
|
|
42
|
+
if (value === undefined) {
|
|
43
|
+
// Check if it's a custom key path not in the schema
|
|
44
|
+
const customConfig = await this.readCustomConfig();
|
|
45
|
+
return lodash.get(customConfig, keyPath);
|
|
112
46
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
47
|
+
return value;
|
|
48
|
+
}
|
|
49
|
+
async readCustomConfig() {
|
|
50
|
+
try {
|
|
51
|
+
const customConfigPath = path.join(process.env.HOME || "", ".claude-flow-custom-config.json");
|
|
52
|
+
const customConfigContent = await fs.readFile(customConfigPath, "utf-8");
|
|
53
|
+
return JSON.parse(customConfigContent);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
// If custom config doesn't exist or can't be read, return empty object
|
|
56
|
+
return {};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async set(key, value) {
|
|
60
|
+
const config = await this.readConfig();
|
|
61
|
+
// Type assertion to handle full object
|
|
62
|
+
if (typeof value === "object" && value !== null) {
|
|
63
|
+
config[key] = value;
|
|
64
|
+
} else {
|
|
65
|
+
throw new Error("Invalid configuration value");
|
|
66
|
+
}
|
|
67
|
+
await this.writeConfig(config);
|
|
68
|
+
}
|
|
69
|
+
async getAll() {
|
|
70
|
+
return this.readConfig();
|
|
71
|
+
}
|
|
72
|
+
async resetToDefaults() {
|
|
73
|
+
const schemaContent = await fs.readFile(this.schemaPath, "utf-8");
|
|
74
|
+
const schema = JSON.parse(schemaContent);
|
|
75
|
+
// Extract default values from the schema
|
|
76
|
+
const defaultConfig = {
|
|
77
|
+
redis: {
|
|
78
|
+
host: schema.properties.redis.properties.host.default,
|
|
79
|
+
port: schema.properties.redis.properties.port.default
|
|
80
|
+
},
|
|
81
|
+
agent: {
|
|
82
|
+
default_strategy: schema.properties.agent.properties.default_strategy.default,
|
|
83
|
+
max_concurrent_agents: schema.properties.agent.properties.max_concurrent_agents.default,
|
|
84
|
+
log_level: schema.properties.agent.properties.log_level.default
|
|
85
|
+
},
|
|
86
|
+
security: {
|
|
87
|
+
enabled: schema.properties.security.properties.enabled.default,
|
|
88
|
+
max_retry_attempts: schema.properties.security.properties.max_retry_attempts.default
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
await this.writeConfig(defaultConfig);
|
|
92
|
+
return defaultConfig;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
export default ConfigManager;
|
|
96
|
+
|
|
97
|
+
//# sourceMappingURL=config-manager.js.mapop[1] : void 0,
|
|
116
98
|
done: true
|
|
117
99
|
};
|
|
118
100
|
}
|