* fix(browser): read Windows Chrome version metadata
Read PE ProductVersion before a conservative unambiguous install-layout fallback, without interpolating configured paths into PowerShell code.\n\nCo-authored-by: Mukunda Rao Katta <mukunda.vjcs6@gmail.com>
* style(browser): clarify Windows version probe
* fix(browser): use trusted Windows PowerShell path
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* feat(android): support per-gateway custom headers for proxied gateway connections
Per-gateway custom request headers (Cloudflare Access-style service tokens)
for gateways behind authenticating reverse proxies. Headers are credentials:
EncryptedSharedPreferences-stored per endpoint stableId, masked in the manual
connection UI, injected on the OkHttp WebSocket upgrade at connect time via a
provider so edits apply on the next reconnect without re-pairing. Reserved
handshake headers and non-printable-ASCII are sanitized out (OkHttp throws on
them). TLS fingerprint pinning and pairing flows unchanged. Cross-gateway
isolation proven by MockWebServer upgrade-capture test.
Related: #100698
* chore(android): sync native i18n for custom header strings
* fix(android): harden gateway custom headers
* chore(android): resync native i18n inventory
* docs(changelog): defer Android release note
* fix(android): validate custom header names
* chore(android): refresh native i18n inventory
* feat(ui): link file paths in chat and add workspace file viewer sidebar
Auto-detect file paths in chat markdown (plain paths, path:line, inline
code, explicit/absolute links) and render them as clickable links that
open a dedicated file viewer sidebar with line numbers, highlight.js
syntax highlighting, scroll-to-line, in-file search, reveal-in-rail,
open-in-editor, and copy actions. Workspace rail browser entries are
now previewable even when the transcript never touched them;
sessions.files.get serves any file inside the workspace root with the
existing containment, symlink/hardlink, and size guards.
Closes#100615
* feat(ui): linkify file paths in sidebar markdown and fix file-view gutter width
Markdown rendered in the chat detail sidebar now gets the same clickable
file links as chat messages, opening files via the panel's own click
delegation. File viewer gutter uses a fixed per-file digit width so
short lines no longer indent their code past longer ones.
* fix(ui): keep browser-entry active highlight and narrow file content for editor open
loadWorkspace no longer clears the rail active marker for browser-only
entries, so Show in Files keeps the revealed file highlighted after the
forced reload. openInEditor narrows the sidebar content kind before use,
fixing the tsgo type error.
* chore(ui): fix lint findings in file viewer helpers
* fix(ui): harden workspace file previews
* fix(ui): wire file previews through chat panes
* fix(ui): preserve workspace file targets
* fix(ui): preserve workspace file targets
searchMemoryWiki called sharedMemoryManager.search() and getMemoryWikiPage
called manager.readFile() with only a truthiness guard. A memory plugin
whose runtime returns a manager that does not implement the
MemorySearchManager contract crashed shared-backend wiki search with
"sharedMemoryManager.search is not a function" from inside the bundle --
@mem0/openclaw-mem0 <= 1.0.14 registered exactly such a partial manager
(status/probeEmbeddingAvailability/close only).
Guard both call sites and throw an actionable error instead: name the
missing contract method and point at search.backend="local" for wiki-only
access.
* fix(gateway): stop device pairing approval alert floods from retrying devices
A device retrying with a broken token minted a new pending requestId (and
approval alert broadcast) every 5-minute TTL window because refresh preserved
ts and expiry keyed on ts. Pending requests now stay alive via an internal
refreshedAtMs keepalive (ts still owns ordering/--latest), superseded device
requests broadcast device.pair.resolved like node pairing already did, and the
Mac app keeps one alert per device, closes superseded visible alerts, and
resyncs its queue when approving a stale request.
Closes#100974
* chore: satisfy swiftformat and refresh native i18n inventory for pairing prompter changes
* feat(ios): support per-gateway custom headers for proxied gateway connections
Per-gateway custom request headers (Cloudflare Access-style service tokens)
for gateways behind authenticating reverse proxies. Headers are credentials:
Keychain-stored per gateway stableID, masked in settings UI, injected on the
WebSocket upgrade at connect time via a provider so edits apply on the next
reconnect without re-pairing. Reserved handshake headers and control chars
are sanitized out. TLS pinning and pairing flows unchanged. Push relay and
other non-gateway destinations proven header-free by regression test.
Related: #100698
* chore(ios): sync native i18n inventory for custom header strings
* fix(ios): harden gateway custom headers
* chore(ios): resync native i18n inventory
* fix(ios): validate custom header names
Two crashes when a memory plugin misbehaves in bridge mode:
- listActiveMemoryPublicArtifacts sorted plugin-returned artifacts
without
validating them; an artifact missing any of the string fields the
comparator dereferences (kind, workspaceDir, relativePath,
absolutePath,
contentType) crashed wiki status and every other bridge consumer with
"Cannot read properties of undefined (reading 'localeCompare')".
@mem0/openclaw-mem0 <= 1.0.14 shipped record-shaped artifacts with
none
of those fields, typed against a drifted SDK stub. Validate the shape,
drop malformed entries (and non-array listings), and warn once naming
the offending plugin -- the same treatment agentIds already got.
- resolveMemoryWikiStatus gated artifact counting on vaultMode/enabled
but
not bridge.readMemoryArtifacts, so the wiki.status gateway method
still
enumerated artifacts (and hit the crash above) with the flag off, even
though the sync path (bridge.ts) and CLI gateway routing honor it. The
documented workaround therefore never worked for the wiki_status agent
tool. Add the flag to the gate; the count reports null when imports
are
disabled, matching non-bridge modes.
* [AI] fix(sessions): exclude done sessions from transcript freshness rollover guard
Exclude status: "done" from resolveTerminalMainSessionTranscriptRegistryCheck alongside the already-excluded status: "failed". Successful main sessions should stay reusable for the next user message even when transcript mtime slightly exceeds registry updatedAt.
Updated test expectations in:
- src/gateway/server-methods/agent.test.ts (split it.each into done-reuse + endedAt-only-rotate)
- src/commands/agent.session.test.ts (split into done-reuse + endedAt-only-rotate)
- src/auto-reply/reply/session.test.ts (default-done case now expects reuse)
Related to #99964
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(ts): fix TypeScript error in endedAt-only test scenario type
Remove the conditional status spread that TS cannot resolve when
status is absent from the scenario type, and add 'as const' for
narrowed literal inference.
* [AI] fix(comment): correct mtime direction in done exclusion comment
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* review: separate failed/done rationale in comment
* fix(sessions): reuse completed main transcripts
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(telegram): stop local listener and bot on retry loop non-recoverable error
* fix(telegram): reuse webhook shutdown on setup failure
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(openai): strip status from replayed input items for custom openai-responses endpoints
* fix(openai): narrow replay status stripping
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
createNonExitingRuntime.exit() threw a generic Error, making it
impossible for upstream try-catch to distinguish a simulated process
exit from a real runtime crash. Added an ExitError class (internal-only,
not exported from SDK) that callers can check via instanceof.
ExitError is kept internal to avoid expanding the public plugin SDK
API surface without maintainer approval. Tests import directly from
./runtime.js.
Fixes#97796.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(node-host): handle stdout/stderr stream errors in runCommand
* chore(proof): add real behavior proof for node-host runCommand stream errors
* fix(node-host): wait for child exit after stdout/stderr stream errors
* fix(node-host): lint and type errors in proof script and test
* fix(node-host): bound stream-error command shutdown
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(cron): do not set delivery mode to announce when disabling best-effort on payload edits
* fix(cron-cli): update sibling test to expect undefined mode on no-best-effort-deliver
* fix(cron): preserve delivery mode when disabling best effort
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>