Commit Graph

255 Commits

Author SHA1 Message Date
Peter Steinberger
b9fa1ffa27 feat(gateway): system change history RPC and Ask OpenClaw recent-changes panel (#111286)
* feat(gateway): system change history RPC and Ask OpenClaw recent-changes panel

* test(gateway): fix journal fixtures, split custodian page tests, refresh docs map

* chore: quiet lint on journal reader tests and custodian harness
2026-07-19 02:38:05 -07:00
Peter Steinberger
4efcea1fd2 feat(browser): send pages to OpenClaw from the Chrome extension (#111158)
* feat(browser): send pages to the main session from the Chrome extension

One-click page share in the OpenClaw Chrome extension: toolbar popup with an
optional note, page/selection context menu, and Alt+Shift+S. Capture is
selection-first with a readability heuristic, X/Twitter thread extraction, and
Google Docs plain-text export via the user's session cookies. Payloads ride the
existing paired relay WebSocket as a new pageShare message; the gateway-only
page-share sink wraps page text in the external-content safety boundary, then
enqueues a main-session system event and requests an immediate heartbeat
(hooks/wake semantics). Node-hosted relays report a clear unsupported error.

Capture heuristics adapted from Nat Eliason's MIT-licensed send-to-openclaw.

Co-authored-by: Codex <codex@openai.com>

* fix(browser): keep page-controlled metadata inside the share safety boundary

Review findings: move title/URL inside wrapExternalContent (a hostile <title>
must not become trusted header text), prefer the user's selection over the
full Google Docs export, and pass the context-menu selectionText through so
iframe selections and selections cleared during relay reconnect still win.

* fix(browser): bind context-menu shares to the click-time document

Selection shares from the context menu now send the click snapshot directly
(no recapture), so navigations during relay reconnect cannot mislabel the
source and iframe selections are preserved. The Google Docs selection probe
scans all accessible frames before falling back to the full-document export.

* test(browser): expect the page-share handler in relay server args

* fix(browser): probe only the main frame for Google Docs selections

All-frame injection rejects wholesale when one frame is inaccessible and
returns child frames in nondeterministic order, so the probe now reads the
main frame only. Child-frame selections still share correctly through the
context menu's click-time selectionText; toolbar/shortcut entry sends the
full page for that case (named tradeoff in the code comment).

* fix(browser): satisfy page-share CI gates

---------

Co-authored-by: Codex <codex@openai.com>
2026-07-19 01:07:28 -07:00
Peter Steinberger
ccb147518c feat(agents): Swarm core — collector spawn, agents_wait, structured output, caps (gated) (#110932)
* docs: add Swarm implementation spec

* feat(agents): Swarm core — collector spawn, agents_wait, structured output, fastMode, caps

Implements docs/plan/swarms.md §4-6: tools.swarm config gate (default off),
collector-mode sessions_spawn (collect/outputSchema/fastMode/groupId), fail-closed
child approvals, agents_wait race-semantics tool, per-group FIFO scheduler with
maxConcurrent/maxChildrenPerGroup/maxTotalPerGroup caps, additive registry and
state-schema columns (no schema-version bump), and colocated tests.

Part of #110325

* fix(agents): rebase reconciliation — preserve swarm state columns

* fix(agents): O(1) collector session index, cheap-first preflight, collector start lifecycle hooks

Autoreview findings: replace the per-request full registry scan with an
index-maintaining run map and gate the persisted-store fallback behind
isSubagentSessionKey; emit subagent_progress/subagent_spawned from the swarm
scheduler start callback so collector children produce balanced plugin
lifecycle events.

* chore(protocol): regenerate Swift gateway models for swarm fields

* fix(agents): lint cleanup — typed catch, explicit microtask flush, no executor return

* fix(agents): knip/test-support/max-lines cleanup for swarm surfaces

* fix(agents): keep tool-catalog ui-safe — callers pass prepared swarmEnabled fact

resolveSwarmConfig value-import in tool-catalog dragged the server graph into
the Control UI bundle via tool-policy-shared (UNLOADABLE_DEPENDENCY on
subpath aliases). Catalog stays pure; the gateway tools-catalog handler
resolves the gate and passes the boolean.

* fix(agents): reconcile swarm spawn pipeline

* fix(agents): refresh swarm tool metadata

* fix(apps): sync swarm tool localization

* style(agents): compact tool display metadata

* fix(plugin-sdk): account for swarm config surface
2026-07-18 23:30:11 -07:00
Peter Steinberger
a2ccbdfa96 feat(cli): list and resolve pending approvals headlessly (#111060)
* feat(cli): manage pending approvals

* fix(cli): show terminal-safe approval ids raw, reserve id64 tokens for hostile ids

* fix(cli): preserve opaque approval ids verbatim

* fix(cli): tokenize leading-hyphen approval ids for pasteability

* fix(cli): lossless utf16 id64 tokens for opaque approval ids

* fix(cli): resolve approval ids verbatim, no input trim

* fix(cli): scope-only approval auth, reviewer-safe system-agent summaries, skip ill-formed ids

* fix(cli): validate pending approval ids

* fix(cli): align approvals catalog and docs map
2026-07-18 23:23:49 -07:00
FMLS
4074e0cae1 fix(browser): close tracked tabs after gateway restart (#110797)
* fix(browser): preserve tab cleanup across restarts

* fix(browser): disambiguate restart tab aliases

* fix(browser): keep untrack selection type private

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 22:24:20 -07:00
Peter Steinberger
5e51c4bbcc feat(gateway): auto-approve trusted-proxy browser device pairing (#111189)
* feat(gateway): auto-approve trusted-proxy browser device pairing

Adds gateway.auth.trustedProxy.deviceAutoApprove so team gateways behind an
identity-aware proxy (Cloudflare Access, oauth2-proxy, Pomerium) can skip the
manual `openclaw devices approve` step for new Control UI/WebChat devices.

Auto-approval fires only for a new (unpaired) operator browser device on a
connection that already passed trusted-proxy auth with a resolved allowUsers
user. Scope upgrades on existing devices and node pairing stay manual. Granted
scopes are capped to the configured set intersected with the connection's
x-openclaw-scopes proxy cap, operator.admin is rejected at config validation,
and the pairing-store approval rechecks new-device status under the store lock
so a repair/upgrade or concurrent approval can never be silently widened. Each
auto-approval emits an audit log line with the proxy user and granted scopes,
and `openclaw security audit` warns when the mode is enabled.

* docs: regenerate docs map for trusted-proxy auto-approval section
2026-07-18 21:23:55 -07:00
Peter Steinberger
68771ebdfe feat(cron): script payloads behind the trigger gate (#111112)
Run script payloads through the shared headless code-mode executor with payload-grade budgets and success-only trigger.state persistence.

Reuse cron delivery, wake, pacing, and dangerous trigger-gate contracts for notify, wake, and nextCheck results.
2026-07-18 19:24:12 -07:00
Peter Steinberger
b51e3d02c7 docs(meetings): mention Discord voice channels 2026-07-19 02:35:21 +01:00
Peter Steinberger
09dd616782 docs(meetings): add platform comparison guide 2026-07-19 02:17:43 +01:00
Peter Steinberger
d96a87e8e9 docs: document session automation contracts (#111095) 2026-07-18 18:10:14 -07:00
Peter Steinberger
fdf44edf4d docs: document channel ingress guarantees (#111069) 2026-07-18 17:26:41 -07:00
Peter Steinberger
b4187ced90 feat: add live-validated Zoom meeting guest plugin (#111048)
* feat(zoom-meetings): add browser guest transport

* fix(zoom-meetings): type reusable refresh result

* test(meeting-bot): bind reusable refresh callback

* chore(zoom-meetings): use existing plugin label

* chore(zoom-meetings): defer changelog to release

* test(zoom-meetings): cover node setup through public host
2026-07-18 17:17:26 -07:00
Peter Steinberger
4b7d6fa3bf docs: align interactive client behavior (#111047) 2026-07-18 17:00:14 -07:00
Peter Steinberger
56eef79989 fix(channels): recover dead-lettered inbound events (#111029)
* feat(channels): add ingress dead-letter recovery

* fix(channels): preserve dead-letter compatibility

* docs: refresh CLI map for channel dead letters
2026-07-19 00:44:23 +01:00
Peter Steinberger
7562b79465 refactor(channels): share durable ingress monitor (#111017)
* refactor(channels): share durable ingress monitor

* fix(channels): harden ingress monitor shutdown

* docs: refresh SDK documentation map
2026-07-19 00:42:08 +01:00
Peter Steinberger
556a2ee276 feat(cron): add per-job dynamic cadence (#110978)
Add optional per-job pacing bounds across the cron API, CLI, tool schema, public output, and SQLite job envelope, requiring at least one bound. Allow only the currently running paced job to record a one-shot next_check proposal and carry it through isolated-run completion.

After successful runs, clamp the proposal to the job bounds and persist an exact one-shot slot marker so maintenance preserves only that timestamp. Clear the marker on runs, edits, and schedule normalization; preserve existing no-proposal, skip, timeout, and error scheduling behavior.
2026-07-18 23:43:39 +01:00
Peter Steinberger
a5ec26fa3c fix: prevent LINE channel reloads from hanging on stalled deliveries (#110971)
* fix(channels): bound ingress shutdown and document retention

* docs(channels): note ingress shutdown behavior

* chore: keep release notes in pull request

* docs: refresh documentation map

* fix(line): preserve deferred claims during shutdown

* fix(line): handle late abandonment failures
2026-07-18 23:25:33 +01:00
Peter Steinberger
460e3e669c fix(canvas): restore shipped policy/host-disable contracts; harden workspaces doctor cleanup (#110927)
* fix(dashboard): harden canvas and workspace compatibility

* docs(web): add dashboard architecture

* chore: remove release-owned changelog entry

* docs: update dashboard architecture map
2026-07-18 23:00:00 +01:00
Peter Steinberger
81362bf643 feat(apps,ui): question surface parity and composer takeover (#110681)
* feat(apple): question parity — persistent summaries, skip, reconnect fallback, macOS keyboard

* feat(android): question parity — persistent summaries, skip, reconnect fallback

* feat(ui): question panel replaces composer while expanded

* fix(apps): regenerate question parity contracts

* fix(apps): preserve question reconciliation state

* fix(apps): keep question terminal state monotonic

* test(android): satisfy question test formatting

* fix(security): restore skill audit file reads

* fix(apps): harden question parity edge cases

* fix(apps): preserve expired question summaries

* fix(apps): keep question recovery retries current

* fix(apps): retry stale question recovery snapshots

* fix(android): reset stale question retry budgets

* docs(tools): clarify question composer takeover

* fix(apps): satisfy question recovery release gates

* fix(apps): preserve unknown question outcomes

* fix(apps): harden question action state

* fix(apps): keep unavailable questions terminal

* fix(apps): finalize local question outcomes

* fix(apps): preserve question card API

* fix(apps): reconcile external question answers

* fix(apps): reset question backoff budget

* chore(apps): refresh native i18n inventory

* fix(android): distinguish question skip progress

* fix(android): reconcile locally expired questions

* fix(apps): keep question recovery state fresh

* docs: note question surface parity

* fix(ui): reconcile IME draft before question takeover

* docs: leave question parity notes to release workflow
2026-07-18 21:42:15 +01:00
Peter Steinberger
1cacb12c4d feat(canvas): give show_widget a design system — theme tokens, base styles, live host theme bridge (#110832) 2026-07-18 21:05:16 +01:00
Peter Steinberger
be80cc747c feat(zalouser): recover accepted messages after local crashes (#110916)
* feat(zalouser): add durable ingress recovery

* fix(zalouser): settle aborted ingress claims

* fix(zalouser): preserve concurrent ingress lanes

* docs: refresh generated channel map

* refactor(zalouser): simplify ingress abort listener
2026-07-18 20:32:30 +01:00
Peter Steinberger
6589788c02 docs: The main session concept page and shipped-sidebar updates (#110905)
* docs: add The main session concept page and cross-links

* docs: precise memory-priming wording on the main-session page

* docs: update Control UI sidebar description to the Home and zones model
2026-07-18 20:23:09 +01:00
Peter Steinberger
3572fba7f9 feat(plugin-sdk): guard ingress effects once per event (#110846)
* feat(plugin-sdk): add ingress effect guard

* docs: refresh docs map

* fix(plugin-sdk): propagate effect commit failures

* fix(plugin-sdk): isolate ingress effect namespaces
2026-07-18 19:23:39 +01:00
Peter Steinberger
a115af2774 feat(ui): add reactive OpenClaw health nudges (#110708)
* feat(ui): add reactive custodian health nudges

* fix(ui): distinguish stopped channels from startup failures

* test(ui): update custodian route gateway fixture

* fix(ui): preserve current channel health failures

* fix(ui): ignore recovered channel errors
2026-07-18 15:44:29 +01:00
Peter Steinberger
a068d38b66 refactor(plugins)!: remove experimental workspaces plugin (#110416)
* refactor(plugins)!: remove experimental workspaces plugin

* fix(doctor): remove retired workspaces plugin state

* refactor(doctor): settle retired-workspaces cleanup before legacy-state detect

* chore(i18n): leave workflow-owned locale artifacts to the locale refresh

* ci: retrigger after GitHub scheduling outage
2026-07-18 10:56:37 +01:00
Peter Steinberger
654560f289 feat(ui): add Apps & extensions page to the Control UI (#110563)
* feat(ui): add Apps & extensions page

* feat(ui): add per-theme app-art card illustrations

* docs: describe the Apps and extensions page in control-ui

* fix(ui): keep icons.ts under max-lines, drop unused export, regen docs map
2026-07-18 09:52:34 +01:00
Peter Steinberger
ab093bded4 docs(onboarding): finalize phase status and phase 7 decision (#110543)
* docs(onboarding): final phase status and phase 7 decision

* docs(onboarding): remove shipped refresh follow-up

* docs(onboarding): remove shipped browser follow-up
2026-07-18 09:44:20 +01:00
Chris Eckert
42be965eac improve(mattermost): restart only the changed account on config reload (#99312)
* improve(gateway): restart only the changed account on channel config reload

When a config change is scoped entirely to one channel account
(channels.{kind}.accounts.{accountId}[.*]), restart just that account
instead of the whole channel. Wholesale channel restarts disconnect every
account on the channel; on gateways running many accounts, each
account-scoped config write (adding an account, changing one account's
settings) briefly dropped every other account's connection.

The reload plan gains a restartChannelAccounts bucket populated only when
all of a channel's changed paths are account-scoped; any channel-global
path falls back to the existing wholesale restart, and a channel scheduled
for wholesale restart drops its per-account entries so each (channel,
account) pair restarts at most once. The executor runs per-account
restarts through the existing stopChannel/startChannel accountId parameter.

* fix(gateway): preserve account reload admission

* fix(gateway): scope surgical reloads to isolated plugins

* test(gateway): avoid preactivating reload snapshot

* docs(channels): define account reload isolation contract

* fix(gateway): preflight scoped account reloads

* fix(gateway): re-drain live scoped reload targets

* docs: refresh generated docs map

* fix(mattermost): align scoped reload with durable ingress

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 09:33:06 +01:00
Josh Avant
6def1a9c04 fix: prevent repeated tool-call IDs from poisoning sessions (#110518)
* fix(agents): pair repeated tool calls by occurrence

* docs: regenerate docs map
2026-07-18 00:49:40 -07:00
Peter Steinberger
18a49b3a78 refactor(discord): authorize widgets by channel audience (#110522)
* refactor(discord): authorize widgets by channel audience

* docs: refresh Discord Activity map
2026-07-18 08:42:40 +01:00
Peter Steinberger
d7de67ae02 feat: ask_user follow-ups — harness convergence, channel finalization + reactions, native cards, docked web panel (#110372)
* feat(ask-user): follow-up harness slice

* feat(ask-user): follow-up channels slice

* feat(ask-user): follow-up native slice

* feat(ui): dock question panel above composer with stepper and compact stream summaries

* docs: refresh follow-up integration maps

* test(ui): align terminal summary proof

* fix(infra): echo declared option answers in terminal status when free-text is allowed

* fix(infra): keep reaction answering when display labels are formatter-adjusted

* fix(agents): settle plain-text claims only after question registration commits

* fix(agents,apps): commit-ordered claim persistence, claim-aware prompt delivery, non-blocking question refresh

* fix(harness,infra): reaction-appropriate question copy, caller presentations honored

* fix(native,infra,agents): local-expiry eviction, value-addressed reactions, reserve-before-request

* fix(infra,android): dual-mode question resolver for compact callbacks; reset terminal retention on replayed pending

* fix(harness,discord): claim-aware prompt delivery in run helper; escape finalization labels

* fix(macos): merge transient-content visibility with question cards after main sync

* fix: repair ask user follow-up CI

* test: update limited bootstrap scope expectation

* fix: retain shared question card API

* chore: refresh native i18n inventory
2026-07-18 03:32:39 -04:00
Dave Morin
4b3ee5e7eb feat: let agents remember across private conversations (#100140)
* feat(memory): remember across private conversations

Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>

* chore(docs): regenerate config baseline

* fix(memory): restore recall configuration wiring

* fix(memory): scope recall transcript indexing

* test(memory): repair conversation recall fixtures

* test(memory): split session visibility coverage

* style(memory): format type imports

---------

Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 08:21:43 +01:00
Peter Steinberger
f8e417a774 docs: add database downgrade troubleshooting for the 2026.7.2 schema migration (#110487) 2026-07-18 08:03:16 +01:00
xingzhou
75982be9a3 fix(cli): oversized secrets plans consume unbounded memory (#109652)
* fix(cli): reject oversized secrets plan files

* fix(cli): keep generated secrets plans applyable

* fix(cli): reject special plan files without blocking

* docs(cli): refresh secrets plan documentation map
2026-07-18 07:18:21 +01:00
Peter Steinberger
1c225c855d fix: CLI timeout warnings explain stopped work (#110369)
* fix: clarify CLI timeout failures

* docs: update timeout docs map
2026-07-18 06:18:11 +01:00
Peter Steinberger
a89f01abf4 perf(sqlite): fast schema gates, background integrity verification, and downgrade protection (#110271)
* perf(sqlite): gate schema version before integrity scans and quarantine terminal open failures

* feat(gateway): refuse incompatible database schemas at boot and verify integrity in the background

* feat(update): refuse installing builds that cannot open the current databases

* docs: add database schema reference with version history and downgrade guidance

* test(update): tolerate optional runner options in git-mutation mocks

* refactor(update): split npm package-target metadata out of update-check

* chore: model verifier internals for knip and regenerate docs map

* chore(i18n): resync stale iOS localization catalog

* chore: allowlist read-only preflight and verifier raw SQLite access
2026-07-18 05:49:39 +01:00
Peter Steinberger
19296b003b improve(agents): normalized web_search output contract with boundary-owned wrapping (#110308)
* feat: normalize web search output contract

* refactor(agents): promote web_search contract from a dedicated output module

* fix(agents): wrap unwrapped web_search text and pass unknown provider payloads through as raw

* fix(agents): gate web_search results branch on conforming rows and cover metadata fields

* fix(agents): gate every provider text path at the web_search boundary

* test(agents): align web_search fixtures with boundary-owned wrapping

* fix(agents): make the web_search boundary own the untrusted-content envelope

* fix(agents): report declared web_search errors first and align the documented contract

* fix(agents): bind envelope stripping to real markers and densify result rows

* fix(agents): emit canonical urls and a closed error code from web_search

* fix(agents): keep structured provider error diagnostics in the wrapped message

* fix(agents): satisfy production export and lint gates for the web_search contract
2026-07-18 03:39:29 +01:00
Peter Steinberger
53b53f1977 improve(agents): exact web_fetch output contract with cleaned result shape (#110223)
* feat: add web fetch output contract

* fix(agents): keep web_fetch contract schema module-local

* docs: refresh docs map for the web_fetch result section
2026-07-18 03:28:29 +01:00
Peter Steinberger
57a3739622 fix(ci): regenerate docs_map for the live-tests heading 2026-07-17 21:25:29 -04:00
Peter Steinberger
ec8f6e5e03 feat(browser): add secure per-tab copilot panel (#109817)
* feat(browser): add copilot security contracts

* fix(gateway): expose verified client identity to handlers

* feat(browser): add secure per-tab copilot panel

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* refactor(browser): separate copilot gateway hint custody

* fix(browser): preserve legacy pairing parse shape

* fix(browser): harden copilot lifecycle custody

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* fix(browser): enforce copilot lifecycle boundaries

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* style(browser): format copilot sources

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* fix(browser): preserve copilot consent revocation

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* refactor(browser): split copilot custody owners

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* test(browser): normalize websocket array buffers

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* chore(protocol): regenerate Swift gateway models

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* refactor(browser): model copilot runtime entrypoints

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* fix(browser): honor extension build boundaries

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* test(gateway): assert targeted chat delivery

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* test(gateway): cover targeted delivery calls

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* fix(browser): declare copilot build dependencies

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* fix(ci): clear browser copilot gate failures

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* test(ci): cover copilot lint exclusion

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* fix(browser): gate copilot on relay custody

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

* test(browser): bound copilot relay frames

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>

---------

Co-authored-by: Cameron Beeley <cameron.beeley@gmail.com>
2026-07-18 01:00:23 +01:00
Peter Steinberger
9a93a52a8a feat(onboard): recommendations store with once-semantics and self-naming bootstrap (#110173)
* feat(onboarding): persist app recommendations once

* feat(onboarding): add self-naming birth sequence

* chore(wizard): hoist bootstrap-defer imports to the top of the module

* docs(bootstrap): persist agreed identity into IDENTITY.md and SOUL.md as well

* docs: regenerate docs map after onboarding plan merge

* fix(wizard): reuse a pending stored offer instead of rescanning apps

* fix(onboard): deduplicate bootstrap recommendations
2026-07-17 23:42:01 +01:00
Peter Steinberger
5bab0c2ea8 feat(slack): support running as a real Slack user (user identity) (#109837)
* feat(slack): add user-identity config surface (session token/cookie)

Introduce an account-level identity discriminator ("bot" default | "user") for
the Slack channel, plus sessionToken/sessionCookie secret fields for the
browser-session (user) path. Schema enforces structural coupling only
(identity="user" rejects appToken/signingSecret/relay/non-default mode);
credential presence is deferred to runtime like bot/app tokens. Account entries
inherit the top-level identity. Adds env fallback (SLACK_SESSION_TOKEN/COOKIE,
default account only), secret-contract registration, provenance *Source fields,
and UI hints. Config surface only; resolver/transport are later phases.

* refactor(slack): identity-aware operation-token resolver + dedup

Route Slack read/write token selection through a single identity-aware
resolveSlackOperationToken: identity="user" selects the browser-session token
for both operations (companion cookie attached later at client construction),
identity="bot" keeps the exact userToken/botToken + userTokenReadOnly behavior.
Delete the duplicated token-selection gate in action-runtime and route direct
sends/DM opens through the shared resolver with identity-neutral error wording.
Behavior-neutral for bot identity; net non-test LOC -2.

* refactor(slack): retarget user identity to xoxp + companion app

Replace the abandoned browser-session (xoxc/xoxd) approach for identity="user"
with the official path: authenticate as the human via the existing userToken
(xoxp) while a companion app (appToken/socket or signingSecret/http) carries
events. Remove sessionToken/sessionCookie config, env vars, secret-contract
entries, resolver fields, and their tests. Invert the schema coupling so
identity="user" permits the companion-app transport credentials, and drop the
now-vestigial user-identity structural guard entirely (identity is a permissive
discriminator; credential presence is a runtime concern). Resolver returns the
user token for user-identity reads and writes. Behavior-neutral for bot
identity.

* feat(slack): user-identity provider transport (xoxp + companion app)

Wire the identity="user" event transport. The companion Slack app runs Socket
Mode (appToken) or HTTP (signingSecret) while Bolt authenticates as the human
via the user token (no bot token). Startup auth.test runs on the user token and
its user_id becomes the self/mention target and self-send dedupe id (Bolt's
lazy per-event authorize populates context.botUserId=user_id, so the existing
self-event middleware drops the human's own messages). Identity-aware token
requirements and diagnostics; the bot-token identity warning is suppressed for
user identity. Behavior-neutral for identity="bot".

* feat(slack): user-identity setup, doctor, and docs

Add the setup wizard, doctor/status, and documentation for identity="user".
The wizard collects a user token plus the companion-app transport credential
(app token for socket, signing secret for http) and only persists identity when
"user" so bot setups keep byte-identical generated config; doctor validates the
user token via auth.test and warns on a missing transport credential; account
inspection reports user-token status. Message actions are gated on the active
identity's credential so user accounts expose actions. Docs add the exact
companion-app recipe (user scopes, on-behalf-of-user message events, socket/http
examples, the DM/group-DM-only-via-user-scope note, and self-send dedupe).
Behavior-neutral for identity="bot".

* test(slack): isolate user-identity provider tests to fix parallel flake

The new user-identity provider tests shared the globalThis-stored Slack test
client/handlers across files under parallel isolate:false, so their reaction
closures could reference a prior file's state and intermittently fail sibling
monitor tests (monitor.tool-result reactions). Track started monitors and
abort/await them all in afterEach (even on failed assertions), reset the shared
auth.test/mock state, and dispose the global Slack test runtime per file via a
new disposeSlackTestRuntime helper. Full Slack suite green across repeated
parallel runs.

* fix(slack): regenerate channel config metadata after rebase

* fix(slack): resolve setup consistent-return and doctor dead-export lint

* style: format install script test

* docs(slack): regenerate docs map for user-identity section

* test(slack): use renamed createSlackBoltApp token param in interop test

The rebase folded main's new wrapReceiver test into the renamed
createSlackBoltApp signature (botToken -> token); update the call site.
2026-07-17 23:23:21 +01:00
Peter Steinberger
da44d52ac6 feat: ask_user — structured questions from the agent with web card, channel buttons, and text answers (#109922)
* feat(gateway): add transient question runtime (question.* methods + broadcasts)

* feat(agents): add blocking ask_user question tool with chat prompt delivery and text-reply claim

* feat(ui): interactive in-thread question cards for ask_user

* feat(channels): native tap-to-answer buttons for ask_user on Telegram, Discord, and Slack

* feat(ui): unify codex and gateway question cards with interactive gateway answering

* refactor(agents): collapse ask_user pending state to one registry; docs for ask_user

* fix(agents): include ask_user in normal gateway runs; add question-flow control-ui e2e

* test(ui): avoid credential-shaped fixture in question card test

* refactor(ui): reorder stream-group context keys

* fix(gateway,ui): validate question answers at resolve; reject secret/duplicate-label questions; UI retry and reconnect hardening

* fix(gateway,agents): canonicalize accepted option answers; bound ask_user option labels to 64 chars

* chore(ci): prune unused question exports, allowlist mobile question events, fix discord lint

* chore(ci): regenerate protocol/i18n/docs/tool-display artifacts for question surface

* fix(protocol): flatten QuestionRecord for native codegen; drop TS-only alias from schema registry

* chore(android): regenerate ask-user localization resources

* docs: regenerate docs map after rebase

* fix(ci): avoid stale read-only dependency disks

* test: remove stale reef lint suppression ratchet

* fix(ci): keep source locale drift advisory in release gates

* fix(ci): scope locale advisory handling to parity check
2026-07-17 22:24:17 +01:00
Peter Steinberger
e7f4b99394 docs(onboarding): refresh redesign plan — shipped flow, landing playbook, phase 3 merged (#110121)
* docs(onboarding): refresh redesign plan — shipped flow, landing playbook, phase 3 merged

* docs: refresh generated docs map

* docs: correct onboarding trust and auth notes
2026-07-17 21:43:17 +01:00
Alex Knight
ddb4ed9a47 feat: trace Claude Code CLI model calls (#108304)
* feat: trace Claude CLI model calls

* fix: align Claude CLI trace hierarchy

* fix: distinguish model request and turn telemetry

* fix: satisfy diagnostics CI checks

* fix: distinguish agent-turn telemetry

---------

Authored-by: Alex Knight <15041791+amknight@users.noreply.github.com>
2026-07-18 06:23:49 +10:00
Peter Steinberger
198e3b37b2 feat(onboard): browser-first guided handoff (#110054)
* feat(onboard): add browser-first guided handoff

* chore: drop release-only CHANGELOG edit from browser-handoff branch

* fix(onboard): make browser handoff reach the gateway on real installs

The presence probe connected as a raw shared-auth client with a possibly
SecretRef-managed token, which the gateway rejects as an unpaired Control UI
client ("device identity required"), so the handoff never fired and always
fell through to the terminal hatch. Read presence as a CLI-mode loopback client
(the trusted path every openclaw command uses) so operator.read is granted, and
share that one auth path between the reachability gate and the wait loop. Also
short-circuit when gateway.controlUi.enabled is false so onboarding does not open
a dead dashboard URL and block for the full timeout.

* fix(onboard): share resolved target between handoff gate and wait

The reachability preflight now resolves the same target (and shared secret) the
wait loop uses, and presents the configured secret to the CLI-mode presence
read. Known remaining limitation: on fresh quickstart gateways whose auth token
is written to config but resolved differently at runtime, the presence read is
rejected with a token mismatch and the handoff falls back to the terminal hatch.
Tracked for follow-up before enabling the browser handoff by default.

* docs(onboarding): mark phase 3 browser handoff as held with diagnosis

* docs(onboarding): phase 3 proven end-to-end; token-mismatch hold was a test artifact

* fix(onboard): satisfy docs-map and test-type gates for the handoff branch

* refactor(onboard): split guided manual stage
2026-07-17 18:57:57 +01:00
Peter Steinberger
277f009cc9 feat(linux): Quick Chat floating composer for the Tauri companion (#109947)
* feat(linux): add Quick Chat floating composer to the Tauri companion

- frameless transparent always-on-top quickchat window (on-demand, canvas
  pattern), positioned top-third on the cursor monitor, CSS fade+zoom in/out
- global shortcut Ctrl+Shift+Space on X11 (GNOME reserves Alt+Space); tray
  'Quick Chat' item is the Wayland entry point; blur/Esc/close-request hide
- sends via the CLI agent turn with --message-file staged 0600 (argv is
  world-readable procfs) and cleaned up after the turn; failures surface as
  desktop notifications; Ctrl+Enter also opens the dashboard
- default-agent identity chip (emoji/monogram) from agents list --json, 60s cache
- window-scoped capability + permission set; window-state denylist; docs

* chore(linux): register quickchat.js as a knip native-asset entry
2026-07-17 18:25:27 +01:00
Peter Steinberger
b319493a52 improve: let Code Mode use declared tool result shapes (#109813)
* feat(agents): add Code Mode output contracts

* perf(agents): defer untrusted tool schemas

* chore(plugin-sdk): refresh API baseline

* fix(agents): preserve deferred schema markers

* fix(agents): preserve policy-blocked tool results

* fix(agents): preserve nullable output contracts

* fix(agents): reject policy blocks from success contracts

* fix(agents): preserve output contracts through normalization

* test(agents): type normalized tool fixtures

* fix(agents): validate catalog results before projection

* fix(agents): keep result snapshots internal

* fix(agents): fail closed on unrenderable unions

* fix(agents): preserve empty result markers

* test(agents): keep result fixture discriminator literal

* test(agents): use native own-property check
2026-07-17 14:46:37 +01:00
Peter Steinberger
da69daeb72 feat(onboarding): recommend plugins and skills from installed apps (#109668)
* feat(onboarding): recommend plugins and skills from installed apps

Scan installed macOS apps during classic onboarding (TCC-free), gather
candidates from official catalogs + ClawHub search, let the configured
model pick genuine matches, and offer an opt-in multiselect install step.
Adds a device.apps node-host command (default-off sharing, Android-parity
envelope) so remote gateways can request a paired Mac's inventory, and a
wizard.appRecommendations kill switch. Custom setup-inference completions
no longer inherit the 32-token verification-probe output cap.

* feat(onboarding): recommend apps in guided flow

* fix(onboarding): harden app recommendations against ClawHub self-promotion

Third-party ClawHub skills are never pre-selected regardless of model tier
(publisher-controlled listing text reaches the matcher prompt and could
promote itself); their labels now say they install third-party code.
Installed-app scans follow symlinked .app bundles. Matcher output stays
bounded by the resolved model's own maxTokens budget (documented invariant).

* fix(onboarding): key official catalog candidates by resolved plugin id

Real catalog entries are package manifests without a top-level id; keying the
candidate map and channel/provider classification by entry.id collapsed the
whole official catalog into one undefined-keyed entry, so no official plugin
or channel was ever recommended. Regression test runs against the bundled
catalogs.

* fix(onboarding): satisfy lint, types, deadcode, and migration gates

Split the guided-onboarding test into a self-contained custodian suite to stay
under max-lines. Narrow app-recommendation exports (drop dead node-payload
normalizer, unexport internal types/helpers, route candidate tests through the
public API), replace map-spread with a helper, unexport device.apps result
types, add installedAppsSharing to node-host migration expectations, cast the
wizard multiselect mock, and regenerate the docs map.

* test(onboarding): register new live test in the shard classifier
2026-07-17 14:07:59 +01:00
WhatsSkiLL
4d3b18811e feat(android): add Wear real-time Talk controls (#109483)
* feat(android): add Wear real-time Talk controls

* fix(android): satisfy Wear Talk CI checks

* fix(talk): remove unused client language parameter

* fix(android): harden Wear realtime Talk routing

Co-authored-by: IWhatsskill <284122573+IWhatsskill@users.noreply.github.com>

* chore(android): refresh Wear Talk metadata

* chore(android): align native i18n baseline

---------

Co-authored-by: IWhatsskill <284122573+IWhatsskill@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-17 13:46:05 +01:00