Commit Graph

52066 Commits

Author SHA1 Message Date
Vincent Koc
367d584ee3 fix(installer): install node with apk on alpine 2026-05-24 23:03:12 +02:00
Vincent Koc
acfed375ee fix(installer): detect musl linux shells 2026-05-24 22:47:05 +02:00
Dallin Romney
8ccb11cbfc perf(plugins,gateway): thread metadata snapshot + discovery through hot paths + plugin owner fixes (#84649)
* perf(plugins): thread metadata snapshot and discovery through hot paths

With the snapshot memo now actually hitting, route the snapshot's
manifestRegistry and discovery through the helper chains that already
had fast paths for them. Eliminates redundant per-call rebuilds at
two big amplifiers.

- Provider resolve paths (resolvePluginProviders /
  isPluginProvidersLoadInFlight / resolveOwningPluginIdsForProvider /
  resolveExternalAuthProfilesWithPlugins) self-service a snapshot once
  at the public entry, then thread it as a separate required arg
  through resolvePluginProviderLoadBase,
  resolveExplicitProviderOwnerPluginIds, and the setup/runtime load
  state helpers. Inner reads change from
  'params.pluginMetadataSnapshot?.x' to 'snapshot.x', no more
  enrichedParams clone. loadPluginManifestRegistryForInstalledIndex
  fires drop ~685 -> ~10 per cold start.

- Bundled-channel / auto-enable chain accepts an optional
  PluginDiscoveryResult. discoverOpenClawPlugins is fired once during
  snapshot building (resolveInstalledPluginIndexRegistry already
  produced it internally; now bubbled up through
  loadInstalledPluginIndexWithDiscovery, PluginRegistrySnapshotResult,
  and onto PluginMetadataSnapshot.discovery). load-context reads
  metadataSnapshot.discovery and passes it through
  applyPluginAutoEnable, so the bundled-channel cascade
  (collectConfiguredChannelIds, listBundledChannelIdsWith*,
  listPotentialConfiguredChannelPresenceSignals) short-circuits
  instead of each leaf re-firing discovery. Persisted-cache path is
  unchanged: no discovery on the snapshot, downstream chain handles
  its own fallback (pre-PR behavior on that path).

* test(plugins): isolate snapshot memo across tests that mock manifest registry

The snapshot memo is now process-scoped and effective (~98% hit rate).
Three test files were depending on cache misses (because the broken
cache returned them) — each test would set up its own
loadPluginManifestRegistry mock and expect a fresh derive. With the
cache fixed, an earlier test's mocked registry now leaks into later
tests in the same file.

- io.write-config.test.ts: afterEach now clears the snapshot memo so
  the 'demo' plugin mocked in the first test does not survive into
  'keeps shipped plugin install config records when index migration
  fails', which expects an empty registry to surface the 'plugin not
  found: demo' warning.

- gateway/model-pricing-cache.ts: resetGatewayModelPricingCacheForTest
  also clears the memo. Tests in model-pricing-cache.test.ts assert
  loadPluginManifestRegistryForInstalledIndex was called; the memo
  hit otherwise skips the call.

- providers.test.ts: vi.doMock loadPluginMetadataSnapshot to wrap the
  existing loadPluginManifestRegistryMock fixture. The plumbing
  commit added an auto-fetch fall-through in
  resolveOwningPluginIdsForProvider; without the mock, providers
  tests hit real disk reads and return empty registries (which is
  what surfaced as 9 unrelated-looking failures in the prior CI
  run).

* fix(plugins): preserve setup.cliBackends owner matching in provider scan

resolveOwningPluginIdsForProvider now also checks plugin.setup?.cliBackends.
The pre-PR no-registry fallback used resolvePluginContributionOwners which
includes both top-level cliBackends and setup.cliBackends; the PR's manifest
scan replacement was missing the setup case.

* fix(plugins): inherit active registry workspaceDir before loading metadata snapshot

isPluginProvidersLoadInFlight and resolvePluginProviders now resolve
env and workspaceDir once at the entry point (falling back to
getActivePluginRegistryWorkspaceDir) and pass them into both
loadPluginMetadataSnapshot and resolvePluginProviderLoadBase. Pre-fix
the snapshot used params.workspaceDir raw while the load base inherited
the active workspace, so workspace-scoped provider plugins could be
absent from the snapshot manifest registry even though owner resolution
expected them.

Regression test asserts the snapshot mock receives the active
workspaceDir when the caller omits it.

* perf(gateway): thread discovery into applyPluginAutoEnable call sites

Every gateway applyPluginAutoEnable call now passes the snapshot's
PluginDiscoveryResult so the bundled-channel cascade (collectConfiguredChannelIds
→ listBundledChannelIdsWith* → listPotentialConfiguredChannelPresenceSignals)
short-circuits instead of each leaf re-firing discovery.

Startup-time sites pull discovery from the snapshot/lookup-table they already
hold:
- server-plugin-bootstrap.ts (pluginLookUpTable)
- server-startup-plugins.ts (pluginMetadataSnapshot)
- server-startup-config.ts (pluginMetadataSnapshot)
- server-plugins.ts (pluginLookUpTable, both call sites)

Per-RPC sites (server.impl getRuntimeConfig callback, server-methods/channels
status + start handlers, server-methods/send) source discovery via
getCurrentPluginMetadataSnapshot using the runtime config to validate
compatibility. Falls through to the original slow path when the snapshot is
absent or incompatible.
2026-05-24 13:44:03 -07:00
Vincent Koc
8bf4f7d4a8 fix(ui): split control ui runtime chunks 2026-05-24 22:20:33 +02:00
tanshanshan
fe34141a3d refactor(config): extract GoogleChat schema into zod-schema.providers-googlechat.ts (#82100)
Merged via squash.

Prepared head SHA: 7555272656
Co-authored-by: tanshanshan <22539261+tanshanshan@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-05-24 23:03:35 +03:00
Vincent Koc
6cc8244333 fix(update): suppress internal handoff version warnings 2026-05-24 21:42:42 +02:00
Vincent Koc
0acc3e3216 test(e2e): select installable bundled plugins 2026-05-24 21:36:08 +02:00
Vincent Koc
43252c8099 fix(scripts): harden Windows native opus install 2026-05-24 21:28:09 +02:00
Brian Potter
efd88dc00d fix(agents): match runtime policy entries when session provider is empty (#85970)
Merged via squash.

Prepared head SHA: 1f081b3a8c
Co-authored-by: potterdigital <197414865+potterdigital@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-05-24 22:01:21 +03:00
Vincent Koc
0a98559440 fix(scripts): harden Windows generated formatting 2026-05-24 20:50:07 +02:00
David
07f500aa56 fix(mcp): bound tools/list during catalog discovery (#85063)
Summary:
- The branch adds a 1500 ms internal timeout to bundled MCP `tools/list` catalog discovery, adds slow and hung stdio MCP regression tests, and records the fix in `CHANGELOG.md`.
- PR surface: Source +2, Tests +216, Docs +1. Total +219 across 3 files.
- Reproducibility: yes. The current-main source path is high confidence: bundled MCP connects successfully, then calls `client.listTools` without request options, and the upstream SDK defaults that request to 60000 ms.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(mcp): use internal tools list timeout
- PR branch already contained follow-up commit before automerge: fix(mcp): bound tools/list during catalog discovery
- PR branch already contained follow-up commit before automerge: fix(clawsweeper): address review for automerge-openclaw-openclaw-8506…

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

Prepared head SHA: bbbfb9f059
Review: https://github.com/openclaw/openclaw/pull/85063#issuecomment-4511554739

Co-authored-by: nxmxbbd <32288+nxmxbbd@users.noreply.github.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-05-24 18:37:28 +00:00
Vincent Koc
dfa1a51225 fix(test): focus plugin binding Docker smoke 2026-05-24 20:28:43 +02:00
Vincent Koc
a4fab83b55 test(e2e): fail release memory indexing errors 2026-05-24 20:12:43 +02:00
Vincent Koc
af07769871 test(daemon): fail launchd integration bootstrap errors 2026-05-24 19:57:59 +02:00
Omar Shahine
5c7980fa11 feat(imessage): support thumb approval reactions (#85952)
* feat(imessage): support thumb approval reactions

Mirrors openclaw#85477 (WhatsApp) for the iMessage channel. iMessage can now
deliver exec/plugin approval prompts via the existing imsg/BlueBubbles
transport and resolve approvals from 👍 (allow-once) / 👎 (deny) tapbacks.
Allow-always remains on the manual /approve <id> allow-always fallback.

What changed:
- New approval surfaces under extensions/imessage/src/:
  approval-auth.ts, approval-resolver.ts, approval-reactions.ts,
  approval-handler.runtime.ts, approval-native.ts (+ tests for each).
- channel.ts wires base.approvalCapability to the new iMessage capability.
- send.ts appends the 👍/👎 hint to outbound /approve prompts and registers
  the reaction binding (keyed by accountId + chat_guid/chat_identifier/
  chat_id/handle + messageId) after a successful send.
- monitor/monitor-provider.ts resolves approval reactions ahead of the
  normal inbound decision pipeline so resolution bypasses
  reactionNotifications gating and runs its own actor authorization.
- runtime.ts now exports getIMessageRuntime / getOptionalIMessageRuntime so
  approval-reactions can open a persistent keyed store for binding state
  across gateway restarts.

What did NOT change:
- Core approval surfaces in src/gateway/server-methods/* and src/infra/*
  remain channel-agnostic; the channels.imessage.allowFrom field already
  exists and is reused as the approver list for reactions.
- Other channels and the manual /approve sender-authorized path are
  untouched.

* fix(imessage): address codex review findings on thumb approvals

Addresses 15 findings from the multi-angle codex review:

Critical (correctness / blocking):
- Register CHANNEL_APPROVAL_NATIVE_RUNTIME_CONTEXT_CAPABILITY in the iMessage
  monitor so the gateway can actually deliver native approval prompts via
  approval-handler.runtime.ts (it was dead code without the context lease).
- DM tapback approvals never resolved because send keyed by handle while
  inbound preferred chat_guid. Register and look up under EVERY available
  conversation key (chat_guid / chat_identifier / chat_id / handle); inbound
  probes them all and accepts the first hit.
- Reaction binding now requires the bridge's GUID string (rejecting numeric
  ROWIDs) so the binding key matches inbound reacted_to_guid.
- Outbound regex now requires both a canonical `ID: <approvalId>` header AND
  a matching `/approve <id> <decision>` line, so non-approval messages that
  legitimately mention /approve syntax no longer get a phantom reaction
  binding (and can no longer resolve a colliding live approval).
- Drop is_from_me reaction events so cross-device echoes of the operator's
  own tap cannot self-approve when their handle is in allowFrom.

High (operability / cleanup):
- Non-ApprovalNotFound errors now log at warn via the runtime child logger
  (no longer hidden behind OPENCLAW_LOG_LEVEL=debug).
- In-memory binding is cleared on successful resolve so a toggle 👍👎 (or
  chat.db replay) does not refire and emit a misleading 'expired approval'
  log line. Removed tapbacks are also owned by the shortcut and not surfaced
  as noisy reaction system events.
- Move resolveIMessageReactionContext (and its helpers) to a slim
  monitor/reaction-context.ts so approval-reactions.ts no longer transitively
  pulls monitor/inbound-processing.ts (14+ heavy runtime modules) into the
  hot channel.ts entrypoint per extensions/CLAUDE.md.

Medium (consistency / future-proofing):
- Native runtime exec pending payload now passes agentId, ask, and
  sessionKey through buildExecApprovalPendingReplyPayload so the two
  delivery routes produce identical operator-visible prompts.
- Both delivery paths now use addIMessageApprovalReactionHintToText (single
  insertion point after ID:) so the hint cannot be double-emitted by the
  native runtime path bypassing the idempotency guard.
- Extract replaceApprovalIdPlaceholder into a shared approval-text.ts that
  escapes `$` in the replacement string so an approvalId containing
  `$&`/`$1`-`$9`/`$$` cannot interpolate into the outbound text.
- In-memory Map now stores TTL alongside each entry and prunes expired
  bindings on each register so the gateway no longer accumulates an
  unbounded reaction-target Map.
- bindPending refuses to bind when accountId is missing or the approval is
  already expired, with explicit error logs instead of silent no-ops.
- Reject chat_id=0 as a synthetic key value (chat.db ROWIDs start at 1).
- Drop dead getIMessageRuntime export — only the optional accessor is used.

Documentation:
- docs/channels/imessage.md gains an 'Approval reactions (👍 / 👎)' accordion
  documenting the reaction emoji map, allowFrom approver requirement, the
  /approve <id> allow-always manual fallback, and the deliberate change to
  /approve command authorization for users with non-empty allowFrom.
- CHANGELOG.md entry added under 2026.5.24.

Tests: 411 iMessage tests pass (was 406). Added explicit coverage for the
DM key-mismatch fix, the regex-tightening fix, the is_from_me guard, the
clear-on-success behavior, and the approval-id `$` escape.

* test(imessage): match WhatsApp approval-native test coverage

Backfills the nine cases from extensions/whatsapp/src/approval-native.test.ts
that weren't mirrored in iMessage:

- target-mode exec + plugin prompt rendering with the canonical hint
- target-mode availability when no iMessage target matches
- agentFilter / sessionFilter applied to native handling
- account-scoped target enabled/disabled per account
- shouldSuppressForwardingFallback session-origin exact-match cases
- shouldSuppressForwardingFallback off when native cannot bind (locks down
  the targets-only forwarding path the Lobster live deploy exercised)
- both-mode explicit + unscoped target suppression
- group-origin tapback approvals require explicit approvers

Tests: extensions/imessage/src/approval-native.test.ts 21 passed (was 11).
Total iMessage approval-specific cases now 49 (was 40).

* fix(imessage): preserve service-prefixed direct handles as approvers

ClawSweeper P1 review finding on #85952. normalizeIMessageApproverId was
calling looksLikeIMessageExplicitTargetId() to reject conversation-target
prefixes, but that helper also matches the imessage:/sms:/auto: service
prefixes — which are valid direct-handle forms. Any allowFrom entry like
'imessage:+15551230000' dropped to undefined, leaving approvers empty,
which:
  - silently denied reaction resolution ('reactions require explicit
    approvers'), and
  - let text /approve fall back to implicit same-chat authorization.

Fix: normalize first via normalizeIMessageHandle (strips the service
prefix), then reject only chat_id:/chat_guid:/chat_identifier:
conversation-target shapes that remain after normalization.

Tests:
  - approval-auth.test.ts: assert the resolved approver list contains the
    normalized handle, plus the corollary that a non-matching sender is
    explicitly rejected (no longer masked by the implicit-same-chat
    fallback). Add a separate case covering chat_id/chat_guid/
    chat_identifier rejection (with and without a service prefix).
  - approval-reactions.test.ts: reaction resolution end-to-end with a
    service-prefixed allowFrom entry — proves resolveIMessageApproval is
    called rather than silently denied.

Focused suite: 48 passed (was 47).

* test(imessage): satisfy strict buildPendingPayload signature in render tests

CI check:test-types caught that the render.exec/render.plugin
buildPendingPayload calls were passing accountId (not in the type
signature). The signature is { cfg, request, target, nowMs }. Replace
accountId with target on the four render-test sites so the strict
test-types pass matches the SDK contract:

  - it('renders thumbs-only reaction hints in exec approval prompts')
  - it('renders thumbs-only reaction hints in plugin approval prompts ...')
  - it('renders target-mode exec prompts with concrete thumbs-only ...')
  - it('renders target-mode plugin prompts with concrete thumbs-only ...')

Verified locally with pnpm check:test-types (tsgo:core:test +
tsgo:extensions:test). 49 approval-specific tests still pass.

* fix(imessage): probe every tapback GUID form for approval lookup

ClawSweeper P1 review finding on #85952. readApprovalReactionEvent was
only using reaction.targetGuid (the first/normalized form), but
resolveIMessageReactionContext produces reaction.targetGuids = [normalized,
raw] for both `abc-123` and `p:0/abc-123` forms. If the imsg bridge
returned 'p:0/<guid>' from send() and send.ts registered the binding under
that prefixed key, the inbound resolver probing only the unprefixed form
would miss and the tapback would silently fall through.

Fix:
- Surface every GUID candidate in IMessageApprovalReactionEvent
  (messageIdCandidates).
- maybeResolveIMessageApprovalReaction now probes each candidate in
  precedence order; first hit wins.
- On success / ApprovalNotFoundError, clear the binding under all
  candidate keys so toggle/replay does not refire.

Tests: extensions/imessage/src/approval-reactions.test.ts gains a
'resolves a reaction when the binding was registered under a p:0/…
prefixed GUID and the tapback surfaces both forms' regression case;
22/22 reaction tests pass. Full iMessage suite: 424/424.

* fix(imessage): native approval binding requires GUID, not numeric id

ClawSweeper third P1 review finding on #85952. approval-handler.runtime.ts
deliverPending was using result.messageId as the approval-reaction binding
key, but that field can be a numeric ROWID coerced to a string ('12345')
when the imsg bridge returns only message_id. Inbound tapbacks carry
reacted_to_guid which is always a GUID, so a numeric-id binding can never
match.

Fix mirrors the send.ts forwarding-path treatment:
- IMessageSendResult now exposes a separate guid?: string field, populated
  from the same resolveOutboundMessageGuid helper send.ts already uses for
  the forwarding-path binding. The generic messageId field is unchanged so
  reply-cache, echo-cache, and receipt-building paths still see the
  broadest id form.
- deliverPending now binds against result.guid; when it's undefined (numeric
  ROWID or 'ok'/'unknown' placeholders), the function returns null instead
  of binding against an id the inbound tapback can't possibly match.

Tests: approval-handler.runtime.test.ts gets a deliverPending GUID-only
binding describe block with three regression cases (numeric ROWID refused,
GUID accepted, ok/unknown placeholders refused). vi.mock isolates
sendMessageIMessage so the cases run synchronously without spawning imsg.
11 tests pass across handler.runtime + send specs.

---------

Co-authored-by: Omar Shahine <10343873+omarshahine@users.noreply.github.com>
2026-05-24 10:51:21 -07:00
Vincent Koc
ad71a998ff fix(crabbox): default macos aws runs on demand 2026-05-24 19:31:19 +02:00
Vincent Koc
e4332f7cff fix(scripts): preserve test passthrough args 2026-05-24 19:13:03 +02:00
Vincent Koc
8edc671eb4 fix(e2e): harden Windows plugin assertions 2026-05-24 19:10:10 +02:00
Vincent Koc
5f0315467b fix(test): mount upgrade survivor helper 2026-05-24 18:59:34 +02:00
Ayaan Zaidi
c4525104e9 style(android): sharpen voice mode surfaces 2026-05-24 22:06:36 +05:30
Ayaan Zaidi
955909c988 style(android): refine list surface spacing 2026-05-24 22:06:36 +05:30
Ayaan Zaidi
63a2f69601 fix(android): prevent stale chat during session switches 2026-05-24 22:06:36 +05:30
Ayaan Zaidi
d86ed21f3d fix(android): hide internal chat content blocks 2026-05-24 22:06:36 +05:30
Ayaan Zaidi
cc5eb972e6 feat(android): add pair new gateway action 2026-05-24 22:06:36 +05:30
Ayaan Zaidi
94bc18ad75 fix(android): keep permission setup action visible 2026-05-24 22:06:36 +05:30
Andy Ye
102555c6e0 Advance iMessage catchup cursor after live handling (#85475)
Fixes #85363.

Thanks @TurboTheTurtle.
2026-05-24 09:34:16 -07:00
Vincent Koc
79ee70c8ad fix(scripts): ignore forwarded arg separator 2026-05-24 18:13:14 +02:00
Vincent Koc
5a8ce6a885 fix(test): fail empty gateway startup samples 2026-05-24 17:58:12 +02:00
Vincent Koc
87a2eba427 fix(e2e): harden Windows kitchen sink assertions 2026-05-24 17:47:19 +02:00
Vincent Koc
c643370fd8 fix(e2e): harden Telegram credential paths on Windows 2026-05-24 17:17:28 +02:00
Ayaan Zaidi
be9bb775a5 fix(android): complete qr setup operator handoff 2026-05-24 20:38:57 +05:30
Ayaan Zaidi
0b55a6363e fix(android): align setup pairing scopes 2026-05-24 20:38:57 +05:30
Vincent Koc
dbc08f64c1 fix(test): copy cleanup smoke prepare hook 2026-05-24 16:57:26 +02:00
clawsweeper[bot]
675158c896 fix(secrets): allow hash in exec SecretRef ids (#86072)
Summary:
- The branch widens exec SecretRef id validation/schema/docs/test vectors to allow `#` selector syntax, adds a changelog entry, and includes a small `npm pack` filename helper cleanup.
- Reproducibility: yes. Source inspection on current main shows the shared exec SecretRef validator omits `#`, matching the linked gateway startup failure before resolver execution.

Automerge notes:
- PR branch already contained follow-up commit before automerge: docs(secrets): document hash exec SecretRef ids
- PR branch already contained follow-up commit before automerge: docs(secrets): sync exec SecretRef hash pattern
- PR branch already contained follow-up commit before automerge: fix(secrets): allow hash in exec SecretRef ids
- PR branch already contained follow-up commit before automerge: fix(clawsweeper): address review for automerge-openclaw-openclaw-8073…

Validation:
- ClawSweeper review passed for head 1cf53d95f4.
- Required merge gates passed before the squash merge.

Prepared head SHA: 1cf53d95f4
Review: https://github.com/openclaw/openclaw/pull/86072#issuecomment-4528994482

Co-authored-by: Andy Ye <andy@Andys-MacBook-Pro-2.local>
Co-authored-by: Andy Ye <andylye@outlook.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-05-24 14:56:17 +00:00
Vincent Koc
694d45e535 fix(media): use static image compression metadata 2026-05-24 16:47:59 +02:00
Peter Steinberger
01c5ab8d13 fix(release): verify large plugin npm packs 2026-05-24 15:33:17 +01:00
Vincent Koc
7e51f83aec fix(test): require kitchen sink diagnostic canaries 2026-05-24 16:27:46 +02:00
Vincent Koc
483d7be6c4 fix(scripts): harden Windows upgrade survivor recipe 2026-05-24 16:05:24 +02:00
Vincent Koc
102b2c18e9 fix(installer): count verify progress stage 2026-05-24 15:50:28 +02:00
Tak Hoffman
5bffd17e01 fix: Refine PR template for review state (#86054) 2026-05-24 08:49:02 -05:00
Vincent Koc
125d82cab2 fix(test): repair split agent shard runs 2026-05-24 15:37:59 +02:00
Vincent Koc
ce48e4c197 fix(codex): harden Windows protocol formatting 2026-05-24 15:37:13 +02:00
clawsweeper[bot]
dd01a2e789 fix(openrouter): use endpoint context limits (#86041)
Summary:
- The branch updates OpenRouter dynamic model capability parsing to prefer `top_provider.context_length`, bump ... sk cache version, adds regression coverage and a changelog entry, and adds script helper declaration files.
- Reproducibility: yes. from source and live catalog evidence rather than an authenticated inference turn. Cur ... catalog currently reports a smaller endpoint-specific `top_provider.context_length` for the reported model.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(openrouter): use endpoint context limits
- PR branch already contained follow-up commit before automerge: fix(clawsweeper): address review for automerge-openclaw-openclaw-8594…

Validation:
- ClawSweeper review passed for head 76fcc362d2.
- Required merge gates passed before the squash merge.

Prepared head SHA: 76fcc362d2
Review: https://github.com/openclaw/openclaw/pull/86041#issuecomment-4528646655

Co-authored-by: Andy Ye <35905412+TurboTheTurtle@users.noreply.github.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-05-24 13:32:44 +00:00
Peter Steinberger
8473e8933a test(qa): remove brittle capability flip setup turn 2026-05-24 14:30:59 +01:00
Ayaan Zaidi
5cfb12fa5d fix(telegram): migrate account topic cache sidecars 2026-05-24 18:58:02 +05:30
Ayaan Zaidi
eb9b882dae fix(telegram): migrate legacy cache sidecars 2026-05-24 18:58:02 +05:30
Vincent Koc
5be62e779b fix(scripts): harden Windows ZAI fallback repro 2026-05-24 15:11:37 +02:00
Ayaan Zaidi
400d90a4da style(android): sharpen v2 screen rhythm 2026-05-24 18:37:31 +05:30
Peter Steinberger
c91c3c6e5a test(qa): extend capability flip setup budget 2026-05-24 14:02:22 +01:00
Ayaan Zaidi
24ddd18ae1 fix(android): simplify gateway status copy 2026-05-24 18:24:51 +05:30