Commit Graph

19174 Commits

Author SHA1 Message Date
Peter Steinberger ec866d8abc fix(telegram): clear stale localized command menus (#120885)
* fix(telegram): clear stale localized command menus

* test(telegram): satisfy command menu lint
2026-08-08 22:14:58 -07:00
Peter Steinberger 6192673da4 perf(doctor): delete the heavy doctor barrel and finish slimming enumeration (#120882)
* refactor(plugin-sdk): delete the heavy runtime-doctor barrel

Nothing may pull the state-db/kysely graph through a doctor barrel anymore.
The barrel's remaining heavy exports move to two narrow private-local
subpaths, each with a single purpose:

- doctor-repair-runtime: install-path diagnosis, plugin config removal, and
  state-database schema detect/repair (matrix doctor, voice-call lazy import)
- plugin-state-store-runtime: the sync keyed-store factory. It stays out of
  plugin-state-runtime because hot channel entrypoints import that at module
  load and opening a store pulls the state-database graph.

Doctor closures also stop pulling ssrf-runtime (fetch-guard + gateway net)
for two legacy private-network helpers that live in the lighter ssrf-policy
subpath: mattermost, nextcloud-talk, tlon, matrix.

The closure guard now forbids the two new heavy subpaths instead of the
deleted barrel, so the invariant keeps being enforced where it still applies.

* perf(doctor): keep heavy graphs out of every doctor closure

Doctor enumeration cold-loads each declaring plugin's contract closure, so
one heavy import in a closure is paid by the whole sweep. Four barrels were
still dragging unrelated graphs in for trivial helpers; each is repaired at
the leaf rather than by caching downstream:

- Legacy private-network config migration moves to a config leaf. It only
  reshapes records, but lived beside the SSRF runtime (DNS, proxy, logging),
  costing mattermost ~2.7s. ssrf-policy re-exports it, surface unchanged.
- Streaming config readers move to a leaf. They read two config keys, but
  streaming.ts also formats tool aggregates, pulling tool-display/logging/
  acp-core; that cost slack ~2.3s.
- signal took the channel-secret barrel for isRecord; the canonical plugin
  record guard is string-coerce-runtime (root AGENTS.md).
- llm-task took the provider-model barrel for parseModelRef, now a narrow
  model-ref-parse subpath.

Full doctor enumeration of all 42 declaring plugins, built mode:
legacy config rules 6668ms -> 1265ms, state migrations 184ms -> 127ms.
No plugin remains an outlier; the slowest is now ~380ms against a ~200ms floor.

Public export surfaces of every touched SDK subpath are byte-identical
(verified by diffing built module exports before/after); the API baseline
hashes move only because re-exported declarations emit differently.

The closure guard gains rules for each repaired barrel so the invariant
holds for future closures.

* fix(release): exclude new private-local declarations from the published package

Same pack-path rule as c41da3759f: private-local subpaths ship without d.ts.

* fix(doctor): repair the closure guard violations that break main

The landed guard fails on main: three closures import heavy barrels for one
symbol each. Two more surfaced once the guard learned about the provider-model
barrel. Each gets a narrow subpath at the leaf:

- telegram sent-message-cache + state-migrations took the session-store barrel
  (session accessor + state-db) for resolveStorePath -> session-store-paths
- discord thread-bindings.state took the channel-outbound barrel (reply
  pipeline + channel registry) for one identity write -> outbound-echo-runtime
- discord model-picker took the provider-model barrel for normalizeProviderId,
  which model-ref-parse now exposes beside parseModelRef

The guard also stops walking artifacts of plugins whose manifest declares no
doctor surface. Such a declaration gates the artifact off every enumeration
path exactly as resolvePluginDoctorContracts does, so its closure cost is never
paid; anthropic ("doctorContract": {}) was being held to a cost it cannot
incur. Absent declarations still load eagerly and stay enforced.

Side effect worth naming: discord's built doctor contract now loads again.
On main both discord and telegram fail to require in packaged builds (an
ESM-only transitive dep) and silently lose their repairs; this restores
discord and takes enumerated legacy config rules from 87 to 99. Telegram's
built artifact still pulls execa through dist chunking - a build-level defect
with a different owner, filed as follow-up.
2026-08-08 22:01:44 -07:00
Peter Steinberger 7443882f45 refactor(chutes): move OAuth refresh into provider plugin (#120840)
* refactor(chutes): move OAuth refresh into provider plugin

* test(chutes): prove OAuth refresh load ordering
2026-08-08 21:50:25 -07:00
Peter Steinberger 6246f67784 refactor(clickclack): reuse session URL contract (#120810) 2026-08-08 21:22:51 -07:00
Peter Steinberger e1ec95dcbf refactor(auth): dedupe profile upserts and approval resolvers (#120831)
* refactor(auth): dedupe profile upserts and approval resolvers

* test(auth): mock canonical locked upsert

* test(auth): mock locked upsert during onboarding
2026-08-08 21:14:16 -07:00
Peter Steinberger 99ff5b20f7 fix(discord): keep forum replies in their created thread (#120857) 2026-08-08 20:45:21 -07:00
clawsweeper[bot] c121788611 fix(telegram): prioritize configured commands under menu pressure (#119717)
* fix(telegram): prioritize configured commands under menu pressure
* fix(telegram): preserve custom commands under localized menu pressure

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: ayeshakhalid192007-dev <ayeshakhalid192007@gmail.com>
2026-08-09 09:07:51 +05:30
Peter Steinberger c2e7c819f5 perf(doctor): slim remaining heavy doctor contract closures (#120811)
* perf(doctor): slim remaining heavy doctor contract closures

Follow-up to #120698: several doctor closures still cold-loaded multi-second
kysely-bearing graphs through other broad barrels (session-store-runtime,
realtime-voice, channel-outbound, logging-core, memory-host-core/-events,
sqlite-runtime, persistent-dedupe, and plugin-local barrels).

- lazy-import heavy helpers inside async migration bodies (codex, msteams,
  zalouser, workboard, matrix inbound-dedupe, memory-core migrations)
- bypass plugin-local barrels to defining modules (reef protocol,
  memory-core short-term-promotion)
- move to lighter existing subpaths (slack -> channel-streaming, matrix
  logger -> security-runtime, memory-wiki -> agent-scope-runtime, which now
  also exports resolveSessionAgentId)
- add narrow openclaw/plugin-sdk/realtime-voice-activation for discord's
  sync wake-name doctor rules
- split src/infra/kysely-sync-cache-state.ts so sqlite-transaction clears
  Kysely caches without value-loading kysely; split the memory-host-sdk
  kysely bridge off the schema/transaction bridge
- guard: forbid the heavy barrels in doctor closures with per-kind scoping

Cold enumeration per plugin: discord 52.6s->0.3s, msteams 30.9s->0.5s,
codex 29.6s->2.6s, zalouser 28.8s->2.3s, matrix 27.2s->3.2s,
slack 17.5s->1.5s, reef 9.9s->0.7s, memory-core 6.4s->3.6s,
workboard 3.4s->0.25s; all kysely-free except llm-task (named follow-up).

* fix(plugins): route slack streaming compat through a focused streaming-config subpath

The channel-streaming compat barrel is deprecated for extension production
code (deprecated-api-usage guard + SDK package contract). Add the narrow
non-deprecated openclaw/plugin-sdk/channel-streaming-config subpath for the
pure streaming config readers, and drop the now consumer-less
short-term-promotion barrel re-exports knip flagged.

* test(plugins): register memory-host-sdk kysely bridge in package boundary inventory

* fix(plugins): classify realtime-voice-activation as private-local

ClawSweeper P2: the subpath exports only a default target, which is the
private-local shape; register it in plugin-sdk-private-local-only-subpaths,
the package-boundary d.ts alias maps, and correct the public surface budgets
(realtime-voice-activation no longer counts as public).

* fix(release): exclude realtime-voice-activation declarations from the published package

Private-local subpaths ship without d.ts; register the files negation the
release pack-path check requires.
2026-08-08 20:28:58 -07:00
Peter Steinberger b7add0b560 fix(telegram): honor polling retry cooldown in watchdog (#120841) 2026-08-08 20:24:05 -07:00
Peter Steinberger 41a778d91a fix(browser): recover stalled Copilot gateway connections (#120839) 2026-08-08 20:20:14 -07:00
Peter Steinberger 673246c42a fix(google-meet): stop failed voice gateway connections (#120822) 2026-08-08 19:20:19 -07:00
Peter Steinberger fbdbe9c162 fix(mistral): reset transcription state after reconnect (#120813) 2026-08-08 18:59:23 -07:00
sunlit-deng 6287c88c3b fix(googlechat): reject invalid UTF-8 in API JSON responses (#120239)
… regression

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-08-08 20:54:17 -05:00
Peter Steinberger d52827a8c0 fix(google-meet): redial after completed voice calls (#120807) 2026-08-08 18:40:50 -07:00
Peter Steinberger a663063d4d fix(browser): reclaim stalled extension relay connections (#120806) 2026-08-08 18:37:05 -07:00
Peter Steinberger 75dbe52e3e refactor: one code path behind doctor legacy-state migrations (#120716)
* refactor(doctor): prefer manifest route-state owners

* refactor(doctor): unify config repair declarations

* refactor(doctor): unify legacy state migrations

* fix(doctor): satisfy migration pipeline guards

* fix(plugin-sdk): keep doctor adapter inside boundary
2026-08-08 18:23:15 -07:00
Peter Steinberger ba7561d25d fix(telegram): acquire polling queue before starting worker (#120800) 2026-08-08 18:20:04 -07:00
sunlit-deng 89c792bf64 fix(google): reject malformed video operation JSON (#115465)
* fix(google): reject malformed video operation JSON

* fix(google): reuse shared provider JSON reader for video operations

Route successful Google video operation responses through the canonical
readProviderJsonResponse so fatal UTF-8 decoding and malformed-JSON wrapping
stay on the shared provider contract. Keep the lenient non-OK detail path.
2026-08-09 04:15:39 +03:00
Peter Steinberger 23f36d27ee fix(discord): deduplicate directory peers across guilds (#120797) 2026-08-08 17:55:16 -07:00
Peter Steinberger 8cb53c7b55 perf(doctor): keep bundled doctor contract closures dependency-light (#120698)
* perf(doctor): keep bundled doctor contract closures dependency-light

Doctor contract enumeration cold-loads each plugin's doctor-contract-api
closure via jiti, so a static value import of openclaw/plugin-sdk/runtime-doctor
pulled the state-db/kysely graph (~4.3s per closure) into
listPluginDoctorLegacyConfigRules / listPluginDoctorStateMigrationEntries.

- migrate all light doctor-contract closures (66 files) to the
  dependency-light openclaw/plugin-sdk/runtime-doctor-migrations subpath
- voice-call: load detect/repairOpenClawStateDatabaseSchema* lazily inside
  the migration bodies; keep only a type-only static runtime-doctor import
- matrix: split pure credential record shapes/normalizers into
  credentials-state.ts so the doctor closure no longer imports the sync
  plugin-state store through credentials-read
- guard: doctor-contract-closure-guard.test.ts now forbids static value
  imports of runtime-doctor in closures alongside agent-runtime

* fix(matrix): keep credential revocation record type module-local

Knip production scan flags the export as consumer-less; the type is only
referenced by the exported union and revocation guard signature.
2026-08-08 17:51:31 -07:00
Peter Steinberger 970a82624a fix(elevenlabs): preserve repeated committed speech segments (#120792) 2026-08-08 17:38:29 -07:00
Peter Steinberger 2a7782674e fix(telegram): clean up every failed webhook startup phase (#120788) 2026-08-08 17:27:19 -07:00
Josh Avant a345ede685 fix(codex): preserve configured MCP tools in scheduled turns (#120366) 2026-08-08 19:25:39 -05:00
Peter Steinberger 5439732124 fix(discord): remove only the bot own reactions (#120785) 2026-08-08 17:21:03 -07:00
Peter Steinberger bb019e4a53 fix(providers): preserve realtime tool-result delivery ownership (#120776)
Co-authored-by: Wan Yong <wan.yong@xydigit.com>
2026-08-08 17:03:43 -07:00
Peter Steinberger fc1948dab5 fix(elevenlabs): surface realtime provider error events (#120772) 2026-08-08 16:58:30 -07:00
Peter Steinberger 4050fb02e0 fix(telegram): prevent session-count routing slowdown (#120774) 2026-08-08 16:54:25 -07:00
zengLingbiao 2289d9658a fix(diagnostics-prometheus): send Content-Length on metrics HEAD responses (#120212)
* fix(diagnostics-prometheus): send Content-Length on metrics HEAD responses

* fix(diagnostics-prometheus): harden HEAD metadata proof

Punchcard-Session: ember-willow-timber-gk

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

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-08-08 16:45:04 -07:00
Peter Steinberger 6972ef80b7 fix(telegram): classify hosted media size errors consistently (#120757) 2026-08-08 16:44:44 -07:00
Peter Steinberger b55e1e3a55 fix(imessage): preserve native attachment message identities (#120739) 2026-08-08 16:21:18 -07:00
Peter Steinberger 45dd558d92 fix(codex): prevent session handoffs and native tasks from losing thread ownership (#120740)
* fix(codex): preserve thread ownership across session lifecycles

* test(codex): keep canonical context-engine session fixtures

* fix(codex): fence replacement thread rollback by ownership

* fix(codex): fence thread handoffs by physical client ownership

* fix(codex): derive conversation privacy from its source session

* fix(codex): claim active native subagents at their lifecycle owner

* fix(codex): preserve conversation ownership when detach fails

* fix(codex): fence stale native child close notifications

* fix(codex): preserve active child ownership during rollback

* test(codex): keep lifecycle fixtures aligned with public contracts

* fix(codex): preserve rollback failure causes across ownership recovery

* fix(codex): retain aggregate rollback causes through lint analysis

* fix(codex): release native children when idle retention fails
2026-08-08 16:20:16 -07:00
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
Jason (Json) 68d625b278 fix: keep credentials out of assistant transcripts (#120728) 2026-08-08 16:24:02 -06: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
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 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 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
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
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 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
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
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
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
wanyongstar fe908cf309 fix(matrix): ignore out-of-range hex escapes in env account tokens (#120428)
* fix(matrix): ignore out-of-range hex escapes in env account tokens

decodeMatrixEnvAccountToken guarded String.fromCodePoint with
Number.isFinite, which does not bound the Unicode range: a MATRIX_*
env var whose _X<hex>_ escape exceeds 0x10FFFF (e.g.
MATRIX_A_X110000_B_HOMESERVER) threw RangeError out of
listMatrixEnvAccountIds, crashing discovery of every env-backed
Matrix account during startup and doctor checks. Escapes above the
Unicode max are now rejected like any other malformed token.

* chore(matrix): tighten decoder invariant comment

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

* chore(matrix): clarify decoder invariant

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

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-08 12:24:41 -07:00
Peter Steinberger 0487b6812c fix(qa): honor Crabbox SSH fallback ports (#120539) 2026-08-08 12:01:30 -07:00
Peter Steinberger 47f78a32eb fix(ai): preserve long Responses sessions after server compaction (#120457)
* fix(ai): preserve Responses server compaction state

Persist opaque Responses compaction items as fenced provider replay state so long stateless sessions can resume authoritative compressed history without exposing it in display or diagnostics. Carry state through worker transcripts and prune replay prefixes without splitting tool pairs.

Release note: Preserve long OpenAI Responses sessions across server-side compaction and worker restarts.

Related: #95788

* test(ai): align long-context fixtures with CI contracts

Make tool-result fixtures type-complete, use the canonical model selector helper, remove unused test-helper exports, and route the paid long-context live probe through the dedicated Gateway profile shard.

* test(ai): type mocked Responses terminal events

Give the mock SSE event collection an explicit open event shape so terminal response events coexist with output-item events under the root test typecheck.

* fix(ai): suppress rejected compaction replay

Persist a route-fenced suppression tombstone when encrypted-content recovery rejects a compaction item, so later turns do not retry the same opaque state. Preserve the tombstone through transcript redaction and cover successful fallback followed by the next turn.

* fix(ai): keep compaction suppression transport-private

Keep the suppression contract local to its sole Responses transport owner and make the regression fixture satisfy root type and lint checks without widening the Plugin SDK surface.

* refactor(ai): remove compaction suppression re-export

* fix(ai): scope compaction suppression to replay route

Keep foreign-route rejection tombstones from hiding the newest compatible Responses compaction while preserving same-route suppression.

* fix(ai): harden Responses replay recovery

Stage encrypted replay recovery so compaction is only suppressed after an attributable rejection. Preserve terminal ordering and keep provider replay within worker frame budgets without truncating opaque state.

* refactor(ai): centralize Responses output indexes

Keep normalized output identity tracking in the stream-slot owner, move response failure state to its diagnostic owner, and remove the obsolete replay clone export so exact-head static gates remain shrink-only.

* fix(ai): retain idless terminal tool identity

Use the canonical empty identity only when a provider supplies neither call nor item id, preventing terminal recovery from duplicating a done-only tool call while preserving stronger identities when available.

* fix(sessions): hide provider replay from public events

* fix(ai): stage encrypted replay recovery

* fix(ai): keep replay attempt kind internal

* fix(ai): route Azure through replay recovery

Use the shared encrypted-content retry owner for Azure Responses so compaction suppression and prompt-observer variants stay coherent across transports.

* fix(ai): harden replay persistence boundaries

Fence Azure replay by the resolved request endpoint, drop invalid replay during transcript sanitization, and surface worker-launch replay omissions through the existing redacted diagnostic path.
2026-08-08 11:55:26 -07:00
Peter Steinberger 01ae18c076 fix(clawrouter): honor advertised reasoning efforts (#120631) 2026-08-08 11:01:34 -07:00