@kernel.chat/kbot 3.82.0 → 3.85.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.
@@ -13,7 +13,7 @@ import { createCanvas } from 'canvas';
13
13
  import { drawRobot, drawMoodParticles, drawHat, drawPet, drawBuddyCompanion } from './sprite-engine.js';
14
14
  import { initIntelligence, tickIntelligence, handleIntelligenceCommand, drawBrainPanel, getBrainAction, tickMiniGame, drawMiniGameOverlay, tickProgression, updateQuestProgress, drawQuestPanel, tickRandomEvent, drawRandomEvent, shippedEffects, extraJokeResponses, multiLanguageGreetings } from './stream-intelligence.js';
15
15
  import { initStreamBrain, analyzeChatForDomains, tickStreamBrain, handleBrainCommand, drawBrainActivity } from './stream-brain.js';
16
- import { renderLighting, renderBloom, renderPostProcessing, renderSky, renderParticles, tickParticles as tickRenderParticles, createParticleEmitter, drawCharacterEffects, checkMoodTransition, renderDamageFlash, buildCharacterLights, buildCharacterBloom, getAmbientForTime, renderAnimatedWater, renderLavaFlow, buildParallaxLayers, renderParallaxLayers, tickGrowingPlants, renderGrowingPlants } from './render-engine.js';
16
+ import { renderLighting, renderBloom, renderPostProcessing, renderSky, renderParticles, tickParticlesPBD, createParticleEmitter, drawCharacterEffects, checkMoodTransition, renderDamageFlash, buildCharacterLights, buildCharacterBloom, getAmbientForTime, renderAnimatedWater, renderLavaFlow, buildParallaxLayers, renderParallaxLayers, tickGrowingPlants, renderGrowingPlants, createRadianceGrid, updateRadianceGrid, renderRadianceOverlay, renderSubsurfaceGlow, buildSubsurfacePanels, createFrameCache, renderVolumetricFog, getFogParams, computeAnimationParams } from './render-engine.js';
17
17
  const KBOT_DIR = join(homedir(), '.kbot');
18
18
  const CHAT_BRIDGE_FILE = join(KBOT_DIR, 'stream-chat-live.json');
19
19
  const MEMORY_FILE = join(KBOT_DIR, 'stream-memory.json');
@@ -1447,6 +1447,11 @@ let charState = {
1447
1447
  growingPlants: [],
1448
1448
  parallaxLayers: [],
1449
1449
  isExecutingTool: false,
1450
+ radianceGrid: createRadianceGrid(),
1451
+ frameCache: createFrameCache(),
1452
+ animParams: { blinkRate: 0.2, wobbleFreq: 0.04, wobbleAmp: 2, glowPulseSpeed: 0.1, breathSpeed: 0.05, energyLevel: 0.5 },
1453
+ lastMoodForCache: 'wave',
1454
+ lastGroundForCache: 'grass',
1450
1455
  };
1451
1456
  // ─── Phase 1: Buddy Speech Pools ─────────────────────────────
1452
1457
  const BUDDY_SPEECH_POOL = {
@@ -2106,6 +2111,24 @@ function renderFrame() {
2106
2111
  // Update world
2107
2112
  updateParticles();
2108
2113
  tickPhysics();
2114
+ // NVIDIA: Compute animation params from stream context
2115
+ {
2116
+ const elapsed = Math.floor((Date.now() - charState.startTime) / 1000);
2117
+ const streamMinutes = elapsed / 60;
2118
+ const recentMessages = charState.chatMessages.slice(-30);
2119
+ const chatTimespanMs = recentMessages.length > 1
2120
+ ? (Date.now() - recentMessages[0]?.timestamp || Date.now()) : 60000;
2121
+ const chatRate = recentMessages.length / Math.max(1, chatTimespanMs / 60000);
2122
+ const viewerEstimate = Math.max(1, Math.floor(memory.totalMessages / 3) + Object.keys(memory.users).length);
2123
+ charState.animParams = computeAnimationParams(chatRate, viewerEstimate, charState.mood, world.timeOfDay, streamMinutes);
2124
+ }
2125
+ // NVIDIA: Detect cache invalidation triggers
2126
+ const moodChanged = charState.mood !== charState.lastMoodForCache;
2127
+ const worldChanged = world.ground !== charState.lastGroundForCache;
2128
+ if (moodChanged)
2129
+ charState.lastMoodForCache = charState.mood;
2130
+ if (worldChanged)
2131
+ charState.lastGroundForCache = world.ground;
2109
2132
  // AAA: Continuous particle effects for biomes
2110
2133
  if (world.ground === 'lava' && animFrame % 4 === 0) {
2111
2134
  charState.renderParticles.push(...createParticleEmitter('fire', 50 + Math.random() * 480, 485, 1));
@@ -2113,8 +2136,11 @@ function renderFrame() {
2113
2136
  if (world.ground === 'space' && animFrame % 12 === 0) {
2114
2137
  charState.renderParticles.push(...createParticleEmitter('aura', charState.robotX + 160, 280, 1));
2115
2138
  }
2116
- // AAA: Tick render particles
2117
- charState.renderParticles = tickRenderParticles(charState.renderParticles);
2139
+ // AAA: Tick render particles (cap at 150 to prevent performance issues)
2140
+ if (charState.renderParticles.length > 150) {
2141
+ charState.renderParticles = charState.renderParticles.slice(-150);
2142
+ }
2143
+ charState.renderParticles = tickParticlesPBD(charState.renderParticles, 480, charState.robotX + 160, 280);
2118
2144
  // AAA: Tick growing plants
2119
2145
  tickGrowingPlants(charState.growingPlants);
2120
2146
  // PRIORITY 2: Screen shake offset
@@ -2126,6 +2152,8 @@ function renderFrame() {
2126
2152
  }
2127
2153
  ctx.save();
2128
2154
  ctx.translate(shakeOffX, shakeOffY);
2155
+ // NVIDIA: Early moodColor resolution (needed by fog and all rendering)
2156
+ const moodColorHex = MOOD_COLORS[charState.mood] ?? COLORS.green;
2129
2157
  // Background — AAA: base fill + procedural sky
2130
2158
  ctx.fillStyle = world.events.includes('lightning') ? '#ffffff' : getWorldBg();
2131
2159
  ctx.fillRect(0, 0, WIDTH, HEIGHT);
@@ -2170,6 +2198,12 @@ function renderFrame() {
2170
2198
  ctx.fillRect(p.x, p.y, 2, 6);
2171
2199
  }
2172
2200
  }
2201
+ // NVIDIA: Volumetric fog (between background and character layers)
2202
+ {
2203
+ const fogParams = getFogParams(world.ground, world.timeOfDay);
2204
+ const fogLights = buildCharacterLights(charState.robotX, 90, 10, moodColorHex, animFrame, world.events.includes('lightning'), world.items.map(i => ({ x: i.x, y: i.y, emoji: i.emoji, name: i.name })));
2205
+ renderVolumetricFog(ctx, WIDTH, HEIGHT, animFrame, fogParams.density, fogParams.color, fogLights);
2206
+ }
2173
2207
  // World items (physics-enabled)
2174
2208
  ctx.fillStyle = COLORS.text;
2175
2209
  ctx.font = '18px "Courier New", monospace';
@@ -2319,7 +2353,6 @@ function renderFrame() {
2319
2353
  const glowCenterX = robotX + 16 * robotScale;
2320
2354
  const glowCenterY = robotY + 26 * robotScale;
2321
2355
  const glowRadius = 10 * robotScale;
2322
- const moodColorHex = MOOD_COLORS[charState.mood] ?? COLORS.green;
2323
2356
  const grad = ctx.createRadialGradient(glowCenterX, glowCenterY, 0, glowCenterX, glowCenterY, glowRadius);
2324
2357
  grad.addColorStop(0, hexToRgba(moodColorHex, 0.2));
2325
2358
  grad.addColorStop(1, hexToRgba(moodColorHex, 0));
@@ -2350,6 +2383,11 @@ function renderFrame() {
2350
2383
  drawMoodParticles(ctx, robotX, robotY, robotScale, charState.mood, animFrame);
2351
2384
  // AAA: Render advanced particles
2352
2385
  renderParticles(ctx, charState.renderParticles);
2386
+ // NVIDIA: Subsurface scattering on translucent panels
2387
+ {
2388
+ const sssPanels = buildSubsurfacePanels(charState.robotX, 90, robotScale, moodColorHex);
2389
+ renderSubsurfaceGlow(ctx, sssPanels);
2390
+ }
2353
2391
  // PRIORITY 6: Draw hat AFTER robot so it layers on top
2354
2392
  if (charState.hat !== 'none') {
2355
2393
  drawHat(ctx, robotX, robotY, robotScale, charState.hat, animFrame);
@@ -2722,6 +2760,13 @@ function renderFrame() {
2722
2760
  const lights = buildCharacterLights(charState.robotX, 90, robotScale, moodColorHex, animFrame, hasLightning, world.items.map(i => ({ x: i.x, y: i.y, emoji: i.emoji, name: i.name })));
2723
2761
  renderLighting(ctx, lights, WIDTH, HEIGHT, ambientLevel);
2724
2762
  }
2763
+ // ── NVIDIA: Radiance Grid — ambient light propagation ──
2764
+ {
2765
+ const hasLightning = world.events.includes('lightning');
2766
+ const lights = buildCharacterLights(charState.robotX, 90, 10, moodColorHex, animFrame, hasLightning, world.items.map(i => ({ x: i.x, y: i.y, emoji: i.emoji, name: i.name })));
2767
+ updateRadianceGrid(charState.radianceGrid, lights);
2768
+ renderRadianceOverlay(ctx, charState.radianceGrid, WIDTH, HEIGHT);
2769
+ }
2725
2770
  // ── AAA: Bloom Effect ──
2726
2771
  {
2727
2772
  const robotScale = 10;
@@ -3342,6 +3387,9 @@ export function registerStreamRendererTools() {
3342
3387
  buddy: initBuddyForStream(),
3343
3388
  dreamInsights: [], dreamInsightIndex: 0, dreamInsightTime: 0, isDreamingWithOllama: false,
3344
3389
  renderParticles: [], growingPlants: initGrowingPlants(), parallaxLayers: buildParallaxLayers(world.ground, 580), isExecutingTool: false,
3390
+ radianceGrid: createRadianceGrid(), frameCache: createFrameCache(),
3391
+ animParams: { blinkRate: 0.2, wobbleFreq: 0.04, wobbleAmp: 2, glowPulseSpeed: 0.1, breathSpeed: 0.05, energyLevel: 0.5 },
3392
+ lastMoodForCache: 'wave', lastGroundForCache: 'grass',
3345
3393
  };
3346
3394
  animFrame = 0;
3347
3395
  lastChatCount = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kernel.chat/kbot",
3
- "version": "3.82.0",
3
+ "version": "3.85.0",
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": {