* 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>
Twilio strips query parameters from WebSocket URLs in <Stream> TwiML,
so the auth token set via ?token=xxx never arrives on the WebSocket
connection. This causes stream rejection when token validation is enabled.
Fix: pass the token as a <Parameter> element inside <Stream>, which
Twilio delivers in the start message's customParameters field. The
media stream handler now extracts the token from customParameters,
falling back to query string for backwards compatibility.
Co-authored-by: McWiggles <mcwigglesmcgee@users.noreply.github.com>
- Guard against undefined/empty token in buildGatewayAuthConfig
- Automatically generate random token when token param is undefined, empty, or whitespace
- Prevents JSON.stringify from writing literal string "undefined" to config
- Add tests for undefined, empty, and whitespace token cases
Fixes#13756
Co-authored-by: Klawd Asklee <klawdebot@gmail.com>
* fix(gateway): handle async EPIPE on stdout/stderr during shutdown
The console capture forward() wrapper catches synchronous EPIPE errors,
but when the receiving pipe closes during shutdown Node emits the error
asynchronously on the stream. Without a listener this becomes an
uncaught exception that crashes the gateway, causing macOS launchd to
permanently unload the service.
Add error listeners on process.stdout and process.stderr inside
enableConsoleCapture() that silently swallow EPIPE/EIO (matching the
existing isEpipeError helper) and re-throw anything else.
Closes#13367
* guard stream error listeners against repeated enableConsoleCapture() calls
Use a separate streamErrorHandlersInstalled flag in loggingState so that
test resets of consolePatched don't cause listener accumulation on
process.stdout/stderr.
When internal tools (e.g. TTS) emit MEDIA:/tmp/... with absolute paths,
isValidMedia() correctly rejects them for security. However, the rejected
MEDIA: line was kept as visible text in the output, leaking the path to
the user.
Now strip MEDIA: lines that look like local paths even when the path
is invalid, so they never appear as user-visible text.
Closes#14365
Co-authored-by: Echo Ito <echoito@MacBook-Air.local>
When the gateway is installed as a macOS launch agent and no token is
configured, the service enters an infinite restart loop because launchd
does not inherit shell environment variables. Auto-generate a token
during `gateway install` when auth mode is `token` and no token exists,
matching the existing pattern in doctor.ts and configure.gateway.ts.
The token is persisted to the config file and embedded in the plist
EnvironmentVariables for belt-and-suspenders reliability.
Relates-to: #5103, #2433, #1690, #7749
* fix(an-08): apply security fix
Generated by staged fix workflow.
* fix(an-08): apply security fix
Generated by staged fix workflow.
* fix(an-08): stabilize bluebubbles auth fixture for security patch
Restore the default test password in createMockAccount and add a
fallback password query in createMockRequest when auth is omitted.
This keeps the AN-08 loopback-auth regression tests strict while
preserving existing monitor behavior tests that assume authenticated
webhook fixtures.
The Next.js web app was only built inside the gateway process on first
boot. When the daemon was freshly installed (e.g. `onboard
--install-daemon`), the LaunchAgent would start and block on `next
build`, causing a noticeably slow first startup.
Add `ensureWebAppBuilt()` to `src/gateway/server-web-app.ts` — a
standalone pre-build function that checks for `.next/BUILD_ID` and runs
dep install + `next build` if missing. Skips silently when the web app
is disabled, already built, in dev mode, or inapplicable (global npm
install without `apps/web`).
Call both `ensureWebAppBuilt()` and `ensureControlUiAssetsBuilt()` before
the daemon is installed in every relevant path:
- Interactive onboarding (`onboarding.finalize.ts`) — moved the existing
Control UI build from after the daemon install to before it, and added
the web app build alongside it.
- Non-interactive onboarding (`daemon-install.ts`) — added both pre-build
calls before `service.install()`.
- Standalone `openclaw gateway install` CLI (`daemon-cli/install.ts`) —
added both pre-build calls before `service.install()`.
- Configure wizard (`configure.wizard.ts`) — added the web app build
alongside the existing Control UI build.
Updated test mocks for `ensureWebAppBuilt` in onboarding, configure
wizard, and daemon CLI coverage tests.
Bumped version to 2026.2.6-3.7 and published to npm.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Remove standalone Next.js output; gateway now installs deps and builds
on first start, skips if .next/BUILD_ID already exists
- Rename openclaw→ironclaw workspace refs in all 30 extensions + clawdbot/moltbot
- Add @tiptap/core as explicit dep in apps/web (pnpm strict mode requires it)
- Improve ensureDepsInstalled: detect pnpm workspace vs npm global install
- Remove pre-build step from deploy.sh; ship source, build on user machine
- Update package.json files to include full apps/web/ source
Co-authored-by: Cursor <cursoragent@cursor.com>
- Add gateway.webApp config (enabled, port, dev) as the unified toggle
for both the Next.js web UI and the built-in control UI
- Spawn Next.js app alongside the gateway; stop it on shutdown
- Auto-enable webApp in config for new and existing installs
- Pre-build Next.js in deploy.sh and ship .next/ in the npm package
so installed users get instant startup (no build step)
- Gateway skips build when pre-built .next/ exists; builds on first
run for dev/git-checkout users
- Onboarding "Open the Web UI" now opens the Ironclaw web app
- Fix pre-existing Next.js build errors (ES2023 lib, Tiptap v3 types,
Suspense boundary, ReportConfig type alignment)
- Rename deploy target from openclaw-ai-sdk to ironclaw
Co-authored-by: Cursor <cursoragent@cursor.com>
Rebrand from OpenClaw to Ironclaw across 16 files:
Web app (apps/web):
- layout.tsx: update metadata title to "Ironclaw" and description to
"AI CRM with an agent that connects to your apps and does the work for you"
- page.tsx: change landing page heading from "OpenClaw Dench" to "Ironclaw"
- agent-runner.ts: rename stderr log prefix to [ironclaw stderr]
- package.json: rename package from "openclaw-web" to "ironclaw-web"
Package identity (root):
- package.json: rename package from "openclaw-ai-sdk" to "ironclaw",
update description to reflect CRM/workspace focus, change bin entry
from "openclaw-ai-sdk" to "ironclaw"
- openclaw.mjs: update error message to reference "ironclaw"
- src/version.ts: change CORE_PACKAGE_NAME to "ironclaw"
CLI and TUI:
- command-format.ts: extend CLI prefix regex to accept both "ironclaw"
and "openclaw" for backward compatibility
- register.agent.ts: update example identity name to "Ironclaw" with
🔩 emoji (replacing 🦞)
- tui.ts: rename TUI header from "openclaw tui" to "ironclaw tui"
Onboarding and configuration wizards:
- configure.wizard.ts: rename engine selection prompts and wizard intro
headers to "Ironclaw"
- onboarding.ts: rename onboarding intro and security warning text
- onboarding.finalize.ts: rename all dashboard/control-UI messages and
Brave Search setup instructions to reference "Ironclaw"
Security audit:
- audit.ts: rename state-dir permission warning details to "Ironclaw"
- audit-extra.ts: rename plugin remediation text to "Ironclaw"
Telegram:
- bot-message-context.ts: rename access-denied message to "Ironclaw"
Rebrand the project from the OpenClaw/Lobster identity to Ironclaw with
a new iron-metallic visual language across CLI and web UI.
## CLI identity
- Rename default CLI name from `openclaw` to `ironclaw` (keep `openclaw`
in KNOWN_CLI_NAMES and regex for backward compat)
- Set process.title to `ironclaw`; update all `[openclaw]` log prefixes
to `[ironclaw]`
- Add `IRONCLAW_*` env var checks (IRONCLAW_HIDE_BANNER,
IRONCLAW_NO_RESPAWN, IRONCLAW_NODE_OPTIONS_READY,
IRONCLAW_TAGLINE_INDEX) with fallback to legacy `OPENCLAW_*` variants
## Animated ASCII banner
- Replace the old lobster block-art with a figlet "ANSI Shadow" font
IRONCLAW ASCII wordmark
- Add `gradient-string` dependency for terminal gradient rendering
- Implement iron shimmer animation: a bright highlight sweeps across the
ASCII art (~2.5 s at 12 fps, 3 full gradient cycles) using a rotating
iron-to-silver color array
- Make `emitCliBanner` async to support the animation; update all call
sites (preaction hook, route, run-main) to await it
- Move banner emission earlier in `runCli()` so it appears for all
invocations (bare command, subcommands, help) with the existing
bannerEmitted guard preventing double-emission
## Iron palette and theme
- Rename LOBSTER_PALETTE → IRON_PALETTE in `src/terminal/palette.ts`
with new cool-steel color tokens (steel grey accent, bright silver
highlight, dark iron dim, steel bl info)
- Re-export LOBSTER_PALETTE as backward-compatible alias
- Update `src/terminal/theme.ts` to import and use IRON_PALETTE
## Tagline cleanup
- Remove lobster-themed, Apple-specific, and platform-joke taglines
- Fix smart-quote and em-dash formatting across remaining taglines
- Add "Holiday taglines" comment grouping for date-gated entries
## Web UI
- Add `framer-motion`, `fuse.js`, and `next-themes` to web app deps
- Add custom font files: Bookerly (regular/bold/italic), SpaceGrotesk
(light/regular/medium/semibold/bold), FoundationTitlesHand
- Update chat panel labels: "OpenClaw Chat" → "Ironclaw Chat",
"Message OpenClaw..." → "Message Ironclaw..."
- Update sidebar header: "OpenClaw Dench" → "Ironclaw"
- CSS formatting cleanup: expand single-lins, add consistent
blank lines between selector blocks, normalize child combinator
spacing (li > ul → li>ul)