Root cause: fetch() calls had no timeout, could hang indefinitely
during batch status polling, eventually triggering SIGKILL.
Changes:
- Add fetchWithTimeout() helper with AbortController
- Default 30s timeout for status checks (OPENAI_FETCH_TIMEOUT_MS)
- 60s timeout for file upload/download operations
- Add retry logic with exponential backoff for network failures
- Wrap batch status polling in retryAsync for transient errors
This ensures:
1. No indefinite hangs - all network calls time out
2. Graceful recovery from temporary network issues
3. Clear error messages on timeout
4. Process completes or fails within expected timeframe
Fixes#4370
Tests verify that string thread IDs (Slack thread_ts) are correctly
included in queue routing keys and found in item searches. Covers
the regression where typeof === 'number' silently ignored string IDs,
collapsing different Slack threads into the same routing key.
Slack thread_ts values are always strings (e.g. "1769742846.264069"),
so the typeof === "number" checks never matched, causing queued replies
to lose their thread context and post as top-level channel messages.
Replace all three typeof === "number" checks with != null to handle
both string (Slack) and numeric thread IDs.
Fixes#4380
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>
When running multiple Telegram bot accounts bound to different agents,
the /new command (and other slash commands) would send confirmation
messages via the wrong bot because the context was missing AccountId.
The fix adds AccountId: route.accountId to the context payload in
registerTelegramNativeCommands, matching how bot-message-context.ts
handles regular messages.
Fixes#2537
- Add msg.video_note to media extraction chain in bot/delivery.ts
- Add placeholder detection for video notes in bot-message-context.ts
- Video notes (rounded square video messages) are now processed and downloaded like regular videos
Fixes issue where video note messages were silently dropped because they weren't in the media handling logic.
Native slash commands (e.g. /verbose, /status) should not emit tool
summaries. Gate onToolResult behind CommandSource !== 'native' in
addition to the existing ChatType !== 'group' check.
Add test for native command exclusion.
- provides onToolResult in DM sessions (ChatType=direct)
- does not provide onToolResult in group sessions (ChatType=group)
- sends tool results via dispatcher in DM sessions
Replaces the old cross-provider test that expected onToolResult to
always be undefined.
875b018ea removed onToolResult from dispatch-from-config.ts to prevent
tool summaries leaking into group channels. However, this also broke
verbose tool summaries in DM/private sessions where they are expected.
This restores onToolResult but gates it behind ChatType !== 'group',
so group channels remain unaffected while DM verbose works again.
mirror=false is passed to sendPayloadAsync to avoid duplicating tool
summaries in the session transcript (matching the block reply behavior).
Fixes#2665