Commit Graph

62468 Commits

Author SHA1 Message Date
Galin Iliev
c6ade83a5c fix: avoid stale dashboard child context budgets (#97332)
* fix(gateway): avoid stale child session context tokens

* fix(gateway): avoid stale child session context tokens

---------

Co-authored-by: Galin Iliev <Galin.Iliev@microsoft.com>
2026-06-27 21:31:18 -07:00
Josh Avant
07b934901a fix: scanned PDF pages reach chat vision models (#97354)
* fix: forward scanned PDF page images to chat models

* fix: remove stale reply option cast
2026-06-27 23:01:08 -05:00
Gio Della-Libera
1b0766080a Add hosted catalog source profile validation (#95969)
Merged via squash.

Prepared head SHA: 6dc6ca154c
Co-authored-by: giodl73-repo <235387111+giodl73-repo@users.noreply.github.com>
Co-authored-by: giodl73-repo <235387111+giodl73-repo@users.noreply.github.com>
Reviewed-by: @giodl73-repo
2026-06-27 20:56:54 -07:00
Andy Ye
830467bc93 fix(imessage): stage remote media for plugin claims (#91803) 2026-06-27 19:36:21 -07:00
Gio Della-Libera
d1b917120a Persist hosted catalog snapshots in state (#95964)
Merged via squash.

Prepared head SHA: 372ec63c99
Co-authored-by: giodl73-repo <235387111+giodl73-repo@users.noreply.github.com>
Co-authored-by: giodl73-repo <235387111+giodl73-repo@users.noreply.github.com>
Reviewed-by: @giodl73-repo
2026-06-27 19:01:22 -07:00
Dallin Romney
78f7de01c1 test: link local e2e qa coverage wrappers (#97150) 2026-06-27 18:34:36 -07:00
Gio Della-Libera
3630d502eb Doctor: expose gateway runtime findings (#97075)
* feat(doctor): expose gateway runtime findings

* fix(doctor): redact gateway health targets
2026-06-27 17:17:49 -07:00
Dallin Romney
7bbd09047b docs: simplify macOS app overview (#97120)
* docs: simplify macOS app docs

* docs: preserve macOS app detail links

* docs: address macOS review feedback
2026-06-27 16:04:30 -07:00
Shakker
c53dbcaf4d fix: surface delegated Testbox proof status 2026-06-27 23:53:53 +01:00
Shakker
461e551e85 test: clarify delegated Testbox proof status 2026-06-27 23:53:52 +01:00
Galin Iliev
dc575d148a fix: page sessions_history beyond truncated tails (#97101)
* Add sessions history offset pagination

* Fix sessions_history pagination after tool caps

* Fix sessions_history PR CI blockers

* Update sessions_history prompt snapshots

* Fix offset history projection windows

---------

Co-authored-by: Galin Iliev <5711535+galiniliev@users.noreply.github.com>
2026-06-27 15:30:49 -07:00
Gio Della-Libera
12685ee6b7 Add hosted catalog snapshot fallback (#95877)
Merged via squash.

Prepared head SHA: 5f71635bba
Co-authored-by: giodl73-repo <235387111+giodl73-repo@users.noreply.github.com>
Co-authored-by: giodl73-repo <235387111+giodl73-repo@users.noreply.github.com>
Reviewed-by: @giodl73-repo
2026-06-27 15:26:49 -07:00
Gio Della-Libera
36722014ef Doctor: expose configured plugin install findings (#96171)
* feat(doctor): expose configured plugin install findings

* fix(doctor): satisfy configured plugin mapper lint
2026-06-27 14:18:50 -07:00
zengLingbiao
1b8b8500ce fix(auto-reply): truncate user-facing text on UTF-16 boundary (#97299)
Summary:
- The PR imports `truncateUtf16Safe` and uses it for the Codex usage-limit preview and verbose working-label truncation paths in auto-reply.
- PR surface: Source +2. Total +2 across 2 files.
- Reproducibility: yes. Current main uses raw `slice(0, N)` at both reported user-facing truncation sites, and ... ludes terminal before/after output showing dangling surrogates before the fix and safe truncation after it.

Automerge notes:
- No ClawSweeper repair was needed after automerge opt-in.

Validation:
- ClawSweeper review passed for head 74a0a32ed9.
- Required merge gates passed before the squash merge.

Prepared head SHA: 74a0a32ed9
Review: https://github.com/openclaw/openclaw/pull/97299#issuecomment-4820038635

Co-authored-by: zenglingbiao <zeng.lingbiao@xydigit.com>
Approved-by: takhoffman
2026-06-27 20:39:32 +00:00
Gio Della-Libera
c29e1fe764 Add hosted external catalog feed loader (#95868)
Merged via squash.

Prepared head SHA: 76da9328af
Co-authored-by: giodl73-repo <235387111+giodl73-repo@users.noreply.github.com>
Co-authored-by: giodl73-repo <235387111+giodl73-repo@users.noreply.github.com>
Reviewed-by: @giodl73-repo
2026-06-27 13:20:05 -07:00
Ayaan Zaidi
c52adf7505 test(telegram): cover retained preview chunk gaps 2026-06-27 12:30:57 -07:00
Ayaan Zaidi
199700de26 fix(telegram): replay retained preview gaps 2026-06-27 12:30:57 -07:00
Hannes Rudolph
b14a95b3fd docs: revert v2026.6.9 changelog update (#97306)
This reverts commit ebf1ba70d5.
2026-06-27 13:04:51 -06:00
Hannes Rudolph
ebf1ba70d5 docs: update changelog for v2026.6.9 (#97124) 2026-06-27 12:37:53 -06:00
Hannes Rudolph
78d70230b6 docs: align v2026.6.10 changelog heading (#97297) 2026-06-27 12:37:24 -06:00
shengting
98ed83f848 fix(model-fallback): don't rethrow provider-side AbortErrors as user cancellations (#90908)
* fix(model-fallback): don't rethrow provider-side AbortErrors as user cancellations

When the LLM API closes the connection mid-stream, the fetch layer
surfaces AbortError("This operation was aborted") with no external
abort signal triggered. The old guard `shouldRethrowAbort()` returned
false for these errors (because isTimeoutError matched the message),
so they fell through to the fallback loop but were never retried —
the error propagated up and produced SILENT_REPLY_TOKEN in group
sessions, permanently silencing the topic.

Replace the guard with a direct check: only rethrow AbortError when
the external abort signal is actually set (user/gateway cancellation).
Provider-side AbortErrors without an external signal now fall through
to the next fallback candidate, giving the system a chance to recover.

* fix(cron): forward abort signal into runWithModelFallback

Thread the cron executor's abort signal into the shared
runWithModelFallback call so that cron timeouts and cancellations
stop the fallback chain instead of retrying with the next candidate.

Previously, the run callback checked params.abortSignal?.aborted and
threw, but runWithModelFallback itself had no signal — so the new
guard in model-fallback.ts could not distinguish a caller abort from
a provider-side AbortError and would retry silently.

Also adds a focused regression test verifying the signal is forwarded.

---------

Co-authored-by: Shengting Xie <shengting@openclaw.ai>
Co-authored-by: yayu <yayu@yayuMacStudio.local>
2026-06-27 20:53:16 +03:00
Gio Della-Libera
1bdde66950 Doctor: expose plugin registry findings (#96169)
Merged via squash.

Prepared head SHA: cf4399955e
Co-authored-by: giodl73-repo <235387111+giodl73-repo@users.noreply.github.com>
Co-authored-by: giodl73-repo <235387111+giodl73-repo@users.noreply.github.com>
Reviewed-by: @giodl73-repo
2026-06-27 10:00:50 -07:00
llagy009
2720ac06b7 fix(duckduckgo): guard out-of-range numeric HTML entities (#96583)
decodeHtmlEntities decoded numeric entities with String.fromCodePoint(parseInt(...)) without a range check, so an out-of-range entity such as &#99999999; or &#x110000; threw RangeError and made the whole results page fail to parse. Validate the code point is within 0..0x10FFFF and keep the original entity text otherwise. Add a regression covering decimal and hex out-of-range entities plus a valid astral entity.
2026-06-27 09:37:58 -07:00
miorbnli
ce15f348bb fix(telegram): use idempotent retry context for delete/reaction (#96612)
reactMessageTelegram and deleteMessageTelegram passed context: "send" to
isRecoverableTelegramNetworkError, which disables message-snippet matching
(allowMessageMatch defaults to false only for "send"). Both operations are
idempotent (setMessageReaction / deleteMessage are safe to repeat), yet a
transient snippet-only network error (e.g. "socket hang up", "undici network
error" with no error code) was not retried — stricter than polling/webhook/
unknown, which all default allowMessageMatch to true. Users saw spurious
reaction/delete failures on transient network errors.

Add delete | react to TelegramNetworkErrorContext (additive) and use them at
the two callers. The helper default (context !== "send") is unchanged, so
delete/react now match polling/webhook/unknown. sendMessage keeps "send".

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-27 09:31:52 -07:00
llagy009
e5c3c59c67 fix(synology-chat): truncate sanitized input on UTF-16 boundary (#96574)
sanitizeInput truncated long messages with String.slice(0, 4000), which
can cut through an astral character's surrogate pair (e.g. an emoji at
the 4000-char boundary), leaving a lone surrogate in the sanitized text
passed downstream.

Use truncateUtf16Safe so truncation never splits a surrogate pair,
keeping the existing 4000-char budget and '... [truncated]' suffix.

Adds tests asserting the truncated output stays UTF-16 well formed and
that a supplementary-plane character is preserved when it fits.
2026-06-27 09:31:33 -07:00
llagy009
2e881ab1c6 fix(googlechat): truncate approval card text on UTF-16 boundary (#96573)
truncateText sliced the approval card text paragraph with String.slice,
which can cut through an astral character's surrogate pair (e.g. an emoji
straddling the 1797-char limit), leaving a lone surrogate in the card
text sent to Google Chat.

Use truncateUtf16Safe from the plugin SDK so truncation never splits a
surrogate pair, keeping the '...' suffix and the existing length budget.

Adds tests asserting the truncated Command card text stays UTF-16 well
formed and that an astral character is preserved when it fits.
2026-06-27 09:31:26 -07:00
llagy009
90c20d15c2 fix(slack): truncate approval mrkdwn on UTF-16 boundary (#96576)
truncateSlackMrkdwn cut approval Block Kit mrkdwn (Command/Request/
plugin description) with String.slice(0, maxChars - 1), which can split
an astral character's surrogate pair at the 2600-char preview limit,
leaving a lone surrogate in the chat.postMessage/chat.update payload.

Slice with sliceUtf16Safe so truncation never splits a surrogate pair,
keeping the existing ellipsis suffix and length budget.

Adds tests asserting exec command and plugin request mrkdwn stay free of
lone surrogates, plus a BMP regression keeping the existing limit.
2026-06-27 09:31:20 -07:00
llagy009
cb8bc71ff8 fix(whatsapp): elide auto-reply text on UTF-16 boundary (#96580)
elide truncated text with String.slice(0, limit) on a UTF-16 code-unit
index, so an astral character straddling the limit was cut into a lone
surrogate; the truncated-char count was also computed from the fixed
limit rather than the actual kept length.

Truncate with truncateUtf16Safe so a surrogate pair is never split, and
derive the truncated-char count from the kept length so the annotation
stays accurate.

Adds tests asserting no lone surrogate when the limit lands inside an
emoji and that a complete astral character is kept when it fits.
2026-06-27 09:31:16 -07:00
llagy009
b5c662f4f5 fix(codex): keep CLI session preview text on code-point boundaries (#96582)
truncateText shortened the cached lastMessage preview with value.slice(0, max - 3), which can cut a surrogate pair in half and emit a lone surrogate into the codex CLI session list JSON. Use the shared truncateUtf16Safe helper so truncation falls back to a whole code-point boundary. Add regressions for both the history.jsonl and sessions/**/*.jsonl preview paths.
2026-06-27 09:31:00 -07:00
llagy009
d693ed4af3 fix(qqbot): truncate reminder job name on code-point boundary (#96575)
generateJobName truncated reminder content with String.slice(0, 20) on
a UTF-16 code-unit index, so an astral character (e.g. an emoji) landing
on the boundary was cut into a lone surrogate, producing a malformed
cron job name.

Truncate with the shared truncateUtf16Safe helper so a surrogate pair is
never split, keeping the existing 20-unit budget and ellipsis suffix.

Adds a test asserting the truncated job name contains no lone surrogate.
2026-06-27 09:30:52 -07:00
llagy009
6c5a9fde9f fix(msteams): truncate reflection prompt on UTF-16 boundary (#96578)
buildReflectionPrompt truncated the thumbed-down response with
String.slice(0, 500) on a UTF-16 code-unit index, so an astral
character straddling the 500-char cap was cut into a lone surrogate in
the reflection prompt built for the LLM.

Use truncateUtf16Safe so truncation never splits a surrogate pair,
keeping the existing 500-char budget and '...' suffix.

Adds tests asserting the prompt stays UTF-16 well formed when truncating
and that a boundary emoji is preserved when it fits.
2026-06-27 09:30:26 -07:00
Vincent Koc
b8e3de1160 fix(telegram): recover stalled ingress spool claims (#97118)
* fix(telegram): drain ingress with native queue claims

* fix(telegram): bound native claim drain snapshots

* fix(telegram): recover pid-reused ingress claims

* fix(channels): block claimed candidate lanes

* fix(telegram): recover stalled ingress spool claims

* test(telegram): cover native claimNext drain stalls

---------

Co-authored-by: Dallin Romney <dallinromney@gmail.com>
2026-06-27 09:14:14 -07:00
mikasa
b9c64142e2 fix(agents): keep missing tool results on current model (#95543) 2026-06-27 19:06:56 +03:00
Milosz Jankiewicz
84bcd500c9 feat(xai): route OAuth login through device-code flow (#97249)
Route xAI OAuth through device-code sign-in so remote and headless hosts do not need a localhost callback. Preserve the legacy manual `xai-device-code` auth choice/method as a compatibility alias to the same device-code flow.

Also migrate stale xAI token endpoints on refresh and fail fast on structured refresh errors while keeping retries scoped to detected HTML/Cloudflare challenge responses.

Verification:
- `node scripts/run-vitest.mjs extensions/xai/index.test.ts extensions/xai/xai-oauth.test.ts`
- `node scripts/run-vitest.mjs src/cli/models-cli.test.ts -t 'maps --device-code'`
- `node scripts/run-vitest.mjs src/commands/auth-choice.test.ts -t 'removed provider auth choice'`
- Crabbox local-container live smoke on exact head `fef3cb24afb01cd1f69cf04ef67ed11d71dfadb3`: xAI discovery and device authorization returned 200.
- `$autoreview` after the live smoke: clean.

Co-authored-by: Jaaneek <Jaaneek@users.noreply.github.com>
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
2026-06-27 10:02:57 -06:00
ly-wang19
f857e8d66e fix(terminal): wrap long wide-char words by visible width, not code-point count (#96746)
wrapNoteMessage measures every fit decision in visible columns, but its
splitLongWord fallback (for a single word longer than the line budget) sliced
the word into groups of maxLen code points. maxLen is a visible-column budget,
so a run of wide characters (CJK / fullwidth / emoji, 2 columns each) produced
lines up to twice the budget — e.g. a 24-char CJK word at maxWidth 20 emitted a
40-column line.

Accumulate grapheme visible width (the same unit visibleWidth uses) and start a
new segment when the next grapheme would exceed maxLen, so every wrapped segment
fits the budget; a single grapheme wider than the budget still emits, preserving
progress. ASCII wrapping is unchanged.

Co-authored-by: ly-wang19 <ly-wang19@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 08:50:45 -07:00
clawSean
a048aeae16 fix(qa-lab): treat claude-cli as Anthropic-family for live turn timeouts (#96567)
The live-frontier turn-timeout resolution only matched `anthropic/` models,
so `claude-cli/*` routes fell into the 120s fallback bucket instead of the
180s Anthropic floor, and claude-cli Opus missed the 240s Opus floor — even
though claude-cli serves the same Anthropic Claude models.

Recognize claude-cli as Anthropic-family via a small `isAnthropicFamilyModel`
helper, mirroring the existing `provider === "anthropic" || provider === "claude-cli"`
precedent in the aimock and mock-openai servers.

Co-authored-by: clawSean <260045960+clawSean@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 08:47:33 -07:00
llagy009
4b9e01813e fix(msteams): keep truncated parent context text well-formed (#96569)
summarizeParentMessage truncated the parent body with text.slice(0, PARENT_TEXT_MAX_CHARS - 1), which can cut a surrogate pair in half and emit a lone surrogate into the injected "Replying to @sender: …" system event. Use the shared truncateUtf16Safe helper so truncation falls back to a whole code-point boundary. Add a regression asserting the summary stays isWellFormed() when the limit lands inside an emoji.
2026-06-27 08:47:27 -07:00
llagy009
7830faa5fe fix(whatsapp): convert GFM bold-italic without leaving literal asterisks (#96570)
markdownToWhatsApp only handled **bold** and __bold__, so combined GFM
strong+emphasis such as ***bi***, __*y*__ or **_x_** was reduced by the
plain bold rule first and left a literal ** around the inner emphasis
(e.g. ***bi*** -> **bi**), which WhatsApp renders as plain characters.

Handle the combined strong+emphasis variants before the plain strong
rules and emit WhatsApp bold+italic (*_text_*). Plain bold, italic,
strikethrough and code-span handling are unchanged.

Adds it.each cases for the GFM bold-italic variants and a regression
case ensuring bold-italic markers inside inline code are preserved.
2026-06-27 08:46:45 -07:00
Masato Hoshino
ddedf13190 fix(irc): sanitize internal tool-trace lines from outbound text (#97214)
* fix(irc): sanitize internal tool-trace lines from outbound text

* fix(irc): sanitize internal tool-trace lines from outbound text

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-06-27 08:34:38 -07:00
Gio Della-Libera
cb4244fe15 Doctor: expose state integrity findings (#95979)
Merged via squash.

Prepared head SHA: eb3bd1adad
Co-authored-by: giodl73-repo <235387111+giodl73-repo@users.noreply.github.com>
Co-authored-by: giodl73-repo <235387111+giodl73-repo@users.noreply.github.com>
Reviewed-by: @giodl73-repo
2026-06-27 08:31:56 -07:00
zw-xysk
361869e434 fix(validation): preserve null in anyOf unions instead of coercing to empty string (fixes #96716) (#97212)
* fix(validation): preserve null in anyOf unions instead of coercing to empty string

Fixes #96716

* fix(validation): preserve null in anyOf unions instead of coercing to empty string

* fix(validation): preserve null in anyOf unions instead of coercing to empty string

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-06-27 08:25:42 -07:00
Gio Della-Libera
4010b81a77 Refactor external plugin catalog toward feeds (#95846)
Merged via squash.

Prepared head SHA: 82d05bdc46
Co-authored-by: giodl73-repo <235387111+giodl73-repo@users.noreply.github.com>
Co-authored-by: giodl73-repo <235387111+giodl73-repo@users.noreply.github.com>
Reviewed-by: @giodl73-repo
2026-06-27 07:41:40 -07:00
xingzhou
8fa24325b5 fix(nostr): bound seen tracker timer options (#97133) 2026-06-27 07:40:36 -07:00
mushuiyu886
f4fa10c2c5 fix(clickclack): bound REST success JSON response reads (#96970)
* fix(clickclack): bound REST success JSON response reads

* test(clickclack): harden response cap proof

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-06-27 07:30:32 -07:00
cornna
2100ee7cc8 fix(telegram): avoid duplicate dm chat window context (#89855)
Co-authored-by: Cornna <96944678+ymylive@users.noreply.github.com>
2026-06-27 07:29:57 -07:00
mushuiyu886
6e8f30c0e2 fix(qqbot): bound STT transcription JSON response (#96968) 2026-06-27 07:25:29 -07:00
ooiuuii
9d800b71c0 fix(scripts): route i18n formatter through pnpm runner (#95534) 2026-06-27 07:13:04 -07:00
mushuiyu886
5ccfc97b31 fix(google): bound TTS success JSON response reads (#96984) 2026-06-27 07:00:36 -07:00
mushuiyu886
a7bfc06f45 fix(google-media): bound JSON response reads (#96920)
* fix(google-media): bound JSON response reads

* test(google): relax media response cap assertion

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-06-27 06:46:58 -07:00
Kevin Lin
c5d34c8376 feat(codex): add always plugin approval mode (#97123)
* feat(codex): add always plugin approval mode

* fix(codex): normalize plugin approval decisions

* fix(codex): fail closed on layered approval overrides
2026-06-27 01:19:00 -07:00