922 Commits
Author SHA1 Message Date
Josh AvantandGitHub 33720886c8 fix(agents): keep sender-scoped tools in delegated runs (#110345)
* fix(agents): preserve requester policy across delegation

* fix(agents): keep policy types internal

* test(codex): cover delegated policy forwarding

* fix(agents): harden delegated policy contract

* fix(agents): preserve split-owner completion policy

* fix: version delegated requester snapshots

* fix: refresh delegated policy protocol artifacts
2026-07-20 19:42:06 -05:00
Peter SteinbergerandGitHub 49ff6a4497 fix(protocol): classify system agents in rosters (#111920)
* fix(protocol): classify system agents in rosters

* fix(ci): align agent kind client gates

* fix(ci): keep roster filtering in startup bundle

* chore(ui): remove superseded roster module

* style(android): satisfy agent kind test formatting

* style(linux): format merged agent capability assertion

* fix(config): reject reserved system agent ids

* chore(i18n): refresh native source inventory

* style(android): format agent kind surfaces

* fix(gateway): preserve configured agent ownership
2026-07-20 16:57:04 -07:00
Peter SteinbergerandGitHub d5a8233e76 feat(gateway,ui): agent-scoped model provider credentials (#111796)
* feat: scope model provider credentials by agent

* fix: reject unknown model auth agent ids

* fix: discard stale model provider preload

* fix(gateway): reject whitespace-only explicit agent ids

* fix: scope model provider probes by agent

* fix: complete model provider agent scoping

* fix(ui): always clear the providers refresh flag on completion

* fix(ui): keep probe epochs monotonic across agent switches

* fix: derive agent scope for provider aborts

* fix: satisfy model provider CI checks
2026-07-20 16:22:09 -07:00
Peter SteinbergerandGitHub 324fd4fe6e refactor(channels): delete all media-placeholder consumer awareness (#111891)
Final sweep of the media-placeholder program: with all eleven producers
migrated, the consumer regexes are dead input and are hard-deleted —
media-understanding token un-mixing (bodies are pure user text now),
the persisted-user-turn placeholder drop, the session-memory strip, and
the inbound-event mediaPlaceholder field with its replacement branch
(an intentional removal of shipped SDK surface per the program's
hard-delete decision: plugins still minting placeholder bodies render
them as literal text until updated). formatMediaPlaceholderText remains
the single owner of the <media:kind> vocabulary, used only for
text-only carriers. Legacy tokens in pre-migration history remain
ordinary text.
2026-07-20 09:31:51 -07:00
570f8b4d9e fix(errors): recover from Z.AI token-limit errors (#111744)
* fix(errors): classify Z.AI token-limit overflow

* fix(zai): own token overflow classification

* fix(zai): classify live prompt overflow errors

---------

Co-authored-by: Altay <altay@hey.com>
2026-07-20 17:11:40 +03:00
Peter SteinbergerandGitHub 154a49a78b feat(dashboard): widget capabilities — net CSP, host tools, hardened shared sandbox (#111687)
* feat(boards): enforce widget capability grants

* feat(ui): expose dashboard widget capabilities

* test(dashboard): align rebased gateway contracts

* refactor(dashboard): finish capability alignment

* chore: internalize unused board sandbox exports

* test(dashboard): bind grants to widget instances

* fix(dashboard): close widget authority lifetime gaps

* refactor(ui): preserve modular widget frame ownership

* test(ui): preserve explicit MCP App lease refresh

* test(ui): use shared dashboard sandbox server

* fix(ui): settle widget requests on reconnect

* fix(ui): retry transient widget document loads

* refactor(dashboard): document WebRTC egress residual

* fix(dashboard): clear landing checks
2026-07-20 06:54:44 -07:00
Peter SteinbergerandGitHub 248726fafd feat(anthropic): import Claude Desktop custom groups (#111644)
* feat(anthropic): import Claude Desktop custom groups

* fix(anthropic): resolve Claude Desktop groups from LevelDB entries

Group discovery regexed whole decompressed blocks, so matches were not
attributable to a Local Storage value and byte order decided the winner.
On a real 5.4MB store that mislabelled 59 of 159 sessions, surfacing a
mojibake label spliced out of Snappy copy-record bytes.

Parse SSTable entries properly instead: prefix-delta keys bounded by the
restart array, newest internal sequence per user key (honoring deletions),
and record scanning confined to a single value. Values are normalized so
Chromium's UTF-16 form scans like Latin-1, and unflushed WAL writes keep
precedence over SSTables.

Prod LOC grows ~77; it buys structural correctness in place of ordering
luck, and folds the old index-only walk into one shared entry decoder.

Verified against the live store: 159 assignments, 0 mislabelled versus an
independent entry-level ground truth, 0 control-character labels.

* fix(ui): sort custom session groups ahead of project groups

Custom groups were pushed into the section list as encountered, so their
position depended on roster order rather than the documented behavior;
the existing test only passed because its fixture happened to be ordered
that way. Collect custom and project groups separately and concatenate,
and assert the guarantee with a reversed-input case.

* fix(anthropic): widen LevelDB fixture key type for test typecheck

The prefix-delta helper assigned a Buffer into a Buffer-typed accumulator
whose generic argument differed, which tsgo rejects in the test lane.

* chore(anthropic): drop release-owned changelog edit from the PR

CHANGELOG.md is generated at release time, so a normal PR must not carry
an entry. The release-note context lives in the feature commit message and
the PR body instead.
2026-07-20 00:30:37 -07:00
Peter SteinbergerandGitHub a971188a6d build(client): make @openclaw/gateway-client publishable to npm (#111707) 2026-07-20 00:23:36 -07:00
Jason (Json)andGitHub 6304a47762 feat(dashboard): harden MCP widget authority (#111679) 2026-07-20 00:32:02 -06:00
Peter SteinbergerandGitHub fef846a3f0 build(protocol): make @openclaw/gateway-protocol publishable to npm (#111664)
* build(protocol): make @openclaw/gateway-protocol publishable to npm

* chore(mxc): align package version with release train

* fix(release): support gateway-only core packages
2026-07-19 23:18:24 -07:00
e45ebac97a fix(media): m4a/AAC audio files from non-Apple sources are misidentified as video/mp4 and excluded from audio workflows (#111177)
* fix(media): preserve audio hints for isom-brand m4a/AAC files misidentified as video/mp4

* fix(media): correct ambiguous M4A aliases

Co-authored-by: 潘晓波0668000512 <pan.xiaobo@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-19 22:18:23 -07:00
Peter SteinbergerandGitHub bc76bb8933 feat(agents): agent-controlled session status, attention, and TTL in the sessions tool (#111583)
* feat(agents): agent-controlled session status, attention, and TTL in the sessions tool

* feat(protocol): sessions.patch agent status fields and curated attention icon ids

* chore(protocol): regenerate bindings for agent-status patch fields, unexport internal cap

* chore(sessions): unexport internal agent-status TTL default
2026-07-19 21:01:09 -07:00
Peter SteinbergerandGitHub 64c82812a5 feat(dashboard): pinned MCP apps — board rendering, lease re-mint, durable tool grants (#111524)
* feat(boards): mint pinned MCP app views

* feat(ui): render pinned MCP apps on dashboards

* fix(dashboard): reconcile MCP app rebase

* fix(dashboard): align generated CI contracts

* test(gateway): record board.widget.appView release train

* fix(dashboard): revalidate pinned MCP app views
2026-07-19 19:51:26 -07:00
Peter SteinbergerandGitHub c5f9addb52 fix(ui): keep custodian transcript aligned after inference errors (#111562)
* fix(ui): reconcile invalidated custodian sessions

* test(ui): preserve custodian page harness type
2026-07-19 16:00:08 -07:00
Peter SteinbergerandGitHub 06480d767c feat(dashboard): stitch session dashboards end-to-end — live provider, show_widget pin, board commands (#111218)
* feat(dashboard): pin canvas widgets through board domain

* feat(control-ui): wire session dashboards end to end

* fix(control-ui): preserve direct reset confirmation

* fix(control-ui): localize dashboard default tab

* test(dashboard): satisfy changed typecheck gate

* fix(dashboard): satisfy changed lint gate

* fix(dashboard): harden pinned widget lifecycle

* fix(dashboard): use extracted mock normalizer

* test(dashboard): reconcile hardened board admission tests

* fix(dashboard): align grant and canvas protocol requests

* fix(dashboard): preserve refresh and pin invariants

* fix(boards): treat missing board tables as empty on read-only paths

* fix(boards): accept read-only handles in board table probe

* fix(control-ui): preserve virtual board widget types

* fix(dashboard): align view types with protocol

* fix(dashboard): keep resolved board view typed

* chore(canvas): drop test-only html read wrapper

* chore(release): defer dashboard note generation

* fix(protocol): align board widget put params type

* fix(control-ui): preserve queued reset approval

* fix(control-ui): gate dashboard pinning capability

* chore(test): isolate dashboard capability fixture

* fix(control-ui): refresh dashboard pin affordance
2026-07-19 12:36:54 -07:00
Peter SteinbergerandGitHub 6d4082ef97 fix(ui): prevent unsafe custodian nudge answers (#111430)
* fix(ui): harden custodian nudge actions

* refactor(ui): split custodian page helpers

* fix(ui): classify custodian nudge delivery

* fix(ui): ignore stale custodian question replies

* fix(ui): restore rejected custodian questions

* fix(ui): preserve custodian wizard uncertainty

* refactor(ui): keep nudge text helper private

* test(ui): model uncertain custodian delivery

* fix(ui): scope delayed custodian dismissals

* fix(ui): retain in-flight custodian nudges

* fix(ui): block nudges during hosted wizard input

* chore(protocol): regenerate gateway models
2026-07-19 11:10:41 -07:00
Peter SteinbergerandGitHub c7e7ac2728 refactor: remove expired plugin compatibility surfaces (#111451)
* docs(secrets): remove retired web credential paths

* refactor(web): remove retired provider compatibility paths

* refactor(providers): delete retired compatibility routes

* refactor(secrets): remove retired credential aliases

* refactor(plugin-sdk): delete retired compatibility surfaces

* docs(plugin-sdk): remove retired migration guidance

* chore(plugin-sdk): refresh rebased surface budgets

* chore(plugin-sdk): refresh API removal baseline

* refactor(compat): migrate retired internal callers

* chore(plugin-sdk): refresh current-main baselines

* test(config): migrate plugin-owned secret assertions

* test(gateway): narrow plugin secret refs

* fix(plugin-sdk): preserve private boundary type identity

* chore(compat): remove stale sweep references

* chore(lint): lower max-lines budget

* refactor(secrets): remove unused web helper

* build(plugin-sdk): drop removed compat entries

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): use Linux API baseline hash

* fix(plugin-sdk): preserve private bundled build entries

* fix(plugin-sdk): package private runtime facades

* fix(plugins): preserve external credential contracts
2026-07-19 11:04:48 -07:00
Peter SteinbergerandGitHub 197c4f5a04 feat: generic session discussion seam with Control UI panel (#111337)
* feat: add session discussion panel seam

* fix: keep discussion iframe cookie-capable and changelog release-owned

* test: cover cookie-capable discussion iframe sandbox

* fix: stretch discussion panel host so the embed fills the rail

* fix: keep provider failures retryable and probe discussion availability before showing the action

* fix: block same-origin discussion embeds, show action on catalog sessions, close stale panel on reconnect

* fix: scope discussion probes and panel callbacks to the issuing connection

* fix: dedupe in-flight discussion probes per session

* fix: retry superseded discussion probes and key-scope panel results

* fix: regenerate Swift protocol models and extend advertised-method expectations

* style: format chat-pane-header

* fix: regenerate Kotlin protocol models and date discussion methods in the 2026.7 train

* chore: restore release-owned changelog to main state

* chore: keep changelog untouched relative to merge-base
2026-07-19 09:47:47 -07:00
6c9b31e4d5 fix(ai): honor Retry-After when retry-after-ms is unparseable (#111353)
* fix(ai): honor Retry-After when retry-after-ms is unparseable

The ChatGPT Responses retry path returned as soon as `retry-after-ms` was
present, so a malformed or empty value discarded a valid `Retry-After`
header sent alongside it and the client fell back to blind exponential
backoff. The sibling parser in `provider-transport-fetch.ts` treats the
two headers as ordered preferences and falls through on a parse failure;
this aligns the Responses path with that contract.

* test(ai): deduplicate retry header coverage

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-19 09:26:47 -07:00
Peter SteinbergerandGitHub 8c7f09a3c4 feat(system-agent): durable rolling transcript with openclaw.chat.history (#111440)
* feat(system-agent): durable rolling transcript with openclaw.chat.history

* chore(ui): scanner-safe auth root in custodian session ownership key

* fix(system-agent): durable reset boundary for transcript seeding

* fix(ui): ownership-aware custodian session rotation with capability gating

* fix(ui): bounded history load and reconnect-safe transcript refresh

* fix(ui): keep unknown-outcome warning and event nudges across transport transitions

* fix(ui): flag-backed unknown-outcome warning independent of retry state

* fix(ui): armed ownership boundaries and abandon-before-rotate ordering

* chore(ui): localize the server-side sensitive mask in durable history

* fix(ui): repair rebase-dropped import and mock arity

* chore: gate fixes — void history handler, module-local transcript internals

* refactor(gateway): leaf history-turn contract to keep the module graph acyclic

* chore(gateway): stamp openclaw.chat.history with its introduction train

* test(gateway): record openclaw.chat.history in the 2026.7 train pin
2026-07-19 08:37:00 -07:00
Peter SteinbergerandGitHub adf02e8de4 refactor(plugin-sdk): retire global provider publication (#111426)
* refactor(plugin-sdk): retire global provider publication

* docs: refresh SDK migration map
2026-07-19 07:44:11 -07:00
Peter Steinberger 2a6fd77c08 fix(net-policy): restore ipaddr typing compatibility
Repair main CI by preserving newer ipaddr range labels across merged declarations and narrowing CIDR match operands by address family.
2026-07-19 05:51:18 -07:00
Peter SteinbergerandGitHub 3b84a55d99 refactor(protocol): pre-publish cheat-window cleanup and vintage tracking (#111041)
* fix(codex): drain dynamic-tool handlers before side-thread cleanup

* refactor(protocol): rename question ids to questionId and flatten answer maps

* refactor(protocol): slim worker stack and unify session-catalog shapes

* refactor(protocol): delete dead public surface and polish packaging

* feat(protocol): track release-train vintage on gateway methods and schemas

* fix(apps): align question surfaces merged from main with reshaped protocol

* test(health): shape secret fixtures to scanner-safe token names

* test(health): use scanner-safe token fixtures

* fix(apps): align question surfaces merged from main with reshaped protocol

* fix(ci): prove reshaped protocol in shallow checks

* fix(ui): align sidebar question fixtures with protocol

* fix(apps): read flat Swift question answers

* fix(apps): align question surfaces merged from main with reshaped protocol

* fix(apps): refresh native question inventory

* fix(apps): align macOS snapshot fixtures with protocol

* fix(ui): align narration question fixture with protocol
2026-07-19 04:07:15 -07:00
Peter SteinbergerandGitHub 104691f822 feat(swarm): add QuickJS guest orchestration (#111298)
* feat(swarm): add QuickJS guest orchestration (#110325)

* fix(agents): turn-stable swarm replay identity — distinct exec invocations cannot collide

* fix(agents): turn-stable swarm replay identity — distinct exec invocations cannot collide

* fix(agents): turn-stable swarm replay identity — distinct exec invocations cannot collide
2026-07-19 03:58:59 -07:00
Peter SteinbergerandGitHub 5c9916950e feat(gateway): watched sessions in presence with viewer facepiles (#111225)
* feat(gateway): expose watched sessions in presence

* fix(gateway): resolve concurrent watched-session rollbacks via in-flight state

* fix(ui): viewing CI conformance — lazy facepile, bindings, dead exports

* fix(ui): move viewer presence projection out of the startup chunk

* fix(ui): capture sessionKey before facepile filter closure
2026-07-19 02:53:19 -07:00
Peter SteinbergerandGitHub b9fa1ffa27 feat(gateway): system change history RPC and Ask OpenClaw recent-changes panel (#111286)
* feat(gateway): system change history RPC and Ask OpenClaw recent-changes panel

* test(gateway): fix journal fixtures, split custodian page tests, refresh docs map

* chore: quiet lint on journal reader tests and custodian harness
2026-07-19 02:38:05 -07:00
Peter SteinbergerandGitHub 8631832048 fix: workspace divergence no longer wedges cloud-worker sessions (#111244)
* fix(cloud-workers): resolve workspace divergence with keep-local conflicts

* fix: retain workspace conflicts during worker reclaim

* style: satisfy workspace reconciliation lint

* chore: defer cloud worker changelog to release

* refactor: split cloud workspace reconciliation modules

* fix: satisfy workspace module boundary checks
2026-07-19 01:49:35 -07:00
0f95e66b7f feat(talk): add durable client voice sessions (#111216)
Live-append voice transcripts into the agent session and persist a per-agent SQLite call record across relay and client transcript paths.

Add run-scoped spoken confirmation for high-impact actions, mutation digests, bootstrap-context injection, talk.client.transcript and talk.client.close protocol methods, and Control UI adoption. This adds zero new configuration.

Co-authored-by: Clifton King <clifton@users.noreply.github.com>
2026-07-19 01:06:49 -07:00
Peter SteinbergerandGitHub a8b7290f34 feat(gateway): durable user profiles with email aliases and avatars (#111224)
* feat(gateway): durable user profiles with email aliases and avatars

* fix(gateway): compress merge tombstones, content-hash avatar ETags, users CLI json output

* fix(gateway): lean profile listing, scoped avatar routing, typed email validation

* fix(gateway): protocol-complete profile payloads and consistent store reads

* fix(gateway): mark profile schema ensured only after commit

* fix(gateway): avatar endpoint HEAD support and RFC If-None-Match

* fix(gateway): profiles CI conformance — bindings, lint, knip, sql boundary

* feat(gateway): self-service profile edits for authenticated users

* fix(gateway): users.self bootstrap, tombstone-aware ownership, escaped CLI output

* fix(gateway): raw-DDL allowlist entry and lean profile exports
2026-07-19 00:58:43 -07:00
5a81e9fa81 fix(agents): preserve ANSI sanitizer state across bash chunks (#103706)
* fix(agents): preserve ANSI sanitizer state across bash chunks

* fix(agents): harden streaming ANSI sanitization

Keep incremental parser state in the canonical terminal owner, avoid a second sanitizer pass, and leave OutputAccumulator and public terminal APIs unchanged.\n\nCo-authored-by: Jicheng Xu <xu.jincheng@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 23:33:40 -07:00
Peter SteinbergerandGitHub ccb147518c feat(agents): Swarm core — collector spawn, agents_wait, structured output, caps (gated) (#110932)
* docs: add Swarm implementation spec

* feat(agents): Swarm core — collector spawn, agents_wait, structured output, fastMode, caps

Implements docs/plan/swarms.md §4-6: tools.swarm config gate (default off),
collector-mode sessions_spawn (collect/outputSchema/fastMode/groupId), fail-closed
child approvals, agents_wait race-semantics tool, per-group FIFO scheduler with
maxConcurrent/maxChildrenPerGroup/maxTotalPerGroup caps, additive registry and
state-schema columns (no schema-version bump), and colocated tests.

Part of #110325

* fix(agents): rebase reconciliation — preserve swarm state columns

* fix(agents): O(1) collector session index, cheap-first preflight, collector start lifecycle hooks

Autoreview findings: replace the per-request full registry scan with an
index-maintaining run map and gate the persisted-store fallback behind
isSubagentSessionKey; emit subagent_progress/subagent_spawned from the swarm
scheduler start callback so collector children produce balanced plugin
lifecycle events.

* chore(protocol): regenerate Swift gateway models for swarm fields

* fix(agents): lint cleanup — typed catch, explicit microtask flush, no executor return

* fix(agents): knip/test-support/max-lines cleanup for swarm surfaces

* fix(agents): keep tool-catalog ui-safe — callers pass prepared swarmEnabled fact

resolveSwarmConfig value-import in tool-catalog dragged the server graph into
the Control UI bundle via tool-policy-shared (UNLOADABLE_DEPENDENCY on
subpath aliases). Catalog stays pure; the gateway tools-catalog handler
resolves the gate and passes the boolean.

* fix(agents): reconcile swarm spawn pipeline

* fix(agents): refresh swarm tool metadata

* fix(apps): sync swarm tool localization

* style(agents): compact tool display metadata

* fix(plugin-sdk): account for swarm config surface
2026-07-18 23:30:11 -07:00
Peter SteinbergerandGitHub 932e8be06c feat(agents): canonical agent creation with Custodian hatch flow (#111052)
* refactor(agents): centralize agent creation

* feat(ui): add new agent hatch flow

* refactor(agents): keep creation paths lean

* fix(agents): hide internal creation types
2026-07-18 22:50:02 -07:00
Peter SteinbergerandGitHub c684b13213 feat(gateway): thread authenticated user identity into presence (#111179)
* feat(gateway): thread authenticated user identity into presence

* feat(gateway): regenerate Swift protocol bindings for presence user
2026-07-18 21:06:22 -07:00
Peter SteinbergerandGitHub cc57514e68 refactor(agents): make API registry ownership lifecycle-local (#111137)
* refactor(agents): make API registries lifecycle-owned

* refactor(agents): keep registry runtime ownership internal

* fix(agents): bind session streams to registry runtime

* refactor(agents): keep prepared runtime ownership internal

* test(agents): model lifecycle runtime fixtures

* fix(amazon-bedrock): adapt lifecycle stream types

* fix(agents): complete lifecycle runtime migration

* test(agents): satisfy lifecycle registry static gates
2026-07-18 20:55:07 -07:00
198d2f000f fix(telegram): preserve authored file-reference links (#105911)
* fix(telegram): preserve authored file links

* fix(telegram): preserve authored file links after wrapping

* refactor(telegram): rely on markdown link provenance

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 20:33:05 -07:00
Peter SteinbergerandGitHub 2f00a417ed feat(gateway): session dashboard domain — board RPCs, ticketed widgets, dashboard tool, per-agent persistence (#110960)
* feat(gateway): add session dashboard domain

* test(gateway): cover board event guards

* fix(gateway): authorize board widgets with view tickets

* feat(boards): persist dashboards in agent databases

* test(boards): use tracked SQLite temp directories

* test(gateway): isolate board deletion lifecycle coverage

* fix(boards): harden widget view ticket bindings

* fix(boards): lazily ensure additive board schema

* fix(gateway): complete dashboard integration metadata

* fix(boards): satisfy generated integration checks

* fix(boards): align persistence with repository guards

* fix(boards): retain notice test reset

* fix(protocol): generate dashboard union models

* fix(boards): harden dashboard persistence and serving

* fix(boards): satisfy dashboard CI guardrails
2026-07-18 20:17:51 -07:00
Peter SteinbergerandGitHub 68771ebdfe feat(cron): script payloads behind the trigger gate (#111112)
Run script payloads through the shared headless code-mode executor with payload-grade budgets and success-only trigger.state persistence.

Reuse cron delivery, wake, pacing, and dangerous trigger-gate contracts for notify, wake, and nextCheck results.
2026-07-18 19:24:12 -07:00
Peter SteinbergerandGitHub 756a491a51 fix(speech): strip markdown before TTS and route code-heavy replies sensibly (#110948)
The talk.speak synthesis path passed raw agent text to providers, so talk
mode could read fenced code, links, and tables aloud. Speech normalization
now happens once at the shared synthesis boundary (speech-mode stripMarkdown:
label-only links, decorative bullet/glyph cleanup, punctuation collapsing).
Code-heavy replies (>=50% fenced content, CommonMark-aware scanner incl.
blockquote/list containers and unclosed fences) get routed by surface:
talk.speak speaks a short on-screen fallback line, channel auto-TTS skips
the voice note since the visible text already carries the content, and
explicit conversions (tts.convert, tagged hidden TTS, chat Listen) always
speak stripped best-effort content.
2026-07-18 18:16:43 -07:00
Peter SteinbergerandGitHub 62c5a8b888 fix(gateway): make scope errors machine-readable across clients (#111013)
* fix(gateway): consume structured scope errors

* docs(gateway): clarify tools error boundary

* refactor(gateway): unify node admin policy
2026-07-18 17:53:45 -07:00
Peter SteinbergerandGitHub 593ac4ae0c feat(apps): rewind and fork a session from native chat bubbles (#110886)
* feat(apps): rewind and fork a session from native chat bubbles

* docs(apps): note lease-parity contract on message fork dispatch

* fix(apps): native i18n inventory sync and doc-comment style for bubble actions

* fix(apps): translate native bubble action strings across locales

* fix(apps): refresh generated iOS localization catalog after rebase
2026-07-18 17:52:03 -07:00
Peter SteinbergerandGitHub 8853217ec7 fix(gateway): cancel run-bound approvals on abort and expose approval-park lifecycle (#110993)
* fix: harden approval abort lifecycle

* fix(gateway): recheck abort before committing detached exec authorization

* fix(gateway): recheck abort after inline exec authorization commit

* fix(gateway): propagate run-abort cancellation on the inline approval path

* fix(ci): refresh approval protocol bindings
2026-07-19 00:52:21 +01:00
Peter SteinbergerandGitHub 556a2ee276 feat(cron): add per-job dynamic cadence (#110978)
Add optional per-job pacing bounds across the cron API, CLI, tool schema, public output, and SQLite job envelope, requiring at least one bound. Allow only the currently running paced job to record a one-shot next_check proposal and carry it through isolated-run completion.

After successful runs, clamp the proposal to the job bounds and persist an exact one-shot slot marker so maintenance preserves only that timestamp. Clear the marker on runs, edits, and schedule normalization; preserve existing no-proposal, skip, timeout, and error scheduling behavior.
2026-07-18 23:43:39 +01:00
19d887169f fix(ai): ChatGPT Responses retries errors it classified as non-retryable (#110655)
* fix(ai): ChatGPT Responses retries errors it classified as non-retryable

The retry loop builds its friendly error and throws it from inside the same
try block whose catch treats unknown failures as retryable network errors.
Authentication and bad-request failures were therefore resent up to
maxRetries times, adding 7s of backoff before surfacing the same message.

Tag the already-classified failure with a private error type and rethrow it
unchanged from the catch, leaving the retryable paths untouched.

* test(ai): move retry classification cases to a dedicated file

The provider test file was already near the 1000-line oxlint max-lines
budget, so the new cases pushed it over. Split them out following the
existing <module>.<topic>.test.ts convention.

* refactor(ai): separate HTTP and transport retries

Co-authored-by: Yigtwxx <yigiterdogan023@gmail.com>

* test(ai): clarify synthetic JWT fixture

Co-authored-by: Yigtwxx <yigiterdogan023@gmail.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 23:09:42 +01:00
9f7c7521f1 fix(agents): Responses turns that end incomplete report zero tokens and zero cost (#109904)
* fix(agents): record token usage when a Responses turn ends incomplete

The agent-side Responses processor only had a terminal branch for
response.completed. A stream that ends with response.incomplete — the
max_output_tokens and content_filter cases, and what Azure emits on early
truncation — matched no branch at all, so the event was dropped: usage was
never recorded and stopReason was never set. The turn reports zero tokens and
zero cost, which is the drift in #100954.

#109615 fixed the same split on the package-side processor by finalizing
completed and incomplete through one finalizeResponse. This does the same for
the agent path, which #109615 did not touch: both terminal events now record
usage, cost and service-tier pricing through one helper.

The helper moves to its own module rather than growing openai-responses-transport.ts,
which is a legacy file the max-lines ratchet will not let grow; extracting the
block drops it from 2502 to 2444 lines.

Content-filtered turns are mapped to a provider error instead of a plain length
stop, matching what the package side already does, so the two terminal surfaces
do not disagree.

* fix(agents): keep Responses output backfill on completed turns

Terminal handling now covers response.incomplete, which also routed those
events into backfillCompletedResponseOutput. That reconstruction exists to
recover a final answer when item events never arrived; an incomplete turn has
no final answer, so replaying its partial output persisted truncated text the
streaming path never emitted. Usage and stop-reason recording still apply to
both terminal events.

* refactor(ai): share one Responses terminal usage mapper

The agent transport mapped terminal usage buckets, cost, and stop reasons in
parallel with the package-side processor, so the two could drift on token
buckets, service-tier pricing, or future terminal-event semantics.

Both now call one canonical mapper. openai-responses-shared.ts cannot be
imported across the package boundary, so the mapper lives in its own module
re-exported through the existing internal/openai entry point; no new subpath
is introduced. The agent module keeps only the reasoning-token accounting the
package path does not track.

Merging the two revealed a real disagreement on totalTokens: the package took
the reported total, the agent summed the split buckets. The canonical rule is
now max(bucket sum, reported total), which keeps the reported value while
covering both payloads that omit total_tokens and payloads whose cached_tokens
exceed input_tokens, where clamping leaves the reported total short.

* fix(agents): preserve partial incomplete Responses output

Co-authored-by: Yigtwxx <yigiterdogan023@gmail.com>

* test(agents): cover incomplete terminal output backfill boundaries

The head's partial-output preservation is only safe while it stays a recovery
path. Pin both sides of that guard: text that already streamed must not be
replayed from the terminal payload, and a non-length incomplete stop must not
surface partial text as an answer.

* fix(agents): avoid shadowing Responses options

Co-authored-by: Yigtwxx <yigiterdogan023@gmail.com>

* style(agents): apply oxfmt to the incomplete backfill test

* test(agents): register incomplete Responses suite

Co-authored-by: Yiğit ERDOĞAN <yigiterdogan023@gmail.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 23:03:53 +01:00
clawsweeper[bot]GitHubopenclaw-clawsweeper[bot] <openclaw-clawsweeper[bot]@users.noreply.github.com>Claude Fable 5fuller-stack-dev
b88646cf78 feat(webchat): reply-to a message with hydrated reply context (#110791)
* feat(webchat): reply-to a message with hydrated reply context

Control UI replies now carry the target transcript id as replyToId on
chat.send. The Gateway resolves the replied-to message from session
history and hydrates the channel-agnostic ReplyToId/ReplyToBody/
ReplyToSender envelope fields, so agents receive reply_to_id,
has_reply_context, and the untrusted reply-target block exactly like
Discord replies (mirrors #90263). Reply targets without a persisted
transcript id keep the inline-quote fallback.

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

* fix(webchat): keep non-reply chat.send dispatch ordering and satisfy CI gates

* docs(webchat): match reply-context doc to webchat conversation-info policy

* fix(webchat): hydrate reply bodies from display-visible content only

---------

Co-authored-by: openclaw-clawsweeper[bot] <openclaw-clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
2026-07-18 15:57:59 -06:00
d5b2749fd8 fix(ai): skip blank environment credentials during provider auth (#109691)
* fix(ai): ignore blank environment API keys

* test(ai): avoid credential-shaped fixture assignments

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

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 22:33:54 +01:00
Peter SteinbergerandGitHub 5fe8d6a852 fix(gateway): clients can identify authorization failures (#110925)
* fix(gateway): structure authorization errors

* test(gateway): align authorization contracts

* fix(gateway): regenerate protocol bindings

* fix(gateway): preserve optional scope errors

* fix(gateway): report complete pairing scopes

* style(gateway): format protocol exports
2026-07-18 22:02:28 +01:00
1da345e9d3 fix(mcp): clamp oversized MCP timeouts (#105784)
* fix(mcp): clamp oversized MCP timeouts

* fix(mcp): centralize timer-safe timeout normalization

Co-authored-by: 杨浩宇0668001029 <yang.haoyu@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 21:50:19 +01:00
Peter SteinbergerandGitHub 5fdb0cd24e feat(chat): switch between session transcript branches from the chat header (#110857)
* feat(chat): switch between session transcript branches from the chat header

* fix(chat): type fixes and protocol regen for branch switcher CI
2026-07-18 20:06:36 +01:00
Peter SteinbergerandGitHub 88e5af7097 feat(ui): interleaved sidebar zone with custom session icons and drag ordering (#110682)
* feat(ui): custom session icons with agent-drawable SVG and nav-parity pinned rows

* wip: slice-2 interleaved sidebar zone (pre-review)

* fix(ui): trim icon exports, bypass protocol barrel in startup bundle, regen Swift protocol client

* fix(ui): preserve unknown-agent zone entries on writes, prune entries on any unpin

* fix(ui): reset keeps unloaded session slots; enforce SVG byte cap on canonical form

* fix(ui): archiving a pinned session retires its sidebar zone slot

* fix(ui): persist drag-pinned zone slot only after the pin patch lands

* fix(ui): recompute drop insertion against freshest zone order on pin ack

* fix(ui): consume self-drop events before the zone bailout

* docs(ui): note the non-sidebar unpin pruning contract on pruneSidebarSessionEntry

* refactor(ui): extract pure session-tree projection; drop unused zone type export
2026-07-18 17:13:09 +01:00