Commit Graph

313 Commits

Author SHA1 Message Date
Nate Fikru 6d31d1ecc6 fix(plugins): enforce high-priority override precedence
Make before_agent_start override merging preserve the first defined
model/provider override so higher-priority hooks cannot be overwritten by
lower-priority handlers, and align the corresponding test title and
expectation with the intended precedence behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-16 23:50:24 +01:00
Nate Fikru 2456b17587 test(plugins): add Layer 1+2 tests for model override hook
Layer 1: Hook merger tests verify modelOverride/providerOverride are
correctly propagated through the before_agent_start merger with
priority ordering, backward compatibility, and field isolation.

Layer 2: Pipeline wiring tests verify the earlyHookResult passthrough
contract between run.ts and attempt.ts, graceful error degradation,
and that overrides correctly modify provider/model variables.

19 tests total across 2 test files.
2026-02-16 23:50:24 +01:00
Nate Fikru b90eb51520 feat(plugins): add modelOverride/providerOverride to before_agent_start hook
Enable plugins to override the model and provider for agent runs by
returning modelOverride/providerOverride from the before_agent_start
hook. The hook is now invoked early in run.ts (before resolveModel)
so overrides take effect. The result is passed to attempt.ts via
earlyHookResult to prevent double-firing.

This enables security-critical use cases like routing PII-containing
prompts to local models instead of cloud providers.
2026-02-16 23:50:24 +01:00
Peter Steinberger f717a13039 refactor(agent): dedupe harness and command workflows 2026-02-16 14:59:30 +00:00
Peter Steinberger bfb5a44089 test: speed up plugin optional tools suite 2026-02-16 05:56:26 +00:00
Peter Steinberger bed0e07620 fix(cli): clear plugin manifest cache after install 2026-02-15 23:14:42 +00:00
Peter Steinberger d9d93485d9 refactor(test): share tool hook handler ctx 2026-02-15 22:04:07 +00:00
David Harmeyer 7c822d039b
feat(plugins): expose llm input/output hook payloads (openclaw#16724) thanks @SecondThread
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: SecondThread <18317476+SecondThread@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-15 16:01:00 -06:00
Peter Steinberger c25026f2b3 perf(plugins): lazy-create jiti loader 2026-02-15 19:29:27 +00:00
Peter Steinberger c7b6d6a14e refactor(plugins): reuse createEmptyPluginRegistry 2026-02-15 19:05:00 +00:00
Peter Steinberger 3783cd3850 refactor(plugins): share empty registry factory 2026-02-15 16:44:00 +00:00
Peter Steinberger e2c68cb169 refactor(test): share plugin hook registry helper 2026-02-15 14:44:15 +00:00
Tyler Yust b8f66c260d
Agents: add nested subagent orchestration controls and reduce subagent token waste (#14447)
* Agents: add subagent orchestration controls

* Agents: add subagent orchestration controls (WIP uncommitted changes)

* feat(subagents): add depth-based spawn gating for sub-sub-agents

* feat(subagents): tool policy, registry, and announce chain for nested agents

* feat(subagents): system prompt, docs, changelog for nested sub-agents

* fix(subagents): prevent model fallback override, show model during active runs, and block context overflow fallback

Bug 1: When a session has an explicit model override (e.g., gpt/openai-codex),
the fallback candidate logic in resolveFallbackCandidates silently appended the
global primary model (opus) as a backstop. On reinjection/steer with a transient
error, the session could fall back to opus which has a smaller context window
and crash. Fix: when storedModelOverride is set, pass fallbacksOverride ?? []
instead of undefined, preventing the implicit primary backstop.

Bug 2: Active subagents showed 'model n/a' in /subagents list because
resolveModelDisplay only read entry.model/modelProvider (populated after run
completes). Fix: fall back to modelOverride/providerOverride fields which are
populated at spawn time via sessions.patch.

Bug 3: Context overflow errors (prompt too long, context_length_exceeded) could
theoretically escape runEmbeddedPiAgent and be treated as failover candidates
in runWithModelFallback, causing a switch to a model with a smaller context
window. Fix: in runWithModelFallback, detect context overflow errors via
isLikelyContextOverflowError and rethrow them immediately instead of trying the
next model candidate.

* fix(subagents): track spawn depth in session store and fix announce routing for nested agents

* Fix compaction status tracking and dedupe overflow compaction triggers

* fix(subagents): enforce depth block via session store and implement cascade kill

* fix: inject group chat context into system prompt

* fix(subagents): always write model to session store at spawn time

* Preserve spawnDepth when agent handler rewrites session entry

* fix(subagents): suppress announce on steer-restart

* fix(subagents): fallback spawned session model to runtime default

* fix(subagents): enforce spawn depth when caller key resolves by sessionId

* feat(subagents): implement active-first ordering for numeric targets and enhance task display

- Added a test to verify that subagents with numeric targets follow an active-first list ordering.
- Updated `resolveSubagentTarget` to sort subagent runs based on active status and recent activity.
- Enhanced task display in command responses to prevent truncation of long task descriptions.
- Introduced new utility functions for compacting task text and managing subagent run states.

* fix(subagents): show model for active runs via run record fallback

When the spawned model matches the agent's default model, the session
store's override fields are intentionally cleared (isDefault: true).
The model/modelProvider fields are only populated after the run
completes. This left active subagents showing 'model n/a'.

Fix: store the resolved model on SubagentRunRecord at registration
time, and use it as a fallback in both display paths (subagents tool
and /subagents command) when the session store entry has no model info.

Changes:
- SubagentRunRecord: add optional model field
- registerSubagentRun: accept and persist model param
- sessions-spawn-tool: pass resolvedModel to registerSubagentRun
- subagents-tool: pass run record model as fallback to resolveModelDisplay
- commands-subagents: pass run record model as fallback to resolveModelDisplay

* feat(chat): implement session key resolution and reset on sidebar navigation

- Added functions to resolve the main session key and reset chat state when switching sessions from the sidebar.
- Updated the `renderTab` function to handle session key changes when navigating to the chat tab.
- Introduced a test to verify that the session resets to "main" when opening chat from the sidebar navigation.

* fix: subagent timeout=0 passthrough and fallback prompt duplication

Bug 1: runTimeoutSeconds=0 now means 'no timeout' instead of applying 600s default
- sessions-spawn-tool: default to undefined (not 0) when neither timeout param
  is provided; use != null check so explicit 0 passes through to gateway
- agent.ts: accept 0 as valid timeout (resolveAgentTimeoutMs already handles
  0 → MAX_SAFE_TIMEOUT_MS)

Bug 2: model fallback no longer re-injects the original prompt as a duplicate
- agent.ts: track fallback attempt index; on retries use a short continuation
  message instead of the full original prompt since the session file already
  contains it from the first attempt
- Also skip re-sending images on fallback retries (already in session)

* feat(subagents): truncate long task descriptions in subagents command output

- Introduced a new utility function to format task previews, limiting their length to improve readability.
- Updated the command handler to use the new formatting function, ensuring task descriptions are truncated appropriately.
- Adjusted related tests to verify that long task descriptions are now truncated in the output.

* refactor(subagents): update subagent registry path resolution and improve command output formatting

- Replaced direct import of STATE_DIR with a utility function to resolve the state directory dynamically.
- Enhanced the formatting of command output for active and recent subagents, adding separators for better readability.
- Updated related tests to reflect changes in command output structure.

* fix(subagent): default sessions_spawn to no timeout when runTimeoutSeconds omitted

The previous fix (75a791106) correctly handled the case where
runTimeoutSeconds was explicitly set to 0 ("no timeout"). However,
when models omit the parameter entirely (which is common since the
schema marks it as optional), runTimeoutSeconds resolved to undefined.

undefined flowed through the chain as:
  sessions_spawn → timeout: undefined (since undefined != null is false)
  → gateway agent handler → agentCommand opts.timeout: undefined
  → resolveAgentTimeoutMs({ overrideSeconds: undefined })
  → DEFAULT_AGENT_TIMEOUT_SECONDS (600s = 10 minutes)

This caused subagents to be killed at exactly 10 minutes even though
the user's intent (via TOOLS.md) was for subagents to run without a
timeout.

Fix: default runTimeoutSeconds to 0 (no timeout) when neither
runTimeoutSeconds nor timeoutSeconds is provided by the caller.
Subagent spawns are long-running by design and should not inherit the
600s agent-command default timeout.

* fix(subagent): accept timeout=0 in agent-via-gateway path (second 600s default)

* fix: thread timeout override through getReplyFromConfig dispatch path

getReplyFromConfig called resolveAgentTimeoutMs({ cfg }) with no override,
always falling back to the config default (600s). Add timeoutOverrideSeconds
to GetReplyOptions and pass it through as overrideSeconds so callers of the
dispatch chain can specify a custom timeout (0 = no timeout).

This complements the existing timeout threading in agentCommand and the
cron isolated-agent runner, which already pass overrideSeconds correctly.

* feat(model-fallback): normalize OpenAI Codex model references and enhance fallback handling

- Added normalization for OpenAI Codex model references, specifically converting "gpt-5.3-codex" to "openai-codex" before execution.
- Updated the `resolveFallbackCandidates` function to utilize the new normalization logic.
- Enhanced tests to verify the correct behavior of model normalization and fallback mechanisms.
- Introduced a new test case to ensure that the normalization process works as expected for various input formats.

* feat(tests): add unit tests for steer failure behavior in openclaw-tools

- Introduced a new test file to validate the behavior of subagents when steer replacement dispatch fails.
- Implemented tests to ensure that the announce behavior is restored correctly and that the suppression reason is cleared as expected.
- Enhanced the subagent registry with a new function to clear steer restart suppression.
- Updated related components to support the new test scenarios.

* fix(subagents): replace stop command with kill in slash commands and documentation

- Updated the `/subagents` command to replace `stop` with `kill` for consistency in controlling sub-agent runs.
- Modified related documentation to reflect the change in command usage.
- Removed legacy timeoutSeconds references from the sessions-spawn-tool schema and tests to streamline timeout handling.
- Enhanced tests to ensure correct behavior of the updated commands and their interactions.

* feat(tests): add unit tests for readLatestAssistantReply function

- Introduced a new test file for the `readLatestAssistantReply` function to validate its behavior with various message scenarios.
- Implemented tests to ensure the function correctly retrieves the latest assistant message and handles cases where the latest message has no text.
- Mocked the gateway call to simulate different message histories for comprehensive testing.

* feat(tests): enhance subagent kill-all cascade tests and announce formatting

- Added a new test to verify that the `kill-all` command cascades through ended parents to active descendants in subagents.
- Updated the subagent announce formatting tests to reflect changes in message structure, including the replacement of "Findings:" with "Result:" and the addition of new expectations for message content.
- Improved the handling of long findings and stats in the announce formatting logic to ensure concise output.
- Refactored related functions to enhance clarity and maintainability in the subagent registry and tools.

* refactor(subagent): update announce formatting and remove unused constants

- Modified the subagent announce formatting to replace "Findings:" with "Result:" and adjusted related expectations in tests.
- Removed constants for maximum announce findings characters and summary words, simplifying the announcement logic.
- Updated the handling of findings to retain full content instead of truncating, ensuring more informative outputs.
- Cleaned up unused imports in the commands-subagents file to enhance code clarity.

* feat(tests): enhance billing error handling in user-facing text

- Added tests to ensure that normal text mentioning billing plans is not rewritten, preserving user context.
- Updated the `isBillingErrorMessage` and `sanitizeUserFacingText` functions to improve handling of billing-related messages.
- Introduced new test cases for various scenarios involving billing messages to ensure accurate processing and output.
- Enhanced the subagent announce flow to correctly manage active descendant runs, preventing premature announcements.

* feat(subagent): enhance workflow guidance and auto-announcement clarity

- Added a new guideline in the subagent system prompt to emphasize trust in push-based completion, discouraging busy polling for status updates.
- Updated documentation to clarify that sub-agents will automatically announce their results, improving user understanding of the workflow.
- Enhanced tests to verify the new guidance on avoiding polling loops and to ensure the accuracy of the updated prompts.

* fix(cron): avoid announcing interim subagent spawn acks

* chore: clean post-rebase imports

* fix(cron): fall back to child replies when parent stays interim

* fix(subagents): make active-run guidance advisory

* fix(subagents): update announce flow to handle active descendants and enhance test coverage

- Modified the announce flow to defer announcements when active descendant runs are present, ensuring accurate status reporting.
- Updated tests to verify the new behavior, including scenarios where no fallback requester is available and ensuring proper handling of finished subagents.
- Enhanced the announce formatting to include an `expectFinal` flag for better clarity in the announcement process.

* fix(subagents): enhance announce flow and formatting for user updates

- Updated the announce flow to provide clearer instructions for user updates based on active subagent runs and requester context.
- Refactored the announcement logic to improve clarity and ensure internal context remains private.
- Enhanced tests to verify the new message expectations and formatting, including updated prompts for user-facing updates.
- Introduced a new function to build reply instructions based on session context, improving the overall announcement process.

* fix: resolve prep blockers and changelog placement (#14447) (thanks @tyler6204)

* fix: restore cron delivery-plan import after rebase (#14447) (thanks @tyler6204)

* fix: resolve test failures from rebase conflicts (#14447) (thanks @tyler6204)

* fix: apply formatting after rebase (#14447) (thanks @tyler6204)
2026-02-14 22:03:45 -08:00
Peter Steinberger b93aa7fb66 refactor(plugins): dedupe plugin SDK alias lookup 2026-02-15 05:29:49 +00:00
Peter Steinberger b373461032 refactor(security): share scan path helpers 2026-02-15 04:29:18 +00:00
Peter Steinberger e93764350d refactor(install): share safe install path helpers 2026-02-15 04:27:41 +00:00
Gustavo Madeira Santana 8217d77ece
fix(cli): run plugin gateway_stop hooks before message exit (#16580)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 8542ac77ae
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-14 17:33:08 -05:00
Peter Steinberger a3c695faae perf(test): speed up compaction hook wiring tests 2026-02-14 18:46:24 +00:00
Robby 8e5689a84d
feat(telegram): add sendPoll support (#16193) (#16209)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: b58492cfed
Co-authored-by: robbyczgw-cla <239660374+robbyczgw-cla@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-14 18:34:30 +01:00
Peter Steinberger 4caeb203a6 refactor(install): share package dir install 2026-02-14 15:39:46 +00:00
Peter Steinberger 497b060e49
refactor: simplify manifest registry duplicate detection (#16260) 2026-02-14 16:04:41 +01:00
Peter Steinberger 4f043991e0
fix: suppress false duplicate plugin warnings (#16222) (thanks @shadril238) (#16245) 2026-02-14 15:45:21 +01:00
shadril238 788ea6e9d1 fix: suppress false duplicate plugin id warning for symlinked extensions
When the same plugin directory is discovered through different path
representations (e.g. symlinks), the manifest registry incorrectly
warns about a duplicate plugin id. This is a false positive that
appears for bundled extensions like feishu (#16208).

Compare fs.realpathSync() of both candidates' rootDir before emitting
the duplicate warning. If they resolve to the same physical directory,
silently skip the duplicate instead of warning.

Also change seenIds from Set<string> to Map<string, PluginCandidate>
to track the first-seen candidate for comparison.

Closes #16208
2026-02-14 15:25:51 +01:00
Peter Steinberger ef70a55b7a
refactor(reply): clarify explicit reply tags in off mode (#16189)
* refactor(reply): clarify explicit reply tags in off mode

* fix(plugin-sdk): alias account-id subpath for extensions
2026-02-14 14:15:37 +01:00
Peter Steinberger 6f7d31c426 fix(security): harden plugin/hook npm installs 2026-02-14 14:07:14 +01:00
Peter Steinberger 8c3cc793b7 fix: dedupe before_tool_call in embedded runtime (#15635) (thanks @lailoo) 2026-02-14 02:50:35 +01:00
Peter Steinberger 93dc3bb79a perf(test): avoid npm pack in plugin install e2e fixtures 2026-02-14 00:17:49 +00:00
solstead ab71fdf821
Plugin API: compaction/reset hooks, bootstrap file globs, memory plugin status (#13287)
* feat: add before_compaction and before_reset plugin hooks with session context

- Pass session messages to before_compaction hook
- Add before_reset plugin hook for /new and /reset commands
- Add sessionId to plugin hook agent context

* feat: extraBootstrapFiles config with glob pattern support

Add extraBootstrapFiles to agent defaults config, allowing glob patterns
(e.g. "projects/*/TOOLS.md") to auto-load project-level bootstrap files
into agent context every turn. Missing files silently skipped.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(status): show custom memory plugins as enabled, not unavailable

The status command probes memory availability using the built-in
memory-core manager. Custom memory plugins (e.g. via plugin slot)
can't be probed this way, so they incorrectly showed "unavailable".
Now they show "enabled (plugin X)" without the misleading label.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use async fs.glob and capture pre-compaction messages

- Replace globSync (node:fs) with fs.glob (node:fs/promises) to match
  codebase conventions for async file operations
- Capture session.messages BEFORE replaceMessages(limited) so
  before_compaction hook receives the full conversation history,
  not the already-truncated list

* fix: resolve lint errors from CI (oxlint strict mode)

- Add void to fire-and-forget IIFE (no-floating-promises)
- Use String() for unknown catch params in template literals
- Add curly braces to single-statement if (curly rule)

* fix: resolve remaining CI lint errors in workspace.ts

- Remove `| string` from WorkspaceBootstrapFileName union (made all
  typeof members redundant per no-redundant-type-constituents)
- Use type assertion for extra bootstrap file names
- Drop redundant await on fs.glob() AsyncIterable (await-thenable)

* fix: address Greptile review — path traversal guard + fs/promises import

- workspace.ts: use path.resolve() + traversal check in loadExtraBootstrapFiles()
- commands-core.ts: import fs from node:fs/promises, drop fs.promises prefix

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: resolve symlinks before workspace boundary check

Greptile correctly identified that symlinks inside the workspace could
point to files outside it, bypassing the path prefix check. Now uses
fs.realpath() to resolve symlinks before verifying the real path stays
within the workspace boundary.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address Greptile review — hook reliability and type safety

1. before_compaction: add compactingCount field so plugins know both
   the full pre-compaction message count and the truncated count being
   fed to the compaction LLM. Clarify semantics in comment.

2. loadExtraBootstrapFiles: use path.basename() for the name field
   so "projects/quaid/TOOLS.md" maps to the known "TOOLS.md" type
   instead of an invalid WorkspaceBootstrapFileName cast.

3. before_reset: fire the hook even when no session file exists.
   Previously, short sessions without a persisted file would silently
   skip the hook. Now fires with empty messages array so plugins
   always know a reset occurred.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: validate bootstrap filenames and add compaction hook timeout

- Only load extra bootstrap files whose basename matches a recognized
  workspace filename (AGENTS.md, TOOLS.md, etc.), preventing arbitrary
  files from being injected into agent context.
- Wrap before_compaction hook in a 30-second Promise.race timeout so
  misbehaving plugins cannot stall the compaction pipeline.
- Clarify hook comments: before_compaction is intentionally awaited
  (plugins need messages before they're discarded) but bounded.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: make before_compaction non-blocking, add sessionFile to after_compaction

- before_compaction is now true fire-and-forget — no await, no timeout.
  Plugins that need full conversation data should persist it themselves
  and return quickly, or use after_compaction for async processing.
- after_compaction now includes sessionFile path so plugins can read
  the full JSONL transcript asynchronously. All pre-compaction messages
  are preserved on disk, eliminating the need to block compaction.
- Removes Promise.race timeout pattern that didn't actually cancel
  slow hooks (just raced past them while they continued running).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add sessionFile to before_compaction for parallel processing

The session JSONL already has all messages on disk before compaction
starts. By providing sessionFile in before_compaction, plugins can
read and extract data in parallel with the compaction LLM call rather
than waiting for after_compaction. This is the optimal path for memory
plugins that need the full conversation history.

sessionFile is also kept on after_compaction for plugins that only
need to act after compaction completes (analytics, cleanup, etc.).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: move bootstrap extras into bundled hook

---------

Co-authored-by: Solomon Steadman <solstead@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Clawdbot <clawdbot@alfie.local>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 00:45:45 +01:00
Peter Steinberger caebe70e9a perf(test): cut setup/import overhead in hot suites 2026-02-13 21:23:50 +00:00
Peter Steinberger 2086cdfb9b perf(test): reduce hot-suite import and setup overhead 2026-02-13 20:26:39 +00:00
Peter Steinberger 39e6e4cd2c perf: reduce test/runtime overhead in plugin runtime and e2e harness 2026-02-13 18:24:19 +00:00
Peter Steinberger c2f7b66d22 perf(test): replace module resets with direct spies and runtime seams 2026-02-13 16:04:49 +00:00
Omair Afzal 59733a02c8
fix(configure): reject literal "undefined" and "null" gateway auth tokens (#13767)
* fix(configure): reject literal "undefined" and "null" gateway auth tokens

* fix(configure): reject literal "undefined" and "null" gateway auth tokens

* fix(configure): validate gateway password prompt and harden token coercion (#13767) (thanks @omair445)

* test: remove unused vitest imports in baseline lint fixtures (#13767)

---------

Co-authored-by: Luna AI <luna@coredirection.ai>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 17:04:41 +01:00
Peter Steinberger 41f2f359a5 perf(test): reduce module reload overhead in key suites 2026-02-13 15:45:19 +00:00
Peter Steinberger 9131b22a28 test: migrate suites to e2e coverage layout 2026-02-13 14:28:22 +00:00
JustasM 57d0f65e7d
CLI: add plugins uninstall command (#5985) (openclaw#6141) thanks @JustasMonkev
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: JustasMonkev <59362982+JustasMonkev@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-12 20:11:26 -06:00
Patrick Barletta d34138dfee
fix: dispatch before_tool_call and after_tool_call hooks from both tool execution paths (openclaw#15012) thanks @Patrick-Barletta
Verified:
- pnpm check

Co-authored-by: Patrick-Barletta <67929313+Patrick-Barletta@users.noreply.github.com>
2026-02-12 18:48:11 -06:00
Kyle Tse 2655041f69
fix: wire 9 unwired plugin hooks to core code (openclaw#14882) thanks @shtse8
Verified:
- GitHub CI checks green (non-skipped)

Co-authored-by: shtse8 <8020099+shtse8@users.noreply.github.com>
2026-02-12 18:14:14 -06:00
Peter Steinberger 9f507112b5 perf(test): speed up vitest by skipping plugins + LLM slug 2026-02-12 17:15:43 +00:00
Peter Steinberger 92702af7a2 fix(plugins): ignore install scripts during plugin/hook install 2026-02-11 12:04:30 +01:00
Peter Steinberger 53273b490b fix(auto-reply): prevent sender spoofing in group prompts 2026-02-10 00:44:38 -06:00
max 8d75a496bf
refactor: centralize isPlainObject, isRecord, isErrno, isLoopbackHost utilities (#12926) 2026-02-09 17:02:55 -08:00
quotentiroler 1fad19008e fix: improve code-size gate output and duplicate detection, fix Windows path in source-display 2026-02-09 13:18:51 -08:00
Peter Steinberger 3e63b2a4fa fix(cli): improve plugins list source display 2026-02-09 13:05:48 -06:00
max 40b11db80e
TypeScript: add extensions to tsconfig and fix type errors (#12781)
* TypeScript: add extensions to tsconfig and fix type errors

- Add extensions/**/* to tsconfig.json includes
- Export ProviderAuthResult, AnyAgentTool from plugin-sdk
- Fix optional chaining for messageActions across channels
- Add missing type imports (MSTeamsConfig, GroupPolicy, etc.)
- Add type annotations for provider auth handlers
- Fix undici/fetch type compatibility in zalo proxy
- Correct ChannelAccountSnapshot property usage
- Add type casts for tool registrations
- Extract usage view styles and types to separate files

* TypeScript: fix optional debug calls and handleAction guards
2026-02-09 10:05:38 -08:00
Mariano Belinky 730f86dd5c Gateway/Plugins: device pairing + phone control plugins (#11755) 2026-02-08 18:07:13 +01:00
Abdel Sy Fane bc88e58fcf
security: add skill/plugin code safety scanner (#9806)
* security: add skill/plugin code safety scanner module

* security: integrate skill scanner into security audit

* security: add pre-install code safety scan for plugins

* style: fix curly brace lint errors in skill-scanner.ts

* docs: add changelog entry for skill code safety scanner

* style: append ellipsis to truncated evidence strings

* fix(security): harden plugin code safety scanning

* fix: scan skills on install and report code-safety details

* fix: dedupe audit-extra import

* fix(security): make code safety scan failures observable

* fix(test): stabilize smoke + gateway timeouts (#9806) (thanks @abdelsfane)

---------

Co-authored-by: Darshil <ddhameliya@mail.sfsu.edu>
Co-authored-by: Darshil <81693876+dvrshil@users.noreply.github.com>
Co-authored-by: George Pickett <gpickett00@gmail.com>
2026-02-05 16:06:11 -08:00
cpojer a03d852d65
chore: Migrate to tsdown, speed up JS bundling by ~10x (thanks @hyf0).
The previous migration to tsdown was reverted because it caused a ~20x slowdown when running OpenClaw from the repo. @hyf0 investigated and found that simply renaming the `dist` folder also caused the same slowdown. It turns out the Plugin script loader has a bunch of voodoo vibe logic to determine if it should load files from source and compile them, or if it should load them from dist. When building with tsdown, the filesystem layout is different (bundled), and so some files weren't in the right location, and the Plugin script loader decided to compile source files from scratch using Jiti.

The new implementation uses tsdown to embed `NODE_ENV: 'production'`, which we now use to determine if we are running OpenClaw from a "production environmen" (ie. from dist). This removes the slop in favor of a deterministic toggle, and doesn't rely on directory names or similar.

There is some code reaching into `dist` to load specific modules, primarily in the voice-call extension, which I simplified into loading an "officially" exported `extensionAPI.js` file. With tsdown, entry points need to be explicitly configured, so we should be able to avoid sloppy code reaching into internals from now on. This might break some existing users, but if it does, it's because they were using "private" APIs.
2026-02-03 20:18:16 +09:00
Peter Steinberger d03eca8450 fix: harden plugin and hook install paths 2026-02-02 02:07:47 -08:00
cpojer 935a0e5708
chore: Enable `typescript/no-explicit-any` rule. 2026-02-02 16:18:09 +09:00
cpojer f06dd8df06
chore: Enable "experimentalSortImports" in Oxfmt and reformat all imorts. 2026-02-01 10:03:47 +09:00
cpojer 76361ae3ab
revert: Switch back to `tsc` for compiling. 2026-01-31 18:31:49 +09:00
Peter Steinberger a42e1c82d9 fix: restore tsc build and plugin install tests 2026-01-31 07:54:15 +00:00
cpojer 5ceff756e1
chore: Enable "curly" rule to avoid single-statement if confusion/errors. 2026-01-31 16:19:20 +09:00
cpojer 15792b153f
chore: Enable more lint rules, disable some that trigger a lot. Will clean up later. 2026-01-31 16:04:04 +09:00
cpojer 67945e8d62
chore: Switch from TypeScript to build with `tsdown`, speeds up `pnpm build` by 5-10x. 2026-01-31 15:25:37 +09:00
Peter Steinberger d47b4e6f81 fix: update config types 2026-01-30 03:20:28 +01:00
Peter Steinberger 9a7160786a refactor: rename to openclaw 2026-01-30 03:16:21 +01:00
Peter Steinberger 06289b36da fix(security): harden SSH target handling (#4001)
Thanks @YLChen-007.

Co-authored-by: Edward-x <YLChen-007@users.noreply.github.com>
2026-01-29 16:33:36 +00:00
Josh Palmer 4b5514a259 Tests: default-disable plugins in VITEST 2026-01-29 17:14:14 +01:00
Peter Steinberger 6d16a658e5 refactor: rename clawdbot to moltbot with legacy compat 2026-01-27 12:21:02 +00:00
Peter Steinberger 83460df96f chore: update molt.bot domains 2026-01-27 12:21:01 +00:00
plum-dawg c96ffa7186
feat: Add Line plugin (#1630)
* feat: add LINE plugin (#1630) (thanks @plum-dawg)

* feat: complete LINE plugin (#1630) (thanks @plum-dawg)

* chore: drop line plugin node_modules (#1630) (thanks @plum-dawg)

* test: mock /context report in commands test (#1630) (thanks @plum-dawg)

* test: limit macOS CI workers to avoid OOM (#1630) (thanks @plum-dawg)

* test: reduce macOS CI vitest workers (#1630) (thanks @plum-dawg)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-01-25 12:22:36 +00:00
Peter Steinberger 83f92e34af refactor: align voice-call TTS with core config 2026-01-25 09:29:57 +00:00
Peter Steinberger 458e731f8b fix: newline chunking across channels 2026-01-25 04:11:36 +00:00
Peter Steinberger 3a35d313d9 fix: signal reactions 2026-01-25 03:24:44 +00:00
Tyler Yust 92e794dc18
feat: add chunking mode option for BlueBubbles (#1645)
* feat: add chunking mode for outbound messages

- Introduced `chunkMode` option in various account configurations to allow splitting messages by "length" or "newline".
- Updated message processing to handle chunking based on the selected mode.
- Added tests for new chunking functionality, ensuring correct behavior for both modes.

* feat: enhance chunking mode documentation and configuration

- Added `chunkMode` option to the BlueBubbles account configuration, allowing users to choose between "length" and "newline" for message chunking.
- Updated documentation to clarify the behavior of the `chunkMode` setting.
- Adjusted account merging logic to incorporate the new `chunkMode` configuration.

* refactor: simplify chunk mode handling for BlueBubbles

- Removed `chunkMode` configuration from various account schemas and types, centralizing chunk mode logic to BlueBubbles only.
- Updated `processMessage` to default to "newline" for BlueBubbles chunking.
- Adjusted tests to reflect changes in chunk mode handling for BlueBubbles, ensuring proper functionality.

* fix: update default chunk mode to 'length' for BlueBubbles

- Changed the default value of `chunkMode` from 'newline' to 'length' in the BlueBubbles configuration and related processing functions.
- Updated documentation to reflect the new default behavior for chunking messages.
- Adjusted tests to ensure the correct default value is returned for BlueBubbles chunk mode.
2026-01-25 00:47:10 +00:00
Peter Steinberger d905ca0e02 fix: enforce explicit mention gating across channels 2026-01-24 11:09:33 +00:00
Peter Steinberger 6765fd15eb feat: default TTS model overrides on (#1559) (thanks @Glucksberg)
Co-authored-by: Glucksberg <80581902+Glucksberg@users.noreply.github.com>
2026-01-24 09:42:32 +00:00
Peter Steinberger 6a60d47c53 fix: cover slack open policy gating (#1563) (thanks @itsjaydesu) 2026-01-24 07:09:26 +00:00
Glucksberg 6bd6ae41b1 fix: address code review findings for plugin commands
- Add registry lock during command execution to prevent race conditions
- Add input sanitization for command arguments (defense in depth)
- Validate handler is a function during registration
- Remove redundant case-insensitive regex flag
- Add success logging for command execution
- Simplify handler return type (always returns result now)
- Remove dead code branch in commands-plugin.ts

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 06:28:22 +00:00
Glucksberg f648aae440 fix: clear plugin commands on reload to prevent duplicates
Add clearPluginCommands() call in loadClawdbotPlugins() to ensure
previously registered commands are cleaned up before reloading plugins.
This prevents command conflicts during hot-reload scenarios.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 06:28:22 +00:00
Glucksberg b56587f26e fix: address code review findings for plugin command API
Blockers fixed:
- Fix documentation: requireAuth defaults to true (not false)
- Add command name validation (must start with letter, alphanumeric only)
- Add reserved commands list to prevent shadowing built-in commands
- Emit diagnostic errors for invalid/duplicate command registration

Other improvements:
- Return user-friendly message for unauthorized commands (instead of silence)
- Sanitize error messages to avoid leaking internal details
- Document acceptsArgs behavior when arguments are provided
- Add notes about reserved commands and validation rules to docs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 06:28:22 +00:00
Glucksberg 4ee808dbcb feat: add plugin command API for LLM-free auto-reply commands
This adds a new `api.registerCommand()` method to the plugin API, allowing
plugins to register slash commands that execute without invoking the AI agent.

Features:
- Plugin commands are processed before built-in commands and the agent
- Commands can optionally require authorization
- Commands can accept arguments
- Async handlers are supported

Use case: plugins can implement toggle commands (like /tts_on, /tts_off)
that respond immediately without consuming LLM API calls.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 06:28:22 +00:00
André Abadesso 71f7bd1cfd test: add tests for normalizePluginsConfig memory slot handling 2026-01-24 03:08:27 +00:00
André Abadesso c4c01089ab fix: respect "none" value for plugins.slots.memory 2026-01-24 03:08:27 +00:00
Peter Steinberger d82ecaf9dc refactor: centralize inbound session updates 2026-01-23 23:33:32 +00:00
Peter Steinberger cb8c8fee9a refactor: centralize ack reaction removal 2026-01-23 23:32:14 +00:00
Peter Steinberger 02bd6e4a24 refactor: centralize ack reaction gating 2026-01-23 22:24:31 +00:00
Peter Steinberger b77e730657 fix: add per-channel markdown table conversion (#1495) (thanks @odysseus0) 2026-01-23 18:39:25 +00:00
Peter Steinberger 39d8ff59aa test: trim plugin + telegram test setup 2026-01-23 06:22:09 +00:00
Peter Steinberger 51a9053387 feat: add OpenProse plugin skills 2026-01-23 00:49:40 +00:00
Peter Steinberger fe860de148 fix: quiet update banner and skip duplicate plugin CLI 2026-01-21 07:37:22 +00:00
Peter Steinberger 026e6c4df4 fix: restore bundled plugin discovery 2026-01-21 03:40:05 +00:00
Peter Steinberger a5a3ab958f fix: skip bundled plugin discovery in tests 2026-01-21 03:29:03 +00:00
Peter Steinberger 99fc0fbac1 feat: sync plugin updates with update channel 2026-01-20 16:00:42 +00:00
Peter Steinberger fdb171cb15 refactor: centralize channel ui metadata 2026-01-20 13:11:49 +00:00
Peter Steinberger 9a2bf57e1c refactor: extend channel plugin boundary 2026-01-20 12:07:54 +00:00
Peter Steinberger 636a8e3181 fix: merge plugin manifest types 2026-01-20 11:22:28 +00:00
Peter Steinberger 660f87278c refactor: plugin catalog + nextcloud policy 2026-01-20 11:22:27 +00:00
Shadow 2f6d5805de fix: enforce plugin config schemas (#1272) (thanks @thewilloftheshadow)
Co-authored-by: thewilloftheshadow <thewilloftheshadow@users.noreply.github.com>
2026-01-20 11:03:17 +00:00
Peter Steinberger c17c7b4e24
Merge pull request #1235 from dougvk/feat/tool-dispatch-skill-commands
Plugin API: tool-dispatched skill commands + tool_result_persist hook
2026-01-20 08:52:05 +00:00
Peter Steinberger c5e732951b fix: prefer bundled plugin schema 2026-01-20 08:47:56 +00:00
Shadow 39dfdccf6c
CLI: skip runner rebuilds when dist is fresh (#1231)
Co-authored-by: mukhtharcm <mukhtharcm@users.noreply.github.com>
2026-01-19 13:12:33 -06:00
Doug von Kohorn c3a34408f3 feat: add tool_result_persist hook 2026-01-19 13:11:31 +01:00
Peter Steinberger 0c8ba6599b fix: add plugin config schema helper 2026-01-19 03:39:36 +00:00
Peter Steinberger d1e9490f95 fix: enforce strict config validation 2026-01-19 03:39:25 +00:00
Peter Steinberger d9384785a3 fix: stabilize ci checks 2026-01-19 00:34:26 +00:00
Peter Steinberger 5a4482412d fix(plugins): prefer dist plugin-sdk in tests 2026-01-19 00:15:45 +00:00
Peter Steinberger e97bcf4dae refactor(plugins): improve loader resolution 2026-01-19 00:15:44 +00:00
Peter Steinberger 50fdd514ae refactor(logging): split config + subsystem imports 2026-01-19 00:15:44 +00:00
Peter Steinberger ee36e12f81 fix: log plugin load errors in gateway 2026-01-19 00:15:24 +00:00
Peter Steinberger 690bb192e6 style: format code 2026-01-18 19:36:46 +00:00
Peter Steinberger 601a052216 fix: unblock bundled plugin load 2026-01-18 19:34:21 +00:00
Peter Steinberger 7c49326191 fix: satisfy oxlint spread rule 2026-01-18 18:50:52 +00:00
Peter Steinberger 744d1329cb feat: make inbound envelopes configurable
Co-authored-by: Shiva Prasad <shiv19@users.noreply.github.com>
2026-01-18 18:50:37 +00:00
Peter Steinberger ab340c82fb fix: stabilize tests and logging 2026-01-18 18:43:31 +00:00
Peter Steinberger 57dd0505a3
Merge pull request #1181 from sebslight/plugins/exclusive-slots
Plugins: auto-select exclusive slots
2026-01-18 18:40:38 +00:00
Peter Steinberger 5fe3c36471 fix(build): resolve ts2367 comparisons 2026-01-18 16:35:52 +00:00
Peter Steinberger 32ae4566c6 feat(config): auto-enable configured plugins 2026-01-18 16:35:52 +00:00
Sebastian Slight cef6b16d14 Plugins: auto-select exclusive slots 2026-01-18 11:26:50 -05:00
Peter Steinberger ee6e534ccb refactor: route channel runtime via plugin api 2026-01-18 11:01:16 +00:00
Peter Steinberger b015c7e5ad fix: sync protocol outputs 2026-01-18 08:58:41 +00:00
Peter Steinberger c5e19f5c67 refactor: migrate messaging plugins to sdk 2026-01-18 08:54:00 +00:00
Radek Paclt ebfeb7a6bf feat(memory): add lifecycle hooks and vector memory plugin
Add plugin lifecycle hooks infrastructure:
- before_agent_start: inject context before agent loop
- agent_end: analyze conversation after completion
- 13 hook types total (message, tool, session, gateway hooks)

Memory plugin implementation:
- LanceDB vector storage with OpenAI embeddings
- kind: "memory" to integrate with upstream slot system
- Auto-recall: injects <relevant-memories> when context found
- Auto-capture: stores preferences, decisions, entities
- Rule-based capture filtering with 0.95 similarity dedup
- Tools: memory_recall, memory_store, memory_forget
- CLI: clawdbot ltm list|search|stats

Plugin infrastructure:
- api.on() method for hook registration
- Global hook runner singleton for cross-module access
- Priority ordering and error catching

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 06:34:43 +00:00
Peter Steinberger 15606b4d88 test: cover bundled memory plugin package metadata 2026-01-18 06:30:01 +00:00
Peter Steinberger d4bd387e0e chore(gate): fix lint and formatting 2026-01-18 06:01:25 +00:00
Peter Steinberger e2c10a2b7a feat: support plugin-managed hooks 2026-01-18 05:57:05 +00:00
Peter Steinberger 9c0ff87c86 fix: align plugin runtime and exec wiring 2026-01-18 05:44:22 +00:00
Peter Steinberger b7575a889e refactor: align status with plugin memory slot 2026-01-18 05:40:10 +00:00
Peter Steinberger 016693a1f5 fix: abort embedded prompts on cancel 2026-01-18 05:18:10 +00:00
Peter Steinberger 82e49af5a7 fix: resolve plugin tool meta typing 2026-01-18 04:24:16 +00:00
Peter Steinberger 6da6582ced feat: add optional plugin tools 2026-01-18 04:08:00 +00:00
Peter Steinberger dad69afc84 fix: align plugin runtime types 2026-01-18 03:41:25 +00:00
Peter Steinberger b6d470a679 feat: migrate zalo plugin to sdk 2026-01-18 03:37:26 +00:00
Peter Steinberger 1420d113d8 refactor: migrate extensions to plugin sdk 2026-01-18 02:55:07 +00:00
Peter Steinberger 5b4651d9ed refactor: add plugin sdk runtime scaffolding 2026-01-18 02:52:30 +00:00
Peter Steinberger 9fd9f4c896 feat(plugins): add memory slot plugin 2026-01-18 02:12:10 +00:00
Peter Steinberger 4ca38286d8 chore: fix lint/format and update changelog
Co-authored-by: ItzR3NO <ItzR3NO@users.noreply.github.com>
2026-01-17 10:16:35 +00:00
Peter Steinberger fbf1c3ca3c test: cover plugin enable/disable semantics 2026-01-17 10:16:35 +00:00
Peter Steinberger a6deb0d9d5 feat: bundle provider auth plugins
Co-authored-by: ItzR3NO <ItzR3NO@users.noreply.github.com>
2026-01-17 09:38:53 +00:00
Peter Steinberger 3a6ee5ee00 feat: unify hooks installs and webhooks 2026-01-17 07:08:04 +00:00
Shadow 1ad26d6fea Config: schema-driven channels and settings 2026-01-17 00:43:05 +00:00
Peter Steinberger 4965727f39 chore: run format and fix sandbox browser timeouts 2026-01-16 09:18:58 +00:00
Peter Steinberger 54ec14262b feat: add plugin update tracking 2026-01-16 05:55:05 +00:00
Peter Steinberger a0d2a7232e fix: allow media-only sends 2026-01-16 03:15:26 +00:00
Peter Steinberger 29476b222d fix: restore status usage summary output 2026-01-16 02:49:18 +00:00
Peter Steinberger b7ba94f0c1 fix: harden antigravity claude support (#968)
Co-authored-by: Max <rdev@users.noreply.github.com>
2026-01-16 02:16:17 +00:00
Peter Steinberger af370ab23e fix: align config types after upstream changes 2026-01-16 01:49:07 +00:00
Peter Steinberger 6084421ec6 feat: add provider auth plugins 2026-01-16 00:42:28 +00:00
Peter Steinberger 139f80a291 chore: format sources and update protocol outputs 2026-01-15 05:17:19 +00:00
Peter Steinberger 5abe3c2145 feat: add plugin HTTP hooks + Zalo plugin 2026-01-15 05:04:09 +00:00
Peter Steinberger 5c52dbf661 style: oxfmt fixes (#925) (thanks @grp06) 2026-01-15 03:22:54 +00:00
Peter Steinberger 1b24b6a02b fix: add plugin runtime registry 2026-01-15 02:44:45 +00:00
Peter Steinberger 2b4a68e276 feat: load channel plugins 2026-01-15 02:42:44 +00:00
Peter Steinberger c379191f80 chore: migrate to oxlint and oxfmt
Co-authored-by: Christoph Nakazawa <christoph.pojer@gmail.com>
2026-01-14 15:02:19 +00:00
Peter Steinberger 90342a4f3a refactor!: rename chat providers to channels 2026-01-13 08:40:39 +00:00
Peter Steinberger 2785009c6f fix(config): resolve native commands schemas 2026-01-12 22:59:36 +00:00
Peter Steinberger d3eeddfc2f chore: fix lint after rebase 2026-01-12 22:19:02 +00:00
Peter Steinberger 59c8d2d17f docs: clarify sandbox bind mounts (#790) 2026-01-12 22:06:35 +00:00
Peter Steinberger 42c17adb5e feat: restore voice-call plugin parity 2026-01-12 21:44:19 +00:00
Peter Steinberger 23a0bf2abe fix(plugins): extract archives without system tar 2026-01-12 01:36:18 +00:00
Peter Steinberger 07b93e1d26 test: run npm pack via npm-cli.js 2026-01-12 01:31:26 +00:00
Peter Steinberger 5bdb9c0e99 style: format plugin install test 2026-01-12 01:27:01 +00:00
Peter Steinberger 6947ab18dc fix: load plugin packages from config dirs 2026-01-12 01:25:56 +00:00
Peter Steinberger 177ad3f06d test: pack plugin archives via npm 2026-01-12 01:25:40 +00:00
Peter Steinberger f13ae50ff8 test: plugin install + docker e2e 2026-01-12 01:16:42 +00:00
Peter Steinberger 2f4a248314 feat: plugin system + voice-call 2026-01-12 01:16:39 +00:00
Peter Steinberger 9f9f6b75e7 test: expand include coverage 2026-01-12 00:30:26 +00:00
Peter Steinberger 4b51c96e4e fix: apply model extra params without overwriting stream (#732) (thanks @peschee) 2026-01-12 00:03:48 +00:00
Peter Steinberger 248c731e78 test: expand voice-call coverage 2026-01-11 23:35:47 +00:00
Peter Steinberger 367baaca20 feat: implement voice-call plugin 2026-01-11 23:23:14 +00:00
Peter Steinberger cf0c72a557 feat: add plugin architecture 2026-01-11 12:11:12 +00:00