@kernel.chat/kbot 3.8.1 → 3.9.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/dist/agent.d.ts +2 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +29 -5
- package/dist/agent.js.map +1 -1
- package/dist/automations.d.ts +96 -0
- package/dist/automations.d.ts.map +1 -0
- package/dist/automations.js +576 -0
- package/dist/automations.js.map +1 -0
- package/dist/cli.js +420 -3
- package/dist/cli.js.map +1 -1
- package/dist/collective.d.ts +2 -0
- package/dist/collective.d.ts.map +1 -1
- package/dist/collective.js +4 -0
- package/dist/collective.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -20,7 +20,7 @@ import { clearHistory, clearMemory, compactHistory, restoreHistory } from './mem
|
|
|
20
20
|
import { saveSession, loadSession, listSessions, deleteSession, formatSessionList, } from './sessions.js';
|
|
21
21
|
import { createAgent, removeAgent, getAgent, formatAgentList, formatAgentDetail, PRESETS, getMatrixAgentIds, activateMimic, listMimicProfiles, getMimicProfile, registerBuiltinAgents, formatBuiltinAgentList, formatBuiltinAgentDetail, } from './matrix.js';
|
|
22
22
|
import { getExtendedStats, incrementSessions, learnFact, selfTrain, getTrainingLog, flushPendingWrites } from './learning.js';
|
|
23
|
-
import { banner, bannerCompact, bannerAuth, prompt as kbotPrompt, printError, printSuccess, printInfo, printResponse, printHelp, printGoodbye, setQuiet, } from './ui.js';
|
|
23
|
+
import { banner, bannerCompact, bannerAuth, prompt as kbotPrompt, printError, printSuccess, printInfo, printWarn, printResponse, printHelp, printGoodbye, setQuiet, } from './ui.js';
|
|
24
24
|
import { checkForUpdate, selfUpdate } from './updater.js';
|
|
25
25
|
import { runTutorial } from './tutorial.js';
|
|
26
26
|
import { syncOnStartup, schedulePush, flushCloudSync, isCloudSyncEnabled, setCloudToken, getCloudToken } from './cloud-sync.js';
|
|
@@ -46,6 +46,7 @@ async function main() {
|
|
|
46
46
|
.option('-t, --thinking', 'Show AI reasoning steps')
|
|
47
47
|
.option('--thinking-budget <tokens>', 'Thinking token budget (default: 10000)')
|
|
48
48
|
.option('--self-eval', 'Enable self-evaluation loop (score and retry low-quality responses)')
|
|
49
|
+
.option('--plan', 'Plan mode — read-only exploration, no changes')
|
|
49
50
|
.option('--architect', 'Architect mode — plan-review-implement with dual agents')
|
|
50
51
|
.option('--safe', 'Confirm destructive operations')
|
|
51
52
|
.option('--strict', 'Confirm ALL operations')
|
|
@@ -525,6 +526,161 @@ async function main() {
|
|
|
525
526
|
const speed = system.recommendModelSpeed();
|
|
526
527
|
process.stderr.write(`\n ${AMETHYST('Cost regulation')}: ${speed === 'fast' ? chalk.yellow('conserving (fast model)') : chalk.green('normal (default model)')}\n\n`);
|
|
527
528
|
});
|
|
529
|
+
program
|
|
530
|
+
.command('status')
|
|
531
|
+
.description('Unified Kernel dashboard — version, tools, agents, learning, collective, npm, GitHub, bootstrap')
|
|
532
|
+
.option('--json', 'Output as JSON')
|
|
533
|
+
.action(async (opts) => {
|
|
534
|
+
// Check both subcommand and parent opts (commander absorbs --json at parent level)
|
|
535
|
+
const jsonMode = opts.json || program.opts().json;
|
|
536
|
+
const chalk = (await import('chalk')).default;
|
|
537
|
+
const AMETHYST = chalk.hex('#6B5B95');
|
|
538
|
+
const DIM = chalk.dim;
|
|
539
|
+
const GREEN = chalk.hex('#4ADE80');
|
|
540
|
+
const YELLOW = chalk.hex('#FBBF24');
|
|
541
|
+
const RED = chalk.hex('#F87171');
|
|
542
|
+
const CYAN = chalk.hex('#67E8F9');
|
|
543
|
+
const line = DIM(' ' + '─'.repeat(40));
|
|
544
|
+
// ── 1. Version & latest check ──
|
|
545
|
+
let latestVersion = '';
|
|
546
|
+
let isLatest = false;
|
|
547
|
+
const npmDownloads = {};
|
|
548
|
+
const githubData = {};
|
|
549
|
+
// Fire all network requests in parallel with 3s timeouts
|
|
550
|
+
const [npmVersionRes, npmDlRes, ghRes] = await Promise.allSettled([
|
|
551
|
+
fetch('https://registry.npmjs.org/@kernel.chat/kbot/latest', { signal: AbortSignal.timeout(3000) })
|
|
552
|
+
.then(r => r.json()),
|
|
553
|
+
fetch('https://api.npmjs.org/downloads/point/last-week/@kernel.chat/kbot', { signal: AbortSignal.timeout(3000) })
|
|
554
|
+
.then(r => r.json()),
|
|
555
|
+
fetch('https://api.github.com/repos/isaacsight/kernel', { signal: AbortSignal.timeout(3000) })
|
|
556
|
+
.then(r => r.json()),
|
|
557
|
+
]);
|
|
558
|
+
if (npmVersionRes.status === 'fulfilled' && npmVersionRes.value.version) {
|
|
559
|
+
latestVersion = npmVersionRes.value.version;
|
|
560
|
+
isLatest = VERSION === latestVersion;
|
|
561
|
+
}
|
|
562
|
+
if (npmDlRes.status === 'fulfilled' && npmDlRes.value.downloads !== undefined) {
|
|
563
|
+
npmDownloads.downloads = npmDlRes.value.downloads;
|
|
564
|
+
}
|
|
565
|
+
if (ghRes.status === 'fulfilled' && ghRes.value.stargazers_count !== undefined) {
|
|
566
|
+
githubData.stars = ghRes.value.stargazers_count;
|
|
567
|
+
githubData.issues = ghRes.value.open_issues_count ?? 0;
|
|
568
|
+
}
|
|
569
|
+
// ── 2. Learning stats ──
|
|
570
|
+
const { getStats } = await import('./learning.js');
|
|
571
|
+
const stats = getStats();
|
|
572
|
+
// ── 3. Collective ──
|
|
573
|
+
const { getOptInState } = await import('./collective.js');
|
|
574
|
+
const collectiveState = getOptInState();
|
|
575
|
+
// ── 4. Tools count ──
|
|
576
|
+
const { getAllTools } = await import('./tools/index.js');
|
|
577
|
+
const toolCount = getAllTools().length || 290; // fallback to known count if tools not yet registered
|
|
578
|
+
// ── 5. Bootstrap (autotelic score) ──
|
|
579
|
+
let bootstrapScore = 0;
|
|
580
|
+
let bootstrapMax = 0;
|
|
581
|
+
let bootstrapGrade = '?';
|
|
582
|
+
let bootstrapTopFix = '';
|
|
583
|
+
let distributionPct = '';
|
|
584
|
+
try {
|
|
585
|
+
const { runBootstrap } = await import('./bootstrap.js');
|
|
586
|
+
const report = await runBootstrap();
|
|
587
|
+
bootstrapScore = report.score;
|
|
588
|
+
bootstrapMax = report.maxScore;
|
|
589
|
+
bootstrapGrade = report.grade;
|
|
590
|
+
bootstrapTopFix = report.topFix;
|
|
591
|
+
const distSection = report.sections.find(s => s.name.toLowerCase().includes('distribution'));
|
|
592
|
+
if (distSection) {
|
|
593
|
+
distributionPct = `${Math.round((distSection.score / distSection.maxScore) * 100)}%`;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
catch { /* bootstrap can fail if not in a project dir */ }
|
|
597
|
+
// ── 6. Cognitive modules — count from known list ──
|
|
598
|
+
const cognitiveModules = [
|
|
599
|
+
'learning', 'entropy-context', 'autopoiesis', 'free-energy',
|
|
600
|
+
'predictive-processing', 'reasoning', 'intentionality',
|
|
601
|
+
'temporal', 'confidence', 'strange-loops', 'integrated-information',
|
|
602
|
+
];
|
|
603
|
+
const cognitiveCount = cognitiveModules.length; // 11
|
|
604
|
+
// ── JSON output ──
|
|
605
|
+
if (jsonMode) {
|
|
606
|
+
console.log(JSON.stringify({
|
|
607
|
+
version: VERSION,
|
|
608
|
+
latestVersion: latestVersion || null,
|
|
609
|
+
isLatest,
|
|
610
|
+
tools: toolCount,
|
|
611
|
+
agents: 23,
|
|
612
|
+
cognitiveModules: cognitiveCount,
|
|
613
|
+
learning: {
|
|
614
|
+
patterns: stats.patternsCount,
|
|
615
|
+
solutions: stats.solutionsCount,
|
|
616
|
+
tokensSaved: stats.totalTokensSaved,
|
|
617
|
+
efficiency: stats.efficiency,
|
|
618
|
+
},
|
|
619
|
+
collective: {
|
|
620
|
+
enabled: collectiveState.enabled,
|
|
621
|
+
signalsSent: collectiveState.total_signals_sent,
|
|
622
|
+
},
|
|
623
|
+
npm: { weeklyDownloads: npmDownloads.downloads ?? null },
|
|
624
|
+
github: { stars: githubData.stars ?? null, issues: githubData.issues ?? null },
|
|
625
|
+
bootstrap: {
|
|
626
|
+
score: bootstrapScore,
|
|
627
|
+
maxScore: bootstrapMax,
|
|
628
|
+
grade: bootstrapGrade,
|
|
629
|
+
topFix: bootstrapTopFix,
|
|
630
|
+
},
|
|
631
|
+
}, null, 2));
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
// ── Formatted dashboard ──
|
|
635
|
+
const versionTag = latestVersion
|
|
636
|
+
? (isLatest ? GREEN(' (latest ✓)') : YELLOW(` (update: ${latestVersion})`))
|
|
637
|
+
: DIM(' (offline)');
|
|
638
|
+
const fmtNum = (n) => n.toLocaleString();
|
|
639
|
+
process.stderr.write('\n');
|
|
640
|
+
process.stderr.write(` ${AMETHYST('◉')} ${chalk.bold('Kernel Status')}\n`);
|
|
641
|
+
process.stderr.write(line + '\n');
|
|
642
|
+
process.stderr.write(` ${chalk.bold('Version')} ${VERSION}${versionTag}\n`);
|
|
643
|
+
process.stderr.write(` ${chalk.bold('Tools')} ${fmtNum(toolCount)} ${DIM('|')} ${chalk.bold('Agents')} 23\n`);
|
|
644
|
+
process.stderr.write(` ${chalk.bold('Cognitive')} ${cognitiveCount}/${cognitiveCount} modules active\n`);
|
|
645
|
+
process.stderr.write(line + '\n');
|
|
646
|
+
// Learning
|
|
647
|
+
const tokensSavedStr = stats.totalTokensSaved > 0 ? fmtNum(stats.totalTokensSaved) + ' tokens saved' : 'learning...';
|
|
648
|
+
process.stderr.write(` ${chalk.bold('Learning')} ${fmtNum(stats.patternsCount)} patterns ${DIM('|')} ${fmtNum(stats.solutionsCount)} solutions ${DIM('|')} ${tokensSavedStr}\n`);
|
|
649
|
+
// Collective
|
|
650
|
+
const collectiveEnabled = collectiveState.enabled ? GREEN('enabled') : DIM('disabled');
|
|
651
|
+
const signalsSent = fmtNum(collectiveState.total_signals_sent || 0);
|
|
652
|
+
process.stderr.write(` ${chalk.bold('Collective')} ${collectiveEnabled} ${DIM('|')} ${signalsSent} signals sent\n`);
|
|
653
|
+
process.stderr.write(line + '\n');
|
|
654
|
+
// npm
|
|
655
|
+
if (npmDownloads.downloads !== undefined) {
|
|
656
|
+
process.stderr.write(` ${chalk.bold('npm')} ${CYAN(fmtNum(npmDownloads.downloads))} downloads/week\n`);
|
|
657
|
+
}
|
|
658
|
+
else {
|
|
659
|
+
process.stderr.write(` ${chalk.bold('npm')} ${DIM('unavailable')}\n`);
|
|
660
|
+
}
|
|
661
|
+
// GitHub
|
|
662
|
+
if (githubData.stars !== undefined) {
|
|
663
|
+
const starStr = `${fmtNum(githubData.stars)} star${githubData.stars === 1 ? '' : 's'}`;
|
|
664
|
+
const issueStr = `${fmtNum(githubData.issues)} issue${githubData.issues === 1 ? '' : 's'}`;
|
|
665
|
+
process.stderr.write(` ${chalk.bold('GitHub')} ${starStr} ${DIM('|')} ${issueStr}\n`);
|
|
666
|
+
}
|
|
667
|
+
else {
|
|
668
|
+
process.stderr.write(` ${chalk.bold('GitHub')} ${DIM('unavailable')}\n`);
|
|
669
|
+
}
|
|
670
|
+
// Bootstrap
|
|
671
|
+
if (bootstrapMax > 0) {
|
|
672
|
+
const pct = Math.round((bootstrapScore / bootstrapMax) * 100);
|
|
673
|
+
const gradeColor = pct >= 80 ? GREEN : pct >= 60 ? YELLOW : RED;
|
|
674
|
+
const distStr = distributionPct ? ` ${DIM('— distribution at')} ${distributionPct}` : '';
|
|
675
|
+
process.stderr.write(` ${chalk.bold('Bootstrap')} ${bootstrapScore}/${bootstrapMax} (${gradeColor(bootstrapGrade)})${distStr}\n`);
|
|
676
|
+
}
|
|
677
|
+
process.stderr.write(line + '\n');
|
|
678
|
+
// Next action (top fix from bootstrap)
|
|
679
|
+
if (bootstrapTopFix) {
|
|
680
|
+
process.stderr.write(` ${chalk.bold('Next:')} ${bootstrapTopFix}\n`);
|
|
681
|
+
}
|
|
682
|
+
process.stderr.write('\n');
|
|
683
|
+
});
|
|
528
684
|
program
|
|
529
685
|
.command('immune')
|
|
530
686
|
.description('Self-audit — kbot\'s immune system scans its own code for bugs, security holes, and bad decisions')
|
|
@@ -600,8 +756,10 @@ async function main() {
|
|
|
600
756
|
.option('--disable', 'Opt out of collective learning')
|
|
601
757
|
.option('--status', 'Show collective learning status')
|
|
602
758
|
.option('--pull', 'Pull latest collective patterns')
|
|
759
|
+
.option('--diagnose', 'Run end-to-end health check on collective connectivity')
|
|
760
|
+
.option('--insights', 'Show what the collective knows (hints table + top patterns)')
|
|
603
761
|
.action(async (opts) => {
|
|
604
|
-
const { setOptIn, getCollectiveStats, pullCollectiveHints, pullCollectivePatterns, getOptInState } = await import('./collective.js');
|
|
762
|
+
const { setOptIn, getCollectiveStats, pullCollectiveHints, pullCollectivePatterns, getOptInState, sendSignal, getSignalQueueSize } = await import('./collective.js');
|
|
605
763
|
if (opts.enable) {
|
|
606
764
|
setOptIn(true);
|
|
607
765
|
printSuccess('Collective learning enabled!');
|
|
@@ -620,6 +778,146 @@ async function main() {
|
|
|
620
778
|
printSuccess(`Pulled ${hints.length} routing hints and ${patterns.length} patterns from the collective.`);
|
|
621
779
|
return;
|
|
622
780
|
}
|
|
781
|
+
if (opts.diagnose) {
|
|
782
|
+
console.log();
|
|
783
|
+
printInfo('Collective Health Check');
|
|
784
|
+
printInfo('─'.repeat(40));
|
|
785
|
+
// 1. Opt-in status
|
|
786
|
+
const state = getOptInState();
|
|
787
|
+
if (state.enabled) {
|
|
788
|
+
printSuccess(`Opt-in: enabled (since ${state.opted_in_at || 'unknown'})`);
|
|
789
|
+
}
|
|
790
|
+
else {
|
|
791
|
+
printWarn('Opt-in: disabled — enable with `kbot collective --enable`');
|
|
792
|
+
}
|
|
793
|
+
// 2. Test signal
|
|
794
|
+
printInfo('Sending test signal...');
|
|
795
|
+
// Temporarily need opt-in for sendSignal to work
|
|
796
|
+
const wasEnabled = state.enabled;
|
|
797
|
+
if (!wasEnabled)
|
|
798
|
+
setOptIn(true);
|
|
799
|
+
const testSignal = {
|
|
800
|
+
message_hash: 'test',
|
|
801
|
+
message_category: 'diagnostic',
|
|
802
|
+
message_length: 4,
|
|
803
|
+
routed_agent: 'kernel',
|
|
804
|
+
classifier_confidence: 1.0,
|
|
805
|
+
was_rerouted: false,
|
|
806
|
+
response_quality: 1.0,
|
|
807
|
+
tool_sequence: ['diagnostic_ping'],
|
|
808
|
+
strategy: 'health_check',
|
|
809
|
+
source: 'kbot',
|
|
810
|
+
};
|
|
811
|
+
const signalOk = await sendSignal(testSignal);
|
|
812
|
+
if (!wasEnabled)
|
|
813
|
+
setOptIn(false); // Restore original state
|
|
814
|
+
if (signalOk) {
|
|
815
|
+
printSuccess('Signal send: OK — endpoint accepted the test signal');
|
|
816
|
+
}
|
|
817
|
+
else {
|
|
818
|
+
printError('Signal send: FAILED — endpoint unreachable or rejected the signal');
|
|
819
|
+
}
|
|
820
|
+
// 3. Pull hints
|
|
821
|
+
printInfo('Pulling routing hints...');
|
|
822
|
+
try {
|
|
823
|
+
const hints = await pullCollectiveHints();
|
|
824
|
+
if (hints.length > 0) {
|
|
825
|
+
printSuccess(`Hints pull: OK — ${hints.length} routing hints available`);
|
|
826
|
+
}
|
|
827
|
+
else {
|
|
828
|
+
printWarn('Hints pull: empty — no routing hints available yet');
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
catch {
|
|
832
|
+
printError('Hints pull: FAILED — could not retrieve hints');
|
|
833
|
+
}
|
|
834
|
+
// 4. Pull patterns
|
|
835
|
+
printInfo('Pulling collective patterns...');
|
|
836
|
+
try {
|
|
837
|
+
const patterns = await pullCollectivePatterns();
|
|
838
|
+
if (patterns.length > 0) {
|
|
839
|
+
printSuccess(`Patterns pull: OK — ${patterns.length} patterns available`);
|
|
840
|
+
}
|
|
841
|
+
else {
|
|
842
|
+
printWarn('Patterns pull: empty — no patterns available yet');
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
catch {
|
|
846
|
+
printError('Patterns pull: FAILED — could not retrieve patterns');
|
|
847
|
+
}
|
|
848
|
+
// 5. Signal queue status
|
|
849
|
+
const queueSize = getSignalQueueSize();
|
|
850
|
+
if (queueSize === 0) {
|
|
851
|
+
printSuccess('Signal queue: empty (all signals flushed)');
|
|
852
|
+
}
|
|
853
|
+
else {
|
|
854
|
+
printInfo(`Signal queue: ${queueSize} signal(s) pending flush`);
|
|
855
|
+
}
|
|
856
|
+
// Summary
|
|
857
|
+
console.log();
|
|
858
|
+
printInfo(`Total signals sent: ${state.total_signals_sent}`);
|
|
859
|
+
printInfo(`Last signal: ${state.last_signal_at || 'never'}`);
|
|
860
|
+
console.log();
|
|
861
|
+
return;
|
|
862
|
+
}
|
|
863
|
+
if (opts.insights) {
|
|
864
|
+
console.log();
|
|
865
|
+
printInfo('Collective Intelligence Insights');
|
|
866
|
+
printInfo('═'.repeat(50));
|
|
867
|
+
// Pull fresh data
|
|
868
|
+
const [hints, patterns] = await Promise.all([pullCollectiveHints(), pullCollectivePatterns()]);
|
|
869
|
+
// Routing hints table
|
|
870
|
+
console.log();
|
|
871
|
+
printInfo('Routing Hints');
|
|
872
|
+
printInfo('─'.repeat(50));
|
|
873
|
+
if (hints.length === 0) {
|
|
874
|
+
printWarn('No routing hints available yet. The collective needs more signals.');
|
|
875
|
+
}
|
|
876
|
+
else {
|
|
877
|
+
// Table header
|
|
878
|
+
const catW = 18, agentW = 14, confW = 12, sampW = 8;
|
|
879
|
+
console.log(chalk.bold(' ' +
|
|
880
|
+
'Category'.padEnd(catW) +
|
|
881
|
+
'Best Agent'.padEnd(agentW) +
|
|
882
|
+
'Confidence'.padEnd(confW) +
|
|
883
|
+
'Samples'.padEnd(sampW)));
|
|
884
|
+
console.log(' ' + '─'.repeat(catW + agentW + confW + sampW));
|
|
885
|
+
for (const h of hints) {
|
|
886
|
+
const conf = (h.confidence * 100).toFixed(0) + '%';
|
|
887
|
+
console.log(' ' +
|
|
888
|
+
h.category.padEnd(catW) +
|
|
889
|
+
h.best_agent.padEnd(agentW) +
|
|
890
|
+
conf.padEnd(confW) +
|
|
891
|
+
String(h.sample_count).padEnd(sampW));
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
// Top tool-sequence patterns
|
|
895
|
+
console.log();
|
|
896
|
+
printInfo('Top Tool Sequences');
|
|
897
|
+
printInfo('─'.repeat(50));
|
|
898
|
+
const toolPatterns = patterns
|
|
899
|
+
.filter(p => p.type === 'tool_sequence')
|
|
900
|
+
.sort((a, b) => b.confidence - a.confidence || b.sample_count - a.sample_count)
|
|
901
|
+
.slice(0, 10);
|
|
902
|
+
if (toolPatterns.length === 0) {
|
|
903
|
+
printWarn('No tool-sequence patterns available yet.');
|
|
904
|
+
}
|
|
905
|
+
else {
|
|
906
|
+
for (let i = 0; i < toolPatterns.length; i++) {
|
|
907
|
+
const p = toolPatterns[i];
|
|
908
|
+
const pat = p.pattern;
|
|
909
|
+
const tools = Array.isArray(pat.tools) ? pat.tools.join(' → ') : 'unknown';
|
|
910
|
+
const category = typeof pat.category === 'string' ? pat.category : 'general';
|
|
911
|
+
const conf = (p.confidence * 100).toFixed(0) + '%';
|
|
912
|
+
console.log(chalk.dim(` ${String(i + 1).padStart(2)}.`) +
|
|
913
|
+
` [${category}] ` +
|
|
914
|
+
chalk.cyan(tools) +
|
|
915
|
+
chalk.dim(` (${conf}, ${p.sample_count} samples)`));
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
console.log();
|
|
919
|
+
return;
|
|
920
|
+
}
|
|
623
921
|
// Default: show status
|
|
624
922
|
console.log();
|
|
625
923
|
console.log(getCollectiveStats());
|
|
@@ -1001,6 +1299,113 @@ async function main() {
|
|
|
1001
1299
|
const md = generateChangelog({ since: changelogOpts.since, format: 'markdown' });
|
|
1002
1300
|
process.stdout.write(md);
|
|
1003
1301
|
});
|
|
1302
|
+
// ── Automate subcommands ──
|
|
1303
|
+
const automateCmd = program
|
|
1304
|
+
.command('automate')
|
|
1305
|
+
.description('Event-driven automations — file watchers, schedules, git hooks, webhooks');
|
|
1306
|
+
automateCmd
|
|
1307
|
+
.command('list')
|
|
1308
|
+
.description('List all configured automations')
|
|
1309
|
+
.action(async () => {
|
|
1310
|
+
const { listAutomations, formatAutomationList } = await import('./automations.js');
|
|
1311
|
+
const automations = listAutomations();
|
|
1312
|
+
process.stderr.write(formatAutomationList(automations) + '\n');
|
|
1313
|
+
});
|
|
1314
|
+
automateCmd
|
|
1315
|
+
.command('add')
|
|
1316
|
+
.description('Create a new automation')
|
|
1317
|
+
.requiredOption('--trigger <trigger>', 'Trigger spec (e.g., "file:src/**/*.ts:change", "schedule:every 5m", "git:pre-commit", "webhook:/deploy")')
|
|
1318
|
+
.requiredOption('--agent <agent>', 'Agent to run (e.g., coder, researcher, guardian)')
|
|
1319
|
+
.requiredOption('--prompt <prompt>', 'Prompt to send to the agent')
|
|
1320
|
+
.option('--name <name>', 'Human-readable name for the automation')
|
|
1321
|
+
.option('--tools <tools>', 'Comma-separated list of tools to enable')
|
|
1322
|
+
.action(async (addOpts) => {
|
|
1323
|
+
try {
|
|
1324
|
+
const { createAutomation, parseTriggerString } = await import('./automations.js');
|
|
1325
|
+
const trigger = parseTriggerString(addOpts.trigger);
|
|
1326
|
+
const automation = createAutomation({
|
|
1327
|
+
name: addOpts.name || `${trigger.type}:${addOpts.agent}`,
|
|
1328
|
+
trigger,
|
|
1329
|
+
action: {
|
|
1330
|
+
agent: addOpts.agent,
|
|
1331
|
+
prompt: addOpts.prompt,
|
|
1332
|
+
tools: addOpts.tools ? addOpts.tools.split(',').map((t) => t.trim()) : undefined,
|
|
1333
|
+
},
|
|
1334
|
+
});
|
|
1335
|
+
printSuccess(`Automation created: ${automation.name} (${automation.id})`);
|
|
1336
|
+
printInfo(` Trigger: ${addOpts.trigger}`);
|
|
1337
|
+
printInfo(` Agent: ${addOpts.agent}`);
|
|
1338
|
+
if (trigger.type === 'git') {
|
|
1339
|
+
printInfo(' Git hooks installed.');
|
|
1340
|
+
}
|
|
1341
|
+
if (trigger.type === 'file' || trigger.type === 'schedule') {
|
|
1342
|
+
printInfo(' Run `kbot automate start` to activate the daemon.');
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
catch (err) {
|
|
1346
|
+
printError(err instanceof Error ? err.message : String(err));
|
|
1347
|
+
process.exit(1);
|
|
1348
|
+
}
|
|
1349
|
+
});
|
|
1350
|
+
automateCmd
|
|
1351
|
+
.command('remove')
|
|
1352
|
+
.description('Remove an automation by ID')
|
|
1353
|
+
.argument('<id>', 'Automation ID')
|
|
1354
|
+
.action(async (id) => {
|
|
1355
|
+
const { removeAutomation } = await import('./automations.js');
|
|
1356
|
+
const removed = removeAutomation(id);
|
|
1357
|
+
if (removed) {
|
|
1358
|
+
printSuccess(`Automation "${id}" removed.`);
|
|
1359
|
+
}
|
|
1360
|
+
else {
|
|
1361
|
+
printError(`Automation "${id}" not found.`);
|
|
1362
|
+
process.exit(1);
|
|
1363
|
+
}
|
|
1364
|
+
});
|
|
1365
|
+
automateCmd
|
|
1366
|
+
.command('run')
|
|
1367
|
+
.description('Manually trigger an automation')
|
|
1368
|
+
.argument('<id>', 'Automation ID')
|
|
1369
|
+
.action(async (id) => {
|
|
1370
|
+
const { runAutomation, getAutomation } = await import('./automations.js');
|
|
1371
|
+
const automation = getAutomation(id);
|
|
1372
|
+
if (!automation) {
|
|
1373
|
+
printError(`Automation "${id}" not found.`);
|
|
1374
|
+
process.exit(1);
|
|
1375
|
+
}
|
|
1376
|
+
printInfo(`Running automation: ${automation.name}...`);
|
|
1377
|
+
const result = await runAutomation(id);
|
|
1378
|
+
if (result.success) {
|
|
1379
|
+
printSuccess(`Automation completed successfully.`);
|
|
1380
|
+
if (result.output) {
|
|
1381
|
+
process.stderr.write('\n' + result.output + '\n');
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
else {
|
|
1385
|
+
printError(`Automation failed: ${result.error}`);
|
|
1386
|
+
process.exit(1);
|
|
1387
|
+
}
|
|
1388
|
+
});
|
|
1389
|
+
automateCmd
|
|
1390
|
+
.command('start')
|
|
1391
|
+
.description('Start the automation daemon (file watchers + schedule timers)')
|
|
1392
|
+
.action(async () => {
|
|
1393
|
+
const { startAutomationDaemon, listAutomations } = await import('./automations.js');
|
|
1394
|
+
const automations = listAutomations();
|
|
1395
|
+
if (automations.length === 0) {
|
|
1396
|
+
printError('No automations configured. Use `kbot automate add` first.');
|
|
1397
|
+
process.exit(1);
|
|
1398
|
+
}
|
|
1399
|
+
printInfo('Starting automation daemon...');
|
|
1400
|
+
const { running } = startAutomationDaemon({
|
|
1401
|
+
log: (msg) => process.stderr.write(msg + '\n'),
|
|
1402
|
+
});
|
|
1403
|
+
if (running) {
|
|
1404
|
+
printSuccess('Daemon running. Press Ctrl+C to stop.');
|
|
1405
|
+
// Keep the process alive
|
|
1406
|
+
await new Promise(() => { });
|
|
1407
|
+
}
|
|
1408
|
+
});
|
|
1004
1409
|
program
|
|
1005
1410
|
.command('completions')
|
|
1006
1411
|
.description('Generate shell tab-completion script (bash, zsh, fish)')
|
|
@@ -1021,7 +1426,7 @@ async function main() {
|
|
|
1021
1426
|
if (opts.quiet)
|
|
1022
1427
|
setQuiet(true);
|
|
1023
1428
|
// If a sub-command was run, we're done
|
|
1024
|
-
if (['byok', 'auth', 'ide', 'local', 'ollama', 'kbot-local', 'pull', 'doctor', 'serve', 'agents', 'watch', 'voice', 'export', 'plugins', 'changelog', 'completions'].includes(program.args[0]))
|
|
1429
|
+
if (['byok', 'auth', 'ide', 'local', 'ollama', 'kbot-local', 'pull', 'doctor', 'serve', 'agents', 'watch', 'voice', 'export', 'plugins', 'changelog', 'completions', 'automate', 'status'].includes(program.args[0]))
|
|
1025
1430
|
return;
|
|
1026
1431
|
// Check for API key (BYOK or local provider)
|
|
1027
1432
|
let byokActive = isByokEnabled();
|
|
@@ -1215,6 +1620,7 @@ async function main() {
|
|
|
1215
1620
|
tier,
|
|
1216
1621
|
thinking: opts.thinking || false,
|
|
1217
1622
|
thinkingBudget: opts.thinkingBudget ? (parseInt(opts.thinkingBudget, 10) || 10000) : undefined,
|
|
1623
|
+
plan: opts.plan || false,
|
|
1218
1624
|
};
|
|
1219
1625
|
// Enable self-evaluation if requested
|
|
1220
1626
|
if (opts.selfEval) {
|
|
@@ -1728,6 +2134,17 @@ async function startRepl(agentOpts, context, tier, byokActive = false, localActi
|
|
|
1728
2134
|
}
|
|
1729
2135
|
console.log(chalk.dim(' └─────────────────────────────────────────────────┘'));
|
|
1730
2136
|
console.log();
|
|
2137
|
+
// First-run collective learning nudge
|
|
2138
|
+
try {
|
|
2139
|
+
const { isCollectiveEnabled } = await import('./collective.js');
|
|
2140
|
+
if (!isCollectiveEnabled()) {
|
|
2141
|
+
printInfo('Join 4,000+ developers making kbot smarter for everyone:');
|
|
2142
|
+
printInfo(' kbot collective --enable');
|
|
2143
|
+
printInfo(' (anonymized — never shares code, files, or identity)');
|
|
2144
|
+
console.log();
|
|
2145
|
+
}
|
|
2146
|
+
}
|
|
2147
|
+
catch { /* collective module not available — skip silently */ }
|
|
1731
2148
|
}
|
|
1732
2149
|
else if (sessionCount <= 5) {
|
|
1733
2150
|
// Sessions 2-5: rotate useful tips they might not know
|