Commit Graph

14930 Commits

Author SHA1 Message Date
Peter Steinberger
037ad2bdfb feat(telegram): offer BotFather web app flow in setup help and docs (#100540) 2026-07-06 07:48:55 +01:00
Peter Steinberger
2830b3ef38 fix(browser): diagnose empty WSL2 Chrome replies (#100590)
* fix(browser): diagnose Windows CDP listener mismatch

Base the repair on #93481 while matching Chromium's IPv4-first, IPv6-fallback listener contract and keeping CDP exposure loopback-scoped.

Co-authored-by: ZengWen-DT <ceng.wen@xydigit.com>

* style(docs): format browser troubleshooting table

* docs: refresh browser troubleshooting map

* fix(browser): diagnose reset CDP replies

* docs: refresh browser troubleshooting map

---------

Co-authored-by: ZengWen-DT <ceng.wen@xydigit.com>
2026-07-06 07:42:02 +01:00
Wynne668
6378d5efcc fix(feishu): strip internal tool-trace banners from outbound text (#98705)
Part of #90684

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-06 06:33:16 +00:00
solodmd
1ec42c9acc fix(voyage): close response body stream when batch output JSONL parsing throws (#98840)
The batch output file download path creates a readline interface over a
Readable.fromWeb() response body stream. If JSON.parse throws on a malformed
JSONL line, the for-await loop exits via exception but the readline interface
and underlying Readable stream were never explicitly closed or destroyed,
leaving the HTTP response body stream dangling.

Extract the stream reading into , a testable helper
that wraps the iteration in a try-finally so both reader.close() and
inputStream.destroy() are always called, matching the pattern established in
#98493 for the same class of leak.
2026-07-06 06:32:50 +00:00
Peter Steinberger
20e6983bed fix(gateway): avoid default provider auth startup prewarm (#100667)
* fix(gateway): avoid default provider auth startup prewarm

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>

* docs(changelog): credit provider auth startup fix

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-06 07:32:13 +01:00
xingzhou
a13acacd3c fix(discord): keep command previews emoji-safe (#99539) 2026-07-06 05:40:39 +00:00
Marvinthebored
cbcd6a102c fix(clickclack): reply to a top-level message in-channel, not as a new thread (#100582)
* fix(clickclack): reply to a top-level message in-channel, not as a new thread

sendClickClackText routed any replyToId to createThreadReply, and the inbound
handler stamps replyToId = <triggering message id> on every reply. As a result
every reply to a top-level channel message opened its own thread, so the main
channel timeline showed nothing and the chat was effectively unusable.

Route a bare replyToId to the main channel as a quote-reply (quoted_message_id)
instead — matching the reply-to affordance of the Discord/Slack/Telegram
channels — and reserve threads for genuine thread context (an explicit threadId
or a thread-kind target). DM replies likewise quote-reply in the same
conversation. quoted_message_id is omitted when there is no reply context, so
plain sends are unchanged.

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

* test(clickclack): cover quote payload typing

---------

Co-authored-by: Marvinthebored <marvinthebored@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-05 22:27:27 -07:00
Sulaga
2b51c255f8 feat(tencent): add Tencent Hy3 provider (TokenHub and TokenPlan) (#99076)
Summary:
- Merged feat(tencent): add Tencent Hy3 provider (TokenHub and TokenPlan) after ClawSweeper review.

Automerge notes:
- Ran the ClawSweeper repair loop before final review.
- Included post-review commit in the final squash: fix(tencent): preserve TokenHub auth compatibility
- Included post-review commit in the final squash: refactor(tencent): unify TokenPlan env/flag naming with TokenHub
- Included post-review commit in the final squash: docs: refresh Tencent provider docs metadata
- Included post-review commit in the final squash: fix: allow TokenPlan provider config overlays
- Included post-review commit in the final squash: docs: dedupe Tencent provider glossary labels
- Included post-review commit in the final squash: fix(tencent): repair TokenHub model defaults

Validation:
- ClawSweeper review passed for head 30c9fc130f.
- Required merge gates passed before the squash merge.

Prepared head SHA: 30c9fc130f
Review: https://github.com/openclaw/openclaw/pull/99076#issuecomment-4888527271

Co-authored-by: leisang <leisang@tencent.com>
Co-authored-by: Mason Huang <masonxhuang@tencent.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: hxy91819
2026-07-06 04:29:48 +00:00
Peter Steinberger
0acd851a3b feat(agents): add managed git worktree lifecycle (create/provision/snapshot/restore/GC) (#100535)
Centralized managed worktrees under <state-dir>/worktrees/<repo-fingerprint>/<name>
with branch-per-task (openclaw/<name>), .worktreeinclude provisioning, an optional
.openclaw/worktree-setup.sh repo hook, and a SQLite registry in the shared state DB.
Removal always snapshots the tree (untracked included, gitignored excluded) to
refs/openclaw/snapshots/<id>; restore rebuilds the branch at the original commit with
the snapshot content as uncommitted state. Lossless run-end cleanup, 7-day idle GC for
run-owned worktrees (manual exempt), orphan reconciliation, 30-day snapshot retention.
Surfaces: worktrees.* gateway RPC (operator.admin mutations), openclaw worktrees CLI,
Control UI page, plugin-SDK facade + Workboard kind:"worktree" materialization.

E2E-verified on Testbox: full create->work->remove->restore->gc lifecycle.
2026-07-06 05:24:58 +01:00
sunlit-deng
b7e5465f77 fix(signal): bound receive websocket payloads (#99992)
* fix(signal): bound receive websocket payloads

* docs(signal): explain receive frame cap

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 05:10:57 +01:00
Peter Steinberger
f53103de72 fix(skills): make Skill Workshop lifecycle approvals decidable and non-wedging (#91266, #94249, #93173) (#100498)
Approval wait now fits inside the Codex dynamic-tool watchdog (70s +10s
gateway grace under the 90s kill), approval cards carry proposal id,
skill name, description, file count, and body size (spoof-safe
rendering), and timeouts return a structured pending-not-failed outcome
instead of a bare error. Expired requests cannot execute late; no
auto-apply; generic plugin approvals unchanged.
2026-07-06 04:54:48 +01:00
Peter Steinberger
07e2d633cc feat: show auto-detected provider plans and billing (#100520)
* feat(providers): auto-discover usage billing

* feat(ui): show provider plans and billing

* fix(ui): translate provider billing labels
2026-07-06 04:53:09 +01:00
NIO
a4261cac4d fix(tlon): bound external image upload reads (#100374)
* fix(tlon): bound external image upload reads

* fix(tlon): make upload Blob construction type-clean

* test(tlon): trim upload fixture result

* docs(changelog): note Tlon upload bounds

---------

Co-authored-by: NIO <nocodet@mail.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 04:44:33 +01:00
sunlit-deng
ae53570ea8 fix(browser): notify agent when click triggers download (#93307)
* fix(browser): drain download saves and use monotonic cursor for act response

- Add drainPendingDownloadSaves() to wait for in-flight saveAs before sampling
- Use monotonic downloadSeq cursor instead of bounded-list length
- Propagate downloads info in POST /act response for click/batch/evaluate

Fixes #93250

* fix(lint): add braces around single-line if returns

Fixes eslint(curly) failures in drainPendingDownloadSaves and
pickNewDownloads. PR #93307 required CI gate.

Ref: ClawSweeper P1 review finding

* fix(browser): scope act download metadata to action

* fix(browser): broadcast downloads to all active captures to prevent misattribution

When concurrent /act calls overlap on the same page, using
state.actionDownloadCaptures.at(-1) assigned downloads to the wrong
action's capture. Push managed save promises to all active captures
so the triggering action always receives its download metadata.

Also adds regression tests: broadcast-to-all-captures, sequential
capture isolation, and strengthen the dispose test to assert no
re-capture after disposal.

* fix(browser): prevent unhandled rejection when download capture action throws before drain

Move managedSave.catch() before the captures-branch check so the
rejection handler always runs, preventing an unhandled promise
rejection when the action throws before drain() is called. Simplify
the handler by removing the now-dead return + catch at the bottom.

* fix(browser): type downloads in BrowserActResponse, fix lint unused var

- Add optional downloads field to BrowserActResponse type contract so
  typed callers of browserAct() can consume the new payload without casts.
- Remove unused afterDispose variable in pw-session tests (lint fix).

* fix(test): correct post-dispose download assertion

capture.promises is not cleared by dispose(), so re-draining a disposed
capture still returns pre-dispose results. This is benign — callers
should drain before disposing. Update the test to assert the actual
behavior (still shows old results, new download not captured).

* test(browser): cover /act download metadata response

* refactor(browser): report action-owned downloads safely

* fix(browser): close action download ownership races

* test(browser): type action download capture mock

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 04:07:16 +01:00
Gorkem Erdogan
39916560e4 improve(auto-reply): render chat history since last reply as per-message prose (#100366)
* fix(auto-reply): render chat history since last reply as per-message prose

The inbound chat-history block dumped batched history as a raw JSON array, which models read poorly compared to the chat-window block's per-message prose. Reuse the existing formatChatWindowMessage renderer for history entries so both blocks share one shape, keep the untrusted framing label, and keep media rendered as a bare content-type tag so local paths and URLs stay redacted. Teach the metadata stripper to consume the new prose block form.

* fix(auto-reply): preserve every media content type in chat-history prose

The prose chat-history renderer only forwarded the first attachment's
content type per history message, dropping the rest for entries with
multiple media items. Join all bounded content types instead, and
regenerate the prompt snapshot fixture this changes.

* test(qa-lab): accept prose pending history

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 03:59:29 +01:00
Peter Steinberger
443c582949 fix(ios): restore in-flight runs after reconnect (#100277)
* fix(ios): restore in-flight chat runs from gateway history

Restore active Apple chat ownership across reconnect, foreground, and sequence-gap recovery using the existing chat.history snapshot. Preserve agent/session scoping and Gateway user-turn identity across Codex and Copilot mirrors, including current offline-cache integration.

* fix(ios): restore in-flight chat runs from gateway history
2026-07-06 03:23:38 +01:00
NIO
19f5a4a0bb fix(tlon): bound urbit scry JSON response reads (#100376)
* fix(tlon): bound urbit scry JSON response reads

* fix(tlon): preserve bounded scry diagnostics

* refactor(tlon): tighten scry boundary proof

* docs(changelog): stabilize Tlon response entry

* docs(changelog): close out maintainer batch

* chore(changelog): defer batch closeout

---------

Co-authored-by: NIO <nocodet@mail.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 03:22:59 +01:00
Andy Ye
9d9661e473 fix(ollama): fall back when native streams end early (#100482)
* Classify Ollama incomplete stream errors for fallback

* fix(ollama): own incomplete-stream failover classification

* test(ollama): pin incomplete-stream error contract

* docs(changelog): note Ollama fallback routing

Co-authored-by: Andy Ye <35905412+TurboTheTurtle@users.noreply.github.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 03:12:49 +01:00
clawSean
d84aabf642 feat: add channel pairing request hook (#97733)
* feat: add channel pairing request hook

* fix(plugin-sdk): keep pairing hook types internal

* docs: regenerate docs map

* docs: regenerate docs map

* docs: regenerate docs map

* fix(plugin-sdk): keep pairing hook types internal

* fix(plugin-sdk): keep pairing hook types internal

* docs: refresh plugin hook docs

* docs: refresh plugin hook docs

* docs: refresh plugin hook docs

---------

Co-authored-by: clawSean <260045960+clawSean@users.noreply.github.com>
Co-authored-by: Omar Shahine <omarshahine@users.noreply.github.com>
2026-07-05 19:11:58 -07:00
Moeed Ahmed
0e0f0b16cd fix(telegram): show typing for accepted topic messages (#99965)
Co-authored-by: Moeed Ahmed <5780040+moeedahmed@users.noreply.github.com>
2026-07-05 18:36:49 -07:00
Peter Lee
7cabd19268 fix(voice-call): deliver early TTS via onEarlyText before compaction wait (#94015)
* fix(voice-call): speak before post-turn compaction

Co-authored-by: xialonglee <li.xialong@xydigit.com>

* fix(voice-call): satisfy flush callback contracts

* test(agents): assert block reply message context

* fix(voice-call): preserve deferred answer boundaries

* fix(voice-call): type tool boundary message index

* test(voice-call): initialize tool boundary index

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 02:34:22 +01:00
xingzhou
7a49b160a4 fix(browser): downloads complete over CDP connections (#89416)
* fix(browser): surface navigate downloads in CDP mode

* Validate navigation downloads before saving

* fix(browser): observe navigation download capture timeouts

* refactor(browser): unify managed download capture

* test(browser): satisfy download fixture lint

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 02:26:20 +01:00
xingzhou
a77ea59ce7 fix(bedrock): bound Mantle model discovery fetches (#99961)
* fix(bedrock): bound Mantle model discovery fetches

* fix(bedrock): release rejected Mantle responses

* docs(changelog): position Bedrock Mantle fix

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 02:21:00 +01:00
morluto
f1a374a73a fix(channels): normalize phone identities with stray plus signs (#100467)
* fix(channels): canonicalize phone identity digits

* test(channels): cover phone identity normalization

* test(whatsapp): use shared phone normalizer

* fix(channels): reject invalid normalized phone identities

* fix(signal): preserve strict account input validation

* fix(signal): preserve prefixed allowlist input

* docs(changelog): stabilize phone identity entry

* chore(changelog): defer phone identity entry

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 02:19:11 +01:00
Peter Steinberger
a6e19fe014 fix(slack): avoid repeated thread root media (#100516)
* fix(slack): avoid repeated thread root media

* test(slack): cover reset thread media seeding
2026-07-06 02:17:44 +01:00
pick-cat
ca4e8a7dc8 fix(skills): apply command description limits per channel (#99593)
* fix(skills): keep command spec descriptions UTF-16 safe at the truncation cut

* chore: fix oxlint no-unnecessary-type-assertion in test

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

* chore: fix Skill type completeness in test fixture

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

* fix(skills): prove UTF-16-safe command truncation

* fix(skills): apply description limits per channel

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 18:12:51 -07:00
Andy Ye
d9289a19e1 fix(browser): persist managed Chrome cookies across restarts (#98284)
* fix(browser): preserve managed Chrome cookies

* fix(browser): guard graceful close process ownership

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 01:32:13 +01:00
scoootscooob
7e7fc0075e [codex] Honor all ack scope for room events (#87433)
* fix(discord): honor all ack scope for room events

* fix(channels): align all ack scope for room events

* fix(channels): centralize ambient ack scope

* test(telegram): restore room-event ack fixture

* test(discord): satisfy promise executor lint

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 01:28:41 +01:00
Hemant Sudarshan
bacd1c512a fix(browser): time out remote tab enumeration (#80147)
* fix(browser): time out remote tab enumeration

* chore: remove stale changelog entry

* fix(browser): isolate timed-out read cleanup

* fix(browser): isolate timed-out read cleanup

* test(browser): satisfy connection regression lint

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 00:56:05 +01:00
Peter Steinberger
2ded26a5d6 fix(diffs): share SSR preloads and repair language-pack hydration (#100487)
* fix(diffs): share SSR preloads and repair language-pack hydration

Render viewer and file documents from a single @pierre/diffs SSR preload
per file (mode=both previously ran the full diff+highlight pipeline
twice; 651ms -> 303ms on an 8-file patch), apply the file-mode font bump
as a document-level override, and keep hydration payloads
variant-faithful.

Fix the language-pack runtime downgrading pack-only languages to plain
text at hydration by defining a per-target build flag and forwarding it
to payload normalization.

Also: case-insensitive language hints, identical before/after
short-circuit with details.changed, patch input failures classified as
tool input errors, canonical config values now win over deprecated
aliases, hash-pinned viewer runtime served immutable, truthful
browser-vs-render errors, timing-safe artifact token compare, unref
idle browser timer.

* docs(changelog): link diffs rendering entry to PR

* test(diffs): narrow manifest validation results before value access

* test(tooling): allowlist diffs viewer-client define suppression
2026-07-06 00:34:17 +01:00
Gorkem Erdogan
e7c0673fc5 fix(slack): react action rejects emoji glyphs; member-info userId affordance unclear (#100375)
* fix(slack): normalize react emoji glyphs and clarify member-info userId param

Slack's reactions.add/remove only accept shortcode names, never a raw
Unicode glyph, but the react action's emoji param had no description
steering models away from passing one, so calls like
emoji="" failed with invalid_name. Consolidates the glyph-to-shortcode
map that already existed privately in the ack-reaction dispatch path into
the shared normalizeSlackEmojiName export in actions.ts, the layer that
owns the actual Slack API calls, so the message-tool react action gets the
same normalization.

Also tightens the generic userId param description so models stop trying
target on member-info, which has no target mode and requires userId
directly.

* fix(slack): preserve emoji reaction semantics

* fix(slack): default reactions to inbound message

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 00:15:32 +01:00
sunlit-deng
2525ea41fd fix(openai): bound realtime voice websocket payload at 16 MiB (#99450)
* fix(openai): bound realtime voice websocket payload at 16 MiB

* test(openai): cover realtime voice payload cap

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 00:12:27 +01:00
Peter Steinberger
aaf5ab910c fix: land ten small reliability fixes (#100483)
* fix(agents): harden LSP process failures

Source: #100450

Co-authored-by: morluto <williamlin1327@gmail.com>

* fix(sandbox): report effective workspace layout

Sources: #100435, #100439

Co-authored-by: Aniruddha Adak <aniruddhaadak80@users.noreply.github.com>

Co-authored-by: ZengWen-DT <ceng.wen@xydigit.com>

* fix(security): fail install checks on stream errors

Source: #100413

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* fix(android): normalize all-day calendar events

Source: #100032

Co-authored-by: NianJiuZst <180004567+NianJiuZst@users.noreply.github.com>

* fix(ios): serialize push-to-talk lifecycle

Source: #99942

Co-authored-by: NianJiuZst <180004567+NianJiuZst@users.noreply.github.com>

* fix(talk): reject inherited provider names

Source: #99849

Co-authored-by: zenglingbiao <zeng.lingbiao@xydigit.com>

* fix(android): stop voice capture in background

Source: #99840

Co-authored-by: xialonglee <li.xialong@xydigit.com>

* fix(cron): preserve fallback result classification

Source: #99913

Co-authored-by: jincheng-xydt <xu.jincheng@xydigit.com>

* fix(google): bound Vertex response decompression

Source: #99812

Co-authored-by: 黄剑雄0668001315 <huang.jianxiong@xydigit.com>

* fix(plugins): report malformed discovery JSON

Source: #99892

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* test(sandbox): configure non-default workspace fixture

* test: fix small-fix batch validation

---------

Co-authored-by: morluto <williamlin1327@gmail.com>
Co-authored-by: ZengWen-DT <ceng.wen@xydigit.com>
Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>
Co-authored-by: NianJiuZst <180004567+NianJiuZst@users.noreply.github.com>
Co-authored-by: zenglingbiao <zeng.lingbiao@xydigit.com>
Co-authored-by: xialonglee <li.xialong@xydigit.com>
Co-authored-by: jincheng-xydt <xu.jincheng@xydigit.com>
Co-authored-by: 黄剑雄0668001315 <huang.jianxiong@xydigit.com>
2026-07-06 00:08:51 +01:00
Vincent Koc
7dfc499299 fix(agents): trim media tools in lean mode (#88881)
* fix(agents): trim media tools in lean mode

* fix(agents): preserve lean tool allowlists

* fix(agents): preserve lean tool overrides

* fix(agents): enforce lean policy at harness boundary

* fix(agents): preserve lean override provenance

* test(agents): satisfy lean harness contracts

* docs(changelog): record lean local-model tool trimming

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 00:06:06 +01:00
Vincent Koc
17ba497424 fix(codex): ignore missing mirrored session history (#100484)
* fix(codex): ignore missing mirrored session history

* test(codex): prove missing mirrored history stays quiet

* fix(codex): narrow missing history proof

---------

Co-authored-by: Alex Tang <alextangli@outlook.com>
2026-07-05 16:04:34 -07:00
Peter Steinberger
4da855a1ff fix(slack): prefer native status by default (#100462)
Co-authored-by: Peter Steinberger <steipete@openai.com>
2026-07-05 23:10:08 +01:00
Wei Songqu
46d8e96503 fix(discord): isolate voice connections and close auto-join race (#87530)
* fix(discord): isolate voice connections by account

Co-authored-by: geekhuashan <geekhuashan@gmail.com>

* chore: defer Discord voice accounts changelog

* fix(discord): own auto-join cleanup in lifecycle

* test(discord): bind lifecycle voice mocks

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 23:09:57 +01:00
Omar Shahine
91f5a65df9 fix(imessage): plain-send fallback for threaded replies + db-scoped recovery cursor (#99638) (#100446)
* fix(imessage): retry unthreaded when a threaded reply is unsupported (#99638)

* fix(imessage): scope downtime-recovery cursor to the watched database (#99638)

---------

Co-authored-by: Omar Shahine <10343873+omarshahine@users.noreply.github.com>
2026-07-05 14:58:38 -07:00
Kevin Lin
5fdaa04eca feat(qa-lab): add Codex Slack approval scenarios (#91519)
* feat(qa-lab): add codex slack approval scenarios

* fix(qa-lab): harden Codex Slack approval proof

* fix(qa-lab): validate Codex approval model

* test(qa-lab): verify approved Codex operation

* fix(qa-lab): normalize Slack QA account routing

* fix(qa-lab): read Codex tool result transcripts

* fix(qa-lab): harden Codex approval cleanup

* fix(qa-lab): support Codex Mantis checkpoints

* fix(qa-lab): repair Mantis pnpm bootstrap

* fix(qa-lab): normalize Codex tool result text

* fix(qa-lab): scope Mantis pnpm fallback

* fix(qa-lab): bootstrap pinned pnpm without npm

* fix(qa-lab): terminate pnpm metadata record

* fix(qa-lab): bootstrap official node for mantis

* fix(qa-lab): make mantis pnpm shim executable

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 22:47:18 +01:00
Vincent Koc
8ec5e06cbf fix(realtime): filter malformed provider tool names (#89175)
* fix(realtime): filter malformed provider tool names

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>

* chore: defer realtime tools changelog

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 22:25:24 +01:00
Yuval Dinodia
89881b6611 fix(irc): long non-ASCII messages are silently truncated at the 512-byte line limit (#99138)
* fix(irc): chunk PRIVMSG by UTF-8 byte budget so long non-ASCII messages are not truncated

IRC caps a full protocol line at 512 bytes, but sendPrivmsg split outbound
text by UTF-16 code units against the 350 char default. Multi-byte text such
as CJK or emoji produced lines far beyond 512 bytes and servers silently
dropped the tail of every oversized chunk. The chunker now also enforces a
UTF-8 byte budget derived from the line framing overhead, splitting on code
point boundaries and preferring spaces, while ASCII chunking is unchanged.

* test(irc): move loopback IRC server helper to shared test helpers

The colocated node:net import tripped the network-runtime-boundary PR diff
scan for extensions/irc/src. The loopback server now lives in test/helpers,
outside the scanned network runtime paths, and the CJK, emoji, and ASCII
chunking cases keep driving the real client over a real TCP socket.

* fix(irc): decouple byte budget from character cap and move loopback helper to irc test-support

The byte budget is now derived only from the 512-byte line limit and framing
overhead, independent of messageChunkMaxChars, so low character caps with
multibyte text keep advancing instead of dropping the message. The loopback
IRC server helper moves from test/helpers to the extension-local package-root
test-support surface so extension tests stay off repo helper bridges and raw
socket use stays outside extensions/irc/src.

* fix(irc): enforce UTF-8 wire limits

* test(irc): satisfy loopback harness lint

* test(irc): avoid implicit Promise return

* test(irc): handle loopback close errors

* fix(irc): preserve boundary word splitting

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 22:10:59 +01:00
asock
20163ee182 [codex] fix discord missing voice state handling (#90969)
* fix(discord): treat missing voice state as absent

* fix(discord): narrow absent voice state handling

* chore: defer Discord voice changelog

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 22:10:46 +01:00
frank-beans
664464c750 Preserve provider settings during onboarding updates (#100107)
* Preserve provider settings during onboarding updates

* fix(onboarding): clear omitted request auth

* fix(onboarding): retain canonical provider keys

* fix(onboarding): canonicalize provider updates

* fix(minimax): preserve models across provider aliases

* fix(minimax): preserve secret references during onboarding

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 21:49:58 +01:00
Peter Steinberger
5e0504aa43 feat(ui): simplify Talk settings (#100453)
Co-authored-by: Peter Steinberger <steipete@openai.com>
2026-07-05 21:31:52 +01:00
Gio Della-Libera
85ad4cb200 fix(voice-call): avoid OpenAI realtime double greeting (#86285)
* fix(voice-call): avoid OpenAI realtime double greeting

* fix(voice-call): keep openai greeting proactive

* fix(openai): preserve deferred realtime instructions

* fix(openai): preserve instructions across response retry

* fix(openai): clear stale deferred response instructions

* fix(openai): keep latest deferred response intent

* fix(openai): keep base instructions for explicit speech

* fix(openai): only dedupe prefixed response instructions

* test(openai): narrow realtime user message callback

* fix(voice-call): suppress duplicate OpenAI realtime greeting

* fix(voice-call): keep OpenAI manual speech semantics

* fix(voice-call): keep OpenAI greeting trigger active

* fix(openai): suppress realtime auto responses during manual turns

* test(openai): import realtime bridge type

* refactor(openai): narrow realtime response suppression

* refactor(openai): share realtime turn detection config

* fix(openai): correlate realtime response errors

* fix(openai): flush queued realtime responses

* fix(openai): correlate realtime cancellation errors

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 21:13:20 +01:00
Wynne668
d405cda95a fix(browser): resolve act targetId aliases before mismatch check (#96178)
* fix(browser): resolve act targetId aliases before mismatch check

The /act top-level and batch targetId guards compared the caller-supplied
targetId against the resolved canonical tab.targetId with raw string
equality. Any supported alias form (tabId, label, suggestedTargetId, or a
unique id prefix) resolves to a different canonical id, so act requests that
followed the documented 'prefer suggestedTargetId/tabId/label' guidance were
rejected with 403 ACT_TARGET_ID_MISMATCH even though they named the correct
tab. snapshot/open/close/tabs lack this guard and kept working, matching the
reported symptom matrix.

Resolve the action targetId through the same tab alias resolution the route
used and reject only ids that resolve to a different tab.

* fix(browser): canonicalize act targetId aliases before Playwright dispatch

The /act gate accepted tabId/label/suggested/prefix aliases of the request
tab but left them on action.targetId. The managed executor reads
action.targetId ?? targetId for an exact page lookup (executeSingleAction ->
getPageForTargetId), so an alias missed the lookup and broke the action at
runtime whenever more than one page was open (single-page masked it via the
pages.length===1 fallback). Canonicalize the action targetId (top-level and
nested batch sub-actions) to the resolved tab id before dispatch; reject ids
that resolve to a different tab. Replace the mock-masked contract assertions
with executor-action assertions plus direct canonicalizer unit tests.

* test(browser): brace act-targetId guard clauses for curly lint

* docs(changelog): note browser target alias fix

* docs(changelog): note browser target alias fix

* fix(browser): reject ambiguous batch target aliases

* test(browser): type targetless act fixture

* docs(changelog): move browser alias fix to unreleased

* chore: drop nonessential browser changelog entry

---------

Co-authored-by: Peter Steinberger <peter@steipete.me>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 21:12:13 +01:00
Peter Steinberger
a04b6ced4f test: stabilize load-sensitive test families that break gates under parallel load (#100420)
* test: stabilize process-heavy fixtures under load

* test: stabilize channel mocks under load
2026-07-05 12:53:06 -07:00
llagy009
685c22dfb7 fix(irc): chunk PRIVMSG on UTF-16 boundary to avoid lone surrogates (#96572)
* fix(irc): chunk PRIVMSG on UTF-16 boundary to avoid lone surrogates

sendPrivmsg split long messages with String.slice on a UTF-16 code-unit
index, so an emoji (or other astral character) straddling the split
point was cut into a lone high/low surrogate, sending broken bytes in
the PRIVMSG to the IRC server.

Slice each chunk with sliceUtf16Safe so a surrogate pair is never split.
When the budget is too small to fit even the leading astral character,
emit that character whole so chunking still makes progress.

Adds a socket-level test (fake net/tls socket) asserting no PRIVMSG
chunk contains a lone surrogate, including the one-code-unit budget
edge case, while the existing space-preferring split is preserved.

* refactor(irc): make surrogate-safe chunking direct

* fix(irc): preserve one-unit chunk limits

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 12:14:05 -07:00
Darren2030
39b5bf38f7 fix(voice-call): resolve completed calls from the persisted store on status misses (#99797)
* fix(voice-call): resolve completed calls from the persisted store on status misses

get_status, the legacy status mode, and the voicecall.status gateway method
only consulted the in-memory call manager. Once a call was evicted (finalize,
gateway restart, or max-duration expiry) they reported { found: false } even
though the full record remained on disk. Fall back to the persisted call
history and resolve the NEWEST matching snapshot — history is oldest-first, so
a forward find() returns a stale record (the regression in the prior attempt).

Closes #96586

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(voice-call): use bracket access for mocked getCallHistory assertion

Avoids the typescript(unbound-method) lint rule that flags referencing a
typed method (`runtimeStub.manager.getCallHistory`) as an unbound value.
Bracket access matches the existing mock-assertion pattern in this file
(e.g. `runtimeStub.manager["sendDtmf"]`).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ci: re-trigger QA Smoke (transient build-OOM, also failing main run 28695162780)

* fix(voice-call): resolve persisted calls in the CLI status fallback too

The local CLI `voicecall status` gateway-unavailable fallback only consulted
the in-memory manager, so a completed/evicted call still returned
{ found: false } even though the gateway/tool/legacy status paths now fall
back to the persisted store. Align this fourth status reader: consult
getCallByProviderCallId in addition to getCall, and on an active miss resolve
the NEWEST matching persisted snapshot via getCallHistory(100) +
toReversed().find(...) (history is oldest-first), mirroring the gateway/tool
paths. Return shape is unchanged.

Per review on #96586 (align CLI status before merge).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor(voice-call): centralize persisted status lookup

Co-authored-by: 曾文锋0668000834 <zeng.wenfeng@xydigit.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 12:05:01 -07:00
Peter Steinberger
c730d8f1f1 feat(logbook): automatic work journal plugin with Control UI timeline tab (#99930)
* feat(logbook): automatic work journal plugin with a plugin-contributed Control UI tab

Squash of PR #99930 work for rebase onto the Control UI route refactor:
- extensions/logbook: Dayflow-style capture -> observations -> timeline cards
  pipeline with SQLite store, node capture commands, standup/ask, retention
- plugin SDK/gateway seam: surface "tab" Control UI descriptors projected
  into hello-ok controlUiTabs (scope-filtered, deterministic order)
- Control UI: dynamic plugin tabs with bundled Logbook view
- docs, tests, labeler wiring

* feat(ui): port plugin tabs and Logbook to the route-owned Control UI architecture

- shared /plugin route carries the tab id in the query (?id=<tab>), matching
  the router's exact-path contract
- openclaw-plugin-page renders bundled views (Logbook), sandboxed plugin
  frames (descriptor path), or the unavailable card
- sidebar renders hello controlUiTabs after each group's static routes
- Logbook view/controller live under ui/src/pages/plugin/

* fix(ui): namespace plugin tabs by pluginId to prevent cross-plugin tab id collisions

* fix(logbook): prefer app capture nodes and rotate off failing nodes

* fix(plugins): reject protocol-relative Control UI tab paths

* fix(logbook): harden automatic journal

* docs(changelog): remove maintainer self-credit

* chore(ui): refresh locale metadata after rebase

* fix(logbook): preserve analysis window boundaries

* fix(logbook): align status privacy and timezone

* fix(ui): stop hidden plugin tab polling
2026-07-05 11:50:44 -07:00