Commit Graph

64447 Commits

Author SHA1 Message Date
Masato Hoshino
09b5cdc17f improve(doctor): warn when cron jobs keep failing consecutive runs (#99606)
* improve(doctor): warn when cron jobs keep failing consecutive runs

* improve(doctor): message restart-interrupted runs in the chronic cron failure advisory
2026-07-06 05:40:55 +00:00
pick-cat
7c9c2ef0c3 fix(infra): enforce maxBytes in body-less HTTP error snippet path (#99340)
* fix(infra): enforce maxBytes in body-less HTTP error snippet path

* chore: rebase to trigger CI after boundaries check fix

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

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-06 05:40:52 +00:00
xingzhou
a13acacd3c fix(discord): keep command previews emoji-safe (#99539) 2026-07-06 05:40:39 +00:00
cxbAsDev
5dbad1102f fix(sessions): log warning when parseJsonlEntries skips malformed JSONL lines (#98669)
* fix(sessions): log warning when parseJsonlEntries skips malformed lines

* fix(sessions): also warn in buildSessionInfo for malformed JSONL lines

* fix(sessions): warn in parseSessionEntries for malformed JSONL lines

* test(sessions): add warning regression tests for parseSessionEntries

* test(sessions): add parseJsonlEntries warning regression test

Add test verifying parseJsonlEntries logs warning for malformed JSONL
lines via loadEntriesFromFile, covering the second of three instrumented
session JSONL readers.

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

* test(sessions): update parseSessionEntries warning expectations after rebase

* style(sessions): remove unnecessary type assertion in test

* test(sessions): add buildSessionInfo warning regression tests via SessionManager.list

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-06 05:40:21 +00:00
cxbAsDev
437b177b7d fix(agents): suppress unhandled stdout/stderr stream errors in waitForChildProcess (#100522)
* fix(agents): suppress unhandled stdout/stderr stream errors in waitForChildProcess

* proof(agents): add real behavior proof script for child-process stream error catch

* test(agents): drop synthetic child-process proof wrapper

* proof(agents): replace wrapper with real child-process stream error proof

* style: apply oxfmt to changed files

* test(agents): drop synthetic child-process proof wrapper

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-05 22:35:15 -07:00
cxbAsDev
b6e4cd6bf4 fix(gmail-watcher): catch renewal interval errors (#100342)
* fix(gmail-watcher): catch renewal interval errors

* fix(gmail-ops): catch foreground renewal interval errors; add failing regression test

* proof(gmail-watcher): rewrite proof with real fake-gog subprocess for before/after

* fix(proof): make gmail-watcher foreground proof child exit reliably

* fix(proof): kill fake gog serve child and check spawnSync error in renewal proof

* test(gmail): narrow renewal rejection coverage

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-05 22:34:14 -07:00
Peter Steinberger
89f911f322 refactor(ui): consolidate sidebar navigation contract (#100612)
* fix(ui): restore sidebar navigation contract

* refactor(ui): remove duplicate sidebar navigation model
2026-07-06 06:30:57 +01:00
lin-hongkuan
aca316ee16 fix(anthropic): normalize tuple tool schemas for Opus 4.8 (#100492)
* fix(anthropic): normalize tuple tool schemas

* fix(anthropic): preserve schema instance values

* test(anthropic): cover Opus tuple schemas live

---------

Co-authored-by: lin-hongkuan <lin-hongkuan@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-05 22:28:37 -07:00
Vincent Koc
1f36539ab0 test(release): declare CLI live fixture agent 2026-07-05 22:27:46 -07: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
Voscko
d924ddc428 feat(android): show cron job details (#95107)
* feat(android): add cron job detail view

* fix(android): harden cron job detail loading

* chore(android): refresh native i18n inventory

* test(plugins): register workboard typed hook

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 06:25:37 +01:00
Peter Steinberger
06fbd84d2b test(plugins): register Workboard typed hook contract (#100611) 2026-07-05 22:13:45 -07:00
Peter Steinberger
b18af41f52 perf(gateway): skip redundant startup policy loads 2026-07-06 01:10:00 -04:00
Peter Steinberger
d537139521 feat(macos): adopt the shared read-only chat transcript cache (#100275)
* feat(macos): adopt shared read-only chat transcript cache

Cache-first cold open for the macOS chat window/panel: the last known
transcript and session list paint immediately from the shared SQLite
transcript cache, then live gateway history replaces them wholesale.
Recent chats stay browsable read-only while the gateway is unreachable;
sending remains gated by connection state.

- Wires OpenClawChatSQLiteTranscriptCache into WebChatSwiftUIWindowController;
  DB at ~/Library/Application Support/OpenClaw/chat-cache.sqlite.
- Gateway identity (MacChatTranscriptCache.gatewayID), derivable offline:
  local keys on the canonical gateway state dir; remote/direct keys on the
  full canonical URL (scheme, host, resolved port, percent-encoded
  path/query); remote/ssh keys on the SSH target plus the resolved remote
  gateway port, mirroring the tunnel port resolution. Unconfigured mode
  gets no cache.
- macOS file protection: no per-file Data Protection classes; iOS-only
  attribute stays gated behind #if os(iOS) in the shared store, and the
  per-user container plus FileVault protect at rest.
- Onboarding chat stays uncached (transient guided setup session).

Part of #100194

* feat(macos): wire the offline command outbox into chat windows

* style(macos): fix orphaned doc comment; regenerate docs map

* style(macos): doc-comment lint fix; regenerate docs map on current main
2026-07-06 05:57:16 +01:00
Vincent Koc
55a0012c44 fix(ui): restore sidebar navigation exports 2026-07-06 06:56:09 +02:00
Peter Steinberger
3b33613868 docs(changelog): credit Vincent replay fixes (#100609) 2026-07-06 05:53:35 +01:00
Peter Steinberger
6441858e21 docs: refresh generated docs map (#100603) 2026-07-06 05:47:52 +01:00
Peter Steinberger
87d8fa7e3a fix(config): compare size guard against canonical input (#100591)
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-06 05:47:49 +01:00
github-actions[bot]
82f5ac150f chore(i18n): refresh native locales 2026-07-06 04:42:22 +00:00
pick-cat
f296dc4e68 fix(sessions): persist sender metadata in user turn transcript JSONL (#90552)
* fix(sessions): persist sender metadata in user turn transcript JSONL

Thread senderId/senderName/senderUsername/senderE164 from the channel
inbound context into the persisted user-turn transcript message so that
group chat session JSONL records include __openclaw sender identity.

Ref #90531

* fix(sessions): exclude senderE164 from persisted transcript for privacy

Remove phone-number field from the persisted __openclaw sender envelope,
keeping only senderId, senderName, and senderUsername. Privacy-sensitive
E.164 metadata can be added back by maintainers if needed.

Ref #90531

* fix(infra): spread base fields in applyExecPolicyLayer return values

The `as TBase & ExecPolicyLayer` casts failed because the returned
objects did not spread `...base`, losing generic TBase fields.

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

* fix(infra): use ...base spread instead of ...baseWithoutMode

The baseWithoutMode destructuring produces Omit<TBase, "mode"> which is
not assignable to TBase & ExecPolicyLayer when the as-cast is removed.

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

* fix(infra): preserve baseWithoutMode in second applyExecPolicyLayer branch

The second branch (security/ask override without a mode change) must
exclude base.mode from the spread so that mode is not leaked into results
when only security or ask fields are being overridden.

Without this fix, the spread ...base carries mode through to the returned
object, breaking callers that expect applyExecPolicyLayer to clear stale
mode when applying explicit security/ask policy fields.

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

* fix(sessions): scope persisted sender attribution

* fix(sessions): preserve sender metadata through hooks

* refactor(sessions): keep sender metadata path lean

* fix(sessions): preserve sender metadata in runtime writes

* fix(sessions): preserve queued sender attribution

* test(sessions): use complete message fixtures

* refactor(sessions): rely on narrowed user message type

* test(sessions): use shared temp directory helper

* test(sessions): align sender metadata assertions

* fix(sessions): honor sender metadata redaction hooks

* test(agents): use automatic temp cleanup

* test(sessions): cover queued turn provenance

* test(auto-reply): expect room sender metadata

* refactor(sessions): isolate queued transcript context

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 05:32:19 +01:00
Peter Steinberger
6acc0270aa docs(changelog): credit UI and TUI fixes (#100599) 2026-07-06 05:32:10 +01:00
Peter Steinberger
eedd309c4a fix(config): dedupe repeated validation warnings (#100569)
* fix(config): dedupe repeated validation warnings

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

* docs(changelog): defer config diagnostic note

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-06 05:30:04 +01: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
harish ganeshmurthy
cfcdf2a519 fix(tui): follow active gateway port (#73338)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-06 05:27:35 +01:00
ml12580
d11c80f440 fix(tui): show startup initialization activity (#93999)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 05:27:10 +01:00
Wynne668
f36f3f30ea fix(ui): recover from stale Control UI bundles (#99111)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 05:26:49 +01:00
Peter Steinberger
a0e591c863 fix(cli): reduce plugin hook fallback noise (#100554)
* fix(cli): reduce plugin hook fallback noise

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

* docs(changelog): defer plugin diagnostic note

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-06 05:26:37 +01:00
RayRuan
e9a5dc9bf6 fix(ui): preserve structured connect failures (#54758)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 05:26:33 +01:00
Goutam Adwant
ae6da5bc77 fix(ui): surface coalesced update restarts (#93082)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 05:26:14 +01: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
Peter Steinberger
4b7661e9a0 feat(ios): durable offline command outbox for chat sends (#100331)
* feat(ios): durable offline command outbox for chat sends

Text messages sent while the gateway is unreachable queue in a durable
per-gateway outbox (new outbox_commands table in the per-gateway chat
cache SQLite store, schema v2) instead of failing. Queued bubbles render
with visible Queued/Sending/Not sent states and flush strictly in
createdAt order once transport health recovers; each command's client
UUID rides as the send idempotency key, so at-least-once delivery plus
gateway dedupe keeps the transcript exact.

Contract summary:
- Bounds: 50 queued commands per gateway; refused enqueues keep the
  draft. Queued rows older than 48h expire to failed("expired") rather
  than silently sending stale commands; tap-to-retry refreshes
  createdAt so an expired row can resend as new intent.
- Failure taxonomy: transport-level failures keep rows queued without
  burning retry attempts (backoff ladder, then health drops so the
  reconnect machinery owns pacing); gateway rejections burn attempts
  and fail terminally after 3, with context-menu retry/delete.
- Deletes are tombstoned synchronously and rechecked after the claim
  await so an active flush can never send a removed command; Delete is
  hidden while a bubble is already in flight; offline enqueue is
  guarded against double submit during the health probe.
- Post-reconnect live sends route behind draining outbox rows (FIFO),
  and a cold open assumes a backlog until restore adopts durable rows.
- Crash safety: 'sending' rows revert to 'queued' at startup; flushed
  turns are spliced into the session's cached transcript before their
  outbox row is deleted, and stale history snapshots cannot evict a
  just-flushed turn until a snapshot confirms it.
- Per-gateway scoping and purge ride the transcript cache: one SQLite
  file per gateway; reset/forget drops the queue with the cache.
  Fixture/unpaired transports get no outbox.

Part of #46664

* chore(ios): sync native i18n inventory

* style(chat-ui): satisfy strict SwiftFormat lint (doc comment, scope blank line)
2026-07-06 05:23:46 +01:00
Peter Steinberger
0d509abe9a feat(ios): richer Settings About screen with mascot hero and project links (#100531)
* feat(ios): richer Settings About screen with mascot hero and project links

* chore(i18n): register About screen strings in native i18n inventory
2026-07-06 05:22:26 +01:00
Peter Steinberger
785f197de6 chore(maint): make the PR merge drift guard advisory by default (#100593)
The relevant-mainline-drift check in scripts/pr merge-verify hard-failed
any landing whose prepared head predated a sibling merge, serializing all
agent landings behind a fresh CI cycle per merged PR. Required checks
still gate at the prepared head and GitHub mergeable state still blocks
real conflicts. OPENCLAW_PR_STRICT_DRIFT=1 restores the previous hard
gate for release-critical flows.
2026-07-06 05:14:39 +01:00
NianJiu
37f96bde4d fix(gateway): format usage dates in range timezone (#100567)
* fix: format usage date labels by range timezone

* fix(gateway): keep usage ranges on calendar days

---------

Co-authored-by: NianJiuZst <180004567+NianJiuZst@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-05 21:11:22 -07: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
bf04d049fa feat(goals): keep active session goals in per-turn context + continuance QA scenarios (#100468)
* feat(goals): keep active session goals in per-turn context (#100409)

Active goals now inject one bounded user-role context line on every
non-heartbeat turn, refreshed at queued/interrupt admission via
provenance-tracked generated lines so operator stops take effect
immediately. Adds qa/scenarios/goals continuance scenarios and
goals.* coverage IDs.

* docs: regenerate docs map for goal context section

* fix(qa): use requiredChannelDriver instead of execution.channel pin in goal scenarios
2026-07-06 04:55:10 +01:00
Ayaan Zaidi
97227bde36 fix(gateway): commit runtime snapshot on noop config reloads (#100586)
Commit noop-only reload plans through the runtime secrets activator so getRuntimeConfig readers observe edited config without a Gateway restart, and make heartbeat wakes read the current runtime config while schedule recalculation stays owned by updateConfig/restart-heartbeat. Fixes stale messages.visibleReplies / messages.groupChat.visibleReplies and all sibling none-classified keys. Supersedes #100321; thanks @Sedrak-Hovhannisyan for the report.

Co-Authored-By: Codex <noreply@openai.com>
2026-07-05 20:54:51 -07: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
1090d2a96d perf(agents): slim Skill Workshop prompt section to its routing contract (#100449) (#100481)
Prompt section drops from 13 lines to 2 (2128 -> 319 bytes); action
mechanics move into the skill_workshop tool schema (+25 bytes), for a
net -1784 bytes per request on affected sessions. Routing contract and
approval flow unchanged.
2026-07-06 04:54:38 +01:00
Peter Steinberger
62ecc2306c feat(commands): add /learn to draft skills from recent work (#100442)
* feat(commands): add /learn to draft skills from recent work (#100408)

/learn rewrites the turn into a standards-guided Skill Workshop authoring
instruction: the agent gathers named sources (or distills the current
conversation) and files ONE pending skill proposal via skill_workshop.
Approval flow unchanged; sandboxed/tool-restricted agents get a clear
unavailable reply. Extracts the harness OpenClaw-tools predicate into
shared helpers and reserves the command name against plugin shadowing.

* docs: regenerate docs map for /learn section
2026-07-06 04:54:22 +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
Peter Steinberger
2bed394793 feat(gateway): add system.info RPC and Gateway Host card in Settings (#100478)
* feat(gateway): add system.info RPC and Gateway Host card in Settings

Settings quick page now shows where the Gateway runs and how the host
is doing: machine name, LAN address and runtime port, OS, Node/PID,
uptime, CPU count and load, RAM, and free disk on the state-dir volume.
Backed by a new additive operator.read RPC (system.info); the card
polls every 10s while visible and hides for clients without the read
scope or against older gateways.

Refs #100465

* docs: regenerate docs map for Gateway host status section

* fix(gateway): harden system info compatibility

* fix(ui): clear stale gateway host info

* docs(changelog): note gateway host status
2026-07-06 04:29:19 +01:00
Peter Steinberger
c9219c7f80 docs(changelog): note browser action downloads (#100575) 2026-07-06 04:15:41 +01:00
Bill
e92bfd892a fix(agents): run bootstrap ritual on Claude CLI (#100560)
* fix: CLI-backend agent runtimes skip the BOOTSTRAP.md first-run ritual

CLI-backend runtimes (claude-cli, gemini-cli) never rendered the
"Bootstrap Pending" system-prompt gate the embedded runner produces, so
on a fresh workspace with a pending BOOTSTRAP.md the agent greeted the
user instead of running the first-run bootstrap ritual. BOOTSTRAP.md
reached CLI backends only as passive Project Context, never as a blocking
directive, because bootstrapMode was computed only on the embedded path.

Promote the embedded runner's bootstrap routing to a shared module
(src/agents/bootstrap-routing.ts) so both runtimes share one routing path,
then compute bootstrapMode in the CLI prepare step and thread it through
buildCliAgentSystemPrompt. The embedded-runner change is import-only.

Codex is unaffected: it runs on the embedded runtime and already renders
the gate.

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

* fix(agents): gate CLI bootstrap on native file access

---------

Co-authored-by: kruegerb <william.krueger@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-05 20:13:03 -07:00
github-actions[bot]
d957f5a790 chore(i18n): refresh native locales 2026-07-06 03:08:19 +00: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
Vincent Koc
0bd2a0b879 ci(sdk): refresh plugin api baseline hash 2026-07-06 05:02:28 +02: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
2b48e98148 fix(android): preserve chat sends across reconnect recovery (#100551)
* fix(android): preserve chat recovery ownership

* fix(android): retry reconnect recovery on ticks

* chore(android): refresh native i18n inventory
2026-07-06 03:50:09 +01:00