When a configured Google provider/model row had no explicit
but had a baseUrl set, the fallback defaulted to openai-completions,
causing Gemini requests to route through the OpenAI Responses
transport instead of the native @google/genai transport.
Made resolveConfiguredProviderDefaultApi provider-aware: for the
google provider, the default API is now google-generative-ai.
Root cause: the generic fallback assumed any provider with a baseUrl
should use openai-completions, which is incorrect for Google's native
Gemini API.
Co-authored-by: xin <1052326311+xin@users.noreply.github.com>
Preserve long Feishu streaming replies by falling oversized finals back to chunked message/static-card delivery instead of closing through an over-limit streaming CardKit payload.
Keeps late-final suppression after a streaming card closes, and uses markdown-aware chunking for static card fallback replies.
Fixes#88631.
Co-authored-by: Ted Li <tl2493@columbia.edu>
Phase-signal store reads now recover only missing files and corrupt JSON. Nonrecoverable filesystem read failures propagate so dreaming aborts before overwriting existing phase-signal history with an empty replacement.
Fixes#77881.
Thanks @bennewell35.
Co-authored-by: bennewell35 <newelljben@gmail.com>
Bound DiscordEntityCache entries with a write-time expired-entry sweep and a default 5,000-entry cap while preserving current safe expiry timestamp normalization. This prevents high-cardinality Discord user/channel/guild/member fetches from retaining stale Map entries for the gateway lifetime.
Fixes#77975.
Thanks @fede-kamel.
Co-authored-by: Federico Kamelhar <federico.kamelhar@oracle.com>
Serialize QMD update and embed writes with one per-agent store lock so foreground memory search/index and gateway background QMD work do not write the same index.sqlite concurrently.
The embed path now waits for global embed capacity before taking the per-store lock, so queued embeds do not block same-agent foreground updates while no store write is active.
Fixes#66339
Thanks @openperf.
Co-authored-by: Chunyue Wang <16864032@qq.com>
Remove Telegram runtime JSON sidecar read/write fallback for the prompt-context message cache. Keep legacy sidecar parsing for doctor import into SQLite plugin state and update docs/tests to match.
Fixes#85124.
Anthropic standard API keys no longer resolve as provider usage auth for `openclaw status --usage`, so valid inference keys are not sent to Anthropic's OAuth usage endpoint and surfaced as misleading invalid bearer-token errors.
The provider usage-auth SDK result now has an explicit handled/no-token shape so provider hooks can suppress generic fallback without widening the OAuth helper contract. Docs, Plugin SDK API baseline, and extension package-boundary cache inputs were updated with the new contract.
Thanks @zhangguiping-xydt.
Proof:
- node scripts/run-vitest.mjs src/infra/provider-usage.auth.normalizes-keys.test.ts src/infra/provider-usage.auth.plugin.test.ts extensions/anthropic/index.test.ts
- pnpm plugin-sdk:api:check
- pnpm plugin-sdk:check-exports
- git diff --check origin/main...HEAD
- pnpm docs:list
- pnpm run test:extensions:package-boundary:compile
- autoreview clean: no accepted/actionable findings
- PR CI rollup green: 131 success, 22 skipped, 1 neutral, 0 failures
Co-authored-by: 张贵萍0668001030 <zhang.guiping@xydigit.com>
Count model stream diagnostic response bytes from snapshotless stream chunks, excluding accumulated partial snapshots on delta events. This avoids repeatedly serializing answer-so-far snapshots during streamed model calls and updates OTEL/docs wording for the new metric baseline.
Refs #86599.
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
* refactor: move plugin state slices to sqlite
* fix: keep legacy plugin state migration out of runtime
* fix: add doctor migrations for plugin sqlite state
* fix: preserve teams feedback learning migration keys
* fix: merge teams legacy feedback learnings
* fix: guard doctor imports against plugin state caps
* fix: leave lossy teams learning filenames unmigrated
* fix: preserve teams feedback learning scope
* fix: load plugin doctor contracts from package dist
* fix: satisfy plugin state migration gates
Handle the Telegram isolated-polling spool recovery race where a stale `.processing` claim can disappear between discovery and the final rename back to pending. Recovery now treats `ENOENT` as benign and mirrors the existing duplicate-pending cleanup path for `EEXIST`, avoiding noisy drain-failure logs and spurious failure counters without changing claim ownership semantics.
Adds a regression test that removes the claim from inside `shouldRecover`, after recovery has discovered the entry and before the final rename path, so the old code would hit the reported `ENOENT` window.
Fixes#87847
Co-authored-by: Sebastien Tardif <sebtardif@ncf.ca>
Fixes Codex/plugin-harness cold starts for exact static-catalog model ids such as openai/gpt-5.3-codex without adding a second resolver retry loop. The embedded runner now performs the normal provider-runtime attempt with agent discovery skipped, then consults the bundled static catalog before falling back to generic configured-provider synthesis when plugin harness owns transport.
The OpenAI static catalog row carries the Codex ChatGPT transport metadata, dynamic provider metadata still wins for runtime-owned models, and focused regression coverage exercises both paths.
Fixes#88510.
Co-authored-by: yetval <yetvald@gmail.com>
Show DeepSeek API-key account balance in status/auth-status usage surfaces by adding a summary-only provider usage snapshot path, a DeepSeek balance fetcher, SDK/docs coverage, and focused regression tests.
Maintainer verification accepted the additive provider-usage/status contract and the DeepSeek balance visibility boundary for authenticated status surfaces.
Proof:
- Live DeepSeek balance proof via 1Password-backed DEEPSEEK_API_KEY against https://api.deepseek.com/user/balance; key and balance amount redacted.
- GitHub CI run 26717953383 passed on the current head.
- Real behavior proof run 26718215605 passed after the PR body was refreshed.
- Local clean PR clone: git diff --check; node --max-old-space-size=8192 --import tsx scripts/generate-plugin-sdk-api-baseline.ts --check; node scripts/run-vitest.mjs run src/agents/bash-tools.exec.path.test.ts.
Co-authored-by: Alex Tang <tangli1987118@hotmail.com>
Co-authored-by: litang9 <141409885+litang9@users.noreply.github.com>
Suppress WhatsApp typing indicators only for silent message-tool-only unmentioned group runs. Automatic visible replies and authorized group commands still show composing normally.
Fixes the autoreview regression risk by narrowing suppressTyping and adding coverage for both silent and visible group paths.
Proof:
- pnpm test src/auto-reply/reply/reply-utils.test.ts extensions/whatsapp/src/auto-reply/monitor/inbound-dispatch.test.ts
- .agents/skills/autoreview/scripts/autoreview --mode local
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
- CI run 26717880577 green
Thanks @Bluetegu.
Keep Slack progress-mode drafts on one rolling preview message across assistant and reasoning boundaries while preserving boundary cleanup and the latest visible tool-progress lines. Partial/replace modes still start a fresh draft at assistant boundaries.
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Route Discord thread follow-up messages to plugin-owned bindings by the raw thread id while retaining parent channel fallback matching. This fixes `/codex bind` follow-ups in Discord threads being claimed by the parent OpenClaw route instead of the bound Codex session.
Verification:
- `node scripts/run-vitest.mjs extensions/discord/src/channel.conversation.test.ts src/hooks/message-hook-mappers.test.ts extensions/discord/src/monitor/message-handler.process.test.ts -t "prefers bound session keys|passes Discord thread parent only|routes Discord thread plugin-owned bindings|passes thread parent ids|thread binding"`
- `node scripts/run-vitest.mjs src/auto-reply/reply/dispatch-from-config.test.ts -t "routes Discord thread plugin-owned bindings by raw thread id"`
- `pnpm build`
- `pnpm lint --threads=8`
- `CI=true FORCE_COLOR=0 pnpm lint --threads=8`
- `.agents/skills/autoreview/scripts/autoreview --mode local`
- GitHub: Real behavior proof, check-test-types, check-dependencies, check-prod-types, auto-reply dispatch shard, hooks shard, and extension package boundary passed on head 1e896d9835.
Known unrelated CI noise at merge: broad opengrep/test/lint CI failures are outside the touched Discord/session-binding surface and contradicted by focused local proof where applicable.
Co-authored-by: Hex <hex@openclaw.ai>
Add Claude Opus 4.8 to the GitHub Copilot static model catalog and default model IDs.
Updates provider manifest metadata and regression coverage so fallback/default discovery includes claude-opus-4.8.
PR: #88547
Co-authored-by: saju01 <saju@coderedcorp.com>
When dreaming narrative cleanup calls subagent.deleteSession() in the finally block and it throws, the store row can be left behind referencing a still-present transcript. The scrubber only pruned dreaming rows whose transcript was missing, so these orphans lingered in the recent sessions sidebar with no kind/status/endedAt and accumulated across restarts.
Reclaim a dreaming store row when its transcript is missing OR has aged past DREAMING_ORPHAN_MIN_AGE_MS, then leave the transcript unreferenced so the orphan-transcript pass archives it.
Fixes#88322
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Use the Google Chat thread resource as the ambient message-tool reply target so replies stay in the inbound thread. Normalize the current Google Chat space target and let plugin threading adapters explicitly suppress the generic message-id fallback when a provider needs a thread resource instead of a message resource.
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Franco Viotti <franco-viotti@users.noreply.github.com>
Fix Discord DM pairing for PluralKit senders by storing the pairing identity with the same `pk:<member-id>` form used at inbound lookup time. Also recognizes both canonical direct DM session keys and account-scoped direct DM session keys as DM approval sessions.
Focused proof: `node scripts/run-vitest.mjs extensions/discord/src/approval-native.test.ts extensions/discord/src/monitor/dm-command-auth.test.ts extensions/discord/src/monitor/dm-command-decision.test.ts extensions/discord/src/monitor/message-handler.preflight.test.ts` passed with 4 files and 82 tests.
Closes#86332
Co-authored-by: Sanjays2402 <51058514+Sanjays2402@users.noreply.github.com>
Slack top-level channel mentions with replyToMode off now reply at the channel root instead of inheriting stale or auto-created thread targets.
Existing Slack thread replies and Slack assistant DM thread targets continue to preserve their thread target.
Thanks @lawrencetran.