Fixes#4529
The moltbot compatibility package was broken because bin/moltbot.js
was missing. This file is referenced in package.json but was never
created during the openclaw rename.
This commit adds the missing binary that:
- Forwards all commands to openclaw
- Shows clear deprecation warning
- Guides users to migrate to openclaw package
Without this fix, users who upgraded from moltbot to openclaw by
git pull could not use the gateway because their global moltbot
installation had no working binary.
Test: node packages/moltbot/bin/moltbot.js --version
(requires built openclaw)
Implements WebSocket ping/pong keepalive mechanism to prevent random
disconnects with close code 1006 (abnormal closure).
Changes:
- Add 20-second ping interval when WebSocket connection is open
- Monitor pong responses for connection health
- Enhanced error and close event logging with detailed diagnostics
- Clean up ping interval when connection closes
This fix addresses the root cause of issue #4142 where network
intermediaries (NAT, firewalls, proxies) timeout idle WebSocket
connections. The 20-second ping interval is industry standard practice
for preventing idle connection timeouts.
Fixes#4142
Fixes#4107
Problem:
- Cron jobs with systemEvent payloads enqueue events as passive text
- Agent sees events but doesn't autonomously process them
- Expected behavior: agent should execute complex tasks (spawn subagents, etc.)
Root Cause:
- systemEvents are injected as 'System: [timestamp] text' messages
- Standard heartbeat prompt is passive: 'Read HEARTBEAT.md... reply HEARTBEAT_OK'
- No explicit instruction to process and act on systemEvents
- Exec completion events already had directive prompt, but generic events didn't
Solution:
- Added SYSTEM_EVENT_PROMPT constant with directive language
- Modified heartbeat runner to detect generic (non-exec) systemEvents
- When generic events are present, use directive prompt instead of passive one
- Directive prompt explicitly instructs agent to:
1. Check HEARTBEAT.md for event-specific handling
2. Execute required actions (spawn subagent, perform task, etc.)
3. Reply HEARTBEAT_OK only if no action needed
Changes:
- src/infra/heartbeat-runner.ts:
- Added SYSTEM_EVENT_PROMPT constant (lines 100-105)
- Modified prompt selection logic to detect generic systemEvents (lines 510-523)
- Updated Provider field to reflect 'system-event' context
Testing:
- Build passes (TypeScript compilation successful)
- Pattern follows existing exec-event precedent
- Backward compatible (only affects sessions with pending systemEvents)
Follow-up:
- Add integration test for cron → subagent spawn workflow
- Update documentation on systemEvent best practices
- Enhanced SubagentRunOutcome type with errorType and errorHint fields
- Added categorizeError() helper to classify common error patterns:
* File system errors (ENOENT, EACCES, etc.)
* API/model errors (rate limits, auth failures, invalid requests)
* Network errors (connection refused, DNS failures)
* Timeout errors
* Configuration errors (missing credentials, quota limits)
- Updated error emission in agent-runner-execution.ts to categorize errors
- Updated subagent-registry.ts to capture and propagate new error fields
- Added buildErrorStatusLabel() helper for user-friendly error messages
- Error announcements now include error type and remediation hints
Example improved messages:
- Before: 'failed: unknown error'
- After: 'failed (tool error): ENOENT — File or directory not found'
This makes subagent failures much easier to understand and debug while
maintaining backward compatibility.
The message processing pipeline had a synchronization bug where
limitHistoryTurns() truncated conversation history AFTER
repairToolUseResultPairing() had already fixed tool_use/tool_result
pairings. This could split assistant messages (with tool_use) from
their corresponding tool_result blocks, creating orphaned tool_result
blocks that the Anthropic API rejects.
This fix calls sanitizeToolUseResultPairing() AFTER limitHistoryTurns()
to repair any pairings broken by truncation, ensuring the transcript
remains valid before being sent to the LLM API.
Changes:
- Added import for sanitizeToolUseResultPairing from session-transcript-repair.js
- Call sanitizeToolUseResultPairing() on the limited message array
- Updated variable name from 'limited' to 'repaired' for clarity
Resolves#4315. The slug-generator embedded run was hardcoded to use
DEFAULT_MODEL (claude-opus-4-5) regardless of the user's configured
agents.defaults.model.primary. This caused unexpected Opus charges on
every /new command.
Now uses resolveDefaultModelForAgent() to honor the user's configured
default model, falling back to DEFAULT_MODEL only when no config exists.
Replaced the static image with a responsive logo using the <picture> element for light/dark mode support. Updated contributor name from 'Clawd' to 'Molty'.
Replaces the previous ASCII art in both the CLI banner and the wizard header with a new, wider design and updates the label to 'OPENCLAW' for consistency.
What:
- resolve shell from PATH in bash-tools tests (avoid /bin/bash dependency)
- mock DNS for web-fetch SSRF tests (no real network)
- stub a2ui bundle in canvas-host server test when missing
Why:
- keep gateway test suite deterministic on Nix/Garnix Linux
Tests:
- not run locally (known missing deps in unit test run)
What:
- stub resolvePinnedHostname in web-fetch tests to avoid DNS flake
- close lock file handles via FileHandle.close during cleanup to avoid EBADF
Why:
- make CI deterministic without network/DNS dependence
- prevent double-close errors from GC
Tests:
- pnpm vitest run --config vitest.unit.config.ts src/agents/tools/web-tools.fetch.test.ts src/agents/session-write-lock.test.ts (failed: missing @aws-sdk/client-bedrock)
* refactor(ui): enhance loadSessions function to accept overrides for session loading parameters
- Updated loadSessions to include optional parameters for activeMinutes, limit, includeGlobal, and includeUnknown.
- Modified refreshChat to use the new activeMinutes parameter when loading sessions.
- Removed duplicate applySettingsFromUrl call in handleConnected function.
* feat(ui): implement session refresh functionality after chat
- Added `refreshSessionsAfterChat` property to `ChatHost` and `GatewayHost` types.
- Introduced `isChatResetCommand` function to identify chat reset commands.
- Updated `handleSendChat` to set `refreshSessions` based on chat reset commands.
- Modified `handleGatewayEventUnsafe` to load sessions when chat is finalized and `refreshSessionsAfterChat` is true.
- Enhanced `refreshChat` to load sessions with `activeMinutes` set to 0 for immediate refresh.
NTFS does not allow < or > in filenames, causing the XML filename
escaping test to fail on Windows CI with ENOENT.
Replace file<test>.txt with file&test.txt — & is valid on all platforms
and still requires XML escaping (&), preserving the test's intent.
Fixes#3748
Previous fix only checked skippedEmpty > 0, but when model returns
content: [] no payloads are created at all. Now also checks
replies.length === 0 to catch this case.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>