myaidev-method 0.2.18 → 0.2.22
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/mcp/sparc-orchestrator-server.js +0 -0
- package/.claude/mcp/wordpress-server.js +0 -0
- package/CHANGELOG.md +145 -0
- package/README.md +205 -13
- package/TECHNICAL_ARCHITECTURE.md +64 -2
- package/bin/cli.js +169 -2
- package/dist/mcp/mcp-config.json +138 -1
- package/dist/mcp/openstack-server.js +1607 -0
- package/package.json +2 -2
- package/src/config/workflows.js +532 -0
- package/src/lib/payloadcms-utils.js +343 -10
- package/src/lib/visual-generation-utils.js +445 -294
- package/src/lib/workflow-installer.js +512 -0
- package/src/libs/security/authorization-checker.js +606 -0
- package/src/mcp/openstack-server.js +1607 -0
- package/src/scripts/openstack-setup.sh +110 -0
- package/src/scripts/security/environment-detect.js +425 -0
- package/src/templates/claude/agents/openstack-vm-manager.md +281 -0
- package/src/templates/claude/agents/osint-researcher.md +1075 -0
- package/src/templates/claude/agents/penetration-tester.md +908 -0
- package/src/templates/claude/agents/security-auditor.md +244 -0
- package/src/templates/claude/agents/security-setup.md +1094 -0
- package/src/templates/claude/agents/webapp-security-tester.md +581 -0
- package/src/templates/claude/commands/myai-configure.md +84 -0
- package/src/templates/claude/commands/myai-openstack.md +229 -0
- package/src/templates/claude/commands/sc:security-exploit.md +464 -0
- package/src/templates/claude/commands/sc:security-recon.md +281 -0
- package/src/templates/claude/commands/sc:security-report.md +756 -0
- package/src/templates/claude/commands/sc:security-scan.md +441 -0
- package/src/templates/claude/commands/sc:security-setup.md +501 -0
- package/src/templates/claude/mcp_config.json +44 -0
|
@@ -144,7 +144,7 @@ export class PayloadCMSUtils {
|
|
|
144
144
|
|
|
145
145
|
case 'list':
|
|
146
146
|
return {
|
|
147
|
-
type:
|
|
147
|
+
type: 'list',
|
|
148
148
|
listType: token.ordered ? 'number' : 'bullet',
|
|
149
149
|
start: token.start || 1,
|
|
150
150
|
tag: token.ordered ? 'ol' : 'ul',
|
|
@@ -213,7 +213,10 @@ export class PayloadCMSUtils {
|
|
|
213
213
|
}
|
|
214
214
|
};
|
|
215
215
|
|
|
216
|
-
|
|
216
|
+
// Filter out space tokens and convert remaining tokens
|
|
217
|
+
const children = tokens
|
|
218
|
+
.filter(token => token.type !== 'space')
|
|
219
|
+
.map(convertToken);
|
|
217
220
|
|
|
218
221
|
return {
|
|
219
222
|
root: {
|
|
@@ -229,24 +232,353 @@ export class PayloadCMSUtils {
|
|
|
229
232
|
|
|
230
233
|
/**
|
|
231
234
|
* Parse inline text with formatting (bold, italic, code, links)
|
|
235
|
+
* Supports markdown formatters and converts to Lexical format codes:
|
|
236
|
+
* - **bold** → format: 1
|
|
237
|
+
* - *italic* → format: 2
|
|
238
|
+
* - `code` → format: 16
|
|
239
|
+
* - ***bold+italic*** → format: 3
|
|
232
240
|
*/
|
|
233
241
|
parseInlineText(text) {
|
|
234
|
-
// Simple inline parser for bold, italic, code, links
|
|
235
242
|
const children = [];
|
|
236
243
|
|
|
237
|
-
//
|
|
238
|
-
|
|
239
|
-
|
|
244
|
+
// Strip HTML tags first
|
|
245
|
+
text = text.replace(/<[^>]+>/g, '');
|
|
246
|
+
|
|
247
|
+
// Parse markdown inline formatting using marked's inline lexer
|
|
248
|
+
try {
|
|
249
|
+
const tokens = marked.lexer(text);
|
|
250
|
+
|
|
251
|
+
// Extract inline tokens from paragraph if present
|
|
252
|
+
let inlineTokens = [];
|
|
253
|
+
if (tokens[0]?.type === 'paragraph' && tokens[0].tokens) {
|
|
254
|
+
inlineTokens = tokens[0].tokens;
|
|
255
|
+
} else if (tokens[0]?.tokens) {
|
|
256
|
+
inlineTokens = tokens[0].tokens;
|
|
257
|
+
} else {
|
|
258
|
+
// No inline tokens, return plain text
|
|
259
|
+
return [{
|
|
260
|
+
type: 'text',
|
|
261
|
+
text: text,
|
|
262
|
+
format: 0,
|
|
263
|
+
mode: 'normal',
|
|
264
|
+
style: '',
|
|
265
|
+
detail: 0,
|
|
266
|
+
version: 1
|
|
267
|
+
}];
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Convert each inline token to Lexical format
|
|
271
|
+
for (const token of inlineTokens) {
|
|
272
|
+
switch (token.type) {
|
|
273
|
+
case 'text':
|
|
274
|
+
children.push({
|
|
275
|
+
type: 'text',
|
|
276
|
+
text: token.text,
|
|
277
|
+
format: 0,
|
|
278
|
+
mode: 'normal',
|
|
279
|
+
style: '',
|
|
280
|
+
detail: 0,
|
|
281
|
+
version: 1
|
|
282
|
+
});
|
|
283
|
+
break;
|
|
284
|
+
|
|
285
|
+
case 'strong':
|
|
286
|
+
children.push({
|
|
287
|
+
type: 'text',
|
|
288
|
+
text: token.text,
|
|
289
|
+
format: 1, // IS_BOLD
|
|
290
|
+
mode: 'normal',
|
|
291
|
+
style: '',
|
|
292
|
+
detail: 0,
|
|
293
|
+
version: 1
|
|
294
|
+
});
|
|
295
|
+
break;
|
|
296
|
+
|
|
297
|
+
case 'em':
|
|
298
|
+
children.push({
|
|
299
|
+
type: 'text',
|
|
300
|
+
text: token.text,
|
|
301
|
+
format: 2, // IS_ITALIC
|
|
302
|
+
mode: 'normal',
|
|
303
|
+
style: '',
|
|
304
|
+
detail: 0,
|
|
305
|
+
version: 1
|
|
306
|
+
});
|
|
307
|
+
break;
|
|
308
|
+
|
|
309
|
+
case 'codespan':
|
|
310
|
+
children.push({
|
|
311
|
+
type: 'text',
|
|
312
|
+
text: token.text,
|
|
313
|
+
format: 16, // IS_CODE
|
|
314
|
+
mode: 'normal',
|
|
315
|
+
style: '',
|
|
316
|
+
detail: 0,
|
|
317
|
+
version: 1
|
|
318
|
+
});
|
|
319
|
+
break;
|
|
320
|
+
|
|
321
|
+
case 'link':
|
|
322
|
+
children.push({
|
|
323
|
+
type: 'link',
|
|
324
|
+
url: token.href,
|
|
325
|
+
children: [{
|
|
326
|
+
type: 'text',
|
|
327
|
+
text: token.text,
|
|
328
|
+
format: 0,
|
|
329
|
+
mode: 'normal',
|
|
330
|
+
style: '',
|
|
331
|
+
detail: 0,
|
|
332
|
+
version: 1
|
|
333
|
+
}],
|
|
334
|
+
direction: 'ltr',
|
|
335
|
+
format: '',
|
|
336
|
+
indent: 0,
|
|
337
|
+
version: 3
|
|
338
|
+
});
|
|
339
|
+
break;
|
|
340
|
+
|
|
341
|
+
default:
|
|
342
|
+
// Fallback for any unhandled token types
|
|
343
|
+
children.push({
|
|
344
|
+
type: 'text',
|
|
345
|
+
text: token.raw || token.text || '',
|
|
346
|
+
format: 0,
|
|
347
|
+
mode: 'normal',
|
|
348
|
+
style: '',
|
|
349
|
+
detail: 0,
|
|
350
|
+
version: 1
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
} catch (error) {
|
|
355
|
+
// If parsing fails, return plain text
|
|
356
|
+
children.push({
|
|
357
|
+
type: 'text',
|
|
358
|
+
text: text,
|
|
359
|
+
format: 0,
|
|
360
|
+
mode: 'normal',
|
|
361
|
+
style: '',
|
|
362
|
+
detail: 0,
|
|
363
|
+
version: 1
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
return children.length > 0 ? children : [{
|
|
240
368
|
type: 'text',
|
|
241
|
-
text: text
|
|
369
|
+
text: text,
|
|
242
370
|
format: 0,
|
|
243
371
|
mode: 'normal',
|
|
244
372
|
style: '',
|
|
245
373
|
detail: 0,
|
|
246
374
|
version: 1
|
|
375
|
+
}];
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Validate Lexical JSON structure
|
|
380
|
+
* Ensures output matches PayloadCMS Lexical editor format
|
|
381
|
+
* @param {Object} lexicalJSON - The Lexical JSON to validate
|
|
382
|
+
* @param {Object} options - Validation options
|
|
383
|
+
* @returns {Object} Validation result with errors array
|
|
384
|
+
*/
|
|
385
|
+
validateLexicalStructure(lexicalJSON, options = {}) {
|
|
386
|
+
const errors = [];
|
|
387
|
+
const warnings = [];
|
|
388
|
+
|
|
389
|
+
// Check root structure
|
|
390
|
+
if (!lexicalJSON || typeof lexicalJSON !== 'object') {
|
|
391
|
+
errors.push('Lexical JSON must be an object');
|
|
392
|
+
return { valid: false, errors, warnings };
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (!lexicalJSON.root) {
|
|
396
|
+
errors.push('Missing root node');
|
|
397
|
+
return { valid: false, errors, warnings };
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const root = lexicalJSON.root;
|
|
401
|
+
|
|
402
|
+
// Validate root node
|
|
403
|
+
if (root.type !== 'root') {
|
|
404
|
+
errors.push(`Root type must be 'root', got '${root.type}'`);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
if (!Array.isArray(root.children)) {
|
|
408
|
+
errors.push('Root must have children array');
|
|
409
|
+
return { valid: false, errors, warnings };
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// Validate each child node
|
|
413
|
+
const validateNode = (node, path = 'root') => {
|
|
414
|
+
if (!node || typeof node !== 'object') {
|
|
415
|
+
errors.push(`${path}: Node must be an object`);
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
if (!node.type) {
|
|
420
|
+
errors.push(`${path}: Node missing type property`);
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Validate based on node type
|
|
425
|
+
switch (node.type) {
|
|
426
|
+
case 'heading':
|
|
427
|
+
if (!node.tag || !/^h[1-6]$/.test(node.tag)) {
|
|
428
|
+
errors.push(`${path}: Heading must have tag h1-h6, got '${node.tag}'`);
|
|
429
|
+
}
|
|
430
|
+
if (!Array.isArray(node.children)) {
|
|
431
|
+
errors.push(`${path}: Heading must have children array`);
|
|
432
|
+
}
|
|
433
|
+
break;
|
|
434
|
+
|
|
435
|
+
case 'paragraph':
|
|
436
|
+
if (!Array.isArray(node.children)) {
|
|
437
|
+
errors.push(`${path}: Paragraph must have children array`);
|
|
438
|
+
}
|
|
439
|
+
break;
|
|
440
|
+
|
|
441
|
+
case 'list':
|
|
442
|
+
if (!['bullet', 'number', 'check'].includes(node.listType)) {
|
|
443
|
+
errors.push(`${path}: List listType must be bullet/number/check, got '${node.listType}'`);
|
|
444
|
+
}
|
|
445
|
+
if (!['ul', 'ol'].includes(node.tag)) {
|
|
446
|
+
errors.push(`${path}: List tag must be ul/ol, got '${node.tag}'`);
|
|
447
|
+
}
|
|
448
|
+
if (!Array.isArray(node.children)) {
|
|
449
|
+
errors.push(`${path}: List must have children array`);
|
|
450
|
+
}
|
|
451
|
+
// Validate list items
|
|
452
|
+
node.children?.forEach((item, i) => {
|
|
453
|
+
if (item.type !== 'listitem') {
|
|
454
|
+
errors.push(`${path}.children[${i}]: List child must be listitem, got '${item.type}'`);
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
break;
|
|
458
|
+
|
|
459
|
+
case 'listitem':
|
|
460
|
+
if (!Array.isArray(node.children)) {
|
|
461
|
+
errors.push(`${path}: Listitem must have children array`);
|
|
462
|
+
}
|
|
463
|
+
break;
|
|
464
|
+
|
|
465
|
+
case 'text':
|
|
466
|
+
if (typeof node.text !== 'string') {
|
|
467
|
+
errors.push(`${path}: Text node must have string text property`);
|
|
468
|
+
}
|
|
469
|
+
if (typeof node.format !== 'number') {
|
|
470
|
+
errors.push(`${path}: Text node format must be number, got ${typeof node.format}`);
|
|
471
|
+
}
|
|
472
|
+
// Validate format is valid bitwise combination
|
|
473
|
+
if (node.format !== 0 && options.strictFormat) {
|
|
474
|
+
const validFormats = [1, 2, 3, 4, 8, 16, 32, 64, 128];
|
|
475
|
+
const isValidCombination = (format) => {
|
|
476
|
+
// Check if format is valid bitwise combination of base values
|
|
477
|
+
return format <= 255 && (format & ~255) === 0;
|
|
478
|
+
};
|
|
479
|
+
if (!isValidCombination(node.format)) {
|
|
480
|
+
warnings.push(`${path}: Unusual format value ${node.format}, expected bitwise combination`);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
break;
|
|
484
|
+
|
|
485
|
+
case 'link':
|
|
486
|
+
if (typeof node.url !== 'string') {
|
|
487
|
+
errors.push(`${path}: Link must have string url property`);
|
|
488
|
+
}
|
|
489
|
+
if (!Array.isArray(node.children)) {
|
|
490
|
+
errors.push(`${path}: Link must have children array`);
|
|
491
|
+
}
|
|
492
|
+
break;
|
|
493
|
+
|
|
494
|
+
case 'code':
|
|
495
|
+
if (!Array.isArray(node.children)) {
|
|
496
|
+
errors.push(`${path}: Code must have children array`);
|
|
497
|
+
}
|
|
498
|
+
break;
|
|
499
|
+
|
|
500
|
+
case 'quote':
|
|
501
|
+
if (!Array.isArray(node.children)) {
|
|
502
|
+
errors.push(`${path}: Quote must have children array`);
|
|
503
|
+
}
|
|
504
|
+
break;
|
|
505
|
+
|
|
506
|
+
case 'horizontalrule':
|
|
507
|
+
// HR nodes don't have children
|
|
508
|
+
break;
|
|
509
|
+
|
|
510
|
+
default:
|
|
511
|
+
if (options.strict) {
|
|
512
|
+
warnings.push(`${path}: Unknown node type '${node.type}'`);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// Recursively validate children
|
|
517
|
+
if (Array.isArray(node.children)) {
|
|
518
|
+
node.children.forEach((child, i) => {
|
|
519
|
+
validateNode(child, `${path}.children[${i}]`);
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
// Validate all root children
|
|
525
|
+
root.children.forEach((child, i) => {
|
|
526
|
+
validateNode(child, `root.children[${i}]`);
|
|
247
527
|
});
|
|
248
528
|
|
|
249
|
-
return
|
|
529
|
+
return {
|
|
530
|
+
valid: errors.length === 0,
|
|
531
|
+
errors,
|
|
532
|
+
warnings
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Validate and optionally fix Lexical format codes
|
|
538
|
+
* Ensures format codes follow Lexical bitwise specification
|
|
539
|
+
* @param {number} format - The format code to validate
|
|
540
|
+
* @returns {Object} Validation result
|
|
541
|
+
*/
|
|
542
|
+
validateFormatCode(format) {
|
|
543
|
+
const VALID_FORMATS = {
|
|
544
|
+
BOLD: 1, // 1 << 0
|
|
545
|
+
ITALIC: 2, // 1 << 1
|
|
546
|
+
STRIKETHROUGH: 4, // 1 << 2
|
|
547
|
+
UNDERLINE: 8, // 1 << 3
|
|
548
|
+
CODE: 16, // 1 << 4
|
|
549
|
+
SUBSCRIPT: 32, // 1 << 5
|
|
550
|
+
SUPERSCRIPT: 64, // 1 << 6
|
|
551
|
+
HIGHLIGHT: 128 // 1 << 7
|
|
552
|
+
};
|
|
553
|
+
|
|
554
|
+
if (typeof format !== 'number') {
|
|
555
|
+
return {
|
|
556
|
+
valid: false,
|
|
557
|
+
error: `Format must be number, got ${typeof format}`
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
if (format < 0 || format > 255) {
|
|
562
|
+
return {
|
|
563
|
+
valid: false,
|
|
564
|
+
error: `Format must be between 0 and 255, got ${format}`
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// Decompose format into individual flags
|
|
569
|
+
const flags = [];
|
|
570
|
+
Object.entries(VALID_FORMATS).forEach(([name, value]) => {
|
|
571
|
+
if ((format & value) === value) {
|
|
572
|
+
flags.push(name);
|
|
573
|
+
}
|
|
574
|
+
});
|
|
575
|
+
|
|
576
|
+
return {
|
|
577
|
+
valid: true,
|
|
578
|
+
format,
|
|
579
|
+
flags,
|
|
580
|
+
description: flags.length > 0 ? flags.join(' + ') : 'Plain text'
|
|
581
|
+
};
|
|
250
582
|
}
|
|
251
583
|
|
|
252
584
|
/**
|
|
@@ -372,11 +704,12 @@ export class PayloadCMSUtils {
|
|
|
372
704
|
}
|
|
373
705
|
|
|
374
706
|
/**
|
|
375
|
-
* Health check
|
|
707
|
+
* Health check - verifies PayloadCMS connectivity and database access
|
|
708
|
+
* Uses /api/posts endpoint to verify both API and database are accessible
|
|
376
709
|
*/
|
|
377
710
|
async healthCheck() {
|
|
378
711
|
try {
|
|
379
|
-
const response = await fetch(`${this.url}/api`);
|
|
712
|
+
const response = await fetch(`${this.url}/api/posts?limit=1`);
|
|
380
713
|
return response.ok;
|
|
381
714
|
} catch (error) {
|
|
382
715
|
return false;
|