Related #1926
Signal mentions were appearing as  (object replacement character)
instead of readable identifiers. This caused Clawdbot to misinterpret
messages and respond inappropriately.
Now parses dataMessage.mentions array and replaces the placeholder
character with @{uuid} or @{phone} from the mention metadata.
Fixes#5260
The DISCORD_THREAD_STARTER_CACHE Map was growing unbounded during
long-running gateway sessions, causing memory exhaustion.
This fix adds:
- 5-minute TTL expiry (thread starters rarely change)
- Max 500 entries with LRU eviction
- Same caching pattern used by Slack's thread resolver
The implementation mirrors src/slack/monitor/thread-resolution.ts
which already handles this correctly.
formatConsoleTimestamp previously used Date.toISOString() which always
returns UTC time (suffixed with Z). This confused users whose local
timezone differs from UTC.
Now uses local time methods (getHours, getMinutes, etc.) and appends the
local UTC offset (e.g. +08:00) instead of Z. The pretty style returns
local HH:MM:SS. The hasTimestampPrefix regex is updated to accept both
Z and +/-HH:MM offset suffixes.
Closes#14699
Skills install runs package manager install commands (npm, pnpm, yarn,
bun) without --ignore-scripts, allowing malicious npm packages to
execute arbitrary code via postinstall/preinstall lifecycle scripts
during global installation.
This is inconsistent with the security fix in commit 92702af7a which
added --ignore-scripts to both plugin installs (src/plugins/install.ts)
and hook installs (src/hooks/install.ts). Skills install was overlooked
in that change.
Global install (-g) is particularly dangerous as scripts execute with
the user's full permissions and can modify globally-accessible binaries.
* fix(gateway): increase WebSocket max payload to 5 MB for image uploads
The 512 KB limit was too small for base64-encoded images — a 400 KB
image becomes ~532 KB after encoding, exceeding the limit and closing
the connection with code 1006.
Bump MAX_PAYLOAD_BYTES to 5 MB and MAX_BUFFERED_BYTES to 8 MB to
support standard image uploads via webchat.
Closes#14400
* fix: align gateway WS limits with 5MB image uploads (#14486) (thanks @0xRaini)
* docs: fix changelog conflict for #14486
---------
Co-authored-by: 0xRaini <0xRaini@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
The UsageAccumulator sums cacheRead/cacheWrite across all API calls
within a single turn. With Anthropic prompt caching, each call reports
cacheRead ≈ current_context_size, so after N tool-call round-trips the
accumulated total becomes N × actual_context, which gets clamped to
contextWindow (200k) by deriveSessionTotalTokens().
Fix: track the most recent API call's cache fields separately and use
them in toNormalizedUsage() for context-size reporting. This makes
/status Context display accurate while preserving accumulated output
token counts.
Fixes#13698Fixes#13782
Co-authored-by: akari-musubi <259925157+akari-musubi@users.noreply.github.com>
* fix: prevent FD leaks in child process cleanup
- Destroy stdio streams (stdin/stdout/stderr) after process exit
- Remove event listeners to prevent memory leaks
- Clean up child process reference in moveToFinished()
- Also fixes model override handling in agent.ts
Fixes EBADF errors caused by accumulating file descriptors
from sub-agent spawns.
* Fix: allow stdin destroy in process registry cleanup
---------
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
Two fixes for Google Antigravity (Cloud Code Assist) reliability:
1. Forward-compat model fallback: pi-ai's model registry doesn't include
claude-opus-4-6-thinking. Add resolveAntigravityOpus46ForwardCompatModel()
that clones the opus-4-5 template so the correct api ("google-gemini-cli")
and baseUrl are preserved. Fixes#13765.
2. Fix thinking.signature rejection: The API returns Claude thinking blocks
without signatures, then rejects them on replay. The existing sanitizer
strips unsigned blocks, but the orphaned-user-message path in attempt.ts
bypassed it by reading directly from disk. Now applies
sanitizeAntigravityThinkingBlocks at that code path.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Move appendCacheTtlTimestamp() to after prompt + compaction retry
completes instead of before. The previous placement inserted a custom
entry (openclaw.cache-ttl) between compaction and the next prompt,
which broke pi-coding-agent's prepareCompaction() guard — the guard
only checks if the last entry is type 'compaction', and the cache-ttl
custom entry made it type 'custom', allowing an immediate second
compaction at very low token counts (e.g. 5,545 tokens) that nuked
all preserved context.
Fixes#9282
Relates to #12170
After a successful launchctl kickstart, the stdout.write() for the
status message may fail with EPIPE if the receiving end has already
closed. Catch and ignore EPIPE specifically; re-throw other errors.
Closes#14234
Co-authored-by: Echo Ito <echoito@MacBook-Air.local>
* fix(gateway): drain active turns before restart to prevent message loss
On SIGUSR1 restart, the gateway now waits up to 30s for in-flight agent
turns to complete before tearing down the server. This prevents buffered
messages from being dropped when config.patch or update triggers a restart
while agents are mid-turn.
Changes:
- command-queue.ts: add getActiveTaskCount() and waitForActiveTasks()
helpers to track and wait on active lane tasks
- run-loop.ts: on restart signal, drain active tasks before server.close()
with a 30s timeout; extend force-exit timer accordingly
- command-queue.test.ts: update imports for new exports
Fixes#13883
* fix(queue): snapshot active tasks for restart drain
---------
Co-authored-by: Elonito <0xRaini@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
* fix: exclude maxTokens and token-count fields from config redaction
The /token/i regex in SENSITIVE_KEY_PATTERNS falsely matched fields like
maxTokens, maxOutputTokens, maxCompletionTokens etc. These are numeric
config fields for token counts, not sensitive credentials.
Added a whitelist (SENSITIVE_KEY_WHITELIST) that explicitly excludes
known token-count field names from redaction. This prevents config
corruption when maxTokens gets replaced with __OPENCLAW_REDACTED__
during config round-trips.
Fixes#13236
* fix: honor deleteAfterRun for one-shot 'at' jobs with 'skipped' status
Previously, deleteAfterRun only triggered when result.status was 'ok'.
For one-shot 'at' jobs, a 'skipped' status (e.g. empty heartbeat file)
would leave the job in state but disabled, never getting cleaned up.
Now deleteAfterRun also triggers on 'skipped' status for 'at' jobs,
since a skipped one-shot job has no meaningful retry path.
Fixes#13249
* Cron: format timer.ts
---------
Co-authored-by: nice03 <niceyslee@gmail.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>