Commit Graph

64136 Commits

Author SHA1 Message Date
Chunyue Wang
e1eac7a79d fix(agents): strip system-event prefix from modelPrompt when before_prompt_build hooks add context (#95349)
* fix(agents): strip system-event prefix from modelPrompt when before_prompt_build hooks add context

* fix(agents): preserve prompt boundaries when stripping runtime context

* test(agents): assert nested prompt text in boundary regression

* fix(agents): anchor runtime context stripping to prompt boundaries

* fix(agents): prefer the active prompt boundary

* fix(agents): avoid rewriting prompts without hidden context

* fix(agents): make prompt stripping helper total

* test(agents): drop synthetic prompt boundary proof

* fix(agents): anchor prompt stripping to hook boundaries

* fix(agents): preserve normalized prompt boundaries

* fix(agents): carry prompt build boundaries

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 01:54:01 -07:00
Joey Frasier (Boothe)
7e0d530e07 fix(slack): reconcile ambiguous sends before replay (#97480)
* fix(slack): reconcile ambiguous sends exactly

Co-authored-by: Joey Frasier (Boothe) <joey.frasier@worksuite.com>

* test(infra): cover durable dispatch context

* fix(slack): keep reply policy internal

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 01:48:57 -07:00
Peter Steinberger
091d9564b6 fix(ui): hide duplicate terminal caret (#100240) 2026-07-05 01:48:43 -07:00
Peter Steinberger
8b229a938c fix(ui): simplify OpenAI speed choices (#100190) 2026-07-05 01:46:13 -07:00
Peter Steinberger
f3e3b6985b fix: land nine small correctness fixes (#100204)
* fix(memory-wiki): preserve dollar notes on reimport

Co-authored-by: 李兰 0668001394 <li.lan3@xydigit.com>

* fix(voice-call): handle spawn error during tunnel cleanup

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* fix(media): reject invalid response byte limits

Co-authored-by: linhongkuan <linhk8@mail2.sysu.edu.cn>

* fix(infra): match listening ports exactly

Co-authored-by: 徐闻涵0668001344 <xu.wenhan1@xydigit.com>

* fix(exec): preserve UTF-16 boundaries when truncating output

Co-authored-by: liuhao1024 <sunsky.lau@gmail.com>

* fix(agents): reject surrogate HTML entities

Co-authored-by: mikasa0818 <0668001030@xydigit.com>

* fix(anthropic): guard Claude Fable 5 prefix boundaries

Co-authored-by: 黄剑雄0668001315 <huang.jianxiong@xydigit.com>

* fix(models): render context windows in decimal K

Co-authored-by: harjoth <harjoth.khara@gmail.com>

* fix(clickclack): preserve websocket rejection diagnostics

Co-authored-by: sunlit-deng <yang.jiajun1@xydigit.com>

* fix(exec): use canonical UTF-16 slicing helper

Co-authored-by: liuhao1024 <sunsky.lau@gmail.com>

* style(exec): sort UTF-16 helper imports

* style(exec): sort UTF-16 helper imports

* style(exec): sort UTF-16 helper imports

* style(infra): format response limit helper

* style(infra): format response limit helper

---------

Co-authored-by: 李兰 0668001394 <li.lan3@xydigit.com>
Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>
Co-authored-by: linhongkuan <linhk8@mail2.sysu.edu.cn>
Co-authored-by: 徐闻涵0668001344 <xu.wenhan1@xydigit.com>
Co-authored-by: liuhao1024 <sunsky.lau@gmail.com>
Co-authored-by: mikasa0818 <0668001030@xydigit.com>
Co-authored-by: 黄剑雄0668001315 <huang.jianxiong@xydigit.com>
Co-authored-by: harjoth <harjoth.khara@gmail.com>
Co-authored-by: sunlit-deng <yang.jiajun1@xydigit.com>
2026-07-05 01:44:56 -07:00
Vincent Koc
bb1e0ad724 fix(apps): refresh native i18n inventory 2026-07-05 10:32:46 +02:00
Vincent Koc
53bd4dde6c fix(ci): stabilize manual dispatch checkout 2026-07-05 10:22:26 +02:00
Peter Steinberger
4deb63c979 fix(crestodian): repair post-merge checks (#100223) 2026-07-05 01:17:58 -07:00
Peter Steinberger
05c9dccf35 feat(apps): match the mascot design to the openclaw.ai hero
Aligns the shared OpenClawMascotView with the website hero styling:
per-part bounding-box gradients (SVG objectBoundingBox semantics; the
claws were nearly flat-colored before), antenna stroke width 2, eye
glow r=2, float depth -8% of size, and a light-scheme palette from the
site theme variables. The float now offsets the whole canvas like the
site floats the hero container, so the antennae no longer clip at the
float peak.

macOS adopts the hero glow treatment: the About pane mascot gets the
coral silhouette drop-shadow with the teal hover glow and 1.1 hover
scale, and the onboarding hero replaces its hand-rolled breathing glow
circle with the same silhouette glow.
2026-07-05 01:13:26 -07:00
Peter Steinberger
07bf384a8b feat(crestodian): conversational agent-loop onboarding across CLI, web install, and macOS app (#99935)
* feat(crestodian): AI-first conversational onboarding with typed-op guardrails

Interactive `openclaw onboard` (and bare `openclaw` on a fresh install) now
opens the Crestodian conversation: detection-backed first-run proposal
(Claude Code/Codex logins, API keys), persona AI turns for every free-form
message (configless local-runtime fallback, 60s deadline, deterministic
degradation), approval-gated typed operations, chat-hosted channel setup
(`connect <channel>`), config get/schema read ops with secret redaction, and
a post-write validation hook that feeds schema errors back for a self-fix
turn. Adds the additive gateway `crestodian.chat` method so app clients run
the same conversation. Classic wizard stays behind --classic/explicit flags;
non-interactive automation unchanged; `--modern` becomes a deprecated alias
for `openclaw crestodian`.

* feat(macos): Crestodian chat onboarding and importance-ordered permissions

Replace the gateway step-wizard page with a Crestodian chat over the new
crestodian.chat method (works before any model auth exists), sort the
permissions page by importance with no scrolling, drop the redundant manual
refresh, and bump the onboarding version.

* feat(crestodian): run the custodian on the real agent loop with a ring-zero tool

Crestodian conversations now execute through the same embedded agent runner
as regular agents: a persistent agent session with a single construction-gated
`crestodian` tool wrapping the typed operations (read actions free; mutations
require approved=true asserted from explicit user consent, audited, with
post-write config validation fed back into the loop). The engine prefers the
loop (configured models or the Codex app-server fallback) and degrades to the
single-turn planner, then to deterministic commands. Setup approval seeds the
crestodian exec approval so local model harnesses can run; the configless
Codex backend config now enables exec and direct tool loading (it was
dead-on-arrival behind tools.exec.mode=deny and the tool-search index).

* test(crestodian): type the engine mock signatures for the core test lane

* fix(crestodian): map the advertised create_agent tool action

* fix(crestodian): host-verified approval arming and a macOS setup completion gate

Review findings: the model-supplied approved flag alone could authorize
ring-zero mutations (prompt injection / model error), and removing the macOS
wizard gate let users Next past the Crestodian page with nothing configured.
Mutating tool actions now also require host-verified consent (the engine arms
approval only when the user's actual message is an explicit yes), and local
macOS onboarding blocks advancing until setup authored the config, using the
same signal the old step wizard checked.

* fix(crestodian): bind approval to the exact proposed operation and gate dot navigation

A generic yes no longer authorizes arbitrary mutations: denied mutating tool
calls register a canonical operation fingerprint (host-owned, per session),
and an armed turn executes only the identical call, once. The denial message
is arming-aware so the approved turn self-heals in one roundtrip, and the
agent protocol pre-registers proposals. macOS onboarding page dots now honor
the same setup-completion gate as the Next button.

* fix(crestodian): redact sensitive wizard answers, skip logged-out CLIs, gate programmatic advance

Sensitive channel-wizard answers (tokens, passwords) are redacted from the
AI-visible conversation history; setup and the onboarding welcome never pick
or advertise a definitively logged-out CLI as the model; and macOS
handleNext() honors the page gates for programmatic callers (chat handoff)
just like the Next button.

* fix(crestodian): align the onboarding welcome's configured predicate with the app gate

A valid config carrying only a default model (partial/hand-written) now still
gets the first-run proposal instead of the ready guide, so the macOS setup
gate can always be satisfied from the conversation.

* fix(crestodian): armed turns can never mint their own executable proposal

An approval-mismatched call inside an armed turn no longer re-registers and
invites a retry (which let the model swap the approved operation for another
in the same turn); it voids the approval entirely and requires a fresh yes.
Proposals register only in unarmed turns, which the agent protocol already
does when proposing.

* fix(onboard): route any explicit setup flag to the classic wizard

* fix(ci): satisfy new lint rules, tool-display guard, and generated artifacts for crestodian

* chore(i18n): refresh native inventory after permissions copy wrap

* fix(crestodian): harden conversational onboarding

* docs(crestodian): document conversational onboarding

* test(crestodian): type embedded runner mock

* fix(crestodian): close onboarding security gaps

* chore: retrigger ci
2026-07-05 01:02:53 -07:00
Peter Steinberger
c64a306f90 fix(macos): preserve PATH for SSH helpers (#100214) 2026-07-05 00:45:08 -07:00
Vincent Koc
51255f66eb test(e2e): follow quickstart hook defaults 2026-07-05 09:36:55 +02:00
Dan Hayman
f4908e60fd fix(discord): fall back to text when voice delivery fails (#89962)
* fix(discord): fall back to text when voice delivery fails

* fix(discord): preserve reply target on voice fallback

* fix(discord): suppress duplicate delivered TTS fallback

* refactor(discord): bound voice fallback handling

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 03:19:53 -04:00
Ayaan Zaidi
cfdc2b3ff9 fix(cron): keep default toolsAllow marker when edits echo an unchanged list 2026-07-05 00:18:12 -07:00
Peter Steinberger
e72a2c825d fix(ui): simplify selectable tool error rows (#100199)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 00:08:21 -07:00
Sanjay Santhanam
6cc534bbad fix(discord): reuse stored sessionId across voice (stt-tts) turns (#97746)
* fix(discord): reuse stored sessionId across voice (stt-tts) turns

Discord voice turns previously called agentCommandFromIngress without a
sessionId, so the core session resolver minted a fresh UUID per turn.
Because the codex app-server thread is bound beside the per-session
file, every voice turn produced a new codex thread, a brand-new
rollout-*.jsonl, and lost all prior context.

The fix reads the persisted session entry for the route's sessionKey
(the same supervisor entry already used for the route) and threads that
sessionId into agentCommandFromIngress, mirroring how voice-call's
response-generator and the gateway 'voice.transcript' dispatcher already
keep voice conversations stable.

Adds extensions/discord/src/voice/ingress.test.ts covering both
directions: reuses the stored id when present, and lets core mint a
fresh one when the store is empty.

Fixes #97688

* fix(discord): preserve voice session after rollover

* refactor(discord): keep voice session ownership in core

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 03:00:08 -04:00
Peter Steinberger
009b00f7ba fix(acp-core): keep fallback error redaction (#100191)
* fix(acp-core): keep fallback error redaction

Co-authored-by: linhongkuan <linhk8@mail2.sysu.edu.cn>

* fix(acp-core): keep fallback error redaction

---------

Co-authored-by: linhongkuan <linhk8@mail2.sysu.edu.cn>
2026-07-05 02:54:42 -04:00
xingzhou
c2ea5a2d65 test(tui): lock dunder markdown rendering (#95211)
* test(tui): lock dunder markdown rendering

Co-authored-by: 张贵萍0668001030 <zhang.guiping@xydigit.com>

* test(tui): lock dunder markdown rendering

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 02:50:42 -04:00
Vincent Koc
97935832ab test(qa): keep bundle MCP policy proof packaged 2026-07-05 08:44:52 +02:00
github-actions[bot]
8be1d366a1 chore(i18n): refresh native locales 2026-07-05 06:42:53 +00:00
huangjianxiong
783c0aec50 fix(google-meet): bound JSON response body reads to prevent OOM (#98850)
* fix(google-meet): bound JSON response body reads to prevent OOM

Replace raw response.json() with readProviderJsonResponse (16 MiB cap)
across meet.ts, calendar.ts, and oauth.ts to prevent unbounded memory
allocation from oversized HTTP response bodies.

Also extract duplicated hasConfig check in createGoogleMeetSpace.

Test: loopback HTTP server test with 4 MiB oversized body + valid body.

* fix(test): prove readProviderJsonResponse bounds the 200 success path

Replace loopback server with synthetic Response objects. The oversized
test now returns HTTP 200 with a 17 MiB body — readProviderJsonResponse
rejects it at its 16 MiB cap, proving the bounded read fires on the
success path (not just the already-bounded 500 error path the old test
exercised).

Ref. https://github.com/openclaw/openclaw/pull/98850

* fix(test): add real HTTP transport integration tests for bounded JSON reads

- Add two vitest integration tests that start a real local TCP server,
  fetch through native HTTP transport, and verify readProviderJsonResponse
  correctly rejects oversized responses and passes normal ones.
- Existing synthetic-boundary tests unchanged.

Ref. https://github.com/openclaw/openclaw/pull/98850

* fix(test): wrap server.listen in promise executor to satisfy oxlint no-promise-executor-return

* fix(google-meet): add real SSRF-guard transport integration tests for bounded JSON reads

Adds two new integration tests that route meet.googleapis.com requests
through a local TCP server via spyOnGoogleMeetFetch, exercising the
actual fetchGoogleMeetSpace function end-to-end through the SSRF guard
mock. This addresses ClawSweeper review feedback requesting real
transport-level proof of the bounded read contract.

* fix(google-meet): preserve original fetch reference in spyOnGoogleMeetFetch to avoid recursion

The mockImplementation replaced globalThis.fetch, so calling fetch() inside
the mock called the mock itself. Capture globalThis.fetch before spying and
use the saved reference inside the implementation to avoid infinite recursion.

* fix(google-meet): add console.log debug output to loopback proof tests

Add structured console.log evidence markers to the four real HTTP
transport integration tests so that reviewers can see the bounded-read
contract working through actual TCP connections. Format matches the
established pattern from Alix-007's approved bound-read PRs.

* Revert "fix(google-meet): add console.log debug output to loopback proof tests"

This reverts commit e64c26d17e867f3b18ca0ad3a5d95af9d9809efc.

* fix(google-meet): tighten response body limits

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 02:34:08 -04:00
ooiuuii
1e7694a8a5 fix(whatsapp): serialize overlapping Web sends (#99050)
* fix(whatsapp): serialize web sendMessage calls

* fix(whatsapp): make send serialization socket-owned

* test(qa): narrow live gateway connection fields

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 02:32:36 -04:00
Peter Steinberger
f052a2f23b feat(macos): animate the OpenClaw mascot in About and onboarding
Ports the animated OpenClawMascotView to the macOS app: the About pane
icon and the onboarding hero now render the Canvas+TimelineView mascot
(float/blink/antenna-wiggle/claw-snap, still under Reduce Motion)
instead of the static app icon.

The view moves from apps/ios into the shared OpenClawChatUI target of
OpenClawKit so iOS and macOS consume one copy; the iOS lint filelist
tracks the moved file.
2026-07-04 23:20:11 -07:00
Peter Steinberger
9b60e1429d fix(control-ui): declutter Settings and make Simple/Advanced switch persistent (#100147)
Quick Settings read as competing panels and the Appearance card wrapped/clipped its segmented controls in a narrow side column. Switching to Advanced also had no visible way back — the only return was a "Quick Settings" link buried in the accordion nav.

- Replace the one-way "Advanced" button and buried accordion back link with a persistent Simple/Advanced switch in the page header, mirrored into an in-body row at the mobile breakpoint where the header is hidden.
- Give Appearance a full-width auto-fit grid so Theme/Mode/Roundness/Text size never wrap or clip.
- Drop the duplicate Context Profile side panel for a compact summary line, and only show "Pending" when a change is actually staged (pass savedConfigObject).
- Remove the redundant in-page "Quick Settings" heading and unused preset copy.

Presentation-only within ui/src/pages/config; net -354 non-test LOC. Closes #100145.
2026-07-05 02:20:02 -04:00
Peter Steinberger
c9614e96e6 fix(tui): block unsupported local commands (#100188) 2026-07-05 02:16:51 -04:00
Vincent Koc
10877c1573 test(qa): tolerate delayed MCP channel event poll 2026-07-05 08:09:32 +02:00
Peter Steinberger
062f88e3e3 refactor: extract reusable AI runtime package (#99059)
* refactor: extract reusable AI runtime package

* refactor: complete AI provider relocation

* refactor: keep llm core internal

* refactor(ai): make @openclaw/ai self-contained with host policy ports

Move pure transport helpers (tool projections, strict-schema normalization,
prompt-cache boundary, stream guards, anthropic/openai compat, request
activity) from src into packages/ai; move utf16-slice into
normalization-core. Inject host policy (guarded fetch, redaction,
strict-tool defaults, diagnostics logging) through AiTransportHost with
inert library defaults installed by src/llm/stream.ts. Narrow the public
barrel to instance-scoped createApiRegistry/createLlmRuntime; the
process-default runtime moves behind internal/ and
registerBuiltInApiProviders takes an explicit registry. Delete the
src/llm/api-registry re-export facade.

* fix(ai): teach node, jiti, and vite resolvers the @openclaw/ai and utf16-slice subpaths

The workspace alias tables in root-alias.cjs, plugin-sdk-native-resolver,
sdk-alias, the shared vitest config, and the Control UI vite config only
knew @openclaw/llm-core; Node-side plugin loading resolved @openclaw/ai
through the pnpm symlink to the unbuilt dist (checks-node-compact CI
failures), and the Control UI build broke on the new
normalization-core/utf16-slice subpath.

* chore(ui): drop leftover service-worker debug logging

* build(release): ship @openclaw/ai with its own shrinkwrap and honest dependency set

packages/ai declares only its six real runtime deps (kysely, chalk, json5,
tslog, zod, fs-safe, and proxyline were never imported); orphaned root deps
removed. generate-npm-shrinkwrap now treats publishable packages/* like
publishable plugins so the AI tarball pins its transitive tree even though
workspace deps are omitted from the root shrinkwrap. knip learns the
package entry points; the tsdown dts neverBundle option moves to its
documented deps.dts home; the README documents the no-semver internal/*
contract and host ports.

* docs(ai): add minimal external-consumer example app

examples/ai-chat consumes only the public @openclaw/ai surface (built dist
via the workspace link): isolated runtime, built-in provider registration,
one streamed completion. Supports Anthropic/OpenAI via env keys and a
keyless local Ollama target; live-verified against Ollama.

* docs(ai): document the @openclaw/ai package and workspace shrinkwrap boundary

* chore(check): include examples/ in duplicate-scan targets

* fix: emit normalization package subpaths

* fix: complete AI package boundary artifacts

* fix: align AI package boundary contracts

* fix(ci): stabilize package release contracts

* test: align documentation contract checks

* test: keep cron docs guard aligned

* test: align restored docs contract guards

* test: follow upstream docs contracts

* docs: drop superseded talk wording
2026-07-05 01:56:40 -04:00
Peter Steinberger
913311845e fix(browser): accept no-preference in openclaw browser set media
The /set/media control route accepts dark|light|no-preference|none, but the
CLI rejected no-preference, so prefers-color-scheme: no-preference could not
be emulated from the CLI. Align the CLI argument, validation, and error text
with the route contract and update the browser-control docs media line.
2026-07-05 06:54:13 +01:00
Peter Steinberger
3cf0d00d90 docs: align source contract wording (#100186) 2026-07-05 01:41:40 -04:00
Vincent Koc
c29054a7dc chore(plugin-sdk): refresh API baseline hash 2026-07-05 07:30:57 +02:00
Peter Steinberger
53bdac249d docs: restore source-backed contract details (#100182) 2026-07-05 01:26:25 -04:00
Vincent Koc
214ee02359 test(docs): align rewrite guards with current wording (#100183) 2026-07-04 22:23:10 -07:00
Vincent Koc
76d686cf61 fix(auto-reply): persist first command session updates 2026-07-05 07:09:53 +02:00
Peter Steinberger
1d9fb2773f feat(ui): surface mobile pairing shortcuts (#100157) 2026-07-05 00:47:27 -04:00
Bartok
5dff031467 fix(plugins): stage git plugin clone on target filesystem to avoid EXDEV (#99896)
* fix(plugins): stage git plugin clone on target filesystem to avoid EXDEV

Git plugin installs cloned into os.tmpdir() then atomically renamed the
staged repo into ~/.openclaw/git/. When /tmp and the state dir live on
different filesystems (common in Docker with bind-mounted volumes), the
rename failed with EXDEV: cross-device link not permitted.

Stage the clone under the managed git root (same filesystem as the
destination) so the final rename never crosses devices. Falls back to
os.tmpdir() when the managed root cannot be prepared, preserving prior
behavior.

Closes #99885

* fix(plugins): isolate git clone staging per install

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-04 21:40:20 -07:00
Peter Steinberger
f7d7148cf0 docs: rewrite published docs grounded in current source (#100142)
Source-grounded rewrite of 529 published docs pages with per-unit information-loss verification: 1,713 factual corrections cited to src/**, generated surfaces regenerated, frontmatter titles preserved for i18n, release notes pages untouched. All docs gates green.

Closes #100141
2026-07-05 00:32:47 -04:00
github-actions[bot]
e069cb26f7 chore(i18n): refresh native locales 2026-07-05 04:04:27 +00:00
Vincent Koc
02af382a06 fix(ci): pass release metadata refs as options 2026-07-05 05:58:12 +02:00
Vincent Koc
2bb07361e6 chore(changelog): keep normal fix notes generated 2026-07-05 05:54:16 +02:00
Peter Steinberger
1ab218fda0 fix(agent): hide code mode wait progress (#100164) 2026-07-05 04:52:09 +01:00
Peter Steinberger
d3641421a4 fix(whatsapp): replace refreshed terminal QR (#100159) 2026-07-04 23:42:26 -04:00
truiem-bot
420b3cdd29 feat(slack): support per-channel replyToMode (#82253)
* feat(slack): support per-channel replyToMode

* fix(slack): align per-channel threading contexts

* fix(slack): preserve queued channel reply mode

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-04 23:41:24 -04:00
Vincent Koc
451190d625 fix(mobile): authenticate terminal page with stored operator token 2026-07-05 05:39:12 +02:00
WhatsSkiLL
1c83c2d4a6 fix(android): prevent gateway setup button clipping (#100090)
Co-authored-by: IWhatsskill <284122573+IWhatsskill@users.noreply.github.com>
2026-07-04 23:31:39 -04:00
Vincent Koc
4212de9e08 fix(telegram): count thinking token progress in collapse summary 2026-07-05 05:23:16 +02:00
Peter Steinberger
8251c4094a fix(ui): align activity error badges (#100163)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-04 20:18:20 -07:00
Peter Steinberger
851156af3b feat: animate the OpenClaw mascot across web, iOS, and Android
Ports the openclaw.ai hero mascot animation (body float 4s, eye blink 3s,
antenna wiggle 2s, staggered claw snaps 4s) to every product surface that
shows the logo:

- web: ui/public/favicon.svg now carries SMIL animations, so every <img>
  usage (login gate, sidebar brand, agent avatar fallback) animates with
  no markup changes; CSS animations do not run in <img>-loaded SVGs.
- iOS: new OpenClawMascotView renders the canonical 120x120 vector via
  Canvas + TimelineView (30fps, honors Reduce Motion); OpenClawProMark
  uses it in onboarding, sidebar, and command center. Static PNG imageset
  deleted (watch app keeps its own copy).
- Android: new OpenClawMascot composable (PathParser + infinite
  transitions, honors the OS animator scale) replaces the static vector
  drawable in onboarding and the chat/shell/voice headers, with tint
  support for the monochrome header silhouettes. Drawable deleted.
2026-07-04 20:14:34 -07:00
Peter Steinberger
fcd7eb6130 feat(android): terminal settings screen hosting the gateway terminal page 2026-07-04 20:07:56 -07:00
Peter Steinberger
211e0d7263 feat(ios): Terminal hub destination embedding the gateway terminal page 2026-07-04 20:07:19 -07:00
Peter Steinberger
9c7848928f feat(control-ui): full-screen terminal-only view mode for mobile WebViews 2026-07-04 20:07:18 -07:00