@kernel.chat/kbot 3.8.2 → 3.10.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 +83 -6
- 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 +308 -3
- package/dist/cli.js.map +1 -1
- package/dist/memory-synthesis.d.ts +67 -0
- package/dist/memory-synthesis.d.ts.map +1 -0
- package/dist/memory-synthesis.js +557 -0
- package/dist/memory-synthesis.js.map +1 -0
- package/dist/reflection.d.ts +33 -0
- package/dist/reflection.d.ts.map +1 -0
- package/dist/reflection.js +368 -0
- package/dist/reflection.js.map +1 -0
- package/dist/skill-library.d.ts +60 -0
- package/dist/skill-library.d.ts.map +1 -0
- package/dist/skill-library.js +475 -0
- package/dist/skill-library.js.map +1 -0
- package/dist/spec.d.ts +23 -0
- package/dist/spec.d.ts.map +1 -0
- package/dist/spec.js +177 -0
- package/dist/spec.js.map +1 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -20,6 +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 { maybeSynthesize, getSynthesisStats } from './memory-synthesis.js';
|
|
23
24
|
import { banner, bannerCompact, bannerAuth, prompt as kbotPrompt, printError, printSuccess, printInfo, printWarn, printResponse, printHelp, printGoodbye, setQuiet, } from './ui.js';
|
|
24
25
|
import { checkForUpdate, selfUpdate } from './updater.js';
|
|
25
26
|
import { runTutorial } from './tutorial.js';
|
|
@@ -46,6 +47,7 @@ async function main() {
|
|
|
46
47
|
.option('-t, --thinking', 'Show AI reasoning steps')
|
|
47
48
|
.option('--thinking-budget <tokens>', 'Thinking token budget (default: 10000)')
|
|
48
49
|
.option('--self-eval', 'Enable self-evaluation loop (score and retry low-quality responses)')
|
|
50
|
+
.option('--plan', 'Plan mode — read-only exploration, no changes')
|
|
49
51
|
.option('--architect', 'Architect mode — plan-review-implement with dual agents')
|
|
50
52
|
.option('--safe', 'Confirm destructive operations')
|
|
51
53
|
.option('--strict', 'Confirm ALL operations')
|
|
@@ -525,6 +527,161 @@ async function main() {
|
|
|
525
527
|
const speed = system.recommendModelSpeed();
|
|
526
528
|
process.stderr.write(`\n ${AMETHYST('Cost regulation')}: ${speed === 'fast' ? chalk.yellow('conserving (fast model)') : chalk.green('normal (default model)')}\n\n`);
|
|
527
529
|
});
|
|
530
|
+
program
|
|
531
|
+
.command('status')
|
|
532
|
+
.description('Unified Kernel dashboard — version, tools, agents, learning, collective, npm, GitHub, bootstrap')
|
|
533
|
+
.option('--json', 'Output as JSON')
|
|
534
|
+
.action(async (opts) => {
|
|
535
|
+
// Check both subcommand and parent opts (commander absorbs --json at parent level)
|
|
536
|
+
const jsonMode = opts.json || program.opts().json;
|
|
537
|
+
const chalk = (await import('chalk')).default;
|
|
538
|
+
const AMETHYST = chalk.hex('#6B5B95');
|
|
539
|
+
const DIM = chalk.dim;
|
|
540
|
+
const GREEN = chalk.hex('#4ADE80');
|
|
541
|
+
const YELLOW = chalk.hex('#FBBF24');
|
|
542
|
+
const RED = chalk.hex('#F87171');
|
|
543
|
+
const CYAN = chalk.hex('#67E8F9');
|
|
544
|
+
const line = DIM(' ' + '─'.repeat(40));
|
|
545
|
+
// ── 1. Version & latest check ──
|
|
546
|
+
let latestVersion = '';
|
|
547
|
+
let isLatest = false;
|
|
548
|
+
const npmDownloads = {};
|
|
549
|
+
const githubData = {};
|
|
550
|
+
// Fire all network requests in parallel with 3s timeouts
|
|
551
|
+
const [npmVersionRes, npmDlRes, ghRes] = await Promise.allSettled([
|
|
552
|
+
fetch('https://registry.npmjs.org/@kernel.chat/kbot/latest', { signal: AbortSignal.timeout(3000) })
|
|
553
|
+
.then(r => r.json()),
|
|
554
|
+
fetch('https://api.npmjs.org/downloads/point/last-week/@kernel.chat/kbot', { signal: AbortSignal.timeout(3000) })
|
|
555
|
+
.then(r => r.json()),
|
|
556
|
+
fetch('https://api.github.com/repos/isaacsight/kernel', { signal: AbortSignal.timeout(3000) })
|
|
557
|
+
.then(r => r.json()),
|
|
558
|
+
]);
|
|
559
|
+
if (npmVersionRes.status === 'fulfilled' && npmVersionRes.value.version) {
|
|
560
|
+
latestVersion = npmVersionRes.value.version;
|
|
561
|
+
isLatest = VERSION === latestVersion;
|
|
562
|
+
}
|
|
563
|
+
if (npmDlRes.status === 'fulfilled' && npmDlRes.value.downloads !== undefined) {
|
|
564
|
+
npmDownloads.downloads = npmDlRes.value.downloads;
|
|
565
|
+
}
|
|
566
|
+
if (ghRes.status === 'fulfilled' && ghRes.value.stargazers_count !== undefined) {
|
|
567
|
+
githubData.stars = ghRes.value.stargazers_count;
|
|
568
|
+
githubData.issues = ghRes.value.open_issues_count ?? 0;
|
|
569
|
+
}
|
|
570
|
+
// ── 2. Learning stats ──
|
|
571
|
+
const { getStats } = await import('./learning.js');
|
|
572
|
+
const stats = getStats();
|
|
573
|
+
// ── 3. Collective ──
|
|
574
|
+
const { getOptInState } = await import('./collective.js');
|
|
575
|
+
const collectiveState = getOptInState();
|
|
576
|
+
// ── 4. Tools count ──
|
|
577
|
+
const { getAllTools } = await import('./tools/index.js');
|
|
578
|
+
const toolCount = getAllTools().length || 290; // fallback to known count if tools not yet registered
|
|
579
|
+
// ── 5. Bootstrap (autotelic score) ──
|
|
580
|
+
let bootstrapScore = 0;
|
|
581
|
+
let bootstrapMax = 0;
|
|
582
|
+
let bootstrapGrade = '?';
|
|
583
|
+
let bootstrapTopFix = '';
|
|
584
|
+
let distributionPct = '';
|
|
585
|
+
try {
|
|
586
|
+
const { runBootstrap } = await import('./bootstrap.js');
|
|
587
|
+
const report = await runBootstrap();
|
|
588
|
+
bootstrapScore = report.score;
|
|
589
|
+
bootstrapMax = report.maxScore;
|
|
590
|
+
bootstrapGrade = report.grade;
|
|
591
|
+
bootstrapTopFix = report.topFix;
|
|
592
|
+
const distSection = report.sections.find(s => s.name.toLowerCase().includes('distribution'));
|
|
593
|
+
if (distSection) {
|
|
594
|
+
distributionPct = `${Math.round((distSection.score / distSection.maxScore) * 100)}%`;
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
catch { /* bootstrap can fail if not in a project dir */ }
|
|
598
|
+
// ── 6. Cognitive modules — count from known list ──
|
|
599
|
+
const cognitiveModules = [
|
|
600
|
+
'learning', 'entropy-context', 'autopoiesis', 'free-energy',
|
|
601
|
+
'predictive-processing', 'reasoning', 'intentionality',
|
|
602
|
+
'temporal', 'confidence', 'strange-loops', 'integrated-information',
|
|
603
|
+
];
|
|
604
|
+
const cognitiveCount = cognitiveModules.length; // 11
|
|
605
|
+
// ── JSON output ──
|
|
606
|
+
if (jsonMode) {
|
|
607
|
+
console.log(JSON.stringify({
|
|
608
|
+
version: VERSION,
|
|
609
|
+
latestVersion: latestVersion || null,
|
|
610
|
+
isLatest,
|
|
611
|
+
tools: toolCount,
|
|
612
|
+
agents: 23,
|
|
613
|
+
cognitiveModules: cognitiveCount,
|
|
614
|
+
learning: {
|
|
615
|
+
patterns: stats.patternsCount,
|
|
616
|
+
solutions: stats.solutionsCount,
|
|
617
|
+
tokensSaved: stats.totalTokensSaved,
|
|
618
|
+
efficiency: stats.efficiency,
|
|
619
|
+
},
|
|
620
|
+
collective: {
|
|
621
|
+
enabled: collectiveState.enabled,
|
|
622
|
+
signalsSent: collectiveState.total_signals_sent,
|
|
623
|
+
},
|
|
624
|
+
npm: { weeklyDownloads: npmDownloads.downloads ?? null },
|
|
625
|
+
github: { stars: githubData.stars ?? null, issues: githubData.issues ?? null },
|
|
626
|
+
bootstrap: {
|
|
627
|
+
score: bootstrapScore,
|
|
628
|
+
maxScore: bootstrapMax,
|
|
629
|
+
grade: bootstrapGrade,
|
|
630
|
+
topFix: bootstrapTopFix,
|
|
631
|
+
},
|
|
632
|
+
}, null, 2));
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
// ── Formatted dashboard ──
|
|
636
|
+
const versionTag = latestVersion
|
|
637
|
+
? (isLatest ? GREEN(' (latest ✓)') : YELLOW(` (update: ${latestVersion})`))
|
|
638
|
+
: DIM(' (offline)');
|
|
639
|
+
const fmtNum = (n) => n.toLocaleString();
|
|
640
|
+
process.stderr.write('\n');
|
|
641
|
+
process.stderr.write(` ${AMETHYST('◉')} ${chalk.bold('Kernel Status')}\n`);
|
|
642
|
+
process.stderr.write(line + '\n');
|
|
643
|
+
process.stderr.write(` ${chalk.bold('Version')} ${VERSION}${versionTag}\n`);
|
|
644
|
+
process.stderr.write(` ${chalk.bold('Tools')} ${fmtNum(toolCount)} ${DIM('|')} ${chalk.bold('Agents')} 23\n`);
|
|
645
|
+
process.stderr.write(` ${chalk.bold('Cognitive')} ${cognitiveCount}/${cognitiveCount} modules active\n`);
|
|
646
|
+
process.stderr.write(line + '\n');
|
|
647
|
+
// Learning
|
|
648
|
+
const tokensSavedStr = stats.totalTokensSaved > 0 ? fmtNum(stats.totalTokensSaved) + ' tokens saved' : 'learning...';
|
|
649
|
+
process.stderr.write(` ${chalk.bold('Learning')} ${fmtNum(stats.patternsCount)} patterns ${DIM('|')} ${fmtNum(stats.solutionsCount)} solutions ${DIM('|')} ${tokensSavedStr}\n`);
|
|
650
|
+
// Collective
|
|
651
|
+
const collectiveEnabled = collectiveState.enabled ? GREEN('enabled') : DIM('disabled');
|
|
652
|
+
const signalsSent = fmtNum(collectiveState.total_signals_sent || 0);
|
|
653
|
+
process.stderr.write(` ${chalk.bold('Collective')} ${collectiveEnabled} ${DIM('|')} ${signalsSent} signals sent\n`);
|
|
654
|
+
process.stderr.write(line + '\n');
|
|
655
|
+
// npm
|
|
656
|
+
if (npmDownloads.downloads !== undefined) {
|
|
657
|
+
process.stderr.write(` ${chalk.bold('npm')} ${CYAN(fmtNum(npmDownloads.downloads))} downloads/week\n`);
|
|
658
|
+
}
|
|
659
|
+
else {
|
|
660
|
+
process.stderr.write(` ${chalk.bold('npm')} ${DIM('unavailable')}\n`);
|
|
661
|
+
}
|
|
662
|
+
// GitHub
|
|
663
|
+
if (githubData.stars !== undefined) {
|
|
664
|
+
const starStr = `${fmtNum(githubData.stars)} star${githubData.stars === 1 ? '' : 's'}`;
|
|
665
|
+
const issueStr = `${fmtNum(githubData.issues)} issue${githubData.issues === 1 ? '' : 's'}`;
|
|
666
|
+
process.stderr.write(` ${chalk.bold('GitHub')} ${starStr} ${DIM('|')} ${issueStr}\n`);
|
|
667
|
+
}
|
|
668
|
+
else {
|
|
669
|
+
process.stderr.write(` ${chalk.bold('GitHub')} ${DIM('unavailable')}\n`);
|
|
670
|
+
}
|
|
671
|
+
// Bootstrap
|
|
672
|
+
if (bootstrapMax > 0) {
|
|
673
|
+
const pct = Math.round((bootstrapScore / bootstrapMax) * 100);
|
|
674
|
+
const gradeColor = pct >= 80 ? GREEN : pct >= 60 ? YELLOW : RED;
|
|
675
|
+
const distStr = distributionPct ? ` ${DIM('— distribution at')} ${distributionPct}` : '';
|
|
676
|
+
process.stderr.write(` ${chalk.bold('Bootstrap')} ${bootstrapScore}/${bootstrapMax} (${gradeColor(bootstrapGrade)})${distStr}\n`);
|
|
677
|
+
}
|
|
678
|
+
process.stderr.write(line + '\n');
|
|
679
|
+
// Next action (top fix from bootstrap)
|
|
680
|
+
if (bootstrapTopFix) {
|
|
681
|
+
process.stderr.write(` ${chalk.bold('Next:')} ${bootstrapTopFix}\n`);
|
|
682
|
+
}
|
|
683
|
+
process.stderr.write('\n');
|
|
684
|
+
});
|
|
528
685
|
program
|
|
529
686
|
.command('immune')
|
|
530
687
|
.description('Self-audit — kbot\'s immune system scans its own code for bugs, security holes, and bad decisions')
|
|
@@ -1143,6 +1300,140 @@ async function main() {
|
|
|
1143
1300
|
const md = generateChangelog({ since: changelogOpts.since, format: 'markdown' });
|
|
1144
1301
|
process.stdout.write(md);
|
|
1145
1302
|
});
|
|
1303
|
+
// ── Automate subcommands ──
|
|
1304
|
+
const automateCmd = program
|
|
1305
|
+
.command('automate')
|
|
1306
|
+
.description('Event-driven automations — file watchers, schedules, git hooks, webhooks');
|
|
1307
|
+
automateCmd
|
|
1308
|
+
.command('list')
|
|
1309
|
+
.description('List all configured automations')
|
|
1310
|
+
.action(async () => {
|
|
1311
|
+
const { listAutomations, formatAutomationList } = await import('./automations.js');
|
|
1312
|
+
const automations = listAutomations();
|
|
1313
|
+
process.stderr.write(formatAutomationList(automations) + '\n');
|
|
1314
|
+
});
|
|
1315
|
+
automateCmd
|
|
1316
|
+
.command('add')
|
|
1317
|
+
.description('Create a new automation')
|
|
1318
|
+
.requiredOption('--trigger <trigger>', 'Trigger spec (e.g., "file:src/**/*.ts:change", "schedule:every 5m", "git:pre-commit", "webhook:/deploy")')
|
|
1319
|
+
.requiredOption('--agent <agent>', 'Agent to run (e.g., coder, researcher, guardian)')
|
|
1320
|
+
.requiredOption('--prompt <prompt>', 'Prompt to send to the agent')
|
|
1321
|
+
.option('--name <name>', 'Human-readable name for the automation')
|
|
1322
|
+
.option('--tools <tools>', 'Comma-separated list of tools to enable')
|
|
1323
|
+
.action(async (addOpts) => {
|
|
1324
|
+
try {
|
|
1325
|
+
const { createAutomation, parseTriggerString } = await import('./automations.js');
|
|
1326
|
+
const trigger = parseTriggerString(addOpts.trigger);
|
|
1327
|
+
const automation = createAutomation({
|
|
1328
|
+
name: addOpts.name || `${trigger.type}:${addOpts.agent}`,
|
|
1329
|
+
trigger,
|
|
1330
|
+
action: {
|
|
1331
|
+
agent: addOpts.agent,
|
|
1332
|
+
prompt: addOpts.prompt,
|
|
1333
|
+
tools: addOpts.tools ? addOpts.tools.split(',').map((t) => t.trim()) : undefined,
|
|
1334
|
+
},
|
|
1335
|
+
});
|
|
1336
|
+
printSuccess(`Automation created: ${automation.name} (${automation.id})`);
|
|
1337
|
+
printInfo(` Trigger: ${addOpts.trigger}`);
|
|
1338
|
+
printInfo(` Agent: ${addOpts.agent}`);
|
|
1339
|
+
if (trigger.type === 'git') {
|
|
1340
|
+
printInfo(' Git hooks installed.');
|
|
1341
|
+
}
|
|
1342
|
+
if (trigger.type === 'file' || trigger.type === 'schedule') {
|
|
1343
|
+
printInfo(' Run `kbot automate start` to activate the daemon.');
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
catch (err) {
|
|
1347
|
+
printError(err instanceof Error ? err.message : String(err));
|
|
1348
|
+
process.exit(1);
|
|
1349
|
+
}
|
|
1350
|
+
});
|
|
1351
|
+
automateCmd
|
|
1352
|
+
.command('remove')
|
|
1353
|
+
.description('Remove an automation by ID')
|
|
1354
|
+
.argument('<id>', 'Automation ID')
|
|
1355
|
+
.action(async (id) => {
|
|
1356
|
+
const { removeAutomation } = await import('./automations.js');
|
|
1357
|
+
const removed = removeAutomation(id);
|
|
1358
|
+
if (removed) {
|
|
1359
|
+
printSuccess(`Automation "${id}" removed.`);
|
|
1360
|
+
}
|
|
1361
|
+
else {
|
|
1362
|
+
printError(`Automation "${id}" not found.`);
|
|
1363
|
+
process.exit(1);
|
|
1364
|
+
}
|
|
1365
|
+
});
|
|
1366
|
+
automateCmd
|
|
1367
|
+
.command('run')
|
|
1368
|
+
.description('Manually trigger an automation')
|
|
1369
|
+
.argument('<id>', 'Automation ID')
|
|
1370
|
+
.action(async (id) => {
|
|
1371
|
+
const { runAutomation, getAutomation } = await import('./automations.js');
|
|
1372
|
+
const automation = getAutomation(id);
|
|
1373
|
+
if (!automation) {
|
|
1374
|
+
printError(`Automation "${id}" not found.`);
|
|
1375
|
+
process.exit(1);
|
|
1376
|
+
}
|
|
1377
|
+
printInfo(`Running automation: ${automation.name}...`);
|
|
1378
|
+
const result = await runAutomation(id);
|
|
1379
|
+
if (result.success) {
|
|
1380
|
+
printSuccess(`Automation completed successfully.`);
|
|
1381
|
+
if (result.output) {
|
|
1382
|
+
process.stderr.write('\n' + result.output + '\n');
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
else {
|
|
1386
|
+
printError(`Automation failed: ${result.error}`);
|
|
1387
|
+
process.exit(1);
|
|
1388
|
+
}
|
|
1389
|
+
});
|
|
1390
|
+
automateCmd
|
|
1391
|
+
.command('start')
|
|
1392
|
+
.description('Start the automation daemon (file watchers + schedule timers)')
|
|
1393
|
+
.action(async () => {
|
|
1394
|
+
const { startAutomationDaemon, listAutomations } = await import('./automations.js');
|
|
1395
|
+
const automations = listAutomations();
|
|
1396
|
+
if (automations.length === 0) {
|
|
1397
|
+
printError('No automations configured. Use `kbot automate add` first.');
|
|
1398
|
+
process.exit(1);
|
|
1399
|
+
}
|
|
1400
|
+
printInfo('Starting automation daemon...');
|
|
1401
|
+
const { running } = startAutomationDaemon({
|
|
1402
|
+
log: (msg) => process.stderr.write(msg + '\n'),
|
|
1403
|
+
});
|
|
1404
|
+
if (running) {
|
|
1405
|
+
printSuccess('Daemon running. Press Ctrl+C to stop.');
|
|
1406
|
+
// Keep the process alive
|
|
1407
|
+
await new Promise(() => { });
|
|
1408
|
+
}
|
|
1409
|
+
});
|
|
1410
|
+
program
|
|
1411
|
+
.command('spec <description>')
|
|
1412
|
+
.description('Generate a formal specification with requirements + acceptance criteria before coding')
|
|
1413
|
+
.option('--implement', 'Generate spec then pass to coder agent for implementation')
|
|
1414
|
+
.option('--agent <name>', 'Override the default architect agent', 'architect')
|
|
1415
|
+
.option('--output <path>', 'Custom output path for the spec file')
|
|
1416
|
+
.action(async (description, specOpts) => {
|
|
1417
|
+
const { generateSpec } = await import('./spec.js');
|
|
1418
|
+
const parentOpts = program.opts();
|
|
1419
|
+
try {
|
|
1420
|
+
await generateSpec(description, {
|
|
1421
|
+
agent: specOpts.agent,
|
|
1422
|
+
output: specOpts.output,
|
|
1423
|
+
implement: specOpts.implement,
|
|
1424
|
+
agentOpts: {
|
|
1425
|
+
model: parentOpts.model,
|
|
1426
|
+
stream: parentOpts.stream ?? true,
|
|
1427
|
+
thinking: parentOpts.thinking || false,
|
|
1428
|
+
thinkingBudget: parentOpts.thinkingBudget ? (parseInt(parentOpts.thinkingBudget, 10) || 10000) : undefined,
|
|
1429
|
+
},
|
|
1430
|
+
});
|
|
1431
|
+
}
|
|
1432
|
+
catch (err) {
|
|
1433
|
+
printError(err instanceof Error ? err.message : String(err));
|
|
1434
|
+
process.exit(1);
|
|
1435
|
+
}
|
|
1436
|
+
});
|
|
1146
1437
|
program
|
|
1147
1438
|
.command('completions')
|
|
1148
1439
|
.description('Generate shell tab-completion script (bash, zsh, fish)')
|
|
@@ -1163,7 +1454,7 @@ async function main() {
|
|
|
1163
1454
|
if (opts.quiet)
|
|
1164
1455
|
setQuiet(true);
|
|
1165
1456
|
// If a sub-command was run, we're done
|
|
1166
|
-
if (['byok', 'auth', 'ide', 'local', 'ollama', 'kbot-local', 'pull', 'doctor', 'serve', 'agents', 'watch', 'voice', 'export', 'plugins', 'changelog', 'completions'].includes(program.args[0]))
|
|
1457
|
+
if (['byok', 'auth', 'ide', 'local', 'ollama', 'kbot-local', 'pull', 'doctor', 'serve', 'agents', 'watch', 'voice', 'export', 'plugins', 'changelog', 'completions', 'automate', 'status', 'spec'].includes(program.args[0]))
|
|
1167
1458
|
return;
|
|
1168
1459
|
// Check for API key (BYOK or local provider)
|
|
1169
1460
|
let byokActive = isByokEnabled();
|
|
@@ -1336,7 +1627,7 @@ async function main() {
|
|
|
1336
1627
|
printInfo(syncMsg);
|
|
1337
1628
|
// Determine if we're in one-shot or REPL mode
|
|
1338
1629
|
const isOneShot = promptArgs.length > 0 &&
|
|
1339
|
-
!['byok', 'auth', 'ide', 'ollama', 'kbot-local', 'pull', 'doctor'].includes(promptArgs[0]);
|
|
1630
|
+
!['byok', 'auth', 'ide', 'ollama', 'kbot-local', 'pull', 'doctor', 'spec'].includes(promptArgs[0]);
|
|
1340
1631
|
const isStdinOnly = !process.stdin.isTTY && promptArgs.length === 0;
|
|
1341
1632
|
if (isOneShot || isStdinOnly || opts.pipe) {
|
|
1342
1633
|
// One-shot / pipe mode: start lazy tools in background (non-blocking).
|
|
@@ -1357,6 +1648,7 @@ async function main() {
|
|
|
1357
1648
|
tier,
|
|
1358
1649
|
thinking: opts.thinking || false,
|
|
1359
1650
|
thinkingBudget: opts.thinkingBudget ? (parseInt(opts.thinkingBudget, 10) || 10000) : undefined,
|
|
1651
|
+
plan: opts.plan || false,
|
|
1360
1652
|
};
|
|
1361
1653
|
// Enable self-evaluation if requested
|
|
1362
1654
|
if (opts.selfEval) {
|
|
@@ -1476,7 +1768,7 @@ async function main() {
|
|
|
1476
1768
|
stdinContent = Buffer.concat(chunks).toString('utf-8').trim();
|
|
1477
1769
|
}
|
|
1478
1770
|
// One-shot mode: kbot "fix the bug" — always stream for speed
|
|
1479
|
-
if (promptArgs.length > 0 && !['byok', 'auth', 'ide', 'ollama', 'kbot-local', 'pull', 'doctor'].includes(promptArgs[0])) {
|
|
1771
|
+
if (promptArgs.length > 0 && !['byok', 'auth', 'ide', 'ollama', 'kbot-local', 'pull', 'doctor', 'spec'].includes(promptArgs[0])) {
|
|
1480
1772
|
if (!opts.pipe)
|
|
1481
1773
|
console.log(bannerCompact());
|
|
1482
1774
|
let message = promptArgs.join(' ');
|
|
@@ -1825,9 +2117,20 @@ async function startRepl(agentOpts, context, tier, byokActive = false, localActi
|
|
|
1825
2117
|
printInfo(`${p.name}`);
|
|
1826
2118
|
}
|
|
1827
2119
|
const sessionCount = incrementSessions();
|
|
2120
|
+
// Three-tier memory: run synthesis on every 10th session (or first time with enough data)
|
|
2121
|
+
if (sessionCount % 10 === 0 || sessionCount === 1) {
|
|
2122
|
+
try {
|
|
2123
|
+
const insightCount = maybeSynthesize();
|
|
2124
|
+
if (insightCount > 0) {
|
|
2125
|
+
printInfo(`Memory synthesis: ${insightCount} insights generated`);
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
catch { /* synthesis is non-critical */ }
|
|
2129
|
+
}
|
|
1828
2130
|
// Return-visit greeting — show kbot's growth
|
|
1829
2131
|
if (sessionCount > 1) {
|
|
1830
2132
|
const stats = getExtendedStats();
|
|
2133
|
+
const synthStats = getSynthesisStats();
|
|
1831
2134
|
const parts = [];
|
|
1832
2135
|
if (stats.patternsCount > 0)
|
|
1833
2136
|
parts.push(`${stats.patternsCount} patterns learned`);
|
|
@@ -1835,6 +2138,8 @@ async function startRepl(agentOpts, context, tier, byokActive = false, localActi
|
|
|
1835
2138
|
parts.push(`${stats.solutionsCount} solutions cached`);
|
|
1836
2139
|
if (stats.knowledgeCount > 0)
|
|
1837
2140
|
parts.push(`${stats.knowledgeCount} facts remembered`);
|
|
2141
|
+
if (synthStats.insightCount > 0)
|
|
2142
|
+
parts.push(`${synthStats.insightCount} insights synthesized`);
|
|
1838
2143
|
if (parts.length > 0) {
|
|
1839
2144
|
printInfo(`Session ${stats.sessions} · ${parts.join(' · ')}`);
|
|
1840
2145
|
}
|