Commit Graph

77250 Commits

Author SHA1 Message Date
Sarah Fortune cdaea2d6b6 fix(slack): route Enterprise Grid messages by workspace (#120087)
* fix(slack): route Grid messages by workspace

* fix(slack): use authorized Grid DM sender

* fix(slack): preserve ordinary client calls in grid routing

* test(slack): keep grid target coverage in scoped suite

* fix(slack): preserve workspace scope in approval routes

* feat(slack): scope Grid uploads and reactions by workspace

* fix(slack): preserve ordinary action read targets

* fix(slack): reuse Grid clients for thread status

* fix(slack): infer current Grid workspace for native actions

* fix(slack): record streamed thread participation promptly

* fix(slack): scope Grid member info to current workspace

* feat(slack): support Grid write actions

* feat(slack): support Grid read actions

* fix(slack): remove obsolete channel resolver

* fix(slack): route current Grid outbound delivery

* test(slack): cover Grid thread participation

* test(slack): use valid Grid team ID

* fix(slack): keep Grid thread participation without bot identity

* fix(slack): enable Grid pin reads

* fix(slack): keep current Grid sends workspace aware

* test(slack): assert Grid send routing synchronously

* refactor(slack): remove obsolete Grid action allowlist

* refactor(slack): derive Grid channel routing targets

* refactor(slack): pass optional team scope uniformly

* test(slack): expect uniform client options

* refactor(slack): name unscoped cache key explicitly

* refactor(slack): always pass action options

* refactor(slack): pass optional team scope directly

* refactor(slack): build team-scoped action options once

* refactor(slack): centralize optional team target formatting

* refactor(slack): construct reconciliation clients from scope

* refactor(slack): resolve delivery policy before sending

* refactor(slack): clarify inbound target roles

* refactor(slack): minimize validated event scope

* fix(slack): route outbound workspace through target

* fix(slack): format post response errors safely

---------

Co-authored-by: Sarah Fortune <sarah.fortune@gmail.com>
2026-08-08 15:38:24 -07:00
Peter Steinberger 08d2062c7f refactor(infra): fold node-pairing facade into device-pairing (#120726)
Completes docs/plan/runners.md milestone 1c by moving node-role pairing behavior and state access under device-pairing-owned modules while preserving shipped migrations.
2026-08-08 15:26:11 -07:00
Peter Steinberger eae4011205 fix(memory): close Windows session test fixtures (#120720) 2026-08-08 15:25:00 -07:00
Jason (Json) 68d625b278 fix: keep credentials out of assistant transcripts (#120728) 2026-08-08 16:24:02 -06:00
Peter Steinberger e70e43fadc fix: prevent LaunchAgent reinstall from leaving gateway down (#120699)
* fix(daemon): restore launchd install failures

* style: format launchd regression tests

* fix(daemon): guard cached launchd installs

* chore: leave changelog to release flow
2026-08-08 15:23:47 -07:00
Dallin Romney 33ea7ffa54 fix(ci): isolate package Telegram QA harness (#120193)
* fix(qa): isolate package Telegram harness

Keep private QA source, dependencies, taxonomy, and SDK dist in the trusted harness while the installed candidate owns its CLI, Gateway runtime, and persisted mock auth. Preserve the documented package RTT canary after taxonomy selection.

Co-authored-by: Dallin Romney <dallinromney@gmail.com>

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

* fix(qa): export private QA harness SDK entries

Canonicalize the QA-only plugin SDK entries shared by the private build and package Telegram harness manifest so qa-runtime and qa-lab resolve from trusted dist.

* fix(qa): expose private runtime to package harness

* fix(qa): surface Telegram observer conflicts

* fix(qa): accept separate preview and final messages

* test(qa): exercise Telegram poll delay contract

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-08-08 15:11:03 -07:00
Jason (Json) f66995cf42 fix: surface process terminal failures (#120724) 2026-08-08 16:10:30 -06:00
Vincent Koc ad664ad859 fix(release): match ClawHub security fixture contract (#120725) 2026-08-09 06:10:19 +08:00
Jason (Json) b550c140c7 fix(context-engine): avoid legacy self-degradation (#120722) 2026-08-08 16:06:26 -06:00
Peter Steinberger fb911a33ac fix(system-agent): keep inference available across routes (#120712)
* fix(system-agent): keep inference available across routes

Accept provider-owned equivalent response model identities and route every new OpenClaw chat through the configured/authenticated inference fallback ladder. Malformed replies may fall through while provider/model and execution-owner uncertainty remain fail-closed.

Fixes #120711

* fix(system-agent): keep malformed fallback route-scoped

Continue to later configured routes from the same provider after empty or malformed model output. Timeout and unavailable results remain provider-wide, while owner and identity uncertainty remain fail-closed.

Addresses ClawSweeper P1 on #120712.
2026-08-08 15:05:19 -07:00
Peter Steinberger 51944498eb refactor(gateway): generalize bulk session patches (#120629)
* refactor(gateway): generalize bulk session patches

* fix(gateway): normalize bulk session fences

* refactor(gateway): simplify normalized target fence

* test(ui): align disconnected session wording
2026-08-08 15:00:09 -07:00
Shakker 50ee791a8a test: cover responsive file preview content states (#116885) 2026-08-08 22:57:46 +01:00
Peter Steinberger c8b5df08eb fix(ui): preserve responsive preview and modal owner layouts 2026-08-08 22:57:46 +01:00
clawsweeper[bot] b067311551 fix(agents): record stop reason in completion trajectory (#118685)
* fix(agents): record stop reason in completion trajectory

* fix(agents): record stop reason in completion trajectory

* fix(agents): record stop reason in completion trajectory

* fix(agents): record stop reason in completion trajectory

* fix(agents): record stop reason in completion trajectory

* fix(agents): record stop reason in completion trajectory

* fix(agents): record stop reason in completion trajectory

* fix(agents): record stop reason in completion trajectory

* fix(agents): record stop reason in completion trajectory

* fix(agents): record stop reason in completion trajectory

* fix(agents): record stop reason in completion trajectory

* fix(agents): record stop reason in completion trajectory

* fix(agents): normalize completion trajectory outcomes

* fix(agents): preserve terminal outcome ownership

* refactor(agents): simplify trajectory completion paths

* test(agents): tighten trajectory outcome matrix

* fix(trajectory): isolate partial export tails

* fix(trajectory): preserve yield and partial-tail ownership

* fix(trajectory): preserve terminal precedence

* fix(trajectory): align terminal status and reason

* fix(trajectory): bound reused-run partial tails

* test(trajectory): cover terminal-only export tails

* fix(trajectory): anchor terminal-only cohorts

---------

Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-08 14:51:50 -07:00
ruel225 2696914aea fix(gateway): target requestHeartbeat to the hook's agentId (#119808) (#119819)
* fix(gateway): target requestHeartbeat to the hook's agentId

Two requestHeartbeat calls in the hook handler (reportHookFailure and
the announce path) did not pass value.agentId or sessionKey, so a hook
targeting one agent woke heartbeats on every configured agent. Pass
the hook's agentId and resolved sessionKey so the wake is scoped to
the agent the hook actually names. (#119808)

* fix(gateway): align fallback hook wake target

Co-authored-by: ruel225 <ruel225@users.noreply.github.com>

* fix(gateway): preserve global hook wake routing

Co-authored-by: ruel225 <ruel225@users.noreply.github.com>

---------

Co-authored-by: ruel225 <ruel225@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-08 14:50:36 -07:00
Peter Steinberger 2fd7c4fea7 refactor(ui): rename stale delete-confirm surface to confirmed-action after hide removal (#120719)
The rewind-only confirmation popover kept "delete" naming from the removed
local-only hide feature (#120681). Rename identifiers and DOM/CSS classes to
confirmed-action, drop the dead right-side placement variant, collapse the
single-caller renderConfirmedActionButton indirection into renderRewindButton,
and localize the hardcoded Cancel / Don't ask again strings.

The openclaw:skip-rewind-confirm localStorage preference key is intentionally
unchanged so users' "Don't ask again" choice survives.
2026-08-08 14:48:50 -07:00
Peter Steinberger 909509a5db fix(codex): resume catalog sessions with the catalog's CODEX_HOME; add main-content terminal placement (#120708)
* fix(codex): pin catalog CODEX_HOME onto terminal resume spawns

The Codex session catalog lists threads through the plugin's supervision
app-server connection, which can run on the agent-scoped Codex home
(homeScope: "agent"). The terminal resume plan spawned a bare
'codex resume <threadId>' under the operator login shell, so the CLI
resolved its default ~/.codex and failed with "No saved session found".

Terminal plans now carry the catalog connection's CODEX_HOME (local and
paired-node paths), the gateway merges plan env into the PTY spawn, and
the triplicated home-scope resolution collapses into one shared
resolveCodexAppServerLocalHomeDir.

* feat(ui): add main-content terminal placement

The terminal panel gains a third dock placement, "main", filling the
content region next to the sidebar like the transcript pane. The panel
header gets a bottom/right/main placement switcher (persisted in the
existing openclaw.terminal.panel.v1 store), and opening a Codex/Claude
session from the session catalog selects main mode so resumed sessions
appear as a full window instead of a bottom strip.
2026-08-08 14:33:20 -07:00
Peter Steinberger 36c6b854eb fix(openai): honor explicit service tier over fast mode (#120696) 2026-08-08 14:26:54 -07:00
Vincent Koc b729806758 fix(release): preserve ClawHub fixture across restart (#120709) 2026-08-09 05:26:16 +08:00
Peter Steinberger e4ff0d67f4 fix(telegram): unblock chats after media claim timeout (#120706)
Claim-owned cancellation now stops pre-adoption media hydration, allowing later same-chat messages to proceed. Webhook handling now uses the canonical Telegram adoption stall timeout.

Fixes #120704.
2026-08-08 14:25:38 -07:00
xin zhuang 2f76ec387a fix: process poll leaves notify-on-exit completion queued (#120585)
* fix(exec): acknowledge notify-on-exit after process poll

* test(exec): mock completion event enqueue

* fix: retire stale exec heartbeat wakes

Prevent acknowledged process completions from turning their queued wake into an unrelated heartbeat. Preserve coalesced task work and keep stale wakes out of scheduler cadence and commitment follow-up.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* test: isolate stale exec heartbeat coverage

Keep existing heartbeat suites below the max-lines ratchet while retaining coverage for stale wake coalescing, scheduler bookkeeping, and commitment fan-out.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(heartbeat): preserve scheduled cadence for stale exec wakes

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* test(heartbeat): keep stale wake coverage within lint limits

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(heartbeat): retire stale exec wakes before busy gates

Preserve scheduled cadence and cron work when coalesced exec wakes are acknowledged, while retiring stale wakes before retryable busy checks.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(heartbeat): accept inferred wake sources

Allow stale-wake preflight to handle the optional source produced by reason inference without weakening the exec-event check.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-08-08 16:23:47 -05:00
Peter Steinberger e6353d85ef fix(daemon): drop stale service version metadata (#120702) 2026-08-08 14:14:22 -07:00
Peter Steinberger cf69593afe fix(cloud-workers): start sessions when primary SSH port is unavailable (#120546)
* fix(cloud-workers): honor Crabbox SSH fallback ports

Select a currently reachable advertised SSH endpoint before returning a Crabbox worker lease, while preserving fail-closed teardown. Allow deletion of failed cloud sessions only after the environment record proves the provider lease is gone, and align the Cloud Workers docs with the shipped configuration and Control UI flow.

* fix(cloud-workers): retry advertised SSH endpoints

Persist provider-advertised SSH fallback ports and retry them through the shared pinned transport used by bootstrap, tunnels, reconnects, and workspace transfers. Keep candidate selection provider-neutral, preserve identity and host-key fencing, and add the same-version SQLite column through the existing additive migration path.

* fix(crabbox): recheck SSH readiness after setup

Treat provider setup as a mutating lifecycle phase: refresh authoritative inspect state and wait for SSH readiness again before returning the lease. This prevents bootstrap from racing setup-triggered SSH restarts on fresh and replayed workers while preserving security attestation and fail-closed teardown.

* fix(cloud-workers): retry bootstrap transfers across ports

Use the shared advertised-port candidate runner for bundle transfer, install, and best-effort upload cleanup as well as preflight. This keeps fresh bootstrap connections on pinned identity and host-key semantics when a previously selected SSH port disappears between phases.

Proof passed: 517 focused tests (1 skipped), final autoreview/TruffleHog clean, targeted lint/format. Full check-changed reached the unrelated max-lines baseline drift on current origin/main: this branch's merge base contains ui/src/pages/chat/components/chat-model-controls.ts while current origin/main removed that baseline entry; do not touch the unrelated baseline.

* fix(cloud-workers): persist fallback ports compatibly

Create the fallback-port companion table lazily as an additive surface, preserving downgrade tolerance for binaries that still expect the older shared-state schema.

* fix(cloud-workers): preserve bundle artifact narrowing

Bind the immutable discriminated artifact before the SSH retry callbacks so bundle-only fields remain narrowed across fresh candidate invocations. Use the shared temp-directory owner in the tunnel fallback test for deterministic cleanup.

* fix(cloud-workers): retire deleted placements

Terminal placement rows retire by exact CAS after session deletion, and managed AWS docs now pin the Gateway SSH CIDR.

* fix(crabbox): await pending AWS attestation

missing authoritative metadata is pending only while the lease is non-ready; ready leases still require explicit false.

* fix(cloud-workers): fence remote command retries

require explicit idempotent/never classification; remote worker launch never retries after ambiguous SSH loss.

* fix(cloud-workers): bound SSH fallback operations
2026-08-08 14:03:36 -07:00
Dirk 57b0e29a2d fix(gateway): preserve board widget HEAD metadata (#120177)
Punchcard-Session: crisp-valley-summit-k6

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-08 13:58:14 -07:00
Peter Steinberger 4930c9d7de refactor(ui): remove local-only chat message hide feature (#120681)
Remove the localStorage-backed per-browser hide action ("Hide in this browser only") so the transcript mirrors agent context. The action was un-undoable because restore() had no UI path.

Stale openclaw:deleted:* localStorage keys become inert.
2026-08-08 13:57:15 -07:00
Peter Steinberger 29a446f886 fix(agents): apply global fast mode to implicit agent (#120697) 2026-08-08 13:55:57 -07:00
Peter Steinberger 21a9428a8a fix(identity): prevent cross-runtime device identity races (#120643)
* fix(identity): coordinate SQLite ownership across runtimes

* fix(ci): route changed-scope fixture tests
2026-08-08 13:55:15 -07:00
Peter Steinberger 99afb31626 fix(ui): reveal question prompts without scroll overlap (#120695)
Question panels now use normal footer flow. Resize following respects explicit backscroll intent, and the latest-message affordance stays above footer surfaces.
2026-08-08 13:54:06 -07:00
Peter Steinberger 47fd629c8d feat(gateway): persist per-origin device auth (#120533)
* feat(gateway): add per-origin device auth

* fix(ui): remove unused gateway scope alias

* test(tui): split gateway chat coverage

* test(tui): update connection test routing

* fix(auth): preserve legacy device auth migration guard
2026-08-08 13:53:31 -07:00
Simone f7d31bdc56 fix(xai): keep voice turns working after malformed terminal output (#120002)
* fix(xai): tolerate malformed terminal output

* test(xai): prove malformed terminal recovery over websocket

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-08 13:52:29 -07:00
Masato Hoshino 7a30b5d0da fix(matrix): ignore a non-positive mediaMaxMb instead of capping media at 0 bytes (#120466)
resolveMediaMaxBytes treated any number as an explicit cap, so
channels.matrix.mediaMaxMb: 0 became a literal 0-byte limit and every
outbound media send failed before upload, while inbound media on the same
account kept working because monitor/index.ts already floors the same field
with Math.max(1, mediaMaxMb).

Only a positive value is a cap now, matching CommonMediaMaxMbSchema; other
values fall through to the existing unset path (per-kind defaults). matrix
is one of three bundled channels that hand-roll this field without a range
constraint, so the config loads without complaint today.
2026-08-08 13:47:52 -07:00
Peter Steinberger f15ce3941f refactor(ui): devices is the user-facing word for paired hardware (#120689)
Implements docs/plan/runners.md milestone 1b.
2026-08-08 13:47:17 -07:00
clawsweeper[bot] 0f43212fb4 fix(process): disclose omitted retained output in finished polls (#120583)
* fix(process): disclose omitted retained output in finished polls

* fix(process): disclose capped pending poll output

Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>

---------

Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-08 13:45:40 -07:00
Peter Steinberger f25385fcda fix(ui): contain transcript focus ring (#120693) 2026-08-08 13:45:18 -07:00
Ayaan Gazali 51960f6579 docs(discord): drop retired ui.components.accentColor and fix heartbeat key name (#118216)
* docs(discord): drop retired ui.components.accentColor and fix heartbeat key name

* docs(discord): remove the retired accent-color example block

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-08 13:43:37 -07:00
wangmiao0668000666 20fe56116d fix(cli): refresh running gateway auth state after models auth order set/clear (#119946)
* fix(cli): refresh running gateway auth state after models auth order set/clear (#114989)

The order set/clear commands wrote the agent auth-profile store from the
CLI process but never notified a running gateway, which keeps serving its
pre-mutation auth snapshot until restart. Sibling auth mutations
(login/logout/profile add) already call refreshRunningGatewayAuthState;
align order set/clear with that contract.

* style: format auth-order.test.ts with oxfmt
2026-08-08 13:43:16 -07:00
Peter Steinberger 8c059f95c5 fix(slack): bound channel member cursor pagination (#120686) 2026-08-08 13:40:07 -07:00
Peter Steinberger 1802d85f3c fix(openai): reject invalid OAuth token response envelopes (#120685)
Validate token response envelopes once in the shared parser used by authorization-code exchange and refresh. Prove null and array responses through both production entry points over real loopback HTTP.

Refs: #120174

Co-authored-by: 毛宇豪0668001457 <mao.yuhao@xydigit.com>
2026-08-08 13:37:33 -07:00
Vincent Koc e455cafa13 fix(release): run ClawHub prepublish fixture from isolated cwd (#120692) 2026-08-09 04:36:14 +08:00
Peter Steinberger da4a656cdb improve: doctor migration checks no longer load every bundled plugin runtime (#120678)
* perf(plugins): declare doctor contract surfaces

* perf(doctor): slim migration import closures

* perf(plugins): narrow doctor declaration record surface and wire owner-test lane

Registry records carry only the doctorContract declaration instead of the whole
parsed manifest, and check:changed now selects the src/plugins-owned declaration
honesty and closure-guard tests for extension module/manifest changes so
cross-lane drift cannot pass PR classification.

* fix(doctor): keep control-plane dist imports require-safe

Keep doctor and channel control-plane chunks off exec-class dependencies, and enforce native require(esm) loading during postbuild.

* chore(plugin-sdk): regenerate API baseline

* chore(plugin-sdk): sync export ordering

* fix(plugins): satisfy doctor contract CI boundaries

* perf(doctor): make qqbot doctor closure dependency-light

qqbot was the last plugin above 5s in doctor state-migration enumeration
(~8s under tsx/jiti). The cost was not the state-key builder (already a
leaf): its doctor closure value-imported the runtime-doctor SDK barrel,
whose plugin-state-store/state-db re-exports pull kysely (~330 modules),
plus security-runtime for one fileExists (~200 modules), all resolved
per-module by jiti during enumeration.

Split the migration-define helpers and light re-exports into a new
private-local plugin-sdk/runtime-doctor-migrations subpath; runtime-doctor
re-exports it so its public surface is byte-identical (API baseline hash
unchanged). qqbot's doctor-contract and state-migrations now import only
the light subpath, swapping fileExists for the equivalent async
legacyStateFileExists already in the closure.

qqbot enumeration: ~8.0s/531 modules -> ~0.25s/18 modules.

* chore(plugin-sdk): drop private-local subpath from API baseline

runtime-doctor-migrations is private-local-only; the baseline tracks public
modules, and the earlier line was generated before the classification.

* fix(plugins): register runtime-doctor-migrations boundary paths

The private-local subpath list feeds the extension package boundary map;
the shared paths config and xai's derived overrides must carry the same
entry or the boundary contract test fails.
2026-08-08 13:29:18 -07:00
licheer-zte bb23b6b5ca fix(doctor): skip legacy main transcript check for SQLite-owned sessions (#119940)
* fix(doctor): skip legacy main transcript check for SQLite-owned sessions

After the SQLite session import, the main session's legacy .jsonl is
archived and 'sessions cleanup' prunes it as unreferenced, but doctor
still warned 'Main session transcript missing' because the main-session
check required the legacy file. The sibling recent-session check already
skips SQLite-owned keys; apply the same ownership guard to the main
session so doctor and cleanup agree. (#119926)

* style(doctor): condense SQLite ownership comment

Co-authored-by: 李琪0668001400 <li.qi16@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-08 13:24:02 -07:00
Vyctor H. Brzezowski 8afd126577 docs: simplify Release and CI navigation (#120684) 2026-08-08 17:23:43 -03:00
wanyongstar 16ab7e8b4a fix(slack): route directory cursor pagination through the shared guard (#120445)
listSlackDirectoryPeersLive/listSlackDirectoryGroupsLive hand-rolled
do/while loops with no repeated-cursor detection and no page bound,
while every other users.list/conversations.list consumer goes through
collectSlackCursorPages. A Slack API or proxy edge that keeps
returning the same non-empty next_cursor made directory queries
paginate forever, growing the member/channel arrays without bound.
Both loops now go through collectSlackCursorPages, which throws on a
repeated cursor and caps total pages.
2026-08-08 13:20:37 -07:00
Peter Steinberger 6f94e7b23d docs: clarify OpenAI fast mode precedence (#120682) 2026-08-08 13:14:10 -07:00
Peter Steinberger 83e24f8421 fix(llm-core): settle result() when a stream ends without a terminal event (#120508)
* fix(llm-core): settle result() when a stream ends without a terminal event

EventStream.end() with no argument and no prior terminal event left the final
result promise pending forever; any consumer awaiting result() dead-ended
silently for the whole run budget (the agent loop's fall-through in
streamAssistantResponse awaits exactly that promise). All in-repo pumps push
terminals or pass end(result), so this only fires on producer contract
violations — which previously hung and now reject loudly with a named error.
A pre-attached catch keeps iterate-only consumers free of unhandled
rejections. Also dedupe the agent loop's two identical final-message blocks
into one finalizeAssistantMessage helper (net-negative production delta).

Follow-up from #120426's turn-liveness investigation.

* fix(llm-core): void the intentional rejection pre-catch

ClawSweeper P1: the pre-attached no-op catch returns a Promise that would
float under typescript/no-floating-promises.
2026-08-08 13:07:58 -07:00
Vincent Koc 33a5f37937 fix(release): repair survivor fixture assertion quoting (#120680) 2026-08-09 03:53:51 +08:00
wanyongstar 9c3e4ce431 fix(browser): bound batch action nesting depth in act request normalization (#120274)
* fix(browser): bound batch action nesting depth in act request normalization

normalizeActRequest recursed over batch nesting with no depth bound, so a
~1MB POST /act body with tens of thousands of nested batch levels parsed
fine and then crashed normalization with RangeError: Maximum call stack
size exceeded before the ACT_MAX_BATCH_ACTIONS count check could run,
surfacing an internal stack overflow as the 400 validation message.

Thread the existing ACT_MAX_BATCH_DEPTH limit through normalizeBatchAction/
normalizeActRequest and reject deeper nesting up front with a clear
'batch nesting exceeds maximum depth of 5' error, matching the bound the
Playwright executor already enforces at dispatch time.

* fix(browser): match batch depth executor boundary

Accept the six wrapper levels supported by the Playwright executor and reject the seventh during request normalization.

Co-authored-by: 万拥 0668000723 <wan.yong@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-08 12:52:59 -07:00
Peter Steinberger 0b85f9c174 feat: resolve short session references in the gateway (#120512)
* feat(gateway): resolve short session references

* refactor(ui): delegate short session resolution to gateway

* fix: complete short session resolver integration

* fix(gateway): filter deleted-agent short sessions

* fix(ui): support older gateway short links

* docs(web): qualify short-link candidate limits for older gateways

* refactor(protocol): split session resolve schema

* fix(gateway): filter session resolver visibility
2026-08-08 12:52:06 -07:00
Peter Steinberger 1609ae9b62 fix(gateway): refresh active session listings (#120424) 2026-08-08 12:52:00 -07:00
Peter Steinberger fb608005b5 fix(update): log campaign lifecycle for debugging (#120669) 2026-08-08 12:51:51 -07:00