Commit Graph

171 Commits

Author SHA1 Message Date
Jason (Json)
01a7f4fb3f feat(ui): add images and model selection to new sessions (#107358)
Merged via squash.

Prepared head SHA: cf99b5bab5
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Reviewed-by: @fuller-stack-dev
2026-07-14 04:14:01 -06:00
Peter Steinberger
89f53f1c38 fix(terminal): keystrokes typed while a terminal opens are lost; node PTY relay lifecycle races (#107214)
* fix(terminal): harden node PTY relay and terminal session lifecycle

Pin node relay invokes to the authorized node connection (ROUTE_CHANGED
guard), stop node-side input writes to settled/dead PTYs, finalize
sessions on resize failure like write failure, keep surrogate pairs
intact across scrollback and relay prelude truncation, bound the relay
pre-registration output buffer, and buffer Control UI keystrokes typed
while terminal.open/attach is in flight so slow node-relay opens no
longer drop input. Correct the terminal.data seq doc to its real
contract and pin seq monotonicity, seq-gap bounds, input coercion, and
runner event routing with new tests.

* refactor(terminal): extract startup input buffer and fix CI findings

Move Control UI startup input buffering into terminal-startup-input.ts
(LOC budget), drop a stale session-manager comment, remove a map
spread, and fix test typings for event frames and typed mock access.
2026-07-14 01:22:22 -07:00
Peter Steinberger
d8d2f83cc1 feat(terminal): open Codex/Claude catalog sessions in a terminal on their owning host
Catalog session rows (sidebar context menu + click), the built-in viewer
header, and a new "Open Codex/Claude sessions in" preference can launch the
native CLI (codex resume / claude --resume) in the operator terminal on the
machine that owns the session.

- Gateway-local sessions spawn through the existing terminal launch policy
  (sandbox/enabled gates preserved) with the resume command in the session cwd.
- Paired-node sessions run through a new seq-ordered node PTY relay: a
  duplex node-host command streams PTY output via node.invoke.progress and
  receives keystrokes/resize via a new node.invoke.input event, behind the
  unchanged terminal.* client protocol (TerminalSessionManager gains a backend
  abstraction; node relay reuses the streaming-invoke controller).
- Owner boundary: each plugin owns its resume command and builds argv from a
  validated thread id; the gateway routes node opens through the node command
  allowlist and plugin invoke policy (no advertisement-only trust), and nodes
  re-verify session eligibility before spawning.
- UI setting catalogOpenTarget + canOpenTerminal capability gate every entry
  point; capability requires the owning host to actually have the CLI.

Node PATH is normalized before command-availability probes, Windows .cmd/.bat
shims spawn via ComSpec, and catalog terminal opens reattach persisted tabs
before opening the new tab.
2026-07-13 22:20:50 -07:00
Peter Steinberger
cf8b57e7d0 feat(skills): scan session history for workshop ideas (#106766)
* feat: scan past sessions for skill proposals

* feat(ui): add progressive skill history scans

* fix(ui): keep skill history scans synchronized

* refactor: split skill history scan ownership

* style: fix mock helper formatting

* style: format skill history scan

* build: refresh skill history schema baselines

* build: refresh plugin SDK baseline after rebase

* perf(ui): keep startup request budget bounded

* fix(skills): satisfy history scan integration gates

* fix(ui): bound control ui startup chunks

* build: refresh plugin SDK API baseline

* build(ui): refresh self-learning translation memory

* refactor(ui): split skill workshop state

* fix(ci): refresh skill workshop gates

* fix(ci): satisfy skill history lint

* build: refresh plugin SDK baseline after main rebase
2026-07-13 16:15:50 -07:00
Peter Steinberger
334e7f3f21 feat(apps): add native mobile Automations parity (#106355)
* fix(apps): address native Skills review feedback

* feat(apps): add native Automations parity

* fix(ios): preserve automation editor selection

* fix(android): page automation discovery

* chore(apps): refresh native source inventory

* fix(ios): refresh invalid automation diagnostics

* chore(apps): sync native localization

* fix(cron): stabilize paginated snapshots

* refactor(cron): split pagination helpers

* fix(apps): address final native review feedback

* chore(apps): refresh native source inventory

* fix(ios): dedupe automation list actions

* chore: keep release note in PR context

* fix(ci): repair current main architecture gates

* fix(ios): default new skill requirement fields

* fix(ios): retain queued automation reservations
2026-07-13 15:35:32 -07:00
Peter Steinberger
4319ddbe8c feat(control-ui): import Codex and Claude Code memory (#106406)
* feat(control-ui): import coding assistant memory

* test(migrate): clean memory import temp dirs

* chore: move memory import note to PR body

* build: refresh memory import generated artifacts

* fix(control-ui): complete memory import checks

* build(control-ui): localize memory recovery labels

* fix(control-ui): harden memory import recovery

* refactor(migrate): keep memory import surfaces bounded

* fix(control-ui): use canonical agent row type

* fix(codex): drop dead migration type exports

* fix(migrate): restrict imported memory permissions

* fix(control-ui): preserve memory import recovery state

* fix(control-ui): retain memory import results

* build(control-ui): preserve translation memory history

* fix(control-ui): bind memory import state to agent

* fix(control-ui): unlock memory import after refresh

* test(gateway): preserve memory method suffix

* fix(migrate): bind reviewed memory imports

* fix(migrate): make memory imports retry-safe

* perf(ui): keep memory import lazy

* build: refresh generated artifacts after rebase

* chore: keep migration runtime within LOC guard

* build: refresh Swift protocol model
2026-07-13 15:30:06 -07:00
Peter Steinberger
e3c5821d98 feat(ui): redesign Channels page with guided channel setup wizard (#106469)
* feat(ui): redesign Channels page with guided channel setup wizard

Adds wizard.start flow=channels gateway RPC (additive protocol change) that
drives the shared channel-setup wizard (openclaw channels add) over the
session step protocol. Control UI Channels page becomes a card hub with
plugin-art covers, guided per-channel setup modal (WhatsApp QR pairing via
web.login.*, BotFather/Slack/Discord helper links), and a detail overlay
hosting the full schema config form.

* test(ui): cover channel wizard controller; refresh channels view test props

* chore(mock): use non-token-shaped wizard placeholder

* test(gateway): scanner-safe auth local in channels wizard test

* fix(ui): cancel gateway wizard session on channels page disconnect

* fix(ui): adopt browse-all channel pick and guard dirty config before setup

* fix(ui): cancel gateway session created by a stale wizard.start

* fix(ui): adopt multiselect channel picks; drop redundant String()

* fix(ui): track all wizard-adopted channels so WhatsApp QR runs regardless of pick order

* feat(gateway): report configured channels on terminal channel-wizard result

Replaces the Control UI's channel-adoption heuristic with the authoritative
outcome: the channels flow reports its actual selection after config commit,
the wizard session surfaces it as an additive channels field on the terminal
wizard.next result, and the UI keys WhatsApp QR linking off that.

* refactor(ui): align channels hub with the unified settings design language

Hub becomes settings-language rows (44px art tiles, status dots, uppercase
section headings, hairline groups) instead of a card gallery; the detail
overlay hosts the migrated per-channel settings sections with Run setup in
the header. Wizard dialog and tile/cover styles move to spacing tokens.

* chore(i18n): translate channels hub/setup strings; refresh raw-copy baseline

* refactor: satisfy LOC ratchet and dead-export gates

Split mock-dev channel/plugin fixtures into their own modules, move wizard
runner types/defaults to server-methods/wizard.ts, extract the channels page
wizard host and nostr profile HTTP ops, and unexport internal-only types
(incl. the unused config-form SECTION_META barrel re-export).

* chore(i18n): retranslate channels strings on rebased locale bundles

* fix(test): drop redundant String() in channels wizard e2e

* fix: address channel-wizard review findings

- lock wizard cancellation before durable installs/config writes
- report configured channel accounts on the terminal wizard result and
  start WhatsApp QR pairing for that account (web.login accountId)
- forward request options through the browser gateway client so wizard
  RPC timeouts apply
- render skipped setup as a no-change completion
- keep detail/advanced config reachable for unconfigured channels
- surface the dirty-config warning inside the detail overlay
- adopt the picked channel for wizard title/links in browse-all flows

* fix(ui): local wizard RPC timeout; translate no-change completion strings
2026-07-13 11:49:42 -07:00
Peter Steinberger
9166b23318 feat: configure model providers from the Control UI settings page (#106490)
* feat(gateway): add models.probe RPC, credential provenance, targeted auth logout

* feat(ui): configure model providers from settings — keys, probes, logout, defaults

* docs: Control UI provider configuration section

* fix(ui): confirm fallback shrinkage via replacePaths; guard model catalog refresh races; scanner-safe probe fixtures

* test(models): scanner-safe probe fixture identifier

* chore(i18n): resync model-providers strings after rebase

* fix(gateway-protocol): drop duplicate probe type imports after rebase

* chore(protocol): regenerate Swift client for probe field order

* chore(i18n): resync model-providers strings after main rebase

* test(ui): scope model-providers E2E to settings-section headings

* fix(models): isolate marker probes from stored profiles; emit no_model for config-only providers [AI]

* fix(models): honor configured auth mode for env probes; probe config-bound profiles past auth.order [AI]

* fix(gateway): resolve provider auth aliases in models.probe [AI]

* fix(gateway): scope targeted auth logout to skip provider-wide run abort [AI]

* fix(models): probe requested provider for overrides; unregister ephemeral probe DB [AI]

* fix(gateway): exclude local no-auth markers from models.authStatus API-key provenance [AI]

* chore(i18n): resync model-providers strings for landing
2026-07-13 11:23:34 -07:00
Jason (Json)
b32f59c8c1 feat(ui): create catalog sessions from the sidebar (#105810)
* feat(ui): create sessions from catalog headers

* fix(ui): deduplicate catalog-owned sessions

* fix(ui): preserve catalog session routing state

* fix(ui): keep per-agent session creation in switcher

* fix(anthropic): normalize runtime config snapshot

* test(plugin-sdk): account for model runtime export

* test(plugin-sdk): classify current deprecated surface

* test(ui): follow agent chip menu trigger

* fix(ui): bind catalog drafts to validated agent

* fix(ui): resolve catalog targets from gateway

* refactor(ui): split sidebar session helpers

* chore(ci): complete LOC baseline migration

* fix(ui): extract sidebar session catalog rendering

* fix(anthropic): use provider-relative catalog model id

* chore(ci): ratchet sidebar LOC baselines

* test(ui): cover catalog draft retargeting

* chore(plugin-sdk): refresh API baseline

* style: format catalog session changes

* fix(ui): retry catalog drafts after reconnect

* fix(ui): back off catalog target retries

* fix(ui): keep unresolved catalog drafts locked

* fix(ui): gate catalog creation in core

* fix(ui): keep catalog renderer private

* style(ui): format catalog session target

* chore(plugin-sdk): refresh API baseline

* style(ui): format catalog group state

* Merge latest origin/main CI fixes

* fix(ui): preserve catalog session agent selection

* fix(ui): preserve catalog session agent

* chore(plugin-sdk): refresh API baseline

* fix(ui): type catalog route data

* chore(plugin-sdk): refresh API baseline

* refactor(sessions): centralize transcript path archival

* fix(ui): target expanded agent catalog sessions

* fix(ui): scope catalog actions to expanded agent

* docs(ui): clarify catalog loader fallback

* fix(ui): scope catalog pagination to agent

* test(ui): type sidebar lifecycle refresh

* fix(anthropic): preserve node catalog bindings
2026-07-13 09:25:22 -06:00
Peter Steinberger
2626e97b4c refactor: split oversized catalog and protocol helpers (#106476) 2026-07-13 11:10:42 -04:00
Peter Steinberger
e98c7dfbcb feat(cloud-workers): session placement, dispatch, and worker turn routing (#106332)
* feat(gateway-protocol): add session placement schema

Closed state discriminator for session execution placement (local/requested/provisioning/syncing/starting/active/draining/reconciling/reclaimed/failed), sessions.dispatch params, and worker-admission transcript/live cursor extensions. Swift protocol models mirror the schema.

* feat(state): add worker session placement table

worker_session_placements rows carry placement state, transition generation, worker ownership metadata, ACK cursors, and the turn claim columns used for atomic admission.

* feat(cloud-workers): add durable placement state machine store

SQLite-backed placement store split by concern: state table (placement-state), discriminated record types + shape invariants (placement-record), row codec + CAS transition values (placement-row-codec), atomic turn-claim admission/release/waiters (placement-turn-claims), and lifecycle CAS transitions (placement-store).

* feat(cloud-workers): sync workspaces and attach sessions to worker environments

Environment service session attachment + turn credentials, tunnel workspace commands over a dedicated SSH runner, and git/plain workspace sync into $HOME/.openclaw-worker/workspaces with an immutable manifest. Symlink escapes are rejected locally before transfer (macOS openrsync stat-fails them opaquely) and again by the remote manifest guard.

* feat(worker): run one-shot embedded turns from launch descriptors

Worker runtime executes a single embedded turn from a stdin launch descriptor and reports completed/failed/fenced on stdout for the gateway launcher. Terminal lifecycle live events are deferred past the final transcript flush; transcript projection helpers are shared via transcript-message instead of duplicated in the runtime.

* feat(cloud-workers): dispatch placements and route worker turns

Dispatch service drives local->requested->provisioning->syncing->starting->active with failure teardown (placement-dispatch-failure) and restart/runtime recovery incl. lost-worker reclaim (placement-dispatch-recovery). Worker turn launcher claims the placement turn atomically, builds a windowed launch descriptor (worker-turn-payload), runs the remote one-shot worker, and reconciles the committed transcript; agent runners route turns through the session placement admission provider.

* feat(gateway): expose session placement RPCs and startup reconciliation

sessions.dispatch RPC with lifecycle admission barriers, operator-facing placement projection on session listings, placement-aware session reset guard, and startup/interval reconciliation wiring for worker placements.
2026-07-13 08:03:53 -07:00
Peter Steinberger
f167089d61 feat(nodes): continue Claude catalog sessions on paired nodes via streaming CLI agent runs (#105833)
* feat(gateway): stream node.invoke progress with idle timeouts and cancel

* feat(node-host): opt-in approval-gated claude cli agent run command

* feat(agents): run node-placed claude-cli turns through streaming node invoke

* feat(anthropic): continue claude catalog sessions on advertising nodes

* docs(nodes): document paired-node claude agent runs and continuation

* chore(plugin-sdk): admit spawn-invocation helper into surface budget

* fix(nodes): harden streaming invoke and node run policy from review findings

* test(node-host): prove multi-token tool-policy argv fails closed

* fix(nodes): allowlist cancel event for apps and break node-host type cycle

* chore(protocol): regenerate Swift gateway models for node invoke progress

* chore(node-host): drop test-only export surface flagged by deadcode ratchet

* style(node-host): merge invoke-types imports

* refactor(nodes): split node agent run modules to satisfy the LOC ratchet

* chore(protocol): regenerate android gateway models and sync export baseline

* chore(plugin-sdk): admit spawn-invocation helper and inherited deprecated drift into surface budget

* chore(plugin-sdk): tolerate inherited agent-core deprecated export

* fix(anthropic): drop node param parser orphaned by upstream catalog split

* ci: sync unused-export baseline with healed main

* test(agents): adopt renamed cli backend prepare helper

* style(node-host): format claude run spawn invocation

* ci: retrigger checks

* chore(plugin-sdk): pin surface budgets to healed-base counts

* fix(protocol): restore untyped lazy validators after upstream style change
2026-07-13 07:39:22 -07:00
Peter Steinberger
76796d7c69 refactor(gateway): share closed TypeBox objects (#106441)
* refactor(gateway): share closed TypeBox objects

* fix(gateway): remove unused TypeBox import
2026-07-13 07:21:59 -07:00
Peter Steinberger
c8e401cfad refactor(gateway): infer validator types from schemas (#106428) 2026-07-13 06:49:10 -07:00
Peter Steinberger
5ca0e634bc fix(ios): connect iPhone and Watch to protocol v3 gateways (#106294)
* fix(ios): support gateway protocol v3

* chore(i18n): refresh native source metadata

* fix(watchos): keep direct transport on protocol v4

* chore(i18n): refresh Watch source metadata
2026-07-13 05:44:49 -07:00
Peter Steinberger
6c5084f1ad feat(xai): add realtime voice provider (#106267)
* feat(xai): add realtime voice provider

Co-authored-by: Vitor Cepeda Lopes <vitor@vitorcepedalopes.com>

* fix(xai): satisfy realtime voice validation

* fix(xai): harden realtime relay boundaries

* chore: drop release-owned changelog edit

* chore(i18n): refresh native voice catalogs

* chore(i18n): refresh Control UI raw-copy baseline

* chore(plugin-sdk): refresh API baseline hashes

* chore(i18n): use canonical main catalogs

* chore(i18n): refresh realtime voice source inventory

* chore: refresh xai voice landing head [skip ci]

* chore: refresh integrated protocol artifacts [skip ci]

---------

Co-authored-by: Vitor Cepeda Lopes <vitor@vitorcepedalopes.com>
2026-07-13 05:17:24 -07:00
Peter Steinberger
9086389527 feat(control-ui): agent identity editor, Settings-homed Agents page, scalable chip switcher (#106058)
* feat(control-ui): agent identity editor, settings-homed agents page, chip switcher pinning

* test(control-ui): pinned-agent persistence coverage; persist pins only when set

* refactor(control-ui): split agent menu, identity actions, model staging out of oversized files

* chore(i18n): sync control-ui locale bundles for agent identity/switcher keys

* fix(control-ui): stabilize new sidebar switcher tests; ratchet LOC + export baselines

* chore(review): document identity clear limitation; drop unused export

* feat(control-ui): scope pages to selected agent

* fix(control-ui): keep scoped page state consistent

* docs(control-ui): explain shared agent scope

* fix(control-ui): reconcile agent scope with current ui

* fix(control-ui): preserve complete agent filtering

* fix(control-ui): bound uploaded agent avatars

* test(control-ui): keep pinned-route fixture valid

* test(control-ui): keep pinned-route fixture valid

* chore(i18n): sync locale bundles for agent scoping keys
2026-07-13 04:03:26 -07:00
Peter Steinberger
938d41014f feat(mobile): default pairing to full node access (#105928)
* feat(mobile): default pairing to full node access

* chore: leave release notes to release workflow

* refactor(mobile): bound pairing helpers

* chore(i18n): refresh mobile access inventory

* chore(ci): lower mobile pairing LOC baseline

* fix(mobile): complete pairing validation artifacts

* ci: remove stale transcript target export baseline

* fix(ios): wrap access upgrade guidance

* fix(ios): preserve localized access key

* fix(ci): dedupe read-only SQLite guardrail

* fix(mobile): secure full-access node setup
2026-07-13 02:30:45 -07:00
Peter Steinberger
16b1bd2032 fix(android): support gateway protocol v3 (#106205) 2026-07-13 02:29:16 -07:00
Peter Steinberger
bafabba0df fix(gateway): preserve Control UI turns across restarts (#106151)
* fix(gateway): preserve Control UI turns across restart

* perf(sessions): index restart recovery state

* fix(sessions): avoid replaying pre-admitted turns

* fix(sessions): index per-entry recovery status

* fix(sessions): guard restart failure notices

* fix(sessions): preserve terminal claims across admissions

* fix(sessions): retry failed recovery notices

* fix(sessions): harden restart retry ownership

* fix(gateway): tighten restart recovery typing

* fix(sessions): close restart recovery races

* refactor(sessions): split restart recovery ownership

* chore(sessions): clean restart recovery lint

* chore: drop release-owned changelog entry

* fix(gateway): satisfy restart recovery guards

* test(gateway): cover Control UI durable admission
2026-07-13 02:08:56 -07:00
Ayaan Zaidi
143fed81c1 feat(sessions): reopen history around search hits 2026-07-13 10:27:29 +05:30
Peter Steinberger
e261fa60ce feat(cloud-workers): gateway inference proxy for worker model turns (#105719)
* refactor: clarify prepared auth value

* feat(cloud-workers): add inference proxy protocol

* feat(cloud-workers): persist inference turns

* feat(cloud-workers): execute gateway inference turns

* fix(cloud-workers): support adaptive inference reasoning

* fix(gateway): constrain worker inference policy options

* test(gateway): cover worker inference SQLite store
2026-07-12 15:35:50 -07:00
Peter Steinberger
1b313dc4d4 chore(tooling): enforce indexed access in core tests (#105375)
* test(tooling): enforce indexed access in core tests

* test(tui): constrain theme environment overrides

* test(doctor): enforce indexed access in migration fixtures
2026-07-12 14:29:52 +01:00
Peter Steinberger
4289c6c16c feat(cloud-workers): replayable worker live-event streaming into the session fanout (#105275)
* feat(protocol): add worker live-event frames

* feat(gateway): fan out replayable worker live events

* feat(gateway): add worker live-event replay receiver

* docs(protocol): document worker live events

* fix(gateway): preserve deferred worker live events

* test(gateway): cover deferred worker event projection

* refactor(gateway): revert async projection layer

* fix(gateway): retain buffered worker live events

* fix(gateway): guard buffered terminal admission

* fix(plugin-sdk): trim worker live-event declarations
2026-07-12 13:47:59 +01:00
Peter Steinberger
dba78584ff fix(ui): preserve rejected first message when session send fails (#105261)
* fix(ui): preserve rejected first session message

* chore: leave changelog to release closeout

* fix(protocol): regenerate session create result
2026-07-12 11:09:38 +01:00
Peter Steinberger
5b56a1f664 feat(gateway): land remaining durable-approvals stack and repair main gates (#104837)
* feat(gateway): propagate approvals to ancestor sessions with replay

Squash-rebased #103921 segment onto the native-clients tip on current main.
Session-scoped approval events publish sanitized pending/terminal
transitions to opted-in session audiences, with authoritative pending
replay on stream subscribe and durable-expiry reconciliation through the
owning manager. SessionApprovalEvent/Replay wire types export from the
approvals owner module; Swift models regenerated.

(cherry picked from commit 2d1dcf9747044710111d0c730fc46ba6013a165c)
(cherry picked from commit ccf88efd56b513d07599ffcee997bf0cddaf9adc)
(cherry picked from commit 8eb33f59f00ec9ee4625259b76bd7ae60d2cd480)
(cherry picked from commit c297cbc93c8401e9c79c20f242245a194f5dd236)
(cherry picked from commit 93d68f28601ff37d863da4db009504993a22533a)
(cherry picked from commit d285ccd8b2f212bb57e814107e7709c896e96b7d)
(cherry picked from commit 5c536982231402b1b58d1683794ea9948b32d077)
(cherry picked from commit 1646e5b6dc4dd20de54e10f110a5909be18d7d50)
(cherry picked from commit 35cf1b705b247fb282f4d56ffe74bd2fb238221f)
(cherry picked from commit 4f8ef3699d)
(cherry picked from commit 74fbdcc99d5fff062d67760a51dba4ee9e84479b)
(cherry picked from commit 222b285502681d2be14b1819798e9ee5555f431e)
(cherry picked from commit b9e744951f676b600e7c5322bfd04b0e99797c07)
(cherry picked from commit 9e904efde5)
(cherry picked from commit 678f2384fa)
(cherry picked from commit 72842e5cf6)
(cherry picked from commit be74c25e80e84a1f065053766f23efb84822e811)
(cherry picked from commit 93ba8c4b09)
(cherry picked from commit 8f23761372)

* feat(gateway): fail-closed plugin and tool approval gates

Squash-rebased #103932 segment onto the ancestor-propagation tip on
current main. Plugin node.invoke approvals claim a one-shot allow-once
decision before handing execution authority to the policy, so observation
or retry cannot replay a consumed approval; sibling tool gates bind
approval ids to their originating reviewer identity.

(cherry picked from commit 122df0d75281f572c012b6484ed5daf085d1d577)
(cherry picked from commit f23d8ac240a8dcf2a42c4daaae962263975a0ae8)
(cherry picked from commit 8632fb6436a224dac7a9a9ef0216884530de2c24)
(cherry picked from commit d9fe2dd5c53665e5732f5f3da5ed1907a686ade8)
(cherry picked from commit bb139f2c8aa36ddad70413e1ef79ff491a6f2ecd)
(cherry picked from commit 9b3e056b68ea515c7d4baef269289b6670570480)
(cherry picked from commit b11e66b59a7af1f3b08712de06864aed64d349e4)
(cherry picked from commit a12916ee592d03dfa35e86a2aaede4476a5d4e5d)
(cherry picked from commit d699de840fc8346892b9ae244fe3c3e8c4413032)
(cherry picked from commit 9b7e5a9608)
(cherry picked from commit 4b507593f1b2f10b4496984c84a2803b853e5c5e)
(cherry picked from commit 56408a186733c4eeb5aa76bd5907cde7b0cd3d5b)
(cherry picked from commit a4051d6d8353d39d6fa0b5d69c36e06c3cd3e796)
(cherry picked from commit 76829805a7)
(cherry picked from commit a8b493f934)
(cherry picked from commit aceb990597)
(cherry picked from commit a29b0e75482470c53a9fb4fe3f204e14cf71868f)
(cherry picked from commit 2e3be08653)
(cherry picked from commit c9ae3d7202)

* fix: main-gate repairs for the durable-approvals stack

- android: capture createdAtMs on the pending exec-approval write at
  registration; canonical readback after a refresh that already replaced
  the visible rows was dropping the approval instead of surfacing the
  still-pending reconciliation message (#104913 merged without this)
- android: generous CI timeout ceilings in GatewayExecApprovalRuntimeTest
- agents: hermetic model-discovery test via the plugins/provider-runtime
  boundary (lazy plugin-runtime resolution hangs vitest workers since #104770)
- cli: usage-cost settle-budget test asserts the budget bound on every call
  instead of pinning the poll count (fast hosts fit a second poll in 50ms)
- protocol coverage: allowlist session.approval for ios/android (native
  review rides exec.approval push/nudge delivery)
- docs map, native i18n inventory, plugin-sdk api baseline regenerated
2026-07-12 10:51:38 +01:00
Peter Steinberger
55254c3a0b feat(nodes): route alerts to the active computer (#105083)
* feat(nodes): route alerts by active computer

* fix(ci): allowlist node presence mobile coverage

* test(prompts): refresh node presence snapshots

* fix(macos): await presence reporter actor hop

* fix(macos): type presence test delivery state

* docs(nodes): add active presence guide

* docs(nodes): format presence troubleshooting
2026-07-12 10:05:50 +01:00
Peter Steinberger
6fc564278d feat(agents): sessions_search full-text recall over past session transcripts (#105057)
Adds a core sessions_search agent tool backed by a SQLite FTS5 index that
lives next to the transcript rows in the per-agent database. Indexing is
transactional: user/assistant text is indexed inside the same write
transaction that persists the event, deletes drop index rows in the same
transaction, and branch rewinds mark the session dirty so the next search
rebuilds it from the same visible-path resolution sessions_history uses
(which also lazily backfills doctor-migrated databases). Search executes
gateway-side behind an additive sessions.search method with a bounded
session-key allowlist; visibility, sandbox restrictions, and snippet
redaction mirror sessions_history.

Closes #100978
2026-07-12 09:15:41 +01:00
Peter Steinberger
6038480915 feat(ui): browse Gateway and node folders from one root (#105114)
* feat(ui): browse Gateway and node folders

* chore: keep changelog release-owned

* chore: refresh native i18n inventory

* refactor(macos): isolate node filesystem commands
2026-07-12 09:07:07 +01:00
Peter Steinberger
d14bb8ec44 fix: resume replay-safe work after gateway restarts (#104997)
* fix: resume replay-safe work after gateway restart

* chore: leave restart note to release process

* fix: sync restart recovery protocol artifacts
2026-07-12 06:37:22 +01:00
Peter Steinberger
68f0eee5ae fix(ui): harden workspace file editing (#104885)
* fix(ui): retain unsaved workspace file drafts

* fix(ui): reset restored draft hash

* fix(ui): keep all unsaved file drafts

* fix(ui): harden workspace file editing

* fix(ui): canonicalize workspace file identity

* fix(gateway): serialize workspace file saves globally

* chore: keep release notes in PR body

* docs: refresh generated docs map
2026-07-11 19:25:47 -07:00
Peter Steinberger
7a456e362d feat(channels): add typed cross-surface approval actions (#103679)
* fix(gateway): approval registry hardening and protocol-surface follow-ups

Follow-up delta to the merged #103579 head, rebased onto current main:
- gateway-protocol wire types derive from owner-module schema consts
  (types.ts tombstone) and ProtocolSchemas leaves the package index so the
  public plugin-sdk d.ts graph tree-shakes the registry declaration
- approval access authority follows the operator.approvals scope tier with
  reviewerDeviceIds as the opt-in restriction (cross-surface
  first-answer-wins; requester identity gates only legacy adapters)
- plugin node.invoke approvals register directly so unrenderable
  presentations fail closed before request routing
- exec-approval manager reconciliation with #103515 revocation hardening
  (resolution source attribution, one-shot ask-fallback consumption)
- surface-report pins and plugin-sdk API baseline refreshed; Swift models
  regenerated

* feat(channels): add typed operator approval actions

Squash-rebased #103679 segment onto the durable-approval-registry tip on
current main. Typed approval/command/select presentation actions replace
raw-string inference across slack/telegram/discord/matrix/imessage/whatsapp,
approval.resolve carries an explicit kind, and channel adapters map native
callback envelopes through the typed action registry.

Drift reconciliation: deprecated buildExecApprovalInteractiveReply assertions
dropped (#104650 removed the shims); worker_environments bootstrap-column
migration kept alongside the approval resolution_ref backfill; plugin-sdk API
baseline regenerated.

(cherry picked from commit 68765a5d39d2118c88a7a54d00387337912d4494)
(cherry picked from commit 8642ac12af142e4b751f4f30d4b114615e7e5f66)
(cherry picked from commit 036c4bc39499925fc03de16ec9302e346769350a)
(cherry picked from commit 19dc350d6bc34e29a5169c6bc80971b0ad12adde)
(cherry picked from commit fc978b0bad86aef421c79f6a211b25cc1b743c01)
(cherry picked from commit 10de4d1ed5071f9be6ad1ee5d1e32c0fa8c9d11c)
(cherry picked from commit 9a664ced1b1fa740172b258f355f1a82925ae41c)
(cherry picked from commit c5ff69abbf444139e9e007bfa45beb0f00ffea54)
(cherry picked from commit d466a80795)
(cherry picked from commit f5b4fe40dd5c961322f8553cc80b2fdfb3f6503e)
(cherry picked from commit 7340b4749a4cc4c72f7a41cce1bc9cb550cae038)
(cherry picked from commit a151f41808f23ae60b10305ccd2bc959b9169a86)

* fix(approvals): preserve typed transport ownership

* test(imessage): narrow chunked approval text

* refactor(protocol): remove retired type tombstone

* fix(plugin-sdk): align surface budgets after rebase

* docs(changelog): note typed operator approvals

* docs(changelog): defer typed approval release note
2026-07-11 18:31:05 -07:00
Peter Steinberger
82667a66e5 feat(ui): editable file panel with CodeMirror and sessions.files.set hash-CAS writes (#104757)
* feat(gateway): add sessions.files.set workspace file write with hash CAS (#104698)

* feat(ui): CodeMirror file editor panel with CAS save + clickable tool-card paths (#104698)

* fix(gateway): issue the file CAS hash only for strict-UTF-8 text (#104698)

* docs(web): document the editable file detail panel (#104698)

* fix(gateway,ui): round-trip BOM and CRLF bytes through the file editor (#104698)

* fix(ui): keep mixed-line-ending files read-only in the file editor (#104698)

* fix(ui): re-gate editability when a conflict reload returns non-editable content (#104698)

* fix(gateway): reject NUL bytes in sessions.files.set replacement content (#104698)

* fix(gateway,ui): regenerate protocol bindings, fix prod types and lint for file editor (#104698)
2026-07-11 17:36:28 -07:00
Peter Steinberger
04f945fabe feat(cloud-workers): durable transcript commit protocol for worker sessions (#104809)
* feat(cloud-workers): add transcript commit protocol

* feat(cloud-workers): persist transcript commit replay state

* feat(cloud-workers): apply transcript commits to sessions

* fix(cloud-workers): harden transcript commit admission

* fix(cloud-workers): recover branched transcript commits

* fix(cloud-workers): preserve diagnostic semantics
2026-07-11 17:29:07 -07:00
Peter Steinberger
3255b3218a feat: unify external sessions with native catalog pagination (#104717)
* feat(gateway): add generic sessions.catalog surface with plugin SDK registration seam

* feat(agents): support one-shot forked CLI session resume with successor rebinding

* feat(anthropic): adopt local Claude CLI sessions into native chats via catalog continue

* feat(codex): register the session catalog provider independently of supervision

* refactor(ui): delete the retired custom Claude/Codex session tab views

* feat(ui): render external session catalogs as native sidebar sessions and chat panes

* docs: describe the unified native session catalog

* fix: harden forked CLI resume and catalog transcript mapping after review

* fix: satisfy strict typecheck for catalog source guard and imported message cast

* chore(i18n): regenerate session catalog locales

* fix(codex): simplify session source guard type

* fix(ui): paginate sidebar session catalogs

* chore(i18n): refresh catalog metadata after main merge

* fix(ui): harden session catalog pagination refresh

* test(agents): use sqlite session accessor in fork tests

* fix(ci): refresh session catalog generated surfaces

* fix(ui): align session catalog locales

* fix: address session catalog review findings

* fix(sessions): roll back failed plugin catalog adoption

* test(sessions): preserve CLI binding literals

* fix(ui): restore native session pagination label

* docs: note external session catalogs

* Revert "docs: note external session catalogs"

This reverts commit cfb503f160.
2026-07-11 17:26:26 -07:00
snowzlmbot
be373ea516 improve(android): show provider-configured model details (#101912)
* feat(android): show provider model inventory

Co-authored-by: snowzlmbot <293528334+snowzlmbot@users.noreply.github.com>

* fix(gateway): project provider inventory routes

* style(android): satisfy provider inventory ktlint

* chore(android): sync provider inventory i18n

* style(android): finish provider inventory formatting

* fix(android): harden provider inventory refresh

* test(gateway): type provider inventory fixture

* chore(protocol): regenerate Swift model choice

* chore(android): sync provider inventory i18n

* test(gateway): pin provider inventory discovery mode

* chore(android): sync provider inventory landing

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: snowzlmbot <293528334+snowzlmbot@users.noreply.github.com>
2026-07-11 17:22:16 -07:00
Peter Steinberger
02dc25a1b5 feat(gateway): persist operator approvals (#103579)
* feat(gateway): persist operator approvals

* fix(gateway): preserve approval ids exactly

* fix(gateway): enforce approval reviewer bindings

* fix(gateway): reconcile durable approvals with exec revocation hardening

Map #103515 semantics onto the durable lifecycle: resolutionSource and
one-shot consumeAskFallback stay process-local record facts, trusted
auto-review resolves through the durable CAS as a runtime resolver, and
lost races settle with the winner's operator source. Also: derive the
audience walker cap from the store cap, report APPROVAL_ALREADY_RESOLVED
for a resolve that loses the CAS race, document approval.get/resolve in
the protocol docs, and regenerate Swift models on the new base.

* fix(approvals): validate resolver kind

* docs(approvals): explain malformed verdict denial

* fix(protocol): regenerate approval models after rebase

* chore: leave changelog entry to release generation

* fix(gateway): preserve approval registration boundaries

* test(gateway): prove multi-device approval races

* test(gateway): keep approval order assertion stable

* docs: index operator approval architecture

* fix(protocol): bound approval declaration exports
2026-07-11 16:53:49 -07:00
Peter Steinberger
f929fd9865 feat(ui): chat background-tasks rail detects running work eagerly and shows live tool activity (#104776)
* feat(ui): detect background tasks eagerly and show live tool activity in the chat rail

Track tool-start counts and the last tool name per task run in the task
registry, persist them on task_runs, and expose them as additive optional
TaskSummary fields. The chat background-tasks rail now loads its snapshot
eagerly so the collapsed toggle badge detects running work immediately,
and rows show a live elapsed timer, tool-use count, and the tool
currently in use (run duration for finished rows).

Issue: #104775

* fix(ui): translate background-task activity strings and refresh generated protocol models

The singular tool-use label is literal ("1 tool use") because several
locales legitimately drop the count placeholder in singular forms, which
fail-closes the placeholder guard in the i18n sync. Locale bundles are
the authenticated ui:i18n:sync output (fallbacks=0); GatewayModels.swift
is protocol:gen:swift output for the new TaskSummary fields.

* chore(ui): refresh i18n raw-copy baseline after rebase
2026-07-11 16:51:48 -07:00
Peter Steinberger
847460600f feat(macos): redesign device-code sign-in (#104766)
* feat(macos): redesign device-code sign-in

* chore(i18n): refresh native string inventory

* fix(macos): localize device-code completion action

* fix(auth): preserve device-code fallback copy

* fix(xai): report browser launch accurately
2026-07-11 16:43:21 -07:00
Peter Steinberger
b80ab618c3 feat(cloud-workers): authenticated worker protocol with closed ingress and minted credentials (#104688)
* feat(cloud-workers): add authenticated worker protocol

* feat(cloud-workers): add worker credential primitives

* docs(gateway): document closed worker protocol

* test(cloud-workers): keep protocol fixtures lean

* fix(cloud-workers): bound live worker connections

* fix(cloud-workers): close admission and cleanup gaps

* docs: regenerate docs map for worker protocol page
2026-07-11 13:45:14 -07:00
Peter Steinberger
7a466b33f3 feat: add metadata-only message audit events (#103903)
* feat: add metadata-only message audit events

* chore(protocol): restore generated swift models and config baseline after rebase

* fix(state): gate agent-db ownership check before schema version

* fix(cli): sync audit command description into the root-help catalog

* fix(audit): require destination proof before classifying outbound messages as direct

* refactor(audit): drop dead migration guard and add contract comments

* docs(gateway): add dedicated audit history page and cross-links

* test(e2e): enable direct-mode message audit in the telegram proof SUT config

* test(channels): expect declared conversationKind in durable delivery session context

* fix(audit): record the routing channel id for inbound rows from plugin channels

* fix(audit): match channel-prefixed delivery targets in the destination route gate

* fix(audit): validate explicit target kind against the destination route kind

* fix(audit): use the canonical target-prefix grammar in the destination route gate and fail closed on foreign migration tables

* fix(audit): normalize nested provider and kind target prefixes in the destination gate

* fix(audit): strip registered provider aliases and the direct kind prefix in the destination gate

* chore(docs): refresh config baseline after rebase
2026-07-11 13:14:08 -07:00
Peter Steinberger
8310c565e0 feat(onboarding): add provider sign-in (#104502)
* feat(onboarding): add provider sign-in flows

* fix(oauth): keep callback compatibility

* fix(onboarding): reconcile lost auth outcomes

* fix(onboarding): lock auth cancellation at commit

* fix(onboarding): close provider auth lifecycle gaps

* fix(onboarding): make terminal auth failures dismissable

* fix(onboarding): satisfy native app checks

* fix(onboarding): reconcile absent auth sessions

* fix(onboarding): bound provider auth sessions

* fix(onboarding): open provider auth links safely

* test(onboarding): use scanner-safe auth fixtures

* revert: keep established onboarding auth fixtures

* fix(onboarding): close provider auth cancellation gaps

* fix(gateway): retain uncollected wizard results

* fix(onboarding): bind provider reconciliation attempt

* fix(i18n): avoid guessing moved string identities

* style(onboarding): normalize remote auth choices efficiently

* fix(protocol): refresh optional provider auth choices

* test(gateway): cover provider auth dispatch order

* refactor(macos): split onboarding setup support

* fix(macos): refresh merged native checks
2026-07-11 13:00:17 -07:00
Peter Steinberger
96f0983a85 fix(onboarding): skip setup for configured gateways and require inference first (#102883)
* fix(crestodian): keep onboarding RPCs restart-safe

* fix(profiles): isolate approval state migrations

* fix(crestodian): bypass configured gateway setup

* test(crestodian): type onboarding mocks

* fix(onboarding): require inference before Crestodian

* fix(onboarding): enforce verified inference handoff

* fix(macos): reset setup on gateway endpoint edits

* chore(i18n): refresh native source inventory

* fix(gateway): keep socket on request cancellation

* test(packaging): require workspace templates

* fix(onboarding): bind setup to verified inference

* fix(onboarding): align inference gate contracts

* fix(crestodian): classify concurrent policy rejection

* test(crestodian): expect registry restoration

* fix(onboarding): bind setup to configured gateways

* fix(codex): preserve startup phase deadlines

* test(crestodian): match fail-closed policy ordering

* test(onboarding): assert bound gateway handoff

* fix(codex): bind runtime resolution to spawn cwd

* test(crestodian): assert policy rejection order

* fix(cli): preserve gateway routing across restarts

* fix(macos): fail closed during gateway edits

* test(macos): cover gateway route generation races

* chore: keep release notes out of onboarding PR

* fix(ci): refresh onboarding generated checks

* style(swift): align gateway channel formatting

* fix(ci): refresh plugin SDK surface budgets

* fix(ci): resync native string inventory

* refactor(swift): split gateway channel support

* test(doctor): isolate plugin compatibility registry

* test(macos): isolate gateway onboarding fixtures

* test(macos): assert gateway lease health ordering

* fix(codex): reconcile computer-use startup changes
2026-07-11 10:25:14 -07:00
Peter Steinberger
49b5b862ac feat: node-hosted plugins — dynamic tools, MCP servers, and skills (#90431)
* feat: node-hosted plugins — dynamic tools, MCP servers, and skills

Nodes become declarative plugin hosts:
- node.pluginTools.update: node hosts publish plugin-registered agent tool
  descriptors; gateway materializes them as agent tools executing via
  node.invoke under the node command allowlist, with tools.effective
  invalidation and node online/offline removal.
- Trusted paired-node descriptors: no gateway-side plugin registration
  required; gateway.nodes.pluginTools.enabled off-switch (default on);
  description/count caps; deterministic node-prefixed collision names.
- Declarative node-hosted MCP: nodeHost.mcp.servers (McpServerConfig shape)
  starts MCP clients on the node host, publishes tools as pluginId node-mcp,
  executes via built-in mcp.tools.call.v1 with per-layer timeouts, failure
  isolation, and orphan-safe shutdown. No re-pairing when servers change.
- Node-hosted skills: node.skills.update publishes ~/.openclaw/skills
  content (64 skills/64KB/512KB caps both sides); gateway merges them into
  the skills snapshot while connected and exec host=node is available, with
  node:// locators, node-prefixed collisions, disabled command dispatch,
  and gateway.nodes.skills.enabled + nodeHost.skills.enabled switches.
- Security: node-supplied pluginIds cannot satisfy pluginId-scoped tool
  allowlists unless gateway-registered; reserved node-mcp id requires the
  core MCP descriptor shape; protocol registry kept out of public
  plugin-sdk dts.
- E2E: pond harness proves publication, MCP round-trip, skills locator, and
  disconnect/reconnect for all three surfaces.

* style: format node-plugin-tools test

* fix(skills): keep status loader unfiltered when eligibility is passed

skills.status started passing eligibility for the node-skill merge, which
flipped loadWorkspaceSkillEntries into filtered mode and dropped disabled
skills from status reports (QA plugin-lifecycle-hot-reload timeout). Status
now merges node skills explicitly around an unfiltered load. Also: regen
docs_map for new node docs sections; add the intentional node-host MCP
onclose suppression to the lint-suppression allowlist.
2026-07-11 10:16:34 -07:00
Peter Steinberger
5ca46a6554 feat(cloud-workers): pinned SSH tunnel runtime and provider-owned key resolution (#104553)
* feat(cloud-workers): add pinned SSH tunnel runtime

* feat(crabbox): resolve cloud worker SSH identities

* docs(cloud-workers): document SSH tunnel contracts
2026-07-11 09:26:08 -07:00
Peter Steinberger
03cab29505 feat(cloud-workers): worker bundle production, pinned SSH bootstrap, and admission handshake (#104532)
* feat(gateway-protocol): add worker admission handshake

* feat(cloud-workers): build and bootstrap worker bundles

* feat(cloud-workers): wire bootstrap lifecycle

* fix(cloud-workers): state host-key TOFU fallback without warning-comment suppression

* test(cloud-workers): assemble host-key fixture to satisfy review secret scanner

* test(cloud-workers): assemble redaction fixture to satisfy review secret scanner

* fix(cloud-workers): require pinned SSH host keys

* fix(state): add ssh_host_key to additive worker_environments migration
2026-07-11 08:14:30 -07:00
haruai
597de699d0 fix: route node policy plugin approvals (#98561)
* fix: route node policy plugin approvals

* refactor(gateway): simplify node approval routing

* fix(gateway): preserve node approval routes

* chore(protocol): refresh node invoke model

---------

Co-authored-by: haruaiclone-droid <281899875+haruaiclone-droid@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-11 05:37:45 -07:00
Peter Steinberger
90e465833b feat(gateway): durable cloud worker environments, provider SDK contract, and lifecycle RPCs (#104401)
* docs(plan): add cloud workers design plan

* feat(plugin-sdk): add cloud worker provider foundations

* feat(protocol): add worker environment lifecycle shapes

* feat(gateway): persist worker environment lifecycles

* test(gateway): pin environment inventory assertion for damaged worker store

* style(cloud-workers): satisfy lint and docs formatting

* fix(gateway): narrow worker environment type boundaries

* chore(plugin-sdk): account for WorkerProvider surface growth

* docs: regenerate docs map
2026-07-11 04:54:27 -07:00
Peter Steinberger
7bf80dc2c6 chore(tooling): enforce formatting and refresh TypeScript checks (#104239)
* chore(tooling): enforce current formatter and refresh checks

* chore(tooling): keep release changelog formatter-owned

* chore(tooling): retain compatible Node type surface

* ci: enforce formatting for docs-only changes

* ci: isolate docs formatter check

* chore(tooling): apply updated lint and format rules

* chore(tooling): satisfy updated switch lint

* style(ui): apply Linux formatter layout

* test(doctor): match quiet local audio contribution

* test(doctor): assert quiet output only

* test(doctor): follow restored information contract
2026-07-11 01:09:51 -07:00
Peter Steinberger
f94a7dc183 feat(codex): supervise native Codex sessions (#104045)
* feat(codex): add native session supervision

* fix(codex): harden supervision integration

* fix(codex): preserve locked harness ownership

* fix(codex): fence native session archive

* fix(codex): revalidate archive binding ownership

* feat(codex): integrate supervision runtime

* feat(sessions): preserve harness-owned execution

* feat(sessions): persist harness ownership invariants

* feat(gateway): enforce harness-owned sessions

* feat(setup): enable detected Codex supervision

* feat(mac): expose supervised Codex sessions

* feat(ui): make Codex sessions actionable

* docs(codex): document session supervision

* test(codex): cover integration ownership

* chore(i18n): refresh supervision inventories

* fix(setup): finalize Codex activation atomically

* test(codex): narrow binding store update

* fix(sessions): preserve legacy model locks

* test(macos): serialize Codex catalog fixtures

* fix(sessions): preserve legacy lock admission

* chore(i18n): reconcile supervision metadata

* test(sessions): mark legacy lock fixture

* fix(macos): drain final Codex catalog frame

* docs: leave supervision note to release

* style(macos): satisfy Codex catalog type length

* chore: record session accessor seam owners

* fix(macos): honor configured Codex supervision

* fix(codex): preserve harness-owned model locks

* fix(codex): satisfy supervision lint gates

* chore(i18n): refresh native supervision inventory

* fix(codex): align supervision validation contracts

* fix(codex): close supervision boundary gaps

* fix(codex): preserve supervision activation contracts

* fix(codex): dispose standalone supervision runtime

* fix(codex): pin supervised source connection

* fix(plugins): bind delegated runs to exact session target

* fix(codex): scope supervised sessions to configured agents

* fix(codex): fingerprint effective supervision home

* fix(codex): normalize supervision plugin policy

* fix(codex): keep supervised bindings stable across upgrades

* fix(codex): guard all supervised binding connections

* fix(codex): preserve catalog filters and pending CAS identity

* fix(codex): preserve supervision identity for diagnostics

* fix(codex): bind uncertain commits to supervision connection

* fix(codex): satisfy supervision type boundaries

* fix(macos): reconcile current main validation

* fix(codex): handle absent runtime config in supervision

* fix(doctor): own local audio acceleration check

* fix(codex): satisfy integration lint gates

* fix(codex): satisfy lifecycle safety guards
2026-07-11 00:12:08 -07:00