Commit Graph

62540 Commits

Author SHA1 Message Date
黄伟浩
35fcfe85cd fix(plugins): preserve mutable hook context (#97281)
* fix(plugins): preserve mutable hook context

* fix(plugins): satisfy hook context lint
2026-06-28 12:28:30 -07:00
aliahnaf2013-max
f527def0a9 fix(tasks): harden ACP task cancellation (#97352)
* fix(tasks): harden acp task cancellation

* test(gateway): cover acp task cancellation handler
2026-06-28 12:27:49 -07:00
WhatsSkiLL
7ac8b48a08 fix: flush embedded transcript before afterTurn (#97342)
Fixes #97301

Co-authored-by: OpenClaw PR Agent <openclaw-pr-agent@example.invalid>
2026-06-28 12:22:58 -07:00
qingminlong
9f66f61d05 docs: add scripts directory index (#97250) 2026-06-28 12:19:30 -07:00
Yung-Chen Tang
f3bcee8b2e fix: clarify pinned plugin dry-run updates (#97282)
* fix: clarify pinned plugin dry-run updates

* fix(plugins): normalize pinned npm dry-run versions
2026-06-28 12:18:31 -07:00
LiLan0125
a083c76621 fix(bedrock): honor adaptive model max tokens (#97343) 2026-06-28 12:15:02 -07:00
wangmiao0668000666
66ffad1176 fix(azure-openai-responses): bound SSE response reads via buildGuardedModelFetch (#97349)
Inject buildGuardedModelFetch with resolved Azure base URL into both
SDK constructors (OpenAI and AzureOpenAI path) so Azure Responses
requests route through OpenClaw's guarded transport (SSRF policy,
timeout, retry limiting, SSE/JSON synthesis caps).

The non-OK response body cap is applied lazily inside the shared
sanitizeOpenAISdkSseResponse guard via TransformStream — closes the
unbounded response.text() OOM path for hostile 4xx/5xx responses
while preserving the OpenAI SDK's ability to cancel and retry.

- src/llm/providers/azure-openai-responses.ts: pass guardedFetch into
  both OpenAI and AzureOpenAI SDK constructors (no per-provider wrapper)
- src/agents/provider-transport-fetch.ts: add capNonOkResponseBodyLazily
  helper and wire into sanitizeOpenAISdkSseResponse for !response.ok
- src/agents/provider-transport-fetch.test.ts: 2 inline tests
  (cap fires + SDK cancel preserves source)

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-28 12:14:53 -07:00
Masato Hoshino
c026546063 fix(signal): sanitize internal tool-trace lines from outbound text (#97360)
Wrap the signal outbound sanitizeText hook with sanitizeAssistantVisibleText so assistant internal tool-trace scaffolding is stripped before delivery, matching the sibling channel fixes under #90684 (Telegram #95774, Google Chat #95084, IRC #97214).
2026-06-28 12:14:45 -07:00
Masato Hoshino
cd6d0f9b00 fix(slack): sanitize internal tool-trace lines from outbound text (#97367)
Wrap the slack outbound sanitizeText hook with sanitizeAssistantVisibleText so assistant internal tool-trace scaffolding is stripped before delivery, matching the sibling channel fixes under #90684 (Telegram #95774, Google Chat #95084, IRC #97214).
2026-06-28 12:14:35 -07:00
ly-wang19
20645753a4 fix(feishu): truncate streaming-card summary on a code-point boundary (#97462)
truncateSummary used clean.slice(0, max - 3), which can cut between the
two UTF-16 halves of a surrogate pair (emoji / astral char) straddling
the limit. The serialized card summary then carries a lone high
surrogate that Feishu renders as the replacement char.

Slice with the surrogate-safe sliceUtf16Safe helper instead, matching
the pattern already used in extensions/slack/src/truncate.ts, so a
straddling code point is dropped whole.

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-28 12:10:42 -07:00
aditya-vithaldas
3e90125c88 fix: clarify exec tool failure warnings (#97511)
* clarify exec failure warnings

* fix exec failure raw command labels

* preserve node context in exec failure warnings

* fix exec raw context warnings

* fix exec payload test metadata types

* fix raw exec command backtick parsing

* chore: retrigger ci after security-fast outage

---------

Co-authored-by: aditya-vithaldas <13113194+aditya-vithaldas@users.noreply.github.com>
2026-06-28 12:10:33 -07:00
ly-wang19
3e64d84712 fix(qqbot): treat escaped pipes as literal content when splitting table cells (#97429)
splitTableCells/splitPartialTableCells split on every '|', including a GFM
backslash-escaped pipe ('\|'), which is literal cell content rather than a
column delimiter. A cell containing '\|' was therefore mis-counted as multiple
columns, so the oversized-row fallback (renderTableRowAsFields) rendered the
trailing content under the wrong header.

Split via an escape-aware scan that treats '\|' as a literal '|' (and '\\' as
a literal backslash so a following '|' still delimits). Behavior is byte-for-byte
unchanged for any row without an escaped pipe, so existing chunking is preserved.

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-28 12:03:52 -07:00
Omar Shahine
9b9a124cc5 Fix Codex message-tool-only source reply completion (#95942)
* fix(codex): recognize message tool source replies

* fix(codex): accept numeric source message ids

* fix(codex): account for source reply SDK surface

* fix(codex): require delivered reply receipts

* fix(codex): reject alias-routed source replies

* fix(codex): require delivered non-send telemetry

* fix(codex): honor normalized source routes

---------

Co-authored-by: Omar Shahine <10343873+omarshahine@users.noreply.github.com>
2026-06-28 12:02:36 -07:00
ly-wang19
4b36cf451c fix(line): truncate template title/altText on grapheme boundaries, not raw UTF-16 (#97428)
* fix(line): truncate template title/altText on grapheme boundaries, not raw UTF-16

createConfirmTemplate/createButtonTemplate/createTemplateCarousel/createCarouselColumn/
createImageCarousel truncated title and altText with a raw `.slice(0, N)`, so an
emoji straddling a LINE field limit (e.g. a 40-char button title) was cut in half,
leaving a lone high surrogate that LINE renders as the replacement char or rejects.
Route those fields through the file's existing grapheme-safe truncateTemplateText
(already used for the text body) via a small truncateOptionalTemplateText wrapper.
Byte-identical for all-BMP input; only straddling-emoji truncation changes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: retry OpenGrep scan (HTTP 502 infra flake)

* test(line): cover grapheme-safe template fields

---------

Co-authored-by: ly-wang19 <ly-wang19@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-06-28 11:59:59 -07:00
ly-wang19
630034ef62 fix(memory-wiki): keep claim freshness tied to evidence timestamps (#97465)
* fix(memory-wiki): keep claim freshness tied to evidence

* fix(memory-wiki): preserve page freshness fallback only for untimestamped claims

---------

Co-authored-by: ly-wang19 <ly-wang19@users.noreply.github.com>
2026-06-28 11:58:45 -07:00
Masato Hoshino
25490d4c42 fix(matrix): sanitize internal tool-trace lines from outbound text (#97372)
Wrap the matrix outbound sanitizeText hook with sanitizeAssistantVisibleText so assistant internal tool-trace scaffolding is stripped before delivery, matching the sibling channel fixes under #90684 (Telegram #95774, Google Chat #95084, IRC #97214).
2026-06-28 11:58:36 -07:00
qingminlong
5e1f4c1073 fix(memory): stop light dreaming from restaging stale summaries (#97446)
* fix(memory): stop restaging stale light dreams

* fix(memory): preserve cross-day light freshness
2026-06-28 11:58:24 -07:00
ooiuuii
3c826ed5c9 fix: shorten managed npm generation paths (#97488) 2026-06-28 11:58:16 -07:00
NIO
245c18da5a fix(agents): retry compaction on provider-side AbortErrors (#97504)
Align inner compaction retry and compaction-safeguard provider fallback
with the #90908 signal.aborted pattern so undici disconnect AbortErrors
retry or fall back to LLM instead of producing degraded placeholder
summaries. Caller abort remains terminal.

Co-authored-by: NIO <nocodet@mail.com>
2026-06-28 11:55:25 -07:00
xingzhou
fb7e10e868 fix(auth): recover from malformed API-key profiles (#97520)
* fix: reject malformed API-key auth profiles

* fix(auth): detect onboard command API-key variants

* fix(auth): reject malformed API-key flags
2026-06-28 11:54:24 -07:00
NIO
4c477ee632 fix(openai): bound embedding-batch and realtime session JSON response reads (#97533) 2026-06-28 11:53:50 -07:00
wangmiao0668000666
bd0c052aa5 fix(oauth): bound github-copilot OAuth response reads at 16 MiB (#97499)
* fix(oauth): bound github-copilot OAuth response reads at 16 MiB

* chore: trigger CI re-run after PR body update
2026-06-28 11:53:46 -07:00
Yung-Chen Tang
fcff01cc82 fix: archive role-ordering reset transcripts (#97544)
* fix: archive role-ordering reset transcripts

* test: fix session reset archive lint
2026-06-28 11:46:54 -07:00
NIO
51064bda4d fix(signal): bound GitHub release info JSON response with readProviderJsonResponse (#97536)
Replace bare `await response.json()` in `installSignalCliFromRelease` with
`readProviderJsonResponse` (16 MiB cap, stream cancel on overflow). The
external GitHub Releases endpoint can include a large `body` changelog field;
the error path was already guarded but the success path was unbounded.
The existing inner catch continues to convert overflow errors into the
graceful `{ ok: false, error: "Failed to parse signal-cli release info." }` path.

Adds a regression test verifying the stream is cancelled before all chunks are
read on an oversized 20 MiB streaming response.

Co-authored-by: NIO <nocodet@mail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-28 11:46:25 -07:00
liuhao1024
ee72fa7f5f fix(auth): skip legacy OAuth repair when destination profile already exists (#97541)
When doctor --fix runs legacy OAuth profile id repair, it picks the
single non-legacy OAuth profile as the migration target. If that target
profile already exists as a separate user-configured account, the repair
unconditionally overwrites it, destroying the account's config
(displayName, email) and collapsing two distinct accounts into one.

Add a guard: if the destination profile id already exists in
cfg.auth.profiles, skip the repair entirely to preserve both accounts.
Also pass cfg to resolveAuthProfileMetadata so config-set displayName
is preserved when the repair does proceed.

Fixes #97522
2026-06-28 11:46:20 -07:00
Jimmy Puckett
71347ef999 fix(msteams): handle message card submit values (#97546) 2026-06-28 11:46:16 -07:00
ly-wang19
eff68d2c77 fix(line): truncate action fields on code-point boundaries
Use surrogate-safe truncation for LINE action labels/data, including card-command, markdown link, quick-reply, and media-control action surfaces, with focused regression coverage.
2026-06-28 11:37:51 -07:00
Lu Wang
168299fc7d fix(telegram): tell models to use <tg-math> for rich-text formulas (#97197)
* fix(telegram): tell models to use <tg-math> for rich-text formulas

The Telegram rich-text capability hint advertised 'formulas' without
specifying syntax. Models (especially fallback models) default to
$...$ or \(...\) LaTeX delimiters, which Telegram Bot API 10.1 rich
messages do not render as math, so formulas appear as literal text.

Telegram Bot API 10.1 renders formulas only via <tg-math> (inline) and
<tg-math-block> (block) tags with raw LaTeX inside. Spell that out in the
hint, matching the existing HTML-tag style used for <sup>/<mark>/<details>.

* test(telegram): assert math rich-text prompt hint

---------

Co-authored-by: wangwllu <wangwllu@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-06-28 11:33:38 -07:00
ly-wang19
881ec2f93f fix(mattermost): truncate draft previews on code-point boundaries (#97472)
Summary:
- The PR replaces Mattermost draft preview raw UTF-16 slicing with the existing SDK `sliceUtf16Safe` helper and adds a regression test for an emoji that straddles the preview limit.
- PR surface: Source +1, Tests +26. Total +27 across 2 files.
- Reproducibility: yes. Source inspection shows current main raw-slices at `maxChars - 3`; driving `createMatt ...  at UTF-16 indices 8-9 reaches the lone-surrogate path, though I did not run tests in this read-only sweep.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(mattermost): truncate draft previews on code-point boundaries

Validation:
- ClawSweeper review passed for head 86d0dd2a06.
- Required merge gates passed before the squash merge.

Prepared head SHA: 86d0dd2a06
Review: https://github.com/openclaw/openclaw/pull/97472#issuecomment-4825788514

Co-authored-by: ly-wang19 <ly-wang19@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
2026-06-28 18:20:33 +00:00
pick-cat
e5205a4cef fix(gateway): scope tools.effective global agent lookup
Pass the requested agent into tools.effective global-session loading while preserving non-global session ownership guards, with handler and gateway regression coverage.
2026-06-28 11:20:03 -07:00
mushuiyu886
45f261ff7a fix(memory-wiki): truncate import insights safely
Use the shared UTF-16 safe truncation helper for Memory Wiki import insight summaries and add regression coverage for surrogate-boundary summaries.
2026-06-28 11:19:55 -07:00
Alix-007
48f34b1d4d fix(openrouter): bound video response reads
Route OpenRouter video submit and poll success JSON through the shared bounded provider JSON reader, preserving malformed-response mapping and SSRF request policy coverage.
2026-06-28 11:19:47 -07:00
Vincent Koc
b70d1aae57 ci(docker): publish releases to Docker Hub (#97122)
* ci(docker): publish releases to Docker Hub

* ci(docker): clarify beta image tags
2026-06-28 11:15:34 -07:00
吴杨帆
f9dddea72a fix(gateway): expose idempotencyKey in chat history metadata (#96273)
* fix(gateway): surface idempotency key in history metadata

* test(gateway): avoid unsafe optional chain

* fix(gateway): preserve oversized transcript idempotency keys

* fix(gateway): preserve oversized idempotency keys

* fix(gateway): reuse transcript json helpers

---------

Co-authored-by: 吴杨帆 <39647285+leno23@users.noreply.github.com>
2026-06-28 11:07:51 -07:00
ly-wang19
ad8e7dcfe2 fix(agents): truncate console text on code-point boundaries (#96296)
sanitizeForConsole filtered control characters code-point-aware but then
truncated with sanitized.slice(0, maxChars), which cuts on UTF-16 code units.
When the cap landed between the two code units of an astral character (emoji,
CJK extension, etc.) the output ended in a lone high surrogate before the
ellipsis. Cap on code points instead.

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-28 11:07:37 -07:00
ly-wang19
55d7b5b36c fix(matrix): truncate reply context on code-point boundaries (#97471)
truncateReplyBody used a raw value.slice(0, MAX_REPLY_BODY_LENGTH - 3)
to shorten long reply bodies. When the cut index fell between the two
UTF-16 code units of a surrogate pair (e.g. an emoji), the slice left a
lone high surrogate before the ellipsis, which renders as a broken glyph
in the reply context shown to the agent.

Replace the raw slice with sliceUtf16Safe from the plugin SDK so the
truncation never cuts inside a surrogate pair. A normal (non-astral)
body is unaffected.

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-28 11:06:36 -07:00
zengLingbiao
e445d614c0 fix(shared): use UTF-16 safe truncation in assistant error formatting (#97289)
* fix(shared): truncate assistant error text on UTF-16 boundary

Use truncateUtf16Safe from the existing utf16-slice utility instead of
String.prototype.slice(0, 600), which can split a surrogate pair and
produce malformed Unicode when the error message contains characters
outside the Basic Multilingual Plane (emoji, rare CJK, etc.).

* test(shared): add regression test for UTF-16 safe error truncation

Verify formatRawAssistantErrorForUi does not produce dangling surrogates
when truncating a fallback raw error message with a non-BMP character
(emoji) straddling the 600-code-unit boundary.

* fix(agents): truncate assistant error text fallback on UTF-16 boundary

Use truncateUtf16Safe instead of String.prototype.slice(0,600) in
formatAssistantErrorText and its companion comparison in
isRawAssistantErrorPassthrough, preventing dangling surrogates when
non-BMP characters straddle the 600-code-unit truncation boundary.
2026-06-28 11:06:20 -07:00
Naseem Muhammad
9ff8510f52 fix path to Discord Developer Mode in setup guide (#97336) 2026-06-28 11:03:25 -07:00
Tirion Prole
928aa3ea7e [codex] Update Claude CLI billing docs (#96848)
* Update Claude CLI billing docs

* Sync Claude live testing billing note
2026-06-28 11:03:17 -07:00
qingminlong
a10add7531 fix(models): mark local Ollama rows available (#97491)
* fix(models): mark local Ollama rows available

* fix(models): mark local Ollama rows available

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-06-28 10:53:15 -07:00
Andy Ye
b580258e94 fix(heartbeat): suppress stream-error placeholders (#97364) 2026-06-28 10:48:21 -07:00
wendy
6ce88ca51d fix(irc): prevent ghost nick collisions on rejoin after network delay (#96108)
* fix(irc): prevent ghost nick collisions on rejoin after network delay

* test(irc): add regression tests for fallback nick uniqueness

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: wendy-chsy <wan.wenyan@xydigit.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-28 10:47:39 -07:00
frond scribe 🌿
dd4e2abfb5 fix: use no-output placeholder for empty OpenAI tool results (#97423)
Co-authored-by: scribe-dandelion-cult <scribe-dandelion-cult@hotmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-28 10:47:31 -07:00
miorbnli
feba78fc8f fix(sessions): fail fast on non-serializable JSONL root values (#97356)
serializeJsonlLine returned JSON.stringify(entry) without guarding the
undefined return case. When the root value is undefined, a function, or a
symbol, JSON.stringify returns undefined, which serializeJsonlEntry's template
literal coerced to the literal string "undefined" and wrote to disk. That is
not valid JSON, so parseJsonlEntries silently skipped the line — a fail-silent
loss of a transcript entry with no error log.

Throw a TypeError instead so the caller fixes the bad value before it reaches
the file. Circular references and BigInt already throw via JSON.stringify and
are unaffected. Null, primitives, and plain objects are unchanged.

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-28 10:47:24 -07:00
Ben.Li
a5379472f7 feat(onboard): show setup timeline note (#97482)
* feat(onboard): show setup timeline note

* test(agents): stabilize retained lock CI flakes
2026-06-28 10:47:11 -07:00
wangmiao0668000666
2e5e5e5af9 fix(media-understanding): append actionable install hint when media provider is missing (#97484)
Gates the install hint on the official external provider catalog's
`mediaUnderstandingProviders` contract so only true media-provider
packages (e.g. groq) emit the actionable hint; channel-only ids (e.g.
feishu) and providers without a media-understanding contract (e.g.
amazon-bedrock) fall back to the legacy bare error message verbatim.

Also tightens the gateway recovery wording from generic 'restart the
gateway' to 'stop and start the gateway service' per the canonical
issue reporter's actual recovery flow (full systemd stop/start, not
hot-reload).

Co-authored-by: wangmiao0668000666 <wangmiao0668000666@users.noreply.github.com>
2026-06-28 10:45:44 -07:00
ly-wang19
4a0cd56139 fix(ui): roll formatTokens over to "M" instead of rendering "1000k" (#96298)
* fix(ui): roll formatTokens over to "M" instead of rendering "1000k"

formatTokens picks the kilo branch on the raw value (< 1_000_000), then renders
Math.round(tokens/1000). For 999_500..999_999 that rounds to 1000, producing the
nonsensical "1000k" instead of rolling over to the M branch. Re-check the rounded
kilo value and fall through to "M" when it reaches 1000, matching the sibling
formatCompactTokenCount.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* ci: retry — server-startup-session-migration timeout is main-branch flake, unrelated to formatTokens

---------

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-28 10:45:12 -07:00
Masato Hoshino
949b1af433 fix(status): distinguish runtime-loaded plugins from installed inventory (#97479)
* fix(status): distinguish runtime-loaded plugins from installed inventory

/status plugins merged disk-scan plugin records with the active runtime
registry, so the detailed Loaded: list could include plugins that were
installed/config-enabled but never loaded at runtime. Record the runtime-
loaded plugin ids on the health snapshot, carry them through the merge, and
make Loaded: reflect runtime-confirmed plugins; show installed/discovered
plugins that are not active as a neutral "Installed (not active)" inventory
line rather than an error.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(status): include pinned runtime registries in loaded ids

Build runtimeLoadedPluginIds from all live runtime registry surfaces via
collectLivePluginRegistries() (active plus any pinned channel / http-route /
session-extension registry) and render Loaded: from that id set directly, so a
plugin live only through a pinned surface still counts as loaded instead of
being dropped or misreported as "Installed (not active)".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 10:44:56 -07:00
NIO
c0883a531d fix(openrouter): bound generation-cost JSON response reads (#97490) 2026-06-28 10:44:36 -07:00
NIO
0d59280131 fix(deepinfra): bound video generation JSON response reads (#97486) 2026-06-28 10:44:28 -07:00