Add openai/chat-latest as an explicit direct API-key OpenAI model override, document the moving alias, and normalize unsupported Responses text verbosity for that model.
* feat(channels list): drop auth providers, add --all, surface installed/configured/enabled
`openclaw channels list` used to conflate two very different surfaces: chat
channels and OAuth/API-key auth providers for model routing. The auth
section was the first and most visible block in the output even for
operators who only cared about chat channels, and its JSON `auth` key
leaked model-provider identities into a command whose top-level help
describes it as channel management. Worse, the command silently hid
every channel that had no configured account, so users could not tell
from `channels list` which bundled or catalog channels were even
available to configure.
Split the surface cleanly around channels only:
1. Remove the `Auth providers (OAuth + API keys)` text section and the
`auth` field from the JSON payload. Model-provider auth profiles
remain reachable via `openclaw models auth list`, which is where
they conceptually belong.
2. Add a `--all` flag to surface every channel an operator could
configure: bundled channel plugins that have no account yet and
catalog-listed external channels whose plugin package is not even
installed on disk. Without `--all` the output still shows only
channels with at least one configured account, matching the
previous default behavior so existing scripts keep working. The
"empty" default path now prints a hint pointing at `--all`.
3. Render three explicit status tags per row — `installed` /
`not installed`, `configured` / `not configured`, `enabled` /
`disabled` — so bundled-but-unconfigured plugins and installable
catalog channels both render with accurate state instead of being
invisible. Installed state comes from the same
`isCatalogChannelInstalled` probe the setup flow uses, so it stays
consistent with `openclaw onboard` and `channels add`.
4. JSON payload now carries an `origin` per channel (`configured`,
`available`, `installable`) alongside `installed: boolean`, which
lets tooling distinguish "user has set this up" from "user could
set this up" without second-guessing.
Register `--all` on both the Commander CLI and the fast-path route-arg
parser so the flag works in both code paths, update the one routes
test that asserted the parsed args shape, and rewrite the old auth
profiles surface test as a broader `channels list` behavior spec
covering default output, `--all` output, JSON shape (no `auth`), and
the bundled-unconfigured + catalog-not-installed cases.
Docs: call out that `channels list` is chat-channel only now, mention
`--all`, and point at `openclaw models auth list` for what used to be
the auth providers block.
* fix(channels list): surface catalog channels that are installed on disk but not yet configured
The previous `--all` path filtered catalog entries with
`!installedByChannelId.get(entry.id)` before rendering them as
catalog-only rows. That assumed "catalog entry not already rendered
as a plugin row" implied "not installed", which is wrong: an external
channel plugin package can be installed on disk (`isCatalogChannelInstalled`
returns true) while the read-only channel loader still declines to
surface a plugin object for it — the loader only activates channels
that appear in user config, so a plugin that is installed but never
configured ended up in neither bucket and silently dropped out of
`channels list --all`.
Operator-facing symptom: `pnpm openclaw channels list --all` omitted
WeCom (and any other catalog channel in the same state) even though
its npm package was present on disk and its catalog entry existed,
while rendering every other uninstalled catalog channel as expected.
Fix: drop the `installed` filter from `catalogOnlyLines` so every
catalog entry that is not already represented by a plugin row is
rendered, and let the row itself carry the real installed/not-installed
tag. Two renderings now land in the catalog-only bucket:
- Not installed — rendered as `not installed, not configured, disabled`
(installable row).
- Installed but unconfigured — rendered as `installed, not configured,
disabled` (ready-to-configure row). The JSON `origin` for this case
becomes `available`, matching the existing origin for bundled
plugins that are installed but unconfigured, so downstream tooling
sees a consistent "you could configure this now" signal regardless
of whether the plugin came from bundled sources or from the catalog.
Regression test added under the WeCom scenario.
* refactor(channels list): drop model-provider usage surface, make the command channel-only
`openclaw channels list` used to append a model-provider usage/quota
snapshot (Anthropic, OpenRouter, OpenAI Codex, Gemini, Zai, Minimax,
etc.) under every invocation. That was a leftover from the days when
`channels list` was the only "operator overview" command; the same
data is now owned by `openclaw status` (overview) and
`openclaw models list` (per-provider), which handle timeouts, probe
errors, and output shape consistently for that class of data. Keeping
the snapshot wired into `channels list` meant:
- Every default invocation made one blocking `loadProviderUsageSummary`
call that fanned out to every configured provider billing/auth
endpoint, adding seconds of latency to a command that otherwise
just reads local config.
- `channels list --no-usage` was the escape hatch, but the flag was
itself a self-sustaining bug: it only existed because the command
did work that did not belong to it.
- JSON consumers had an optional `usage` key whose shape was owned by
the provider-usage module, not by the channels module, so any
change upstream silently reshaped `channels list --json` output.
- Failed provider fetches printed provider-side errors on a command
that never advertised itself as a provider-health surface.
Scope this PR tightens, in one move:
1. Remove `loadProviderUsageSummary` / `formatUsageReportLines` usage
from `src/commands/channels/list.ts`. The command now only reads
config, the read-only channel plugin registry, and the trusted
catalog — matching its name.
2. Drop `--no-usage` from the Commander CLI registration, from the
fast-path route-arg parser (`parseChannelsListRouteArgs`), and
from `ChannelsListOptions`. The flag is gone, not silently
ignored, so anyone depending on it will get a clear
"unknown option" from Commander and from the fast-path router.
3. Drop the `usage` key from `channels list --json` payloads. Shape
of the `chat` record and the new `origin` / `installed` tags
introduced earlier in this branch are unchanged.
4. Print a single-line migration pointer at the bottom of the text
output so operators who expected usage know where it went
(`openclaw status` / `openclaw models list`). This replaces what
used to be a block of fetched provider data with one static line,
so it cannot fail or add latency.
5. Update `docs/cli/channels.md` troubleshooting to remove the
`--no-usage` mention and point at the two new entry points.
6. Update tests: drop the `loadProviderUsageSummary` mock and the
`"keeps JSON output valid when usage loading fails"` case,
replace it with a positive assertion that `payload.usage` is
undefined (locking in the narrower contract), and remove `usage`
from every `channelsListCommand(...)` call to match the narrowed
`ChannelsListOptions` type. The route-args test is updated to
expect `{ json, all }` without `usage`.
No other command changes. `openclaw status` and `openclaw models list`
already render usage; they are the documented replacements.
Breaking-ish surface:
- CLI: `channels list --no-usage` now fails with "unknown option".
Tooling should drop the flag — there is nothing left to opt out of.
- JSON: `channels list --json` no longer carries a top-level `usage`
key. Tooling that read it must migrate to
`openclaw status --json` or `openclaw models list --json`.
* fix(channels.list.test): widen isCatalogChannelInstalled mock signature to accept entry param
CI typecheck failed because the mock was declared with a zero-arg signature while one test called mockImplementation(({ entry }) => …). Tighten the generic so vitest's mock accepts the same params the real helper does.
* changelog: record channels list channel-only rework (#78456)
Fixes Feishu native topic starter routing by hydrating a missing topic thread ID before session resolution.\n\nCloses #78262.
(cherry picked from commit 8cc762daff)
Remove stale managed-root openclaw manifests, locks, hidden locks, and installed copies before npm plugin installs.
Relink plugin-local openclaw peer symlinks after shared-root npm install, rollback, update, and uninstall mutations so SDK-using plugins keep resolving openclaw/plugin-sdk/*.
Force safe npm commands out of inherited legacy/strict peer-dependency modes.
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
(cherry picked from commit 8e533490ab)
Adds cap_drop and no-new-privileges hardening for the bundled gateway Docker Compose services.\n\nThanks @VintageAyu.
(cherry picked from commit f9da484365)
* fix(telegram): reuse preview for long text finals
* test(qa): cover long telegram finals
* fix(qa): satisfy extension lint
* fix(qa): keep telegram long final fixture to two chunks
* test(telegram): cover three chunk finals
* fix(telegram): force long final preview boundary
(cherry picked from commit e03fe1e289)
The Slack docs jumped straight from intro into the Quick Setup tabs
without telling readers when to pick each transport. Add a Choosing
Socket Mode or HTTP Request URLs section above Quick Setup with a
concern-by-concern table (public URL, outbound network, tokens, dev
laptops, scaling, multi-account, slash command transport, signing,
recovery) plus a Note pointing at the right default for each shape.
Also add an Info block under the HTTP Quick Setup manifest explaining
why the manifest carries three url fields (slash_commands[].url,
event_subscriptions.request_url, interactivity.request_url) — Slack's
manifest schema requires them spelled out separately even though
OpenClaw routes by payload type, and slash commands silently no-op
without their url field in HTTP mode.
The Quick Setup steps in docs/channels/slack.md previously sent users to
the `#manifest-and-scope-checklist` anchor lower on the page to copy the
manifest, breaking the copy-paste flow. Pull the manifest inline as a
Mintlify <CodeGroup> for both Socket Mode and HTTP Request URLs tabs and
add a Minimal variant for workspaces that restrict scopes (drops
files:*, reactions:*, pins:*, mpim:*, emoji:read, usergroups:read while
keeping DMs, channel/group history, mentions, App Home, and slash
commands). Recommended matches extensions/slack/src/setup-shared.ts.
Existing Manifest and scope checklist section stays as the canonical
per-scope reference.
Cross-link from docs/concepts/qa-e2e-automation.md so QA maintainers see
the production manifest reference, while keeping the QA Driver/SUT pair
of manifests inline (the lane intentionally needs two distinct apps so
its shape is different from a single-app production install).
Two correctness fixes from code review.
1. Zod schema (src/config/zod-schema.agent-runtime.ts) was strict and
rejected tools.loopDetection.postCompactionGuard.* keys at validation
time, making the guard's documented configurability inaccessible at
gateway startup. Adds ToolLoopPostCompactionGuardSchema with both
optional fields and wires it into ToolLoopDetectionSchema.
2. The runner observation cursor in pi-embedded-runner/run.ts used
absolute indices into state.toolCallHistory, but that array is
trimmed at historySize (default 30). Once the buffer was full, new
records shifted out from under the cursor and the guard silently
missed every loop in long-running sessions. Replaces the index
cursor with a monotonic toolOutcomeSeq on SessionState that
recordToolCallOutcome bumps on each observable push (unmatched
branch only, mirroring the prior cursor's effective semantics).
The runner now reads the most recent (currentSeq - lastSeq) entries
from the tail of toolCallHistory, which is trim-resilient.
Adds zod parse tests for the new config keys (valid, empty, unknown
key, non-positive, non-integer) and a runner regression test that
seeds toolCallHistory at the trim cap before triggering a
post-compaction loop, asserting the abort still fires.
Refs #77474
Arms the guard at each of the three compaction-success points in
run.ts and observes tool-call outcomes from the diagnostic session
state's toolCallHistory after each attempt. Aborts with
PostCompactionLoopPersistedError when the same (tool, args, result)
triple repeats windowSize times within the post-compaction window.
Refs #77474
Two missing cross-references uncovered by the 24-hour doc audit:
- docs/help/faq-models.md: link to `openclaw models auth list` from the
"What is an auth profile?" accordion. The command was added in
23eb44b045 but the FAQ never pointed users at it.
- docs/security/network-proxy.md: list `tools.web.fetch.useTrustedEnvProxy`
in Related Proxy Terms. The opt-in is fully documented in
docs/tools/web-fetch.md but the proxy reference page omitted the
cross-reference, leaving the page incomplete for proxy-state triage.
The `gateway restart` Command-options accordion only listed `--force`,
`--wait`, and `--json` even though `--safe` is a fully-supported flag
(documented in the prose at line 112 and rejected by lifecycle.ts when
combined with --force/--wait). Add --safe to the option list and a
Lifecycle-behavior bullet that explains the preflight-defer behavior
plus its mutual exclusion with --force and --wait, matching
src/cli/daemon-cli/lifecycle.ts:153-156.