@kernel.chat/kbot 3.17.2 → 3.19.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/cli.js +72 -1
- package/dist/cli.js.map +1 -1
- package/dist/observer.d.ts +34 -0
- package/dist/observer.d.ts.map +1 -0
- package/dist/observer.js +246 -0
- package/dist/observer.js.map +1 -0
- package/dist/seed-knowledge.d.ts +22 -0
- package/dist/seed-knowledge.d.ts.map +1 -0
- package/dist/seed-knowledge.js +176 -0
- package/dist/seed-knowledge.js.map +1 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -395,6 +395,66 @@ async function main() {
|
|
|
395
395
|
process.stderr.write('\n');
|
|
396
396
|
process.exit(0);
|
|
397
397
|
});
|
|
398
|
+
program
|
|
399
|
+
.command('observe')
|
|
400
|
+
.description('Ingest observations from Claude Code sessions — kbot learns from what Claude does')
|
|
401
|
+
.option('--stats', 'Show observer statistics')
|
|
402
|
+
.option('--reset', 'Reset the observer log and cursor')
|
|
403
|
+
.action(async (opts) => {
|
|
404
|
+
const { ingestObservations, getObserverStats, getLogPath } = await import('./observer.js');
|
|
405
|
+
const chalk = (await import('chalk')).default;
|
|
406
|
+
if (opts.reset) {
|
|
407
|
+
const { existsSync, unlinkSync } = await import('node:fs');
|
|
408
|
+
const { join } = await import('node:path');
|
|
409
|
+
const { homedir } = await import('node:os');
|
|
410
|
+
const dir = join(homedir(), '.kbot', 'observer');
|
|
411
|
+
for (const f of ['session.jsonl', 'cursor.json', 'stats.json']) {
|
|
412
|
+
const p = join(dir, f);
|
|
413
|
+
if (existsSync(p))
|
|
414
|
+
unlinkSync(p);
|
|
415
|
+
}
|
|
416
|
+
printSuccess('Observer log reset.');
|
|
417
|
+
process.exit(0);
|
|
418
|
+
}
|
|
419
|
+
if (opts.stats) {
|
|
420
|
+
const stats = getObserverStats();
|
|
421
|
+
console.log();
|
|
422
|
+
console.log(chalk.hex('#6B5B95')(' ◉ kbot Observer'));
|
|
423
|
+
console.log(chalk.dim(` Log: ${getLogPath()}`));
|
|
424
|
+
console.log();
|
|
425
|
+
console.log(` Total observed: ${stats.totalObserved}`);
|
|
426
|
+
console.log(` Sessions observed: ${stats.sessionsObserved}`);
|
|
427
|
+
console.log(` Sequences learned: ${stats.sequencesLearned}`);
|
|
428
|
+
console.log(` Facts learned: ${stats.factsLearned}`);
|
|
429
|
+
console.log(` Last ingested: ${stats.lastIngested || 'never'}`);
|
|
430
|
+
if (Object.keys(stats.toolFrequency).length > 0) {
|
|
431
|
+
console.log();
|
|
432
|
+
console.log(chalk.bold(' Tool frequency:'));
|
|
433
|
+
const sorted = Object.entries(stats.toolFrequency).sort((a, b) => b[1] - a[1]).slice(0, 10);
|
|
434
|
+
for (const [tool, count] of sorted) {
|
|
435
|
+
console.log(` ${String(count).padStart(4)}x ${tool}`);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
console.log();
|
|
439
|
+
process.exit(0);
|
|
440
|
+
}
|
|
441
|
+
// Default: ingest new observations
|
|
442
|
+
printInfo('Ingesting observations from Claude Code sessions...');
|
|
443
|
+
const result = await ingestObservations();
|
|
444
|
+
if (result.processed === 0) {
|
|
445
|
+
printInfo('No new observations to ingest.');
|
|
446
|
+
printInfo(`Log file: ${getLogPath()}`);
|
|
447
|
+
printInfo('The Claude Code PostToolUse hook writes here after every tool call.');
|
|
448
|
+
}
|
|
449
|
+
else {
|
|
450
|
+
printSuccess(`Ingested ${result.processed} tool calls from ${result.sessions.length} session(s)`);
|
|
451
|
+
if (result.patterns > 0)
|
|
452
|
+
printInfo(` Sequences learned: ${result.patterns}`);
|
|
453
|
+
if (result.facts > 0)
|
|
454
|
+
printInfo(` Facts learned: ${result.facts}`);
|
|
455
|
+
}
|
|
456
|
+
process.exit(0);
|
|
457
|
+
});
|
|
398
458
|
program
|
|
399
459
|
.command('doctor')
|
|
400
460
|
.description('Diagnose your kbot setup — check everything is working')
|
|
@@ -1985,7 +2045,7 @@ async function main() {
|
|
|
1985
2045
|
if (opts.quiet)
|
|
1986
2046
|
setQuiet(true);
|
|
1987
2047
|
// If a sub-command was run, we're done
|
|
1988
|
-
if (['byok', 'auth', 'ide', 'local', 'ollama', 'kbot-local', 'pull', 'doctor', 'serve', 'agents', 'watch', 'voice', 'export', 'plugins', 'changelog', 'completions', 'automate', 'status', 'spec', 'a2a', 'init', 'email-agent', 'imessage-agent', 'consultation'].includes(program.args[0]))
|
|
2048
|
+
if (['byok', 'auth', 'ide', 'local', 'ollama', 'kbot-local', 'pull', 'doctor', 'serve', 'agents', 'watch', 'voice', 'export', 'plugins', 'changelog', 'completions', 'automate', 'status', 'spec', 'a2a', 'init', 'email-agent', 'imessage-agent', 'consultation', 'observe'].includes(program.args[0]))
|
|
1989
2049
|
return;
|
|
1990
2050
|
// Check for API key (BYOK or local provider)
|
|
1991
2051
|
let byokActive = isByokEnabled();
|
|
@@ -2669,6 +2729,17 @@ async function startRepl(agentOpts, context, tier, byokActive = false, localActi
|
|
|
2669
2729
|
printInfo(`${p.name}`);
|
|
2670
2730
|
}
|
|
2671
2731
|
const sessionCount = incrementSessions();
|
|
2732
|
+
// Seed knowledge on first run — give new users a head start
|
|
2733
|
+
if (sessionCount <= 2) {
|
|
2734
|
+
try {
|
|
2735
|
+
const { loadSeedKnowledge } = await import('./seed-knowledge.js');
|
|
2736
|
+
const seed = await loadSeedKnowledge();
|
|
2737
|
+
if (seed.seeded) {
|
|
2738
|
+
printInfo(`Loaded ${seed.patterns} patterns + ${seed.facts} knowledge entries from seed data`);
|
|
2739
|
+
}
|
|
2740
|
+
}
|
|
2741
|
+
catch { /* seed loading is non-critical */ }
|
|
2742
|
+
}
|
|
2672
2743
|
// Three-tier memory: run synthesis on every 10th session (or first time with enough data)
|
|
2673
2744
|
if (sessionCount % 10 === 0 || sessionCount === 1) {
|
|
2674
2745
|
try {
|