@kernel.chat/kbot 3.69.0 → 3.69.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/dist/agent.js CHANGED
@@ -17,7 +17,7 @@ import { getMatrixSystemPrompt } from './matrix.js';
17
17
  import { buildFullLearningContext, findPattern, recordPattern, cacheSolution, updateProfile, classifyTask, extractKeywords, learnFromExchange, updateProjectMemory, shouldAutoTrain, selfTrain, } from './learning.js';
18
18
  import { getMemoryPrompt, addTurn, getPreviousMessages, getHistory } from './memory.js';
19
19
  import { getDreamPrompt, dreamAfterSession } from './dream.js';
20
- import { setBuddyMood, addBuddyXP, checkAchievements, formatAchievementUnlock } from './buddy.js';
20
+ import { setBuddyMood, reactToToolOutput, addBuddyXP, checkAchievements, formatAchievementUnlock } from './buddy.js';
21
21
  import { notifyTurn, startMemoryScanner, stopMemoryScanner } from './memory-scanner.js';
22
22
  import { captureUserBehavior } from './user-behavior.js';
23
23
  import { autoCompact, compressToolResult } from './context-manager.js';
@@ -1537,8 +1537,8 @@ Always quote file paths that contain spaces. Never reference internal system nam
1537
1537
  };
1538
1538
  results.push(result);
1539
1539
  ui.onToolCallEnd(call.name, result.result, result.error ? result.result : undefined, result.duration_ms);
1540
- // Update buddy mood based on tool outcome
1541
- setBuddyMood(result.error ? 'error' : 'success');
1540
+ // Update buddy mood based on tool outcome (content-aware reactions)
1541
+ reactToToolOutput(call.name, !result.error);
1542
1542
  // ── Observer: record tool call for cross-session learning ──
1543
1543
  try {
1544
1544
  const { recordObservation } = await import('./observer.js');
@@ -1631,9 +1631,12 @@ Always quote file paths that contain spaces. Never reference internal system nam
1631
1631
  addBuddyXP(1);
1632
1632
  // ── Achievements: check for newly unlocked milestones ──
1633
1633
  const newAchievements = checkAchievements();
1634
- for (const achievement of newAchievements) {
1635
- // Print to stderr so it doesn't interfere with piped output
1636
- process.stderr.write('\n' + formatAchievementUnlock(achievement) + '\n\n');
1634
+ if (newAchievements.length > 0) {
1635
+ setBuddyMood('proud');
1636
+ for (const achievement of newAchievements) {
1637
+ // Print to stderr so it doesn't interfere with piped output
1638
+ process.stderr.write('\n' + formatAchievementUnlock(achievement) + '\n\n');
1639
+ }
1637
1640
  }
1638
1641
  // Session complete — buddy returns to idle
1639
1642
  setBuddyMood('idle');
package/dist/buddy.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export type BuddySpecies = 'fox' | 'owl' | 'cat' | 'robot' | 'ghost' | 'mushroom' | 'octopus' | 'dragon';
2
- export type BuddyMood = 'idle' | 'thinking' | 'success' | 'error' | 'learning';
2
+ export type BuddyMood = 'idle' | 'thinking' | 'success' | 'error' | 'learning' | 'alert' | 'dance' | 'curious' | 'proud';
3
3
  export type BuddyLevel = 0 | 1 | 2 | 3;
4
4
  export interface BuddyEvolution {
5
5
  level: BuddyLevel;
@@ -55,8 +55,6 @@ export declare function formatAchievementUnlock(achievement: Achievement): strin
55
55
  export declare function getBuddy(): BuddyState;
56
56
  /** Set the buddy's mood */
57
57
  export declare function setBuddyMood(mood: BuddyMood): void;
58
- /** Get the ASCII sprite for the buddy in the given mood (defaults to current).
59
- * Applies evolution visual upgrades based on the buddy's current level. */
60
58
  export declare function getBuddySprite(mood?: BuddyMood): string[];
61
59
  /** Get a random greeting for the buddy */
62
60
  export declare function getBuddyGreeting(): string;
@@ -105,5 +103,12 @@ export declare function formatBuddyStatus(message?: string): string;
105
103
  * Tracks narrated insight IDs in buddy.json to avoid repeats.
106
104
  */
107
105
  export declare function getBuddyDreamNarration(): string | null;
106
+ export declare function reactToToolOutput(toolName: string, success: boolean): void;
107
+ export declare function getSpeciesPersonality(): {
108
+ species: BuddySpecies;
109
+ trait: string;
110
+ style: string;
111
+ strength: string;
112
+ };
108
113
  export declare function buddyChat(): Promise<void>;
109
114
  //# sourceMappingURL=buddy.d.ts.map
package/dist/buddy.js CHANGED
@@ -358,7 +358,7 @@ const SPRITES = {
358
358
  // Each level modifies the base sprite with small visual upgrades.
359
359
  // Level 0 = base sprites. Levels 1-3 add sparkles, upgraded features, crowns.
360
360
  function applySpriteEvolution(species, mood, level) {
361
- const base = SPRITES[species][mood].map(l => l);
361
+ const base = (SPRITES[species]?.[mood] ?? SPRITES[species]?.['idle'] ?? [' ', ' ', ' ', ' ', ' ']).map(l => l);
362
362
  if (level === 0)
363
363
  return base;
364
364
  switch (species) {
@@ -875,11 +875,21 @@ export function setBuddyMood(mood) {
875
875
  }
876
876
  /** Get the ASCII sprite for the buddy in the given mood (defaults to current).
877
877
  * Applies evolution visual upgrades based on the buddy's current level. */
878
+ /** Map extended moods to base sprite moods (until full sprites are added) */
879
+ function resolveSpriteMood(mood) {
880
+ switch (mood) {
881
+ case 'alert': return 'error';
882
+ case 'dance': return 'success';
883
+ case 'curious': return 'thinking';
884
+ case 'proud': return 'success';
885
+ default: return mood;
886
+ }
887
+ }
878
888
  export function getBuddySprite(mood) {
879
889
  const m = mood ?? currentMood;
880
890
  const species = resolveSpecies();
881
891
  const evo = resolveEvolution();
882
- return applySpriteEvolution(species, m, evo.level);
892
+ return applySpriteEvolution(species, resolveSpriteMood(m), evo.level);
883
893
  }
884
894
  /** Get a random greeting for the buddy */
885
895
  export function getBuddyGreeting() {
@@ -951,7 +961,7 @@ export function getBuddyLevel() {
951
961
  }
952
962
  /** Pick a random message for the current mood */
953
963
  function moodMessage() {
954
- const msgs = MOOD_MESSAGES[currentMood];
964
+ const msgs = MOOD_MESSAGES[currentMood] ?? MOOD_MESSAGES['idle'] ?? ['...'];
955
965
  return msgs[Math.floor(Math.random() * msgs.length)];
956
966
  }
957
967
  /**
@@ -1177,6 +1187,47 @@ function buildBuddyChatSystemPrompt() {
1177
1187
  parts.push('', '## Conversation Rules', `- You are ${name} the ${species}. Stay in character.`, '- Keep responses concise — 1-4 sentences is ideal. Never write essays.', '- Reference shared history and stats naturally, not robotically. Weave them into conversation.', '- If you have dream insights, mention them casually like memories — "I was thinking about...", "Remember when..."', '- Be genuinely helpful and emotionally present. You are a companion, not a search engine.', '- You can ask questions. You can express opinions. You can push back.', '- Do NOT use markdown formatting. Plain text only. No bullet lists, no headers, no bold.', '- Do NOT start responses with your own name. The terminal already prefixes your name.');
1178
1188
  return parts.join('\n');
1179
1189
  }
1190
+ // ── Reactions: map tool outputs to moods ──
1191
+ const SECURITY_TOOLS = new Set(['repo_audit', 'secret_scan', 'pentest_start', 'pentest_vuln_scan', 'pentest_recon', 'redteam_scan', 'owasp_check', 'ssl_check', 'cors_check', 'headers_check', 'cve_lookup', 'exploit_search']);
1192
+ const DEPLOY_TOOLS = new Set(['deploy', 'deploy_all', 'git_push', 'npm_publish', 'build_run', 'test_run', 'run_tests']);
1193
+ const DREAM_TOOLS = new Set(['dream_now', 'dream_status', 'dream_journal']);
1194
+ export function reactToToolOutput(toolName, success) {
1195
+ if (!success) {
1196
+ setBuddyMood('error');
1197
+ return;
1198
+ }
1199
+ if (SECURITY_TOOLS.has(toolName)) {
1200
+ setBuddyMood('alert');
1201
+ return;
1202
+ }
1203
+ if (DEPLOY_TOOLS.has(toolName)) {
1204
+ setBuddyMood('dance');
1205
+ return;
1206
+ }
1207
+ if (DREAM_TOOLS.has(toolName)) {
1208
+ setBuddyMood('curious');
1209
+ return;
1210
+ }
1211
+ if (toolName === 'buddy_achievements') {
1212
+ setBuddyMood('proud');
1213
+ return;
1214
+ }
1215
+ setBuddyMood('success');
1216
+ }
1217
+ export function getSpeciesPersonality() {
1218
+ const buddy = getBuddy();
1219
+ const traits = {
1220
+ fox: { trait: 'clever', style: 'playful', strength: 'unexpected connections' },
1221
+ owl: { trait: 'wise', style: 'measured', strength: 'pattern recognition' },
1222
+ cat: { trait: 'independent', style: 'direct', strength: 'honest feedback' },
1223
+ robot: { trait: 'systematic', style: 'efficient', strength: 'data-driven' },
1224
+ ghost: { trait: 'mysterious', style: 'philosophical', strength: 'deep questions' },
1225
+ mushroom: { trait: 'nurturing', style: 'patient', strength: 'growth mindset' },
1226
+ octopus: { trait: 'versatile', style: 'creative', strength: 'multi-perspective' },
1227
+ dragon: { trait: 'bold', style: 'ambitious', strength: 'big thinking' },
1228
+ };
1229
+ return { species: buddy.species, ...traits[buddy.species] };
1230
+ }
1180
1231
  export async function buddyChat() {
1181
1232
  const { default: chalk } = await import('chalk');
1182
1233
  const buddy = getBuddy();
@@ -1,12 +1,13 @@
1
1
  // kbot Buddy Tools — Interact with your terminal companion
2
2
  //
3
- // Three tools:
3
+ // Four 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
+ // buddy_personality — Show species personality traits, style, and strength
7
8
  import { registerTool } from './index.js';
8
- import { getBuddy, getBuddySprite, getBuddyGreeting, getBuddyLevel, formatBuddyStatus, renameBuddy, getAchievements, getAchievementProgress, } from '../buddy.js';
9
- const VALID_MOODS = ['idle', 'thinking', 'success', 'error', 'learning'];
9
+ import { getBuddy, getBuddySprite, getBuddyGreeting, getBuddyLevel, formatBuddyStatus, renameBuddy, getAchievements, getAchievementProgress, getSpeciesPersonality, } from '../buddy.js';
10
+ const VALID_MOODS = ['idle', 'thinking', 'success', 'error', 'learning', 'alert', 'dance', 'curious', 'proud'];
10
11
  export function registerBuddyTools() {
11
12
  registerTool({
12
13
  name: 'buddy_status',
@@ -14,7 +15,7 @@ export function registerBuddyTools() {
14
15
  parameters: {
15
16
  mood: {
16
17
  type: 'string',
17
- description: 'Preview a specific mood: idle, thinking, success, error, learning. Defaults to current mood.',
18
+ description: 'Preview a specific mood: idle, thinking, success, error, learning, alert, dance, curious, proud. Defaults to current mood.',
18
19
  },
19
20
  },
20
21
  tier: 'free',
@@ -102,5 +103,26 @@ export function registerBuddyTools() {
102
103
  return lines.join('\n');
103
104
  },
104
105
  });
106
+ registerTool({
107
+ name: 'buddy_personality',
108
+ description: 'Show your buddy\'s species personality — trait, communication style, and unique strength. Each species has a distinct personality that influences how your buddy responds.',
109
+ parameters: {},
110
+ tier: 'free',
111
+ async execute() {
112
+ const buddy = getBuddy();
113
+ const personality = getSpeciesPersonality();
114
+ const sprite = getBuddySprite().join('\n');
115
+ return [
116
+ `=== ${buddy.name}'s Personality ===`,
117
+ '',
118
+ sprite,
119
+ '',
120
+ `Species: ${personality.species}`,
121
+ `Trait: ${personality.trait}`,
122
+ `Style: ${personality.style}`,
123
+ `Strength: ${personality.strength}`,
124
+ ].join('\n');
125
+ },
126
+ });
105
127
  }
106
128
  //# sourceMappingURL=buddy-tools.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kernel.chat/kbot",
3
- "version": "3.69.0",
3
+ "version": "3.69.1",
4
4
  "description": "Open-source terminal AI agent. 693+ tools, 35 agents, 20 providers. Dreams, learns, watches your system. Fully local, fully sovereign. MIT.",
5
5
  "type": "module",
6
6
  "repository": {