Commit Graph

2976 Commits

Author SHA1 Message Date
Peter Steinberger
fd3ca8a34c refactor: dedupe agent and browser cli helpers 2026-03-03 00:15:00 +00:00
Peter Steinberger
6b85ec3022 docs: tighten subscription guidance and update MiniMax M2.5 refs 2026-03-03 00:02:37 +00:00
Peter Steinberger
bb60687b89 refactor(nodes): dedupe camera payload and node resolve helpers 2026-03-02 23:32:41 +00:00
Peter Steinberger
c703aa0fe9 fix(agents): align sandboxed ACP prompt guidance 2026-03-02 23:24:02 +00:00
Peter Steinberger
3bf19d6f40 fix(security): fail-close node camera URL downloads 2026-03-02 23:23:39 +00:00
Peter Steinberger
7066d5e192 refactor: extract shared sandbox and gateway plumbing 2026-03-02 23:16:47 +00:00
Vincent Koc
0954b6bf5f fix(hooks): propagate ephemeral sessionId through embedded tool contexts (#32273)
* fix(plugins): expose ephemeral sessionId in tool contexts for per-conversation isolation

The plugin tool context (`OpenClawPluginToolContext`) and tool hook
context (`PluginHookToolContext`) only provided `sessionKey`, which
is a durable channel identifier that survives /new and /reset.
Plugins like mem0 that need per-conversation isolation (e.g. mapping
Mem0 `run_id`) had no way to distinguish between conversations,
causing session-scoped memories to persist unbounded across resets.

Add `sessionId` (ephemeral UUID regenerated on /new and /reset) to:
- `OpenClawPluginToolContext` (factory context for plugin tools)
- `PluginHookToolContext` (before_tool_call / after_tool_call hooks)
- Internal `HookContext` for tool call wrappers

Thread the value from the run attempt through createOpenClawCodingTools
→ createOpenClawTools → resolvePluginTools and through the tool hook
wrapper.

Closes #31253

Made-with: Cursor

* fix(agents): propagate embedded sessionId through tool hook context

* test(hooks): cover sessionId in embedded tool hook contexts

* docs(changelog): add sessionId hook context follow-up note

* test(hooks): avoid toolCallId collision in after_tool_call e2e

---------

Co-authored-by: SidQin-cyber <sidqin0410@gmail.com>
2026-03-02 15:11:51 -08:00
Peter Steinberger
02eeb08e04 fix: enforce sandbox workspace mount mode (#32227) (thanks @guanyu-zhang) 2026-03-02 22:59:11 +00:00
Evan
7cbcbbc642 fix(sandbox): same fix for browser.ts - make /workspace bind mount read-only when workspaceAccess is not rw
The identical buggy logic from docker.ts also exists in browser.ts.
Applying the same fix here.
2026-03-02 22:58:09 +00:00
Evan
903e4dff35 fix(sandbox): make /workspace bind mount read-only when workspaceAccess is not rw
This ensures that when workspaceAccess is set to 'ro' or 'none', the
sandbox workspace (/workspace inside the container) is mounted as
read-only, matching the documented behavior.

Previously, the condition was:
  workspaceAccess === 'ro' && workspaceDir === agentWorkspaceDir

This was always false in 'ro' mode because workspaceDir equals
sandboxWorkspaceDir, not agentWorkspaceDir.

Now the logic is simplified:
  - 'rw': /workspace is writable
  - 'ro': /workspace is read-only
  - 'none': /workspace is read-only
2026-03-02 22:58:09 +00:00
dunamismax
d9fdec12ab fix(signal): fall back to toolContext.currentMessageId for reactions
Signal reactions required an explicit messageId parameter, unlike
Telegram which already fell back to toolContext.currentMessageId.
This made agent-initiated reactions fail on Signal because the
inbound message ID was available in tool context but never used.

- Destructure toolContext in Signal action handler
- Fall back to toolContext.currentMessageId when messageId omitted
- Update reaction schema descriptions (not Telegram-specific)
- Add tests for fallback and missing-messageId rejection

Closes #17651
2026-03-02 22:53:04 +00:00
Bob
ac11f0af73 Security: enforce ACP sandbox inheritance for sessions_spawn (#32254)
* Security: enforce ACP sandbox inheritance in sessions_spawn

* fix: add changelog attribution for ACP sandbox inheritance (#32254) (thanks @dutifulbob)

---------

Co-authored-by: Onur <2453968+osolmaz@users.noreply.github.com>
2026-03-02 23:50:38 +01:00
Vincent Koc
44183c6eb1 fix(hooks): consolidate after_tool_call context + single-fire behavior (#32201)
* fix(hooks): deduplicate after_tool_call hook in embedded runs

(cherry picked from commit c129a1a74ba247460c6c061776ceeb995c757ecf)

* fix(hooks): propagate sessionKey in after_tool_call context

The after_tool_call hook in handleToolExecutionEnd was passing
`sessionKey: undefined` in the ToolContext, even though the value is
available on ctx.params. This broke plugins that need session context
in after_tool_call handlers (e.g., for per-session audit trails or
security logging).

- Add `sessionKey` to the `ToolHandlerParams` Pick type
- Pass `ctx.params.sessionKey` through to the hook context
- Add test assertion to prevent regression

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit b7117384fc1a09d60b25db0f80847a3519ddb3c3)

* fix(hooks): thread agentId through to after_tool_call hook context

Follow-up to #30511 — the after_tool_call hook context was passing
`agentId: undefined` because SubscribeEmbeddedPiSessionParams did not
carry the agent identity. This threads sessionAgentId (resolved in
attempt.ts) through the session params into the tool handler context,
giving plugins accurate agent-scoped context for both before_tool_call
and after_tool_call hooks.

Changes:
- Add `agentId?: string` to SubscribeEmbeddedPiSessionParams
- Add "agentId" to ToolHandlerParams Pick type
- Pass `agentId: sessionAgentId` at the subscribeEmbeddedPiSession()
  call site in attempt.ts
- Wire ctx.params.agentId into the after_tool_call hook context
- Update tests to assert agentId propagation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit aad01edd3e0d367ad0defeb691d5689ddf2ee617)

* changelog: credit after_tool_call hook contributors

* Update CHANGELOG.md

* agents: preserve adjusted params until tool end

* agents: emit after_tool_call with adjusted args

* tests: cover adjusted after_tool_call params

* tests: align adapter after_tool_call expectation

---------

Co-authored-by: jbeno <jim@jimbeno.net>
Co-authored-by: scoootscooob <zhentongfan@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 14:33:37 -08:00
Peter Steinberger
3cb851be90 test: micro-optimize heavy gateway/browser/telegram suites 2026-03-02 22:29:04 +00:00
Alessandro Rodi
f257818ea5 fix(sandbox): prevent Windows PATH from poisoning docker exec (#13873)
* fix(sandbox): prevent Windows PATH from poisoning docker exec shell lookup

On Windows hosts, `buildDockerExecArgs` passes the host PATH env var
(containing Windows paths like `C:\Windows\System32`) to `docker exec -e
PATH=...`. Docker uses this PATH to resolve the executable argument
(`sh`), which fails because Windows paths don't exist in the Linux
container — producing `exec: "sh": executable file not found in $PATH`.

Two changes:
- Skip PATH in the `-e` env loop (it's already handled separately via
  OPENCLAW_PREPEND_PATH + shell export)
- Use absolute `/bin/sh` instead of bare `sh` to eliminate PATH
  dependency entirely

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

* style: add braces around continue to satisfy linter

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

* fix(test): update assertion to match /bin/sh in buildDockerExecArgs

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 16:17:33 -06:00
Peter Steinberger
3beb1b9da9 test: speed up heavy suites with shared fixtures 2026-03-02 21:58:35 +00:00
Peter Steinberger
6358aae024 refactor(infra): share windows path normalization helper 2026-03-02 21:55:12 +00:00
Peter Steinberger
55a2d12f40 refactor: split inbound and reload pipelines into staged modules 2026-03-02 21:55:01 +00:00
Shawn
ef89b48785 fix(agents): normalize windows workspace path boundary checks (#30766)
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 15:47:02 -06:00
Peter Steinberger
ab8b8dae70 refactor(agents): dedupe model and tool test helpers 2026-03-02 21:31:36 +00:00
Peter Steinberger
42e402dfba fix: clear pending tool-call state across provider modes (#32120) (thanks @jnMetaCode) 2026-03-02 21:28:02 +00:00
jiangnan
11aa18b525 fix(agents): clear pending tool call state on interruption regardless of provider
When `allowSyntheticToolResults` is false (OpenAI, OpenRouter, and most
third-party providers), the guard never cleared its pending tool call map
when a user message arrived during in-flight tool execution. This left
orphaned tool_use blocks in the transcript with no matching tool_result,
causing the provider API to reject all subsequent requests with 400 errors
and permanently breaking the session.

The fix removes the `allowSyntheticToolResults` gate around the flush
calls. `flushPendingToolResults()` already handles both cases correctly:
it only inserts synthetic results when allowed, and always clears the
pending map. The gate was preventing the map from being cleared at all
for providers that disable synthetic results.

Fixes #32098

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 21:28:02 +00:00
Peter Steinberger
3a08e69a05 refactor: unify queueing and normalize telegram slack flows 2026-03-02 20:55:15 +00:00
Jason Separovic
00347bda75 fix(tools): strip xAI-unsupported JSON Schema keywords from tool definitions
xAI rejects minLength, maxLength, minItems, maxItems, minContains, and
maxContains in tool schemas with a 502 error instead of ignoring them.
This causes all requests to fail when any tool definition includes these
validation-constraint keywords (e.g. sessions_spawn uses maxLength and
maxItems on its attachment fields).

Add stripXaiUnsupportedKeywords() in schema/clean-for-xai.ts, mirroring
the existing cleanSchemaForGemini() pattern. Apply it in normalizeToolParameters()
when the provider is xai directly, or openrouter with an x-ai/* model id.

Fixes tool calls for x-ai/grok-* models both direct and via OpenRouter.
2026-03-02 20:37:07 +00:00
Mitch McAlister
f534ea9906 fix: prevent reasoning text leak through handleMessageEnd fallback
When enforceFinalTag is active (Google providers), stripBlockTags
correctly returns empty for text without <final> tags. However, the
handleMessageEnd fallback recovered raw text, bypassing this protection
and leaking internal reasoning (e.g. "**Applying single-bot mention
rule**NO_REPLY") to Discord.

Guard the fallback with enforceFinalTag check: if the provider is
supposed to use <final> tags and none were seen, the text is treated
as leaked reasoning and suppressed.

Also harden stripSilentToken regex to allow bold markdown (**) as
separator before NO_REPLY, matching the pattern Gemini Flash Lite
produces.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 20:32:01 +00:00
Peter Steinberger
4b50018406 fix: restore helper imports and plugin hook test exports 2026-03-02 19:57:33 +00:00
Peter Steinberger
7003615972 fix: resolve rebase conflict markers 2026-03-02 19:57:33 +00:00
Peter Steinberger
9617ac9dd5 refactor: dedupe agent and reply runtimes 2026-03-02 19:57:33 +00:00
liuxiaopai-ai
c48a0621ff fix(agents): map sandbox workdir from container path 2026-03-02 19:56:18 +00:00
bmendonca3
4985c561df sessions: reclaim orphan self-pid lock files 2026-03-02 19:53:41 +00:00
Vincent Koc
a19a7f5e6e feat(security): Harden Docker browser container chromium flags (#23889) (#31504)
* Gateway: honor OPENCLAW_GATEWAY_URL override for remote/local calls

* Agents: fix sandbox sessionKey usage for PI embedded subagent calls

* Sandbox: tighten browser container Chromium runtime flags

* fix: add sandbox browser defaults for container hardening

* docs: expand sandbox browser default flags list

* fix: make sandbox browser flags optional and preserve gateway env auth overrides

* docs: scope PR 31504 changelog entry

* style: format gateway call override handling

* fix: dedupe sandbox browser chrome args

* fix: preserve remote tls fingerprint for env gateway override

* fix: enforce auth for env gateway URL override

* chore: document gateway override auth security expectations
2026-03-02 11:28:27 -08:00
Peter Steinberger
ea1fe77c83 fix: normalize coding-plan providers in auth order validation 2026-03-02 19:26:09 +00:00
justinhuangcode
14baadda2c fix(tools): honor fsPolicy.workspaceOnly in image/pdf tool localRoots
PR #28822 fixed the Write/Edit tools to respect `tools.fs.workspaceOnly`,
but the image and PDF tools still unconditionally include default local
roots (`~/.openclaw/media`, `~/.openclaw/agents`, etc.) when computing
the `localRoots` allowlist for non-sandbox mode.

When `fsPolicy.workspaceOnly` is true, restrict `localRoots` to only the
workspace directory so that files outside the workspace are rejected by
`assertLocalMediaAllowed()`.

Relates to #31716

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 19:24:33 +00:00
justinhuangcode
aab87ec880 fix(agents): scope volcengine-plan/byteplus-plan auth lookup to profile resolution
The configure flow stores auth credentials under `provider: "volcengine"`,
but the coding model uses `volcengine-plan` as its provider. Add a scoped
`normalizeProviderIdForAuth` function used only by `listProfilesForProvider`
so coding-plan variants resolve to their base provider for auth credential
lookup without affecting global provider routing.

Closes #31731

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 19:22:19 +00:00
scoootscooob
6c7d012320 fix(openrouter): skip reasoning.effort injection for x-ai/grok models
x-ai/grok models on OpenRouter do not support the reasoning.effort
parameter and reject payloads containing it with "Invalid arguments
passed to the model." Skip reasoning injection for these models, the
same way we already skip it for the dynamic "auto" routing model.

Closes #32039

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 19:20:11 +00:00
Saurabh
1ef9a2a8ea fix: handle HTTP 529 (Anthropic overloaded) in failover error classification
Classify Anthropic's 529 status code as "rate_limit" so model fallback
triggers reliably without depending on fragile message-based detection.

Closes #28502
2026-03-02 18:59:10 +00:00
bmendonca3
738f5d4533 skills: make sherpa-onnx-tts bin ESM-compatible 2026-03-02 18:30:42 +00:00
bmendonca3
a6489ab5e9 fix(agents): cap openai-completions tool call ids to provider-safe format (#31947)
Co-authored-by: bmendonca3 <bmendonca3@users.noreply.github.com>
2026-03-02 18:08:20 +00:00
Peter Steinberger
d4bf07d075 refactor(security): unify hardened install and fs write flows 2026-03-02 17:23:29 +00:00
Peter Steinberger
104d32bb64 fix(security): unify root-bound write hardening 2026-03-02 17:12:33 +00:00
Peter Steinberger
07b16d5ad0 fix(security): harden workspace bootstrap boundary reads 2026-03-02 17:07:36 +00:00
Artale
1b462ed174 fix(test): use NTFS junctions and platform guards for symlink tests on Windows (openclaw#28747) thanks @arosstale
Verified:
- pnpm install --frozen-lockfile
- pnpm test src/agents/apply-patch.test.ts src/agents/sandbox/fs-bridge.test.ts src/agents/sandbox/validate-sandbox-security.test.ts src/infra/archive.test.ts

Co-authored-by: arosstale <117890364+arosstale@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 10:45:19 -06:00
Peter Steinberger
18f8393b6c fix: harden sandbox writes and centralize atomic file writes 2026-03-02 16:45:12 +00:00
Peter Steinberger
0dbb92dd2b fix(security): harden tar archive extraction parity 2026-03-02 16:36:56 +00:00
zwffff
8828418111 test(subagent-announce): fix flaky Windows-only test failure (#31298) (openclaw#31370) thanks @zwffff
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check (fails on main baseline issues in extensions/googlechat and extensions/phone-control)
- pnpm test:e2e src/agents/subagent-announce.format.e2e.test.ts

Co-authored-by: zwffff <5809959+zwffff@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-02 10:33:07 -06:00
Peter Steinberger
c973b053a5 refactor(net): unify proxy env checks and guarded fetch modes 2026-03-02 16:24:26 +00:00
Tak Hoffman
21708f58ce fix(exec): resolve PATH key case-insensitively for Windows pathPrepend (#25399) (#31879)
Co-authored-by: Glucksberg <markuscontasul@gmail.com>
2026-03-02 10:14:38 -06:00
Peter Steinberger
17c434f2f3 refactor: split browser context/actions and unify CDP timeout policy 2026-03-02 16:02:39 +00:00
Peter Steinberger
b28e472fa5 fix(agents): validate sessions_spawn agentId format (#31381) 2026-03-02 15:59:45 +00:00
root
0c6db05cc0 fix(agents): add strict format validation to sessions_spawn for agentId
Implements a strict format validation for the agentId parameter in
sessions_spawn to fully resolve the ghost workspace creation bug reported
in #31311.

This fix introduces a regex format gate at the entry point to
immediately reject malformed agentId strings. This prevents error
messages (e.g., 'Agent not found: xyz') or path traversals from being
mangled by normalizeAgentId into seemingly valid IDs (e.g.,
'agent-not-found--xyz'), which was the root cause of the bug.

The validation is placed before normalization and does not interfere
with existing workflows, including delegating to agents that are
allowlisted but not globally configured.

New, non-redundant tests are added to
sessions-spawn.allowlist.test.ts to cover format validation and
ensure no regressions in allowlist behavior.

Fixes #31311
2026-03-02 15:59:45 +00:00