Skip to content

Merge upstream/main (v2026.2.3) into develop#7

Merged
CompassHXM merged 562 commits intodevelopfrom
merge-upstream-2026.2.3
Feb 5, 2026
Merged

Merge upstream/main (v2026.2.3) into develop#7
CompassHXM merged 562 commits intodevelopfrom
merge-upstream-2026.2.3

Conversation

@CompassHXM
Copy link
Owner

Summary

Sync with upstream openclaw v2026.2.3.

New Features

Security Improvements

Cron System Enhancements

  • Default isolated jobs to announce delivery mode
  • Enhanced delivery modes and configuration options
  • One-shot job behavior improvements
  • Better timestamp validation and file sync

Channel Features

Provider Support

  • Cloudflare AI Gateway provider - New AI gateway option
  • Moonspot API China endpoint - Support for cn.moonshot.ai

UI/UX

  • New messages indicator for chat interface
  • Landing page revamp
  • Shell completion improvements with auto-fix

Bug Fixes

Compatibility

  • WeChat plugin verified compatible (no breaking changes to ChannelPlugin interface)
  • Build passes
  • Local testing confirmed working

obviyus and others added 30 commits February 2, 2026 17:38
… (openclaw#7195)

* fix(telegram): handle Grammy HttpError network failures (openclaw#3815)

Grammy wraps fetch errors in an .error property (not .cause). Added .error
traversal to collectErrorCandidates in network-errors.ts.

Registered scoped unhandled rejection handler in monitorTelegramProvider
to catch network errors that escape the polling loop (e.g., from setMyCommands
during bot setup). Handler is unregistered when the provider stops.

* fix(telegram): address review feedback for Grammy HttpError handling

- Gate .error traversal on HttpError name to avoid widening search graph
- Use runtime logger instead of console.warn for consistency
- Add isGrammyHttpError check to scope unhandled rejection handler
- Consolidate isNetworkRelatedError into isRecoverableTelegramNetworkError
- Add 'timeout' to recoverable message snippets for full coverage
What: replace <2/<30 text in zh-CN AGENTS template with safe wording
Why: avoid MDX parse errors during docs build
Tests: not run (doc text change)
What: wrap clawhub.com in an explicit URL link in zh-CN skills doc
Why: avoid Mintlify broken-link parser treating trailing punctuation as part of the URL
Tests: not run (doc text change)
What: switch clawhub.com reference to explicit Markdown link syntax
Why: MDX parser rejects angle-bracket autolinks
Tests: not run (doc text change)
What: enforce zh-CN tone (你/你的), Skills/local loopback/Tailscale terms, Gateway网关
Why: keep future translation output consistent with issue feedback
Tests: not run (prompt/glossary change)
What: switch to 你/你的 tone; standardize Skills/Gateway网关/local loopback/私信 wording
Why: align zh-CN docs with issue 6995 feedback + idiomatic tech style
Tests: pnpm docs:build
- Increase near-bottom threshold from 200px to 450px so one long message
  doesn't falsely register as 'near bottom'
- Make force=true only override on initial load (chatHasAutoScrolled=false),
  not on subsequent refreshChat() calls
- refreshChat() no longer passes force=true to scheduleChatScroll
- Add chatNewMessagesBelow flag for future 'scroll to bottom' button UI
- Clear chatNewMessagesBelow when user scrolls back to bottom
- Add 13 unit tests covering threshold, force behavior, streaming, and reset
shakkernerd and others added 27 commits February 4, 2026 19:51
…lation

- Export `resolveCompletionCachePath` and `completionCacheExists` for external use
- Update `installCompletion` to require cache existence (never use slow dynamic pattern)
- Add `usesSlowDynamicCompletion` to detect old `source <(...)` patterns
- Add `getShellProfilePath` helper for consistent profile path resolution
- Update `formatCompletionSourceLine` to always use cached file
- Add `checkShellCompletionStatus` to get profile/cache/slow-pattern status
- Add `ensureCompletionCacheExists` for silent cache regeneration
- Add `doctorShellCompletion` to check and fix completion issues:
  - Auto-upgrade old slow dynamic patterns to cached version
  - Auto-regenerate cache if profile exists but cache is missing
  - Prompt to install if no completion is configured
- Import and call `doctorShellCompletion` during doctor run
- Checks/fixes completion issues before gateway health check
- Replace inline completion logic with `checkShellCompletionStatus` and `ensureCompletionCacheExists`
- Auto-upgrade old slow dynamic patterns silently during update
- Auto-regenerate cache if profile exists but cache is missing
- Prompt to install if no completion is configured
- Replace inline completion logic with `checkShellCompletionStatus` and `ensureCompletionCacheExists`
- Auto-upgrade old slow dynamic patterns silently during onboarding
- Auto-regenerate cache if profile exists but cache is missing
- Prompt to install if no completion is configured
- Use `checkShellCompletionStatus` and `ensureCompletionCacheExists` from doctor-completion
- Display "Uses slow pattern" status in output
- Simulate doctor/update/onboard behavior for all completion scenarios
- Remove duplicated utility functions
* feat: per-channel responsePrefix override

Add responsePrefix field to all channel config types and Zod schemas,
enabling per-channel and per-account outbound response prefix overrides.

Resolution cascade (most specific wins):
  L1: channels.<ch>.accounts.<id>.responsePrefix
  L2: channels.<ch>.responsePrefix
  L3: (reserved for channels.defaults)
  L4: messages.responsePrefix (existing global)

Semantics:
  - undefined -> inherit from parent level
  - empty string -> explicitly no prefix (stops cascade)
  - "auto" -> derive [identity.name] from routed agent

Changes:
  - Core logic: resolveResponsePrefix() in identity.ts accepts
    optional channel/accountId and walks the cascade
  - resolveEffectiveMessagesConfig() passes channel context through
  - Types: responsePrefix added to WhatsApp, Telegram, Discord, Slack,
    Signal, iMessage, Google Chat, MS Teams, Feishu, BlueBubbles configs
  - Zod schemas: responsePrefix added for config validation
  - All channel handlers wired: telegram, discord, slack, signal,
    imessage, line, heartbeat runner, route-reply, native commands
  - 23 new tests covering backward compat, channel/account levels,
    full cascade, auto keyword, empty string stops, unknown fallthrough

Fully backward compatible - no existing config is affected.
Fixes openclaw#8857

* fix: address CI lint + review feedback

- Replace Record<string, any> with proper typed helpers (no-explicit-any)
- Add curly braces to single-line if returns (eslint curly)
- Fix JSDoc: 'Per-channel' → 'channel/account' on shared config types
- Extract getChannelConfig() helper for type-safe dynamic key access

* fix: finish responsePrefix overrides (openclaw#9001) (thanks @mudrii)

* fix: normalize prefix wiring and types (openclaw#9001) (thanks @mudrii)

---------

Co-authored-by: Gustavo Madeira Santana <[email protected]>
…penclaw#8702)

* feat(heartbeat): add accountId config option for multi-agent routing

Add optional accountId field to heartbeat configuration, allowing
multi-agent setups to explicitly specify which Telegram account
should be used for heartbeat delivery.

Previously, heartbeat delivery would use the accountId from the
session's deliveryContext. When a session had no prior conversation
history, heartbeats would default to the first/primary account
instead of the agent's intended bot.

Changes:
- Add accountId to HeartbeatSchema (zod-schema.agent-runtime.ts)
- Use heartbeat.accountId with fallback to session accountId (targets.ts)

Backward compatible: if accountId is not specified, behavior is unchanged.

Closes openclaw#8695

* fix: improve heartbeat accountId routing (openclaw#8702) (thanks @lsh411)

* fix: harden heartbeat accountId routing (openclaw#8702) (thanks @lsh411)

* fix: expose heartbeat accountId in status (openclaw#8702) (thanks @lsh411)

* chore: format status + heartbeat tests (openclaw#8702) (thanks @lsh411)

---------

Co-authored-by: m1 16 512 <[email protected]>
Co-authored-by: Gustavo Madeira Santana <[email protected]>
…dating (openclaw#8432)

* TUI/Gateway: fix pi streaming + tool routing

* Tests: clarify verbose tool output expectation

* fix: avoid seq gaps for targeted tool events (openclaw#8432) (thanks @gumadeiras)
…, harden sticker caching (openclaw#9077)

* Telegram: remove @ts-nocheck from bot.ts and bot-message-dispatch.ts

- bot/types.ts: TelegramContext.me uses UserFromGetMe (Grammy) instead of manual inline type
- bot.ts: remove 6 unsafe casts (as any, as unknown, as object), use Grammy types directly
- bot.ts: remove dead message_thread_id access on reactions (not in Telegram Bot API)
- bot.ts: remove resolveThreadSessionKeys import (no longer needed for reactions)
- bot-message-dispatch.ts: replace ': any' with DispatchTelegramMessageParams type
- bot-message-dispatch.ts: add sticker.fileId guard before cache access
- bot.test.ts: update reaction tests, remove dead DM thread-reaction test

* Telegram: remove duplicate bot.catch handler (only the last one runs in Grammy)

* Telegram: remove @ts-nocheck from bot.ts, fix duplicate error handler, harden sticker caching (openclaw#9077)
…penclaw#9179)

* Gateway: require explicit auth for url overrides

* Gateway: scope credential blocking to non-local URLs only

Address review feedback: the previous fix blocked credential fallback for
ALL URL overrides, which was overly strict and could break workflows that
use --url to switch between loopback/tailnet without passing credentials.

Now credential fallback is only blocked for non-local URLs (public IPs,
external hostnames). Local addresses (127.0.0.1, localhost, private IPs
like 192.168.x.x, 10.x.x.x, tailnet 100.x.x.x) still get credential
fallback as before.

This maintains the security fix (preventing credential exfiltration to
attacker-controlled URLs) while preserving backward compatibility for
legitimate local URL overrides.

* Security: require explicit credentials for gateway url overrides (openclaw#8113) (thanks @victormier)

* Gateway: reuse explicit auth helper for url overrides (openclaw#8113) (thanks @victormier)

* Tests: format gateway chat test (openclaw#8113) (thanks @victormier)

* Tests: require explicit auth for gateway url overrides (openclaw#8113) (thanks @victormier)

---------

Co-authored-by: Victor Mier <[email protected]>
* Message: enforce sandbox for media param

* fix: harden sandboxed media handling (openclaw#8780) (thanks @victormier)

* chore: format message action runner (openclaw#8780) (thanks @victormier)

---------

Co-authored-by: Victor Mier <[email protected]>
* Telegram: remove @ts-nocheck from bot-message.ts, type deps via Omit<BuildTelegramMessageContextParams>

* Telegram: widen allMedia to TelegramMediaRef[] so stickerMetadata flows through

* Telegram: remove @ts-nocheck from bot-message.ts (openclaw#9180)
* Security: gate whatsapp_login by sender auth

* Security: treat undefined senderAuthorized as unauthorized (opt-in)

* fix: gate whatsapp_login to owner senders (openclaw#8768) (thanks @victormier)

* fix: add explicit owner allowlist for tools (openclaw#8768) (thanks @victormier)

* fix: normalize escaped newlines in send actions (openclaw#8768) (thanks @victormier)

---------

Co-authored-by: Victor Mier <[email protected]>
* Telegram: remove @ts-nocheck from bot-handlers.ts, use Grammy types directly, deduplicate StickerMetadata

* Telegram: remove last @ts-nocheck from bot-handlers.ts (openclaw#9206)
…boarding (openclaw#9241)

* fix: infer --auth-choice from API key flags during non-interactive onboarding

When --anthropic-api-key (or other provider key flags) is passed without
an explicit --auth-choice, the auth choice defaults to "skip", silently
discarding the API key. This means the gateway starts without credentials
and fails on every inbound message with "No API key found for provider".

Add inferAuthChoiceFromFlags() to derive the correct auth choice from
whichever provider API key flag was supplied, so credentials are persisted
to auth-profiles.json as expected.

Fixes openclaw#8481

* fix: infer auth choice from API key flags (openclaw#8484) (thanks @f-trycua)

* refactor: centralize auth choice inference flags (openclaw#8484) (thanks @f-trycua)

---------

Co-authored-by: f-trycua <[email protected]>
- Security: owner-only tools + command auth hardening
- Security: harden sandboxed media handling
- feat: per-channel responsePrefix override
- feat: heartbeat accountId config option
- feat: cloudflare ai gateway provider
- feat: add Feishu channel support
- fix: telegram forward metadata + cron delivery guard
- fix: imessage echo loop detection
- Multiple performance and stability improvements
Copilot AI review requested due to automatic review settings February 5, 2026 06:30
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR merges upstream openclaw v2026.2.3 into the develop branch, bringing security hardening, cron system improvements, new channel features, and provider support updates from the main openclaw repository.

Changes:

  • Security improvements including owner-only tools, sandboxed media hardening, and credential exfiltration prevention
  • Cron system enhancements with delivery mode changes and one-shot job improvements
  • New channel support (Feishu) and per-channel response prefix overrides
  • Provider updates (Cloudflare AI Gateway, Moonspot China endpoint)
  • Documentation formatting standardization and new i18n infrastructure

Reviewed changes

Copilot reviewed 184 out of 3449 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
docs/**/*.md Standardized markdown formatting (ordered lists, spacing, trailing commas)
docs/custom.css Added CSS to hide first h1 in content area
docs/.i18n/* New i18n glossary and translation memory infrastructure
apps/macos/Sources/OpenClaw/Cron* Cron delivery mode refactor from isolation to delivery
apps/shared/OpenClawKit/Tools/CanvasA2UI/bootstrap.js Code style fixes (curly braces, private to public field)
apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayChannel.swift Fixed async push handler invocation
Dockerfile Updated CMD and added security notes
docker-compose.yml Fixed port binding and added token env var
.github/workflows/* Updated action versions, added formal conformance check, improved labeling
Various config files Formatting and linting rule updates

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}
await self.pushHandler?(.snapshot(ok))
if let pushHandler = self.pushHandler {
Task { await pushHandler(.snapshot(ok)) }
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pushHandler invocation is now wrapped in a detached Task without error handling. If the pushHandler throws or the actor is deallocated, this could lead to silent failures or crashes. Consider capturing errors and logging them, or using Task with a structured context that can propagate cancellation properly.

Suggested change
Task { await pushHandler(.snapshot(ok)) }
await pushHandler(.snapshot(ok))

Copilot uses AI. Check for mistakes.
Comment on lines +51 to +61
if let at = try container.decodeIfPresent(String.self, forKey: .at),
!at.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
{
self = .at(at: at)
return
}
if let atMs = try container.decodeIfPresent(Int.self, forKey: .atMs) {
let date = Date(timeIntervalSince1970: TimeInterval(atMs) / 1000)
self = .at(at: Self.formatIsoDate(date))
return
}
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When both at and atMs are missing, the thrown DecodingError says "Missing schedule.at" but doesn't mention that atMs is also acceptable. Update the error message to clarify that either field is required, e.g., "Missing schedule.at or schedule.atMs".

Copilot uses AI. Check for mistakes.
Comment on lines +226 to +227
// Avoid stderr pipe backpressure; we don't consume it.
process.standardError = FileHandle.nullDevice
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redirecting stderr to nullDevice silences all error output from the subprocess. If the process fails, debugging will be harder since stderr is discarded. Consider logging stderr to a temporary location or capturing it with a non-blocking pipe and logging on failure.

Copilot uses AI. Check for mistakes.
matrix:
include:
- runtime: node
task: tsgo
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The task name "tsgo" is ambiguous and doesn't clearly describe what this step does. Consider renaming it to something more descriptive like "typecheck" or "tsc-check" to clarify its purpose.

Suggested change
task: tsgo
task: typecheck

Copilot uses AI. Check for mistakes.
"${OPENCLAW_GATEWAY_BIND:-lan}",
"--port",
"${OPENCLAW_GATEWAY_PORT:-18789}"
"18789",
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The port is now hardcoded as a string "18789" instead of using the environment variable ${OPENCLAW_GATEWAY_PORT:-18789}. This removes the ability to configure the port via environment variables, which may be intentional but should be documented if it's a breaking change.

Suggested change
"18789",
"${OPENCLAW_GATEWAY_PORT:-18789}",

Copilot uses AI. Check for mistakes.
#
# For container platforms requiring external health checks:
# 1. Set OPENCLAW_GATEWAY_TOKEN or OPENCLAW_GATEWAY_PASSWORD env var
# 2. Override CMD: ["node","dist/index.js","gateway","--allow-unconfigured","--bind","lan"]
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CMD now starts the gateway with --allow-unconfigured and binds to loopback by default. The comment mentions that external health checks require manual override, but there's no example of how to override this in a docker-compose or kubernetes context. Consider adding a concrete example in the comment.

Suggested change
# 2. Override CMD: ["node","dist/index.js","gateway","--allow-unconfigured","--bind","lan"]
# 2. Override CMD to bind beyond loopback, for example:
# - docker-compose.yml:
# services:
# gateway:
# image: your-image
# environment:
# OPENCLAW_GATEWAY_TOKEN: "changeme"
# command: ["node","dist/index.js","gateway","--allow-unconfigured","--bind","lan"]
# - Kubernetes Deployment (container spec):
# env:
# - name: OPENCLAW_GATEWAY_TOKEN
# value: "changeme"
# command: ["node","dist/index.js","gateway","--allow-unconfigured","--bind","lan"]

Copilot uses AI. Check for mistakes.
@CompassHXM CompassHXM merged commit 5e8406d into develop Feb 5, 2026
11 of 39 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Comments