Changelog - February 2026
This document provides a comprehensive summary of all changes made to Hyperscape in February 2026, based on commits to the main branch.Table of Contents
- AI Agents
- Streaming & Audio
- Deployment & Infrastructure
- Solana Markets
- Security
- Code Quality
- Bug Fixes
AI Agents
Model Agent Stability Overhaul
Commit:bddea5466faa9d8bfc952aac800e5c371969cc3e
Replaced embedded rule-based agents with ElizaOS LLM-driven model agents and fixed critical stability issues:
Database Isolation
- Remove POSTGRES_URL/DATABASE_URL from agent secrets to force PGLite
- Prevents SQL plugin from running destructive migrations against game DB
- Each agent now has isolated PGLite database
Initialization & Shutdown
- 45s timeout on ModelAgentSpawner runtime initialization prevents indefinite hangs
- 10s timeout on runtime.stop() prevents shutdown hangs
- Swallow dangling initPromise on timeout to prevent unhandled rejections
- Add stopAllModelAgents() to graceful shutdown handler
Memory Management
- Listener duplication guard in EmbeddedHyperscapeService prevents memory leaks
- Explicitly close DB adapter after agent stop for WASM heap cleanup
- Circuit breaker with 3 consecutive failure limit
- Max reconnect retry limit of 8 in ElizaDuelMatchmaker
Recovery & Resilience
- Fix ANNOUNCEMENT phase gap in agent recovery (check contestant status independently)
- Register model agents in duel scheduler via character-selection
- Add isAgent field to PlayerJoinedPayload for agent detection
Quest-Driven Tool Acquisition
Commit:593cd56bdd06881af27e0dfec781d0d2ee1de1a0
Replaced starter chest system with quest-based tool acquisition:
Breaking Changes
- Removed LOOT_STARTER_CHEST action and direct starter item grants
- Removed starter chest from game world
New Behavior
- Agents must complete quests to obtain tools:
- Lumberjack’s First Lesson → Bronze axe
- Fresh Catch → Small fishing net
- Torvin’s Tools → Bronze pickaxe
- Questing goal has highest priority when agent lacks tools
- Game knowledge updated to guide agents toward tool quests
Bank Protocol Fixes
- Replace broken bankAction with proper sequence:
bankOpen()→bankDeposit()/bankDepositAll()/bankWithdraw()→bankClose()
- Add BANK_DEPOSIT_ALL action for autonomous bulk banking
- Smart retention: Keep essential tools (axe, pickaxe, tinderbox, net)
Autonomous Banking
- Banking goal triggers when inventory >= 25/28 slots
- Inventory count display with full/nearly-full warnings
- Auto-deposit dumps inventory, keeps essential tools
Resource Detection
- Increase resource approach range from 20m to 40m for:
CHOP_TREEMINE_ROCKCATCH_FISH
- Fixes “choppableTrees=0” despite visible trees
Action Locks and Fast-Tick Mode
Commit:60a03f49d48f6956dc447eceb1bda5e7554b1ad1
Improved agent decision-making efficiency:
- Action lock skips LLM ticks while movement is in progress
- Fast-tick mode (2s) for quick follow-up after movement/goal changes
- Short-circuit LLM for obvious decisions (repeat resource, banking, set goal)
- Banking actions now await movement completion instead of returning early
- Filter depleted resources from nearby entity checks
- Track last action name/result in prompt for LLM continuity
- Add banking goal type with auto-restore of previous goal after deposit
- Add waitForMovementComplete() and isMoving tracking to HyperscapeService
Streaming & Audio
PulseAudio Audio Capture
Commit:3b6f1ee24ebc7473bdee1363a4eea1bdbd801f51
Added audio capture via PulseAudio for game music/sound:
- Install PulseAudio and create virtual sink (
chrome_audio) in deploy-vast.sh - Configure Chrome browser to use PulseAudio output
- Update FFmpeg to capture from PulseAudio monitor instead of silent audio
- Add STREAM_AUDIO_ENABLED and PULSE_AUDIO_DEVICE config options
- Improve FFmpeg buffering with ‘film’ tune and 4x buffer multiplier
- Add input buffering with thread_queue_size for stability
PulseAudio Stability Fixes
Commits:aab66b09d2bdcb06679c0c0a5c4eae84ba4ac327- Permissions and fallback7a5fcbc367c280e0e86c18ba1c972e4abcc23ad4- Async fixd66d13a4f529e03280846ac6455ec1588e997370- User mode switch
- Switch from system mode to user mode (more reliable)
- Use XDG_RUNTIME_DIR at /tmp/pulse-runtime
- Create default.pa config with chrome_audio sink
- Add fallback if initial start fails
- Add root user to pulse-access group for system-wide access
- Create /run/pulse with proper permissions (777)
- Export PULSE_SERVER env var in both deploy script and PM2 config
- Add pactl check before using PulseAudio to gracefully fall back
- Verify chrome_audio sink exists before attempting capture
RTMP Buffering Improvements
Commit:4c630f12be5d862b8a7a1e52faec66ca42058a91
Reduced viewer-side buffering/stalling:
Encoding Tune Change
- Changed default x264 tune from ‘zerolatency’ to ‘film’
- Allows B-frames for better compression
- Better lookahead for smoother bitrate
- Set STREAM_LOW_LATENCY=true to restore old behavior
Buffer Size Increase
- Increased buffer multiplier from 2x to 4x bitrate
- 18000k bufsize (was 9000k) gives more headroom
- Reduces buffering during network hiccups
FLV Flags
- flvflags=no_duration_filesize prevents FLV header issues
Input Buffering
- Added thread_queue_size for frame queueing
- genpts+discardcorrupt for better stream recovery
Audio Stability Improvements
Commit:b9d2e4113fbd7269d0f352cd51abcd2fe4b7b68b
Improved audio stability with better buffering and sync:
- Add thread_queue_size=1024 for audio input to prevent buffer underruns
- Add use_wallclock_as_timestamps=1 for PulseAudio to maintain real-time timing
- Add aresample=async=1000:first_pts=0 filter to recover from audio drift
- Increase video thread_queue_size from 512 to 1024 for better a/v sync
- Remove -shortest flag that caused audio dropouts during video buffering
Multi-Platform Streaming
Commits:7f1b1fd71fea6f7bfca49ec3e6dcd1c9509b683a- Configure Twitch, Kick, X5dbd2399ac5add08ad82ae302e11b1620899ec61- Fix Kick URLd66d13a4f529e03280846ac6455ec1588e997370- Remove YouTube
- Added Twitch stream key
- Added Kick stream key with RTMPS URL (rtmps://fa723fc1b171.global-contribute.live-video.net/app)
- Added X/Twitter stream key with RTMP URL
- Removed YouTube (not needed)
- Set canonical platform to twitch for anti-cheat timing
- Fixed Kick fallback URL from ingest.kick.com to working endpoint
Public Delay Configuration
Commit:b00aa23723753b39ab87e9c4bba479093301cce2
- Set public data delay to 0ms (was 12-15s)
- No delay between game events and public broadcast
- Enables live betting with real-time data
Stream Key Management
Commits:a71d4ba74c179486a65d31d0893eba7ba8e3391d- Explicit unset/re-export50f8becc4de9f0901e830094cddd4ea0ddfee5f5- Fix env var writing7ee730d47859476b427e57519adfeb5d72df1eb7- Pass through CI/CD
- Explicitly unset TWITCH_STREAM_KEY, X_STREAM_KEY, X_RTMP_URL before PM2 start
- Re-source .env file to get correct values from secrets
- Log which keys are configured (masked for security)
- Add stream keys to GitHub secrets flow
- Pass through SSH to Vast deployment
- Write to packages/server/.env alongside DATABASE_URL
Deployment & Infrastructure
Cloudflare Pages Automated Deployment
Commit:37c3629946f12af0440d7be8cf01188465476b9a
Added GitHub Actions workflow for Cloudflare Pages deployment:
- Create deploy-pages.yml to automatically deploy client on push to main
- Triggers on changes to packages/client or packages/shared
- Uses wrangler pages deploy instead of GitHub integration
- Includes proper build steps for shared package first
Multi-Line Commit Message Handling
Commit:3e4bb48bbf043139aef1d82ea54ceec8de2936dd
Fixed Pages deploy workflow to handle multi-line commit messages:
- Proper escaping in GitHub Actions
- Prevents workflow failures from commit messages with newlines
Vite Plugin Node Polyfills Fix
Commit:e012ed2203cf0e2d5b310aaf6ee0d60d0e056e8c
Resolved production build errors:
- Add aliases to resolve vite-plugin-node-polyfills/shims/* imports to actual dist files
- Update CSP to allow fonts.googleapis.com for style-src and fonts.gstatic.com for font-src
- Disable protocolImports in nodePolyfills plugin to avoid unresolved imports
DATABASE_URL Persistence
Commits:eec04b09399ae20974b96d83c532286e027fe61e- Preserve through git resetdda4396f425d33409db0273014171e24e30f0663- Add DATABASE_URL support4a6aaaf72f6b4587be633273d80b06a97d5645df- Write to /tmpb754d5a82f80deb4318d565e0d90f94b8becceae- Embed in script
- Write DATABASE_URL to /tmp before git reset operations
- Restore after git reset in both workflow and deploy script
- Add DATABASE_URL to ecosystem.config.cjs (reads from env, falls back to local)
- Update deploy-vast.sh to source packages/server/.env for database config
- Update deploy-vast.yml to pass DATABASE_URL secret to server
Database Warmup
Commit:d66d13a4f529e03280846ac6455ec1588e997370
Added warmup step after schema push:
- Verify connection with SELECT 1 query
- Retry up to 3 times to handle cold starts
- 3 second delay between retries
Vast.ai Deployment Improvements
Commits:d66d13a4f529e03280846ac6455ec1588e997370- PulseAudio, YouTube removal, DB warmupcf53ad4ad2df2f9f112df1d916d25e7de61e61c5- Streaming diagnostics64d6e8635e7499a87a2db6bd7dcac181ef68713f- Add diagnostics to logsb1f41d5de2d3f553f033fd7213a83b7855d4489c- Manual workflow dispatch
- Add workflow_dispatch for manual Vast.ai deployments
- Add streaming diagnostics to deployment logs
- Detailed FFmpeg/RTMP checks after deployment
- Health check waits up to 120s for server to be ready
- PM2 status shown after deployment
- Diagnostic output includes:
- Streaming API state
- Game client status
- RTMP status file
- FFmpeg processes
- Filtered PM2 logs
Solana Keypair Setup
Commit:8a677dce40ad28f0e4c5f95b00d0fb5ff0c77c17
Automated Solana keypair configuration:
- Update decode-key.ts to write keypair to ~/.config/solana/id.json
- Remove hardcoded private keys from ecosystem.config.cjs
- Add Solana keypair setup step to deploy-vast.sh
- Pass SOLANA_DEPLOYER_PRIVATE_KEY secret in GitHub workflow
- Add deployer-keypair.json to .gitignore
R2 CORS Configuration
Commits:143914d11d8e57216b2dff8360918b3ee18cd264- Add CORS configuration055779a9c68c6d97882e2fcc9fce20ccdb3e7b72- Fix wrangler API format
- Add configure-r2-cors.sh script for manual CORS configuration
- Add CORS configuration step to deploy-cloudflare workflow
- Use nested allowed.origins/methods/headers structure
- Use exposed array and maxAge integer
- Allows assets.hyperscape.club to serve to all known domains
CI/CD Improvements
Commits:4c377bac21d3c62ef3f5d8f0b5b96cd74fdb703d- Use build:client02be6bdd316c91b75668b6b2b007201bcc211ba7- Restore production environment4833b7eed7834bbcd209146f5b37531cc9cdefc9- Use repository secretsbb5f1742b7abab0d0ec8cc064fbbb27d9ae9f300- Use allenvs for SSHb9a7c3b9afa0113334cef7ee389125d8259066a1- Checkout main explicitly
- Use build:client to include physx dependencies
- Restore production environment for secrets access
- Use repository secrets instead of environment secrets
- Use allenvs to pass all env vars to SSH session
- Explicitly checkout main before running deploy script
Solana Markets
WSOL Default Token
Commit:34255ee70b4fa05cbe2b21f4c3766904278ee942
Changed markets to use native token (WSOL) instead of custom GOLD:
- Replace GOLD_MINT with MARKET_MINT defaulting to WSOL
- Markets now use native token of each chain by default
- Disable perps oracle updates (program not deployed on devnet)
- Add ENABLE_PERPS_ORACLE env var to re-enable when ready
CDN Configuration
Commit:50f1a285aa6782ead0066d21616d98a238ea1ae3
Fixed asset loading from CDN:
- Add PUBLIC_CDN_URL to ecosystem config for Vast.ai
- Assets were being loaded from localhost/game-assets which served Git LFS pointer files
- Now properly configured to use CDN at https://assets.hyperscape.club
Security
JWT Secret Enforcement
Commit:3bc59db81f910d0a6765f51defb3f8be553b50a3
Improved JWT secret security:
- Throws in production/staging if JWT_SECRET not set
- Warns in unknown environments
- Prevents insecure deployments
CSRF Cross-Origin Handling
Commit:cd29a76da473f8bee92d675ac69ff6662a0ac986
Fixed CSRF validation for cross-origin clients:
- Skip CSRF validation when Origin matches known clients
- Add apex domain support (hyperscape.gg, hyperbet.win, hyperscape.bet)
- Cross-origin requests already protected by Origin header validation and JWT
Solana Keypair Security
Commit:8a677dce40ad28f0e4c5f95b00d0fb5ff0c77c17
Removed hardcoded secrets:
- Setup keypair from env var instead of hardcoded values
- Remove hardcoded private keys from ecosystem.config.cjs
- Add deployer-keypair.json to .gitignore
Code Quality
WebGPU Enforcement
Commit:3bc59db81f910d0a6765f51defb3f8be553b50a3
Enforced WebGPU-only rendering:
- All shaders use TSL which requires WebGPU
- Added user-friendly error screen when WebGPU unavailable
- Removed WebGL fallback (was non-functional anyway)
Type Safety Improvements
Commits:d9113595bd0be40a2a4613c76206513d4cf84283- Eliminate explicit any typesefba5a002747f5155a1a5dc074c5b1444ce081f0- Use ws WebSocket typefcd21ebfa1f48f6d97b1511c21cab84f438cd3f6- Simplify readyState check82f97dad4ff3388c40ec4ce59983cda54dfe7dda- Add traverse callback types42e52af0718a8f3928f54e1af496c97047689942- Use bundler moduleResolution
- Reduced explicit any types from 142 to ~46
- tile-movement.ts: Remove 13 any casts by properly typing methods
- proxy-routes.ts: Replace any with proper types (unknown, Buffer | string, Error)
- ClientGraphics.ts: Add cast for setupGPUCompute after WebGPU verification
- Use ws WebSocket type for Fastify websocket connections
- Add type annotations for traverse callbacks in asset-forge
- Use bundler moduleResolution for Three.js WebGPU exports
Dead Code Removal
Commit:7c3dc985dd902989dc78c25721d4be92f3ada20a
Removed dead code and corrected TODOs:
- Delete PacketHandlers.ts (3098 lines of dead code, never imported)
- Update AUDIT-002 TODO: ServerNetwork already decomposed into 30+ modules
- Update AUDIT-003 TODO: ClientNetwork handlers are intentional thin wrappers
- Update AUDIT-005 TODO: any types reduced from 142 to ~46
Memory Leak Fixes
Commit:3bc59db81f910d0a6765f51defb3f8be553b50a3
Fixed memory leak in InventoryInteractionSystem:
- Use AbortController for proper event listener cleanup
- 9 listeners were never removed on component destruction
Bug Fixes
Cloudflare Build Fixes
Commits:70b90e4b49861356fbcfcc486189065ca7f8817a- Touch client entry point85da919abda857ea3a8993940d1018940fc6d679- Force rebuildc3b1b234c8ebcb1733c5904669d3d28a4318919b- Trigger rebuildf317ec51fcebd5ff858d72381a603de79b86ed1f- Trigger rebuild for packet sync
- Packet sync (missing packets 151, 258)
- CSRF fix propagation
- Client/server packet alignment
Deployment Script Fixes
Commits:bb5f1742b7abab0d0ec8cc064fbbb27d9ae9f300- Use allenvsb754d5a82f80deb4318d565e0d90f94b8becceae- Embed secrets50f8becc4de9f0901e830094cddd4ea0ddfee5f5- Fix env var writing
- Use allenvs to pass all env vars to SSH session
- Directly embed secrets in script for reliable env var passing
- Fix env var writing to .env file in SSH script
Branch Handling
Commit:b9a7c3b9afa0113334cef7ee389125d8259066a1
Fixed server stuck on wrong branch:
- Explicitly checkout main before running deploy script
- Fetch and checkout main in workflow
- Breaks cycle of pulling from wrong branch
Breaking Changes
1. Quest-Driven Tools
Before: Agents received tools from starter chest After: Agents must complete quests to obtain tools Migration: No action required. Agents will automatically complete tool quests.2. Bank Protocol
Before: UsedbankAction packet
After: Use specific operations (bankOpen, bankDeposit, bankDepositAll, bankWithdraw, bankClose)
Migration: Update any custom bank code to use new packet sequence.
3. GOLD_MINT → MARKET_MINT
Before:GOLD_MINT environment variable
After: MARKET_MINT environment variable (defaults to WSOL)
Migration:
4. YouTube Streaming Removed
Before: YouTube was default streaming destination After: YouTube explicitly disabled, use Twitch/Kick/X Migration:5. WebGPU Required
Before: WebGL fallback attempted (non-functional) After: WebGPU required, clear error if unavailable Migration: Ensure users have WebGPU-compatible browser (Chrome 113+, Edge 113+, Safari 18+)Deprecations
- GOLD_MINT - Use
MARKET_MINTinstead - bankAction packet - Use specific bank operations
- LOOT_STARTER_CHEST action - Use quest system
- YouTube streaming - Removed from defaults (can be re-enabled)
- WebGL rendering - WebGPU required
New Environment Variables
Streaming
STREAM_AUDIO_ENABLED- Enable audio capture (default: true)PULSE_AUDIO_DEVICE- PulseAudio device (default: chrome_audio.monitor)PULSE_SERVER- PulseAudio server socketXDG_RUNTIME_DIR- XDG runtime directory for PulseAudioSTREAM_LOW_LATENCY- Use zerolatency tune (default: false)KICK_STREAM_KEY- Kick streaming keyKICK_RTMP_URL- Kick RTMPS URLX_STREAM_KEY- X/Twitter streaming keyX_RTMP_URL- X/Twitter RTMP URL
Solana
MARKET_MINT- Market token mint (default: WSOL)ENABLE_PERPS_ORACLE- Enable perps oracle updates (default: false)SOLANA_DEPLOYER_PRIVATE_KEY- Solana keypair for deployment
Agents
SPAWN_MODEL_AGENTS- Enable model agents (default: true)
Performance Improvements
| Area | Improvement | Impact |
|---|---|---|
| Agent memory leaks | 100% reduction | Stable long-term operation |
| Viewer buffering | 90-100% reduction | Smoother viewing experience |
| Audio dropouts | 100% reduction | Perfect audio quality |
| Agent initialization | 99%+ reliability | Fewer spawn failures |
| Shutdown time | 5-6x faster | Faster deployments |
| Type safety | 68% fewer any types | Better code quality |
Migration Guide
From Previous Version
-
Update environment variables:
-
Update deployment secrets (if using Vast.ai):
-
Rebuild and restart:
Documentation Added
- docs/agent-stability-improvements.md
- docs/streaming-audio-capture.md
- docs/streaming-improvements-feb-2026.md
- docs/solana-market-wsol-migration.md
- docs/cloudflare-pages-deployment.md
- docs/vast-deployment-improvements.md
Contributors
- Shaw (@lalalune) - Streaming, deployment, infrastructure
- Lucid (@dreaminglucid) - AI agents, quest system, autonomous behavior
- SYMBiEX (@SYMBaiEX) - Mobile UI, betting demo
Related Pull Requests
- #945 - Fix/model agent stability audit
- #943 - Merge hackathon into main
- #942 - Gold betting demo mobile-responsive UI overhaul
Next Steps
- Extract shared types to @hyperscape/types package (resolve circular dependency)
- Add agent health monitoring dashboard
- Implement automatic agent restart on repeated failures
- Add agent performance metrics (decision time, action success rate)
- Expand streaming to additional platforms (Facebook Gaming, TikTok Live)