@kernel.chat/kbot 3.64.0 → 3.66.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.
@@ -375,6 +375,34 @@ export function resetEvolution(agent) {
375
375
  }
376
376
  persist();
377
377
  }
378
+ /**
379
+ * Register an external prompt amendment (e.g. from the dream engine).
380
+ * This allows other subsystems to inject mutations into the evolution state
381
+ * without going through the trace-based evolvePrompt() pipeline.
382
+ *
383
+ * The mutation is tagged with an optional sourceId for traceability
384
+ * (e.g. the dream insight ID that produced it).
385
+ */
386
+ export function registerAmendment(agent, amendment, reason, sourceId) {
387
+ const state = getState();
388
+ const taggedReason = sourceId ? `${reason} [source: ${sourceId}]` : reason;
389
+ const mutation = {
390
+ agent,
391
+ original: getPromptAmendment(agent),
392
+ mutated: `\n\n[Dream-Evolved — ${new Date().toISOString().slice(0, 10)}]\n${amendment}`,
393
+ reason: taggedReason,
394
+ appliedAt: new Date().toISOString(),
395
+ scoreBefore: 0,
396
+ scoreAfter: 0,
397
+ };
398
+ state.mutations.push(mutation);
399
+ if (state.mutations.length > MAX_MUTATIONS) {
400
+ state.mutations = state.mutations.slice(-MAX_MUTATIONS);
401
+ }
402
+ state.generation++;
403
+ persist();
404
+ return mutation;
405
+ }
378
406
  /**
379
407
  * Flush pending state to disk. Call on process exit.
380
408
  */
@@ -15,6 +15,7 @@ interface AuditSection {
15
15
  }
16
16
  declare function auditRepo(repo: string): Promise<AuditResult>;
17
17
  declare function formatAuditReport(result: AuditResult): string;
18
+ declare function formatAuditTerminal(result: AuditResult): string;
18
19
  export declare function registerAuditTools(): void;
19
- export { auditRepo, formatAuditReport };
20
+ export { auditRepo, formatAuditReport, formatAuditTerminal };
20
21
  //# sourceMappingURL=audit.d.ts.map
@@ -2,10 +2,11 @@
2
2
  //
3
3
  // Security, code quality, documentation, dependency health — all in one report.
4
4
  // Designed to be shared. Every audit links back to kbot.
5
+ import chalk from 'chalk';
5
6
  import { registerTool } from './index.js';
6
7
  const GITHUB_API = 'https://api.github.com';
7
8
  const HEADERS = {
8
- 'User-Agent': 'KBot/2.18 (Audit)',
9
+ 'User-Agent': 'KBot/3.65 (Audit)',
9
10
  'Accept': 'application/vnd.github.v3+json',
10
11
  };
11
12
  async function githubFetch(path) {
@@ -17,7 +18,7 @@ async function githubFetch(path) {
17
18
  async function rawFetch(repo, path, branch = 'main') {
18
19
  for (const b of [branch, 'master']) {
19
20
  try {
20
- const res = await fetch(`https://raw.githubusercontent.com/${repo}/${b}/${path}`, { headers: { 'User-Agent': 'KBot/2.18' } });
21
+ const res = await fetch(`https://raw.githubusercontent.com/${repo}/${b}/${path}`, { headers: { 'User-Agent': 'KBot/3.65' } });
21
22
  if (res.ok)
22
23
  return res.text();
23
24
  }
@@ -414,7 +415,7 @@ function formatAuditReport(result) {
414
415
  // Badge
415
416
  const badgeColor = pct >= 80 ? 'brightgreen' : pct >= 60 ? 'yellow' : 'red';
416
417
  const badgeUrl = `https://img.shields.io/badge/kbot_audit-${result.grade}_(${pct}%25)-${badgeColor}`;
417
- lines.push('---', '', '### Add this badge to your README', '', '```markdown', `[![kbot audit: ${result.grade}](${badgeUrl})](https://www.npmjs.com/package/@kernel.chat/kbot)`, '```', '', `*Audited by [kbot](https://www.npmjs.com/package/@kernel.chat/kbot) — 25 specialist agents, 290+ tools, 20 AI providers*`, `*Install: \`npm install -g @kernel.chat/kbot\` | Audit any repo: \`kbot audit owner/repo\`*`);
418
+ lines.push('---', '', '### Add this badge to your README', '', '```markdown', `[![kbot audit: ${result.grade}](${badgeUrl})](https://www.npmjs.com/package/@kernel.chat/kbot)`, '```', '', `*Audited by [kbot](https://www.npmjs.com/package/@kernel.chat/kbot) — 35 specialist agents, 686+ tools, 20 AI providers*`, `*Install: \`npm install -g @kernel.chat/kbot\` | Audit any repo: \`kbot audit owner/repo\`*`);
418
419
  return lines.join('\n');
419
420
  }
420
421
  /** Generate a compact one-line summary for social sharing */
@@ -431,6 +432,128 @@ function formatAuditSummary(result) {
431
432
  summary += ' — Clean bill of health';
432
433
  return summary;
433
434
  }
435
+ // ── Terminal-styled audit report (chalk) ──────────────────────────────────────
436
+ const VIOLET = '#A78BFA';
437
+ const GREEN = '#4ADE80';
438
+ const YELLOW = '#FBBF24';
439
+ const RED = '#F87171';
440
+ const DIM = '#6B7280';
441
+ const WHITE = '#F9FAFB';
442
+ function gradeColor(grade) {
443
+ if (grade === 'A')
444
+ return GREEN;
445
+ if (grade === 'B')
446
+ return GREEN;
447
+ if (grade === 'C')
448
+ return YELLOW;
449
+ if (grade === 'D')
450
+ return YELLOW;
451
+ return RED;
452
+ }
453
+ function statusColor(status) {
454
+ if (status === 'pass')
455
+ return GREEN;
456
+ if (status === 'warn')
457
+ return YELLOW;
458
+ return RED;
459
+ }
460
+ function scoreBar(score, max, width = 20) {
461
+ const pct = max > 0 ? score / max : 0;
462
+ const filled = Math.round(pct * width);
463
+ const empty = width - filled;
464
+ const color = pct >= 0.8 ? GREEN : pct >= 0.6 ? YELLOW : RED;
465
+ return chalk.hex(color)('\u2588'.repeat(filled)) + chalk.hex(DIM)('\u2591'.repeat(empty));
466
+ }
467
+ function boxLine(content, width) {
468
+ // Strip ANSI for length calculation
469
+ const stripped = content.replace(/\x1b\[[0-9;]*m/g, '');
470
+ const pad = Math.max(0, width - stripped.length - 4);
471
+ return chalk.hex(DIM)('\u2502') + ' ' + content + ' '.repeat(pad) + ' ' + chalk.hex(DIM)('\u2502');
472
+ }
473
+ function findingIcon(finding, _sectionStatus) {
474
+ // Heuristic: positive findings get check, negative get appropriate icon
475
+ const negative = /^(no |missing |could not |stale |\.env NOT|not |high dep|default branch is NOT)/i;
476
+ const warning = /^(readme is short|updated \d+d ago)/i;
477
+ if (negative.test(finding))
478
+ return chalk.hex(RED)('\u2717');
479
+ if (warning.test(finding))
480
+ return chalk.hex(YELLOW)('\u26A0');
481
+ return chalk.hex(GREEN)('\u2713');
482
+ }
483
+ function formatAuditTerminal(result) {
484
+ const pct = Math.round((result.score / result.maxScore) * 100);
485
+ const gc = gradeColor(result.grade);
486
+ const lines = [];
487
+ const W = 60; // inner width
488
+ // ── Header box ──
489
+ const title = `AUDIT REPORT: ${result.repo}`;
490
+ const titlePad = Math.max(0, W - title.length - 2);
491
+ const leftPad = Math.floor(titlePad / 2);
492
+ const rightPad = titlePad - leftPad;
493
+ lines.push('');
494
+ lines.push(chalk.hex(VIOLET)('\u256D') +
495
+ chalk.hex(VIOLET)('\u2500'.repeat(leftPad + 1)) +
496
+ chalk.hex(WHITE).bold(` ${title} `) +
497
+ chalk.hex(VIOLET)('\u2500'.repeat(rightPad + 1)) +
498
+ chalk.hex(VIOLET)('\u256E'));
499
+ // Grade line inside box
500
+ const gradeLine = ` Grade ${chalk.hex(gc).bold(result.grade)} ${chalk.hex(DIM)('\u2502')} ${result.score}/${result.maxScore} (${pct}%)`;
501
+ lines.push(boxLine(gradeLine, W + 4));
502
+ // Score bar inside box
503
+ const bar = scoreBar(result.score, result.maxScore, 30);
504
+ const barLine = ` ${bar} ${chalk.hex(gc).bold(`${pct}%`)}`;
505
+ lines.push(boxLine(barLine, W + 4));
506
+ // Summary inside box
507
+ lines.push(boxLine('', W + 4));
508
+ lines.push(boxLine(` ${chalk.hex(WHITE)(result.summary)}`, W + 4));
509
+ // Close header box
510
+ lines.push(chalk.hex(VIOLET)('\u2570') +
511
+ chalk.hex(VIOLET)('\u2500'.repeat(W + 2)) +
512
+ chalk.hex(VIOLET)('\u256F'));
513
+ lines.push('');
514
+ // ── Sections ──
515
+ for (const section of result.sections) {
516
+ const sPct = section.maxScore > 0 ? Math.round((section.score / section.maxScore) * 100) : 0;
517
+ const sc = statusColor(section.status);
518
+ const statusDot = section.status === 'pass'
519
+ ? chalk.hex(GREEN)('\u25CF')
520
+ : section.status === 'warn'
521
+ ? chalk.hex(YELLOW)('\u25CF')
522
+ : chalk.hex(RED)('\u25CF');
523
+ // Section header
524
+ lines.push(` ${statusDot} ${chalk.hex(WHITE).bold(section.name)} ` +
525
+ chalk.hex(DIM)('\u2500'.repeat(Math.max(1, 40 - section.name.length))) +
526
+ ` ${scoreBar(section.score, section.maxScore, 12)} ` +
527
+ chalk.hex(sc).bold(`${sPct}%`));
528
+ // Findings
529
+ for (const f of section.findings) {
530
+ const icon = findingIcon(f, section.status);
531
+ lines.push(` ${icon} ${chalk.hex(DIM)(f)}`);
532
+ }
533
+ lines.push('');
534
+ }
535
+ // ── Footer ──
536
+ const sep = chalk.hex(VIOLET)('\u2500'.repeat(W + 2));
537
+ lines.push(sep);
538
+ lines.push('');
539
+ // Badge markdown
540
+ const badgeColor = pct >= 80 ? 'brightgreen' : pct >= 60 ? 'yellow' : 'red';
541
+ const badgeUrl = `https://img.shields.io/badge/kbot_audit-${result.grade}_(${pct}%25)-${badgeColor}`;
542
+ lines.push(chalk.hex(VIOLET).bold(' Add this badge to your README:'));
543
+ lines.push('');
544
+ lines.push(chalk.hex(DIM)(` [![kbot audit: ${result.grade}](${badgeUrl})](https://www.npmjs.com/package/@kernel.chat/kbot)`));
545
+ lines.push('');
546
+ // Install CTA
547
+ lines.push(chalk.hex(DIM)(' Audited by ') +
548
+ chalk.hex(VIOLET).bold('kbot') +
549
+ chalk.hex(DIM)(' \u2014 35 specialist agents, 686+ tools, 20 AI providers'));
550
+ lines.push(chalk.hex(DIM)(' Install: ') +
551
+ chalk.hex(WHITE)('npm install -g @kernel.chat/kbot') +
552
+ chalk.hex(DIM)(' | Audit any repo: ') +
553
+ chalk.hex(WHITE)('kbot audit owner/repo'));
554
+ lines.push('');
555
+ return lines.join('\n');
556
+ }
434
557
  export function registerAuditTools() {
435
558
  registerTool({
436
559
  name: 'repo_audit',
@@ -453,5 +576,5 @@ export function registerAuditTools() {
453
576
  });
454
577
  }
455
578
  // Export for CLI subcommand
456
- export { auditRepo, formatAuditReport };
579
+ export { auditRepo, formatAuditReport, formatAuditTerminal };
457
580
  //# sourceMappingURL=audit.js.map
@@ -0,0 +1,2 @@
1
+ export declare function registerCollectiveDreamTools(): void;
2
+ //# sourceMappingURL=collective-dream-tools.d.ts.map
@@ -0,0 +1,109 @@
1
+ // kbot Collective Dream Tools — Share and receive dream wisdom
2
+ //
3
+ // Agent-accessible tools for the collective dream sharing system:
4
+ // - collective_dream_status: How many local insights are shareable, opt-in state
5
+ // - collective_dream_optin: Opt in/out of anonymous dream sharing
6
+ import { registerTool } from './index.js';
7
+ import { loadConfig, saveConfig } from '../auth.js';
8
+ import { getDreamStatus } from '../dream.js';
9
+ import { prepareCollectiveDreams } from '../collective-dreams.js';
10
+ // ── Config helpers ──
11
+ const OPTIN_KEY = 'collective_dreams_enabled';
12
+ function isDreamSharingEnabled() {
13
+ const config = loadConfig();
14
+ if (!config)
15
+ return false;
16
+ return config[OPTIN_KEY] === true;
17
+ }
18
+ function setDreamSharingEnabled(enabled) {
19
+ const config = loadConfig() || { default_model: 'auto', default_agent: 'auto' };
20
+ config[OPTIN_KEY] = enabled;
21
+ saveConfig(config);
22
+ }
23
+ // ── Tool Registration ──
24
+ export function registerCollectiveDreamTools() {
25
+ registerTool({
26
+ name: 'collective_dream_status',
27
+ description: 'Show collective dream sharing status — how many local insights qualify for sharing, opt-in state, and what gets anonymized. Use this to check before opting in.',
28
+ parameters: {},
29
+ tier: 'free',
30
+ async execute() {
31
+ const enabled = isDreamSharingEnabled();
32
+ const { insights } = getDreamStatus();
33
+ // Check how many would qualify for sharing (relevance > 0.7)
34
+ const shareable = prepareCollectiveDreams(insights);
35
+ const highRelevance = insights.filter(i => i.relevance > 0.7).length;
36
+ const lines = [
37
+ 'Collective Dream Sharing',
38
+ '========================',
39
+ `Status: ${enabled ? 'OPTED IN' : 'not opted in'}`,
40
+ '',
41
+ `Local insights: ${insights.length}`,
42
+ `High-relevance (>0.7): ${highRelevance}`,
43
+ `Shareable after anonymization: ${shareable.length}`,
44
+ '',
45
+ 'What gets shared (anonymized):',
46
+ ' - Dream category (pattern, preference, skill, etc.)',
47
+ ' - Keywords (PII stripped)',
48
+ ' - Generalized content (names, paths, keys removed)',
49
+ '',
50
+ 'What NEVER gets shared:',
51
+ ' - Raw insight text, file paths, project names',
52
+ ' - API keys, source code, conversation content',
53
+ ' - Your identity or any personal information',
54
+ ];
55
+ if (shareable.length > 0) {
56
+ lines.push('', 'Preview of anonymized insights:');
57
+ for (const s of shareable.slice(0, 3)) {
58
+ lines.push(` [${s.category}] ${s.generalizedContent.slice(0, 120)}`);
59
+ if (s.keywords.length > 0) {
60
+ lines.push(` keywords: ${s.keywords.join(', ')}`);
61
+ }
62
+ }
63
+ if (shareable.length > 3) {
64
+ lines.push(` ... and ${shareable.length - 3} more`);
65
+ }
66
+ }
67
+ if (!enabled) {
68
+ lines.push('', 'To opt in: use the collective_dream_optin tool with enabled=true');
69
+ }
70
+ return lines.join('\n');
71
+ },
72
+ });
73
+ registerTool({
74
+ name: 'collective_dream_optin',
75
+ description: 'Opt in or out of anonymous collective dream sharing. When enabled, high-relevance insights are anonymized and prepared for upload to the collective pool. Other kbot users benefit from aggregated patterns. Persists to ~/.kbot/config.json.',
76
+ parameters: {
77
+ enabled: {
78
+ type: 'boolean',
79
+ description: 'true to opt in, false to opt out',
80
+ required: true,
81
+ },
82
+ },
83
+ tier: 'free',
84
+ async execute(args) {
85
+ const enabled = args.enabled === true || args.enabled === 'true';
86
+ setDreamSharingEnabled(enabled);
87
+ if (enabled) {
88
+ const { insights } = getDreamStatus();
89
+ const shareable = prepareCollectiveDreams(insights);
90
+ return [
91
+ 'Collective dream sharing: ENABLED',
92
+ '',
93
+ `${shareable.length} insights ready to share (anonymized).`,
94
+ 'Your dreams will be stripped of all personal info before sharing.',
95
+ 'You can opt out at any time.',
96
+ ].join('\n');
97
+ }
98
+ else {
99
+ return [
100
+ 'Collective dream sharing: DISABLED',
101
+ '',
102
+ 'No insights will be shared. Your dream journal remains fully private.',
103
+ 'Existing collective data (if any) is not affected.',
104
+ ].join('\n');
105
+ }
106
+ },
107
+ });
108
+ } // end registerCollectiveDreamTools
109
+ //# sourceMappingURL=collective-dream-tools.js.map
@@ -299,6 +299,7 @@ const LAZY_MODULE_IMPORTS = [
299
299
  { path: './dj-set-builder.js', registerFn: 'registerDjSetBuilderTools' },
300
300
  { path: './serum2-preset.js', registerFn: 'registerSerum2PresetTools' },
301
301
  { path: './dream-tools.js', registerFn: 'registerDreamTools' },
302
+ { path: './collective-dream-tools.js', registerFn: 'registerCollectiveDreamTools' },
302
303
  { path: './memory-scanner-tools.js', registerFn: 'registerMemoryScannerTools' },
303
304
  { path: './buddy-tools.js', registerFn: 'registerBuddyTools' },
304
305
  { path: './voice-input-tools.js', registerFn: 'registerVoiceInputTools' },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kernel.chat/kbot",
3
- "version": "3.64.0",
3
+ "version": "3.66.0",
4
4
  "description": "Open-source terminal AI agent. 686+ tools, 35 agents, 20 providers. Fully local, fully sovereign. MIT.",
5
5
  "type": "module",
6
6
  "repository": {