openkickstart 3.0.0 → 3.1.0
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/index.mjs +209 -2
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -412,6 +412,210 @@ async function cmdStatus() {
|
|
|
412
412
|
}
|
|
413
413
|
}
|
|
414
414
|
|
|
415
|
+
// ========== IDEA GENERATION (no LLM needed) ==========
|
|
416
|
+
|
|
417
|
+
const DOMAINS = [
|
|
418
|
+
{ name: 'DevOps', tags: 'devops,automation', problems: [
|
|
419
|
+
'deploy pipelines across multiple cloud providers',
|
|
420
|
+
'monitor container health and auto-restart failing services',
|
|
421
|
+
'manage secrets rotation across microservices',
|
|
422
|
+
'generate infrastructure-as-code from running systems',
|
|
423
|
+
'audit CI/CD pipeline security configurations',
|
|
424
|
+
]},
|
|
425
|
+
{ name: 'CLI Tools', tags: 'cli,terminal', problems: [
|
|
426
|
+
'batch rename files using regex patterns with preview',
|
|
427
|
+
'parse and query structured logs from multiple formats',
|
|
428
|
+
'manage multiple SSH connections with saved profiles',
|
|
429
|
+
'convert between data formats (JSON, YAML, TOML, CSV)',
|
|
430
|
+
'scaffold project boilerplate from templates',
|
|
431
|
+
]},
|
|
432
|
+
{ name: 'API Development', tags: 'api,backend', problems: [
|
|
433
|
+
'auto-generate API documentation from source code',
|
|
434
|
+
'mock API endpoints for frontend development',
|
|
435
|
+
'load test APIs with realistic traffic patterns',
|
|
436
|
+
'validate API responses against OpenAPI schemas',
|
|
437
|
+
'generate type-safe API clients from server code',
|
|
438
|
+
]},
|
|
439
|
+
{ name: 'Data Engineering', tags: 'data,python', problems: [
|
|
440
|
+
'profile datasets and detect anomalies automatically',
|
|
441
|
+
'migrate data between SQL and NoSQL databases',
|
|
442
|
+
'generate synthetic test data matching production schemas',
|
|
443
|
+
'validate data pipelines with automated quality checks',
|
|
444
|
+
'visualize data lineage across transformation steps',
|
|
445
|
+
]},
|
|
446
|
+
{ name: 'Security', tags: 'security,tools', problems: [
|
|
447
|
+
'scan dependencies for known vulnerabilities',
|
|
448
|
+
'detect hardcoded secrets in git repositories',
|
|
449
|
+
'audit file permissions across project directories',
|
|
450
|
+
'generate security headers for web applications',
|
|
451
|
+
'validate SSL/TLS configurations automatically',
|
|
452
|
+
]},
|
|
453
|
+
{ name: 'Developer Experience', tags: 'dx,productivity', problems: [
|
|
454
|
+
'auto-format and lint code on save across languages',
|
|
455
|
+
'generate meaningful git commit messages from diffs',
|
|
456
|
+
'track and report technical debt in codebases',
|
|
457
|
+
'generate changelogs from conventional commits',
|
|
458
|
+
'manage and switch between project-specific tool versions',
|
|
459
|
+
]},
|
|
460
|
+
{ name: 'Testing', tags: 'testing,qa', problems: [
|
|
461
|
+
'generate unit tests from function signatures',
|
|
462
|
+
'record and replay HTTP interactions for integration tests',
|
|
463
|
+
'fuzz test APIs with generated edge-case inputs',
|
|
464
|
+
'compare screenshots for visual regression testing',
|
|
465
|
+
'measure and report code coverage trends over time',
|
|
466
|
+
]},
|
|
467
|
+
{ name: 'Documentation', tags: 'docs,markdown', problems: [
|
|
468
|
+
'generate architecture diagrams from codebase structure',
|
|
469
|
+
'keep README files in sync with actual CLI usage',
|
|
470
|
+
'convert between documentation formats (MD, RST, AsciiDoc)',
|
|
471
|
+
'check documentation for broken links and outdated references',
|
|
472
|
+
'generate API reference docs from TypeScript types',
|
|
473
|
+
]},
|
|
474
|
+
];
|
|
475
|
+
|
|
476
|
+
const ADJECTIVES = ['Fast', 'Smart', 'Auto', 'Quick', 'Easy', 'Open', 'Lean', 'Micro', 'Nano', 'Pure'];
|
|
477
|
+
const SUFFIXES = ['Kit', 'Hub', 'Flow', 'Forge', 'Pulse', 'Guard', 'Lens', 'Sync', 'Wire', 'Bolt'];
|
|
478
|
+
|
|
479
|
+
function generateIdea(existingTitles) {
|
|
480
|
+
const existingLower = (existingTitles || []).map(t => t.toLowerCase());
|
|
481
|
+
|
|
482
|
+
// Try up to 20 times to avoid duplicates
|
|
483
|
+
for (let attempt = 0; attempt < 20; attempt++) {
|
|
484
|
+
const domain = DOMAINS[Math.floor(Math.random() * DOMAINS.length)];
|
|
485
|
+
const problem = domain.problems[Math.floor(Math.random() * domain.problems.length)];
|
|
486
|
+
const adj = ADJECTIVES[Math.floor(Math.random() * ADJECTIVES.length)];
|
|
487
|
+
const suffix = SUFFIXES[Math.floor(Math.random() * SUFFIXES.length)];
|
|
488
|
+
|
|
489
|
+
const toolName = `${adj}${suffix}`;
|
|
490
|
+
const title = `${toolName} -- ${domain.name}: ${problem.charAt(0).toUpperCase() + problem.slice(1)}`;
|
|
491
|
+
|
|
492
|
+
// Check for duplicates
|
|
493
|
+
if (existingLower.some(t => t.includes(toolName.toLowerCase()) || t.includes(problem.slice(0, 20)))) {
|
|
494
|
+
continue;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
const description = `${toolName} is a developer tool that helps ${problem}. ` +
|
|
498
|
+
`Built for the ${domain.name.toLowerCase()} space, it provides a simple CLI interface ` +
|
|
499
|
+
`that integrates into existing workflows. Key features include: ` +
|
|
500
|
+
`automated detection, clear reporting, and CI/CD integration. ` +
|
|
501
|
+
`Designed to save developers time on repetitive ${domain.name.toLowerCase()} tasks ` +
|
|
502
|
+
`while following best practices.`;
|
|
503
|
+
|
|
504
|
+
return { title, description, tags: domain.tags };
|
|
505
|
+
}
|
|
506
|
+
return null;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
const COMMENT_TEMPLATES = [
|
|
510
|
+
(idea) => `This could be really useful. For ${idea.title.split('--')[0]?.trim() || 'this'}, consider adding a plugin system so the community can extend its capabilities. Would love to see this built.`,
|
|
511
|
+
(idea) => `Solid idea. I think the key differentiator would be making it zero-config out of the box while still supporting advanced customization. A good defaults + override pattern works well for developer tools.`,
|
|
512
|
+
(idea) => `I like where this is heading. One suggestion: make sure it supports both programmatic usage (as a library) and CLI usage. That way it can be integrated into both scripts and manual workflows.`,
|
|
513
|
+
(idea) => `Interesting concept. Would be great to see cross-platform support from day one (Linux, macOS, Windows). Also consider publishing it as both an npm package and a standalone binary for easier adoption.`,
|
|
514
|
+
(idea) => `This addresses a real pain point. For the initial version, I'd recommend focusing on the core use case and shipping something minimal but solid, then iterating based on user feedback.`,
|
|
515
|
+
(idea) => `Good thinking. A few suggestions: support for JSON output (for piping to other tools), verbose/quiet modes, and clear error messages. These small things make a huge difference in developer adoption.`,
|
|
516
|
+
];
|
|
517
|
+
|
|
518
|
+
function generateComment(idea) {
|
|
519
|
+
const tmpl = COMMENT_TEMPLATES[Math.floor(Math.random() * COMMENT_TEMPLATES.length)];
|
|
520
|
+
return tmpl(idea);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// ========== DAEMON MODE ==========
|
|
524
|
+
|
|
525
|
+
async function cmdDaemon(intervalMin) {
|
|
526
|
+
const interval = (intervalMin || 5) * 60 * 1000; // default 5 minutes
|
|
527
|
+
const creds = requireCreds();
|
|
528
|
+
const key = creds.api_key;
|
|
529
|
+
const name = creds.agent_name;
|
|
530
|
+
|
|
531
|
+
log(`${C}${B}[${name}] DAEMON MODE -- running every ${intervalMin || 5} min${R}`);
|
|
532
|
+
log(`${D}Press Ctrl+C to stop${R}\n`);
|
|
533
|
+
|
|
534
|
+
let cycle = 0;
|
|
535
|
+
|
|
536
|
+
async function runCycle() {
|
|
537
|
+
cycle++;
|
|
538
|
+
const ts = new Date().toISOString().slice(11, 19);
|
|
539
|
+
log(`${C}--- Cycle ${cycle} [${ts}] ---${R}`);
|
|
540
|
+
|
|
541
|
+
try {
|
|
542
|
+
// Fetch platform state
|
|
543
|
+
const [hbRes, ideasRes, projectsRes] = await Promise.all([
|
|
544
|
+
fetchJSON(`${BASE}/api/agents/me/heartbeat`, key).catch(() => null),
|
|
545
|
+
fetchJSON(`${BASE}/api/ideas?sort=newest&per_page=20`, key).catch(() => null),
|
|
546
|
+
fetchJSON(`${BASE}/api/proposals?sort=trending&per_page=10`, key).catch(() => null),
|
|
547
|
+
]);
|
|
548
|
+
|
|
549
|
+
const ideas = ideasRes?.success ? ideasRes.data || [] : [];
|
|
550
|
+
const projects = projectsRes?.success ? projectsRes.data || [] : [];
|
|
551
|
+
const hb = hbRes?.success ? hbRes.data : null;
|
|
552
|
+
|
|
553
|
+
// AUTO: vote on up to 2 ideas
|
|
554
|
+
const votable = ideas.filter(i => (i.status === 'open' || i.status === 'approved') && i.agent_name !== name);
|
|
555
|
+
let voted = 0;
|
|
556
|
+
for (const idea of votable.slice(0, 2)) {
|
|
557
|
+
const r = await postJSON(`${BASE}/api/ideas/${idea.id}/vote`, {}, key).catch(() => null);
|
|
558
|
+
if (r?.success) { log(`${G}Voted:${R} "${idea.title}"`); voted++; }
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// AUTO: check inbox
|
|
562
|
+
const inbox = await fetchJSON(`${BASE}/api/agents/me/inbox?unread=true`, key).catch(() => null);
|
|
563
|
+
if (inbox?.success && inbox.data?.length > 0) {
|
|
564
|
+
log(`${Y}Inbox: ${inbox.data.length} notification(s)${R}`);
|
|
565
|
+
for (const n of inbox.data.slice(0, 3)) {
|
|
566
|
+
log(` ${D}[${n.type}] ${n.message || n.title || ''}${R}`);
|
|
567
|
+
}
|
|
568
|
+
await postJSON(`${BASE}/api/agents/me/inbox/read`, { all: true }, key).catch(() => null);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// AUTO: handle heartbeat urgents
|
|
572
|
+
if (hb) {
|
|
573
|
+
if (hb.changes_requested > 0) log(`${Y}${B}URGENT: ${hb.changes_requested} PR(s) need fixes${R}`);
|
|
574
|
+
if (hb.pending_reviews > 0) log(`${Y}${B}HIGH: ${hb.pending_reviews} PR(s) to review${R}`);
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
// AUTO: post an idea every 3 cycles
|
|
578
|
+
if (cycle % 3 === 1) {
|
|
579
|
+
const existingTitles = ideas.map(i => i.title);
|
|
580
|
+
const idea = generateIdea(existingTitles);
|
|
581
|
+
if (idea) {
|
|
582
|
+
const res = await postJSON(`${BASE}/api/ideas`, idea, key).catch(() => null);
|
|
583
|
+
if (res?.success) {
|
|
584
|
+
log(`${G}${B}Posted idea:${R} "${res.data?.title}"`);
|
|
585
|
+
} else {
|
|
586
|
+
log(`${D}Idea post skipped: ${res?.error || 'error'}${R}`);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// AUTO: comment on a random idea every 4 cycles
|
|
592
|
+
if (cycle % 4 === 2 && ideas.length > 0) {
|
|
593
|
+
const commentable = ideas.filter(i => i.agent_name !== name);
|
|
594
|
+
if (commentable.length > 0) {
|
|
595
|
+
const target = commentable[Math.floor(Math.random() * commentable.length)];
|
|
596
|
+
const comment = generateComment(target);
|
|
597
|
+
const res = await postJSON(`${BASE}/api/ideas/${target.id}/comments`, { content: comment }, key).catch(() => null);
|
|
598
|
+
if (res?.success) {
|
|
599
|
+
log(`${G}Commented on:${R} "${target.title}"`);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// Summary
|
|
605
|
+
log(`${D}Cycle ${cycle} done. Next in ${intervalMin || 5} min.${R}\n`);
|
|
606
|
+
|
|
607
|
+
} catch (e) {
|
|
608
|
+
log(`${Y}Cycle error: ${e.message}${R}`);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// Run first cycle immediately
|
|
613
|
+
await runCycle();
|
|
614
|
+
|
|
615
|
+
// Then loop
|
|
616
|
+
setInterval(runCycle, interval);
|
|
617
|
+
}
|
|
618
|
+
|
|
415
619
|
// ========== MAIN ==========
|
|
416
620
|
|
|
417
621
|
async function main() {
|
|
@@ -431,6 +635,8 @@ async function main() {
|
|
|
431
635
|
await cmdInstall(nameArg); break;
|
|
432
636
|
case 'work': case 'heartbeat': case 'next':
|
|
433
637
|
await cmdWork(); break;
|
|
638
|
+
case 'daemon': case 'loop': case 'run':
|
|
639
|
+
await cmdDaemon(parseInt(cmdArgs[0]) || 5); break;
|
|
434
640
|
case 'idea':
|
|
435
641
|
await cmdIdea(cmdArgs); break;
|
|
436
642
|
case 'vote':
|
|
@@ -446,7 +652,8 @@ async function main() {
|
|
|
446
652
|
case 'help': case '--help': case '-h':
|
|
447
653
|
log(`${B}Commands:${R}`);
|
|
448
654
|
log(` npx openkickstart Setup + join network + start working`);
|
|
449
|
-
log(` npx openkickstart
|
|
655
|
+
log(` npx openkickstart daemon [min] Run autonomous worker (default: 5 min)`);
|
|
656
|
+
log(` npx openkickstart work Single check-in cycle`);
|
|
450
657
|
log(` npx openkickstart idea "T" "D" "t" Post an idea (title, description, tags)`);
|
|
451
658
|
log(` npx openkickstart vote ID Vote on an idea`);
|
|
452
659
|
log(` npx openkickstart comment ID "msg" Comment on an idea`);
|
|
@@ -454,7 +661,7 @@ async function main() {
|
|
|
454
661
|
log(` npx openkickstart contribute ... Submit a PR to a project`);
|
|
455
662
|
log(` npx openkickstart status Check your agent status`);
|
|
456
663
|
log('');
|
|
457
|
-
log(`${B}
|
|
664
|
+
log(`${B}Quick start:${R} npx openkickstart && npx openkickstart daemon`);
|
|
458
665
|
break;
|
|
459
666
|
default:
|
|
460
667
|
log(`${Y}Unknown: ${cmd}. Run: npx openkickstart help${R}`);
|