* memory-core: add dreaming promotion flow with weighted thresholds
* docs(memory): mark dreaming as experimental
* memory-core: address dreaming promotion review feedback
* memory-core: harden short-term promotion concurrency
* acpx: make abort-process test timer-independent
* memory-core: simplify dreaming config with mode presets
* memory-core: add /dreaming command and tighten recall tracking
* ui: add Dreams tab with sleeping lobster animation
Adds a new Dreams tab to the gateway UI under the Agent group.
The tab is gated behind the memory-core dreaming config — it only
appears in the sidebar when dreaming.mode is not 'off'.
Features:
- Sleeping vector lobster with breathing animation
- Floating Z's, twinkling starfield, moon glow
- Rotating dream phrase bubble (17 whimsical phrases)
- Memory stats bar (short-term, long-term, promoted)
- Active/idle visual states
- 14 unit tests
* plugins: fix --json stdout pollution from hook runner log
The hook runner initialization message was using log.info() which
writes to stdout via console.log, breaking JSON.parse() in the
Docker smoke test for 'openclaw plugins list --json'. Downgrade to
log.debug() so it only appears when debugging is enabled.
* ui: keep Dreams tab visible when dreaming is off
* tests: fix contracts and stabilize extension shards
* memory-core: harden dreaming recall persistence and locking
* fix: stabilize dreaming PR gates (#60569) (thanks @vignesh07)
* test: fix rebase drift in telegram and plugin guards
* feat(gateway): add skills.search and skills.detail RPC methods
Expose ClawHub search and detail capabilities through the Gateway protocol,
enabling desktop/web clients to browse and inspect skills from the registry.
New RPCs:
- skills.search: search ClawHub skills by query with optional limit
- skills.detail: fetch full detail for a single skill by slug
Both methods delegate to existing agent-layer functions
(searchSkillsFromClawHub, fetchSkillDetailFromClawHub) which wrap
the ClawHub HTTP client. No new external dependencies.
Signed-off-by: samzong <samzong.lu@gmail.com>
* feat(skills): add ClawHub skill search and detail in Control UI
Add skills.search and skills.detail Gateway RPC methods with typed
protocol schemas, AJV validators, and handler implementations. Wire
the new RPCs into the Control UI Skills panel with a debounced search
input, results list, detail dialog, and one-click install from ClawHub.
Gateway:
- SkillsSearchParams/ResultSchema and SkillsDetailParams/ResultSchema
- Handler calls searchClawHubSkills and fetchClawHubSkillDetail directly
- Remove zero-logic fetchSkillDetailFromClawHub wrapper
- 9 handler tests including boundary validation
Control UI:
- searchClawHub, loadClawHubDetail, installFromClawHub controllers
- 300ms debounced search input to avoid 429 rate limits
- Dedicated install busy state (clawhubInstallSlug) with success/error feedback
- Install buttons disabled during install with progress text
- Detail dialog with owner, version, changelog, platform metadata
Part of #43301
Signed-off-by: samzong <samzong.lu@gmail.com>
* fix(skills): guard search and detail responses against stale writes
Signed-off-by: samzong <samzong.lu@gmail.com>
* fix(skills): reset loading flags on query clear and detail close
Signed-off-by: samzong <samzong.lu@gmail.com>
* fix(gateway): register skills.search/detail in read scope and method list
Add skills.search and skills.detail to the operator READ scope group
and the server methods list. Without this, unclassified methods default
to operator.admin, blocking read-only operator sessions.
Also guard the detail loading reset in the finally block by the active
slug to prevent a transient flash when rapidly switching skills.
Signed-off-by: samzong <samzong.lu@gmail.com>
* fix(skills): guard search loading reset by active query
Signed-off-by: samzong <samzong.lu@gmail.com>
* test: cover ClawHub skills UI flow
* fix: clear stale ClawHub search results
---------
Signed-off-by: samzong <samzong.lu@gmail.com>
Co-authored-by: Frank Yang <frank.ekn@gmail.com>
Fixes#52576 — the accent/theme color was not applied to the Settings
page title, breadcrumb, section headings, or theme card labels. Changed
four CSS rules from var(--text-strong) to var(--accent) so they reflect
the selected theme consistently.
* feat(ui): wire /steer slash command to sessions.steer RPC
* feat(ui): wire /steer (soft inject) and /redirect (hard restart) slash commands
* test: use generic subagent names in steer/redirect tests
* fix(ui): exempt steer/redirect from busy-queue and guard sessions.list failures
* fix(ui): skip 'all' wildcard in steer/redirect target resolution
* test: register slash-command-executor test in vitest config
* fix(ui): restrict steer target to subagent keys and active sessions
Address two review issues in resolveSteerTarget:
P2: Replace resolveKillTargets with a dedicated resolveSteerSubagent
that matches only on subagent key suffix or label, not agent id.
This prevents false-positive targeting when the first word collides
with an agent id (e.g. "/steer main refine plan").
P1: Filter out ended sessions (endedAt set) so stale subagents with
reused names are not targeted.
* fix(ui): use shared generateUUID for steer idempotency key
* fix: restore telegram test to upstream state (merge artifact)
* fix(ui): track redirected run so Abort works and concurrent sends are blocked
* fix(ui): skip run tracking when /redirect targets a subagent session
* fix(ui): block idle steer runs
* fix(ui): dedupe steer slash command
* fix(ui): show pending steer state
* fix: wire control-ui steer and redirect (#54625) (thanks @fuller-stack-dev)
* fix: tighten steer target resolution (#54625) (thanks @fuller-stack-dev)
---------
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Verified:
- ui: pnpm test -- --run src/ui/markdown.test.ts
- local full gate relaxed for this run; no required GitHub checks reported on the branch
Co-authored-by: jnuyao <2928523+jnuyao@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
* Plugins: add native ask dialog for before_tool_call hooks
Extend the before_tool_call plugin hook with a requireApproval return field
that pauses agent execution and waits for real user approval via channels
(Telegram, Discord, /approve command) instead of relying on the agent to
cooperate with a soft block.
- Add requireApproval field to PluginHookBeforeToolCallResult with id, title,
description, severity, timeout, and timeoutBehavior options
- Extend runModifyingHook merge callback to receive hook registration so
mergers can stamp pluginId; always invoke merger even for the first result
- Make ExecApprovalManager generic so it can be reused for plugin approvals
- Add plugin.approval.request/waitDecision/resolve gateway methods with
schemas, scope guards, and broadcast events
- Handle requireApproval in pi-tools via two-phase gateway RPC with fallback
to soft block when the gateway is unavailable
- Extend the exec approval forwarder with plugin approval message builders
and forwarding methods
- Update /approve command to fall back to plugin.approval.resolve when exec
approval lookup fails
- Document before_tool_call requireApproval in hooks docs and unified
/approve behavior in exec-approvals docs
* Plugins: simplify plugin approval code
- Extract mergeParamsWithApprovalOverrides helper to deduplicate param
merge logic in before_tool_call hook handling
- Use idiomatic conditional spread syntax in toolContext construction
- Extract callApprovalMethod helper in /approve command to eliminate
duplicated callGateway calls
- Simplify plugin approval schema by removing unnecessary Type.Union
with Type.Null on optional fields
- Extract normalizeTrimmedString helper for turn source field trimming
* Tests: add plugin approval wiring and /approve fallback coverage
Fix 3 broken assertions expecting old "Exec approval" message text.
Add tests for the /approve command's exec→plugin fallback path,
plugin approval method registration and scope authorization, and
handler factory key verification.
* UI: wire plugin approval events into the exec approval overlay
Handle plugin.approval.requested and plugin.approval.resolved gateway
events by extending the existing exec approval queue with a kind
discriminator. Plugin approvals reuse the same overlay, queue management,
and expiry timer, with branched rendering for plugin-specific content
(title, description, severity). The decision handler routes resolve calls
to the correct gateway method based on kind.
* fix: read plugin approval fields from nested request payload
The gateway broadcasts plugin approval payloads with title, description,
severity, pluginId, agentId, and sessionKey nested inside the request
object (PluginApprovalRequestPayload), not at the top level. Fix the
parser to read from the correct location so the overlay actually appears.
* feat: invoke plugin onResolution callback after approval decision
Adds onResolution to the requireApproval type and invokes it after
the user resolves the approval dialog, enabling plugins to react to
allow-always vs allow-once decisions.
* docs: add onResolution callback to requireApproval hook documentation
* test: fix /approve assertion for unified approval response text
* docs: regenerate plugin SDK API baseline
* docs: add changelog entry for plugin approval hooks
* fix: harden plugin approval hook reliability
- Add APPROVAL_NOT_FOUND error code so /approve fallback uses structured
matching instead of fragile string comparison
- Check block before requireApproval so higher-priority plugin blocks
cannot be overridden by a lower-priority approval
- Race waitDecision against abort signal so users are not stuck waiting
for the full approval timeout after cancelling a run
- Use null consistently for missing pluginDescription instead of
converting to undefined
- Add comments explaining the +10s timeout buffer on gateway RPCs
* docs: document block > requireApproval precedence in hooks
* fix: address Phase 1 critical correctness issues for plugin approval hooks
- Fix timeout-allow param bug: return merged hook params instead of
original params when timeoutBehavior is "allow", preventing security
plugins from having their parameter rewrites silently discarded.
- Host-generate approval IDs: remove plugin-provided id field from the
requireApproval type, gateway request, and protocol schema. Server
always generates IDs via randomUUID() to prevent forged/predictable
ID attacks.
- Define onResolution semantics: add PluginApprovalResolutions constants
and PluginApprovalResolution type. onResolution callback now fires on
every exit path (allow, deny, timeout, abort, gateway error, no-ID).
Decision branching uses constants instead of hard-coded strings.
- Fix pre-existing test infrastructure issues: bypass CJS mock cache for
getGlobalHookRunner global singleton, reset gateway mock between tests,
fix hook merger priority ordering in block+requireApproval test.
* fix: tighten plugin approval schema and add kind-prefixed IDs
Harden the plugin approval request schema: restrict severity to
enum (info|warning|critical), cap timeoutMs at 600s, limit title
to 80 chars and description to 256 chars. Prefix plugin approval
IDs with `plugin:` so /approve routing can distinguish them from
exec approvals deterministically instead of relying on fallback.
* fix: address remaining PR feedback (Phases 1-3 source changes)
* chore: regenerate baselines and protocol artifacts
* fix: exclude requesting connection from approval-client availability check
hasExecApprovalClients() counted the backend connection that issued
the plugin.approval.request RPC as an approval client, preventing
the no-approval-route fast path from firing in headless setups and
causing 120s stalls. Pass the caller's connId so it is skipped.
Applied to both plugin and exec approval handlers.
* Approvals: complete Discord parity and compatibility fallback
* Hooks: make plugin approval onResolution non-blocking
* Hooks: freeze params after approval owner is selected
* Gateway: harden plugin approval request/decision flow
* Discord/Telegram: fix plugin approval delivery parity
* Approvals: fix Telegram plugin approval edge cases
* Auto-reply: enforce Telegram plugin approval approvers
* Approvals: harden Telegram and plugin resolve policies
* Agents: static-import gateway approval call and fix e2e mock loading
* Auto-reply: restore /approve Telegram import boundary
* Approvals: fail closed on no-route and neutralize Discord mentions
* docs: refresh generated config and plugin API baselines
---------
Co-authored-by: Václav Belák <vaclav.belak@gendigital.com>