@kernel.chat/kbot 3.72.0 → 3.73.1

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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  <p align="center">
4
4
  <strong>kbot</strong><br>
5
- Open-source terminal AI agent. 693+ tools. 35 agents. 20 providers. Dreams, learns, watches your system. $0 local.
5
+ Open-source terminal AI agent. 764+ tools. 35 agents. 20 providers. Dreams, learns, watches your system, controls your phone. $0 local.
6
6
  </p>
7
7
 
8
8
  <p align="center">
@@ -30,7 +30,7 @@ Most terminal AI agents lock you into one provider, one model, one way of workin
30
30
  - **Runs fully offline** — Embedded llama.cpp, Ollama, LM Studio, or Jan. $0, fully private.
31
31
  - **Learns your patterns** — Bayesian skill ratings + pattern extraction. Gets faster over time.
32
32
  - **35 specialist agents** — auto-routes your request to the right expert (coder, researcher, writer, guardian, quant, and 30 more).
33
- - **693+ tools** — files, bash, git, GitHub, web search, deploy, database, game dev, VFX, research, science, finance, security, and more.
33
+ - **764+ tools** — files, bash, git, GitHub, web search, deploy, database, game dev, VFX, research, science, finance, security, music production, iPhone control, and more.
34
34
  - **Programmatic SDK** — use kbot as a library in your own apps.
35
35
  - **MCP server built in** — plug kbot into Claude Code, Cursor, VS Code, Zed, or Neovim as a tool provider.
36
36
 
@@ -65,6 +65,66 @@ kbot dream status # What kbot learned about you
65
65
  - **Companion memory** — email agent remembers every user's preferences, goals, and conversation history
66
66
  - **Proactive follow-ups** — checks in with users who go quiet, referencing their specific context
67
67
 
68
+ ### Your Buddy — Terminal Companion
69
+
70
+ Every kbot user gets a unique ASCII buddy that evolves with them:
71
+
72
+ ```
73
+ [=====] /\ /\ {o,o} /\_/\
74
+ |[o o]| ( .. ) |)__) ( o.o )
75
+ | _ | ) ( -"-"- > ^ <
76
+ |_____| (______)\ -|-|- (_/|\_)
77
+ || || || || _// \\_ | |
78
+ Robot Fox Owl Cat
79
+ ```
80
+
81
+ - **8 species** — deterministic based on your machine. Same user = same buddy always.
82
+ - **4 evolution levels** — levels up with XP from sessions, dreams, tool usage
83
+ - **18 achievements** — First Dream, Centurion, Tool Master, Night Owl, and more
84
+ - **Dream narration** — buddy tells you what it dreamed on startup
85
+ - **Chat mode** — `kbot buddy chat` to talk directly to your buddy via local Ollama ($0)
86
+ - **Leaderboard** — [kernel.chat/#/leaderboard](https://kernel.chat/#/leaderboard)
87
+
88
+ ### iPhone Control
89
+
90
+ Control your iPhone from the terminal:
91
+
92
+ ```
93
+ kbot phone_message --to "mom" --message "on my way" # Send iMessage
94
+ kbot phone_notify # Read notifications
95
+ kbot phone_shortcut --name "Morning Routine" # Run Shortcuts
96
+ kbot phone_call --number "555-1234" # FaceTime call
97
+ kbot phone_clipboard --action write --text "hello" # Universal Clipboard
98
+ ```
99
+
100
+ ### Music Production — Ableton Live Integration
101
+
102
+ ```
103
+ kbot produce_beat --genre trap --instruments roland # Full beat in Ableton
104
+ kbot generate_drum_pattern --genre house --bpm 124 # MIDI drum pattern
105
+ kbot music_idea "late night drive through Tokyo" # Creative blueprint
106
+ kbot ableton_load_effect --track 2 --name "Saturator" # Load any plugin
107
+ ```
108
+
109
+ Programmatic control of Ableton Live 12 — create tracks, load plugins (including Roland Cloud, Serum 2), write MIDI, set device parameters, fire clips. All from the terminal.
110
+
111
+ ### Financial Analysis
112
+
113
+ ```
114
+ kbot market_analysis --ticker AAPL # 5-perspective coordinated analysis
115
+ kbot portfolio_review --holdings '[...]' # MAGI impact, risk scoring
116
+ kbot market_briefing # Morning market summary
117
+ ```
118
+
119
+ ### Cyber Threat Intelligence
120
+
121
+ ```
122
+ kbot threat_feed # Latest CVEs matched to your stack
123
+ kbot ioc_check --indicator "1.2.3.4" # Check IPs/domains/hashes
124
+ kbot attack_surface_scan --domain x.com # Passive recon + security headers
125
+ kbot incident_response --type ransomware # Generate IR playbook
126
+ ```
127
+
68
128
  ### Audit Any Repo in One Command
69
129
 
70
130
  ```
@@ -81,12 +141,18 @@ Checks security, documentation, code quality, CI/CD, community health, and DevOp
81
141
  |---|---|---|---|---|---|
82
142
  | AI providers | 20 | 1 | 1 | 6 | 75+ |
83
143
  | Specialist agents | 35 | 0 | 0 | 0 | 0 |
84
- | Built-in tools | 693+ | ~20 | ~15 | ~10 | ~15 |
144
+ | Built-in tools | 764+ | ~20 | ~15 | ~10 | ~15 |
85
145
  | Science tools | 114 | 0 | 0 | 0 | 0 |
86
146
  | Memory system | 7-tier bidirectional | File-based | No | No | No |
87
147
  | Dream engine | Yes ($0 local) | Cloud API | No | No | No |
88
148
  | Service watchdog | Yes | No | No | No | No |
89
149
  | Behavior learning | Yes | No | No | No | No |
150
+ | Buddy companion | Yes (8 species) | No | No | No | No |
151
+ | iPhone control | Yes | No | No | No | No |
152
+ | Music production | Ableton Live | No | No | No | No |
153
+ | Financial analysis | Multi-agent | No | No | No | No |
154
+ | Threat intelligence | Yes | No | No | No | No |
155
+ | Buddy leaderboard | kernel.chat | No | No | No | No |
90
156
  | Offline mode | Embedded + Ollama | No | No | Ollama | Ollama |
91
157
  | SDK | Yes | No | Yes | No | No |
92
158
  | MCP server | Yes | N/A | No | No | No |
package/dist/buddy.d.ts CHANGED
@@ -74,6 +74,27 @@ export declare function addBuddyXP(amount: number): {
74
74
  levelInfo: BuddyLevelInfo;
75
75
  leveledUp: boolean;
76
76
  };
77
+ /**
78
+ * Sync buddy stats to the cloud leaderboard.
79
+ * Anonymous — uses a SHA-256 hash of hostname+homedir, not user identity.
80
+ * Requires a kernel.chat token (cloud sync enabled).
81
+ */
82
+ export declare function syncBuddyToCloud(): Promise<boolean>;
83
+ /**
84
+ * Fetch the buddy leaderboard from the cloud.
85
+ * Returns ranked entries sorted by XP descending.
86
+ */
87
+ export declare function fetchBuddyLeaderboard(opts?: {
88
+ limit?: number;
89
+ species?: string;
90
+ }): Promise<Array<{
91
+ species: string;
92
+ level: number;
93
+ xp: number;
94
+ achievement_count: number;
95
+ sessions: number;
96
+ rank: number;
97
+ }>>;
77
98
  /**
78
99
  * Get the buddy's current level info without modifying state.
79
100
  * Includes level, XP, XP to next level, and species-specific title.
package/dist/buddy.js CHANGED
@@ -7,7 +7,7 @@
7
7
  // Achievements: milestones that unlock as the user uses kbot. Persisted in buddy.json.
8
8
  //
9
9
  // Persists buddy name + achievements to ~/.kbot/buddy.json
10
- import { homedir } from 'node:os';
10
+ import { homedir, hostname } from 'node:os';
11
11
  import { join } from 'node:path';
12
12
  import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
13
13
  import { createHash } from 'node:crypto';
@@ -15,6 +15,7 @@ import { createInterface } from 'node:readline';
15
15
  import { getDreamStatus, getDreamPrompt } from './dream.js';
16
16
  import { getExtendedStats, getProfileSummary } from './learning.js';
17
17
  import { getToolMetrics } from './tools/index.js';
18
+ import { getCloudToken } from './cloud-sync.js';
18
19
  // ── Paths ──
19
20
  const KBOT_DIR = join(homedir(), '.kbot');
20
21
  const BUDDY_FILE = join(KBOT_DIR, 'buddy.json');
@@ -930,6 +931,8 @@ export function addBuddyXP(amount) {
930
931
  config.evolution = evo;
931
932
  saveBuddyConfig(config);
932
933
  cachedEvolution = evo;
934
+ // Debounced cloud sync — leaderboard update
935
+ scheduleBuddySync();
933
936
  const species = resolveSpecies();
934
937
  const nextLevel = (newLevel < 3 ? (newLevel + 1) : null);
935
938
  const xpToNext = nextLevel !== null ? LEVEL_THRESHOLDS[nextLevel] - evo.xp : null;
@@ -943,6 +946,99 @@ export function addBuddyXP(amount) {
943
946
  leveledUp,
944
947
  };
945
948
  }
949
+ // ── Cloud Sync — Buddy Leaderboard ──
950
+ const ENGINE_URL = 'https://eoxxpyixdieprsxlpwcs.supabase.co/functions/v1/kbot-engine';
951
+ const BUDDY_SYNC_DEBOUNCE_MS = 5 * 60 * 1000; // max once per 5 minutes
952
+ let buddySyncTimer = null;
953
+ let lastBuddySync = 0;
954
+ /** Generate an anonymous device hash from hostname + homedir */
955
+ function getDeviceHash() {
956
+ return createHash('sha256')
957
+ .update(`${hostname()}:${homedir()}`)
958
+ .digest('hex');
959
+ }
960
+ /**
961
+ * Sync buddy stats to the cloud leaderboard.
962
+ * Anonymous — uses a SHA-256 hash of hostname+homedir, not user identity.
963
+ * Requires a kernel.chat token (cloud sync enabled).
964
+ */
965
+ export async function syncBuddyToCloud() {
966
+ const token = getCloudToken();
967
+ if (!token)
968
+ return false;
969
+ try {
970
+ const buddy = getBuddy();
971
+ const lvl = getBuddyLevel();
972
+ const achievements = getAchievements();
973
+ const stats = getExtendedStats();
974
+ const unlockedCount = achievements.filter(a => a.unlockedAt !== null).length;
975
+ const res = await fetch(`${ENGINE_URL}/sync`, {
976
+ method: 'POST',
977
+ headers: {
978
+ 'Content-Type': 'application/json',
979
+ 'Authorization': `Bearer ${token}`,
980
+ },
981
+ body: JSON.stringify({
982
+ action: 'buddy_sync',
983
+ device_hash: getDeviceHash(),
984
+ species: buddy.species,
985
+ level: lvl.level,
986
+ xp: lvl.xp,
987
+ achievement_count: unlockedCount,
988
+ sessions: stats.sessions,
989
+ }),
990
+ signal: AbortSignal.timeout(10_000),
991
+ });
992
+ return res.ok;
993
+ }
994
+ catch {
995
+ return false;
996
+ }
997
+ }
998
+ /** Debounced buddy sync — called from addBuddyXP, max once per 5 minutes */
999
+ function scheduleBuddySync() {
1000
+ const now = Date.now();
1001
+ if (now - lastBuddySync < BUDDY_SYNC_DEBOUNCE_MS)
1002
+ return;
1003
+ if (buddySyncTimer)
1004
+ return;
1005
+ buddySyncTimer = setTimeout(() => {
1006
+ buddySyncTimer = null;
1007
+ lastBuddySync = Date.now();
1008
+ syncBuddyToCloud().catch(() => { }); // fire and forget
1009
+ }, 1000); // short delay to batch rapid XP gains
1010
+ }
1011
+ /**
1012
+ * Fetch the buddy leaderboard from the cloud.
1013
+ * Returns ranked entries sorted by XP descending.
1014
+ */
1015
+ export async function fetchBuddyLeaderboard(opts) {
1016
+ const token = getCloudToken();
1017
+ if (!token)
1018
+ return [];
1019
+ try {
1020
+ const res = await fetch(`${ENGINE_URL}/sync`, {
1021
+ method: 'POST',
1022
+ headers: {
1023
+ 'Content-Type': 'application/json',
1024
+ 'Authorization': `Bearer ${token}`,
1025
+ },
1026
+ body: JSON.stringify({
1027
+ action: 'buddy_leaderboard',
1028
+ limit: opts?.limit ?? 50,
1029
+ ...(opts?.species ? { species: opts.species } : {}),
1030
+ }),
1031
+ signal: AbortSignal.timeout(10_000),
1032
+ });
1033
+ if (!res.ok)
1034
+ return [];
1035
+ const data = await res.json();
1036
+ return data.leaderboard ?? [];
1037
+ }
1038
+ catch {
1039
+ return [];
1040
+ }
1041
+ }
946
1042
  /**
947
1043
  * Get the buddy's current level info without modifying state.
948
1044
  * Includes level, XP, XP to next level, and species-specific title.
package/dist/cli.js CHANGED
@@ -27,7 +27,7 @@ import { banner, bannerCompact, bannerAuth, prompt as kbotPrompt, printError, pr
27
27
  import { checkForUpdate, selfUpdate } from './updater.js';
28
28
  import { runTutorial } from './tutorial.js';
29
29
  import { syncOnStartup, schedulePush, flushCloudSync, isCloudSyncEnabled, setCloudToken, getCloudToken } from './cloud-sync.js';
30
- import { getBuddy, getBuddyGreeting, formatBuddyStatus, getBuddyDreamNarration, renameBuddy, buddyChat, getAchievements, getBuddyLevel } from './buddy.js';
30
+ import { getBuddy, getBuddyGreeting, formatBuddyStatus, getBuddyDreamNarration, renameBuddy, buddyChat, getAchievements, getBuddyLevel, fetchBuddyLeaderboard } from './buddy.js';
31
31
  import chalk from 'chalk';
32
32
  import { createRequire } from 'node:module';
33
33
  const __require = createRequire(import.meta.url);
@@ -3579,6 +3579,62 @@ async function main() {
3579
3579
  console.log();
3580
3580
  process.exit(0);
3581
3581
  });
3582
+ buddyCmd
3583
+ .command('leaderboard')
3584
+ .description('Show the global buddy leaderboard — anonymous rankings across all kbot installs')
3585
+ .option('-l, --limit <n>', 'Number of entries to show', '20')
3586
+ .option('-s, --species <species>', 'Filter by species (fox, owl, cat, robot, ghost, mushroom, octopus, dragon)')
3587
+ .action(async (opts) => {
3588
+ const limit = Math.min(Math.max(parseInt(opts.limit, 10) || 20, 1), 200);
3589
+ const species = opts.species?.toLowerCase();
3590
+ const validSpecies = ['fox', 'owl', 'cat', 'robot', 'ghost', 'mushroom', 'octopus', 'dragon'];
3591
+ if (species && !validSpecies.includes(species)) {
3592
+ printError(`Unknown species "${species}". Valid: ${validSpecies.join(', ')}`);
3593
+ process.exit(1);
3594
+ }
3595
+ printInfo('Fetching leaderboard...');
3596
+ const entries = await fetchBuddyLeaderboard({ limit, species });
3597
+ if (entries.length === 0) {
3598
+ console.log();
3599
+ printWarn('No entries on the leaderboard yet.');
3600
+ printInfo('Use kbot to earn XP and enable cloud sync to appear on the leaderboard.');
3601
+ console.log();
3602
+ process.exit(0);
3603
+ }
3604
+ const SPECIES_ICONS = {
3605
+ fox: '[fox]', owl: '[owl]', cat: '[cat]', robot: '[bot]',
3606
+ ghost: '[gho]', mushroom: '[msh]', octopus: '[oct]', dragon: '[drg]',
3607
+ };
3608
+ const LEVEL_TITLES_SHORT = {
3609
+ 0: 'Novice', 1: 'Adept', 2: 'Master', 3: 'Legend',
3610
+ };
3611
+ const header = species
3612
+ ? `Buddy Leaderboard — ${species}`
3613
+ : 'Global Buddy Leaderboard';
3614
+ console.log();
3615
+ console.log(` ${chalk.bold(header)}`);
3616
+ console.log(` ${chalk.dim('─'.repeat(56))}`);
3617
+ console.log(` ${chalk.dim('#'.padStart(3))} ${chalk.dim('Species'.padEnd(7))} ${chalk.dim('Level'.padEnd(12))} ${chalk.dim('XP'.padStart(6))} ${chalk.dim('Achv'.padStart(4))} ${chalk.dim('Sessions'.padStart(8))}`);
3618
+ console.log(` ${chalk.dim('─'.repeat(56))}`);
3619
+ for (const entry of entries) {
3620
+ const icon = SPECIES_ICONS[entry.species] || entry.species.slice(0, 5);
3621
+ const title = LEVEL_TITLES_SHORT[entry.level] ?? `L${entry.level}`;
3622
+ const levelStr = `${entry.level} ${title}`;
3623
+ const rankStr = String(entry.rank).padStart(3);
3624
+ const xpStr = String(entry.xp).padStart(6);
3625
+ const achvStr = String(entry.achievement_count).padStart(4);
3626
+ const sessStr = String(entry.sessions).padStart(8);
3627
+ // Highlight top 3
3628
+ const rankColor = entry.rank === 1 ? chalk.hex('#FFD700') :
3629
+ entry.rank === 2 ? chalk.hex('#C0C0C0') :
3630
+ entry.rank === 3 ? chalk.hex('#CD7F32') : chalk.white;
3631
+ console.log(` ${rankColor(rankStr)} ${chalk.hex('#A78BFA')(icon.padEnd(7))} ${levelStr.padEnd(12)} ${chalk.hex('#4ADE80')(xpStr)} ${achvStr} ${chalk.dim(sessStr)}`);
3632
+ }
3633
+ console.log();
3634
+ console.log(` ${chalk.dim(`${entries.length} entries shown`)}`);
3635
+ console.log();
3636
+ process.exit(0);
3637
+ });
3582
3638
  buddyCmd.action(() => {
3583
3639
  buddyCmd.commands.find(c => c.name() === 'status')?.parse(['', '', 'status']);
3584
3640
  });
@@ -1,12 +1,13 @@
1
1
  // kbot Buddy Tools — Interact with your terminal companion
2
2
  //
3
- // Four tools:
3
+ // Five tools:
4
4
  // buddy_status — Show buddy name, species, mood, and sprite
5
5
  // buddy_rename — Give your buddy a custom name (persisted to ~/.kbot/buddy.json)
6
6
  // buddy_achievements — Show all achievements with unlock status and progress
7
7
  // buddy_personality — Show species personality traits, style, and strength
8
+ // buddy_leaderboard — Global anonymous leaderboard across all kbot installs
8
9
  import { registerTool } from './index.js';
9
- import { getBuddy, getBuddySprite, getBuddyGreeting, getBuddyLevel, formatBuddyStatus, renameBuddy, getAchievements, getAchievementProgress, getSpeciesPersonality, } from '../buddy.js';
10
+ import { getBuddy, getBuddySprite, getBuddyGreeting, getBuddyLevel, formatBuddyStatus, renameBuddy, getAchievements, getAchievementProgress, getSpeciesPersonality, fetchBuddyLeaderboard, } from '../buddy.js';
10
11
  const VALID_MOODS = ['idle', 'thinking', 'success', 'error', 'learning', 'alert', 'dance', 'curious', 'proud'];
11
12
  export function registerBuddyTools() {
12
13
  registerTool({
@@ -124,5 +125,57 @@ export function registerBuddyTools() {
124
125
  ].join('\n');
125
126
  },
126
127
  });
128
+ registerTool({
129
+ name: 'buddy_leaderboard',
130
+ description: 'Show the global buddy leaderboard — anonymous rankings of all kbot buddies across installs, sorted by XP. Requires cloud sync (kernel.chat token).',
131
+ parameters: {
132
+ limit: {
133
+ type: 'number',
134
+ description: 'Number of entries to show (default 20, max 200)',
135
+ },
136
+ species: {
137
+ type: 'string',
138
+ description: 'Filter by species: fox, owl, cat, robot, ghost, mushroom, octopus, dragon',
139
+ },
140
+ },
141
+ tier: 'free',
142
+ async execute(args) {
143
+ const SPECIES_ICONS = {
144
+ fox: '[fox]', owl: '[owl]', cat: '[cat]', robot: '[bot]',
145
+ ghost: '[gho]', mushroom: '[msh]', octopus: '[oct]', dragon: '[drg]',
146
+ };
147
+ const LEVEL_TITLES_SHORT = {
148
+ 0: 'Novice', 1: 'Adept', 2: 'Master', 3: 'Legend',
149
+ };
150
+ const limit = Math.min(Math.max(Math.floor(Number(args.limit) || 20), 1), 200);
151
+ const species = args.species ? String(args.species).toLowerCase() : undefined;
152
+ const validSpecies = ['fox', 'owl', 'cat', 'robot', 'ghost', 'mushroom', 'octopus', 'dragon'];
153
+ if (species && !validSpecies.includes(species)) {
154
+ return `Unknown species "${species}". Valid: ${validSpecies.join(', ')}`;
155
+ }
156
+ const entries = await fetchBuddyLeaderboard({ limit, species });
157
+ if (entries.length === 0) {
158
+ return 'No entries on the leaderboard yet. Use kbot to earn XP and sync to the cloud!';
159
+ }
160
+ const lines = [];
161
+ const header = species
162
+ ? `=== Buddy Leaderboard — ${species} ===`
163
+ : '=== Global Buddy Leaderboard ===';
164
+ lines.push(header);
165
+ lines.push('');
166
+ // Table header
167
+ lines.push(` ${'#'.padStart(3)} ${'Species'.padEnd(7)} ${'Level'.padEnd(12)} ${'XP'.padStart(6)} ${'Achv'.padStart(4)} ${'Sessions'.padStart(8)}`);
168
+ lines.push(` ${'─'.repeat(3)} ${'─'.repeat(7)} ${'─'.repeat(12)} ${'─'.repeat(6)} ${'─'.repeat(4)} ${'─'.repeat(8)}`);
169
+ for (const entry of entries) {
170
+ const icon = SPECIES_ICONS[entry.species] || entry.species.slice(0, 5);
171
+ const title = LEVEL_TITLES_SHORT[entry.level] ?? `L${entry.level}`;
172
+ const levelStr = `${entry.level} ${title}`;
173
+ lines.push(` ${String(entry.rank).padStart(3)} ${icon.padEnd(7)} ${levelStr.padEnd(12)} ${String(entry.xp).padStart(6)} ${String(entry.achievement_count).padStart(4)} ${String(entry.sessions).padStart(8)}`);
174
+ }
175
+ lines.push('');
176
+ lines.push(`${entries.length} entries shown`);
177
+ return lines.join('\n');
178
+ },
179
+ });
127
180
  }
128
181
  //# sourceMappingURL=buddy-tools.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kernel.chat/kbot",
3
- "version": "3.72.0",
3
+ "version": "3.73.1",
4
4
  "description": "Open-source terminal AI agent. 764+ tools, 35 agents, 20 providers. Dreams, learns, watches your system. Controls your phone. Fully local, fully sovereign. MIT.",
5
5
  "type": "module",
6
6
  "repository": {