Commit Graph

3111 Commits

Author SHA1 Message Date
Ayaan Zaidi
87977d7a19 fix: unblock build type errors 2026-03-03 08:11:51 +05:30
AI南柯(KingMo)
30ab9b2068 fix(agents): recognize connection errors as retryable timeout failures (#31697)
* fix(agents): recognize connection errors as retryable timeout failures

## Problem

When a model endpoint becomes unreachable (e.g., local proxy down,
relay server offline), the failover system fails to switch to the
next candidate model. Errors like "Connection error." are not
classified as retryable, causing the session to hang on a broken
endpoint instead of falling back to healthy alternatives.

## Root Cause

Connection/network errors are not recognized by the current failover
classifier:
- Text patterns like "Connection error.", "fetch failed", "network error"
- Error codes like ECONNREFUSED, ENOTFOUND, EAI_AGAIN (in message text)

While `failover-error.ts` handles these as error codes (err.code),
it misses them when they appear as plain text in error messages.

## Solution

Extend timeout error patterns to include connection/network failures:

**In `errors.ts` (ERROR_PATTERNS.timeout):**
- Text: "connection error", "network error", "fetch failed", etc.
- Regex: /\beconn(?:refused|reset|aborted)\b/i, /\benotfound\b/i, /\beai_again\b/i

**In `failover-error.ts` (TIMEOUT_HINT_RE):**
- Same patterns for non-assistant error paths

## Testing

Added test cases covering:
- "Connection error."
- "fetch failed"
- "network error: ECONNREFUSED"
- "ENOTFOUND" / "EAI_AGAIN" in message text

## Impact

- **Compatibility:** High - only expands retryable error detection
- **Behavior:** Connection failures now trigger automatic fallback
- **Risk:** Low - changes are additive and well-tested

* style: fix code formatting for test file
2026-03-03 02:37:23 +00:00
AaronWander
4c32411bee fix(exec): suggest increasing timeout on timeouts 2026-03-03 02:35:10 +00:00
Gustavo Madeira Santana
91cdb703bd Agents: add context metadata warmup retry backoff 2026-03-02 21:34:55 -05:00
Peter Steinberger
62582fc088 perf(agents): cache per-pass context char estimates 2026-03-03 02:32:13 +00:00
Peter Steinberger
6ab9e00e17 fix: resolve pi-tools typing regressions 2026-03-03 02:27:59 +00:00
Peter Steinberger
d380ed710d refactor(agents): split pi-tools param and host-edit wrappers 2026-03-03 02:19:34 +00:00
Peter Steinberger
70db52de71 test(agents): centralize AgentMessage fixtures and remove unsafe casts 2026-03-03 02:14:15 +00:00
倪汉杰0668001185
0fb3f188b2 fix(agents): only recover edit when oldText no longer in file (review feedback) 2026-03-03 02:06:59 +00:00
倪汉杰0668001185
bf6aa7ca67 fix(agents): treat host edit tool as success when file contains newText after upstream throw (fixes #32333) 2026-03-03 02:06:59 +00:00
nico-hoff
3eec79bd6c feat(memory): add Ollama embedding provider (#26349)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: ac41386543
Co-authored-by: nico-hoff <43175972+nico-hoff@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-02 20:56:40 -05:00
Peter Steinberger
39520ad21b test(agents): tighten pi message typing and dedupe malformed tool-call cases 2026-03-03 01:44:21 +00:00
Sk Akram
bd8c3230e8 fix: force supportsDeveloperRole=false for non-native OpenAI endpoints (#29479)
Merged via squash.

Prepared head SHA: 1416c584ac
Co-authored-by: akramcodez <179671552+akramcodez@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-02 20:43:49 -05:00
David Rudduck
11e1363d2d feat(hooks): add trigger and channelId to plugin hook agent context (#28623)
* feat(hooks): add trigger and channelId to plugin hook agent context

Adds `trigger` and `channelId` fields to `PluginHookAgentContext` so
plugins can determine what initiated the agent run and which channel
it originated from, without session-key parsing or Redis bridging.

trigger values: "user", "heartbeat", "cron", "memory"
channelId values: "telegram", "discord", "whatsapp", etc.

Both fields are threaded through run.ts and attempt.ts hookCtx so all
hook phases receive them (before_model_resolve, before_prompt_build,
before_agent_start, llm_input, llm_output, agent_end).

channelId falls back from messageChannel to messageProvider when the
former is not set. followup-runner passes originatingChannel so queued
followup runs also carry channel context.

* docs(changelog): note hook context parity fix for #28623

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-02 17:39:20 -08:00
Peter Steinberger
6b6af1a64f refactor(tests): dedupe web fetch and embedded tool hook fixtures 2026-03-03 01:37:12 +00:00
Peter Steinberger
c1b37f29f0 refactor(tests): dedupe browser and telegram tool test fixtures 2026-03-03 01:37:12 +00:00
Peter Steinberger
a3b674cc98 refactor(tests): dedupe agent lock and loop detection fixtures 2026-03-03 01:37:12 +00:00
Vincent Koc
747902a26a fix(hooks): propagate run/tool IDs for tool hook correlation (#32360)
* Plugin SDK: add run and tool call fields to tool hooks

* Agents: propagate runId and toolCallId in before_tool_call

* Agents: thread runId through tool wrapper context

* Runner: pass runId into tool hook context

* Compaction: pass runId into tool hook context

* Agents: scope after_tool_call start data by run

* Tests: cover run and tool IDs in before_tool_call hooks

* Tests: add run-scoped after_tool_call collision coverage

* Hooks: scope adjusted tool params by run

* Tests: cover run-scoped adjusted param collisions

* Hooks: preserve active tool start metadata until end

* Changelog: add tool-hook correlation note
2026-03-02 17:23:08 -08:00
Peter Steinberger
61adcea68e fix(test): tighten tool result typing in context pruning tests 2026-03-03 01:18:29 +00:00
Peter Steinberger
1b4062defd refactor(tests): dedupe pi embedded test harness 2026-03-03 01:15:09 +00:00
Peter Steinberger
ddd71bc9f6 fix: guard gemini schema null properties (#32332) (thanks @webdevtodayjason) 2026-03-03 01:12:06 +00:00
webdevtodayjason
1a7a18d0bc fix(agents): guard gemini tool schema properties against null 2026-03-03 01:12:06 +00:00
Peter Steinberger
f0640b0100 fix(test): align gateway and session spawn hook typings 2026-03-03 01:12:01 +00:00
Peter Steinberger
57e1534df8 refactor(tests): consolidate repeated setup helpers 2026-03-03 01:06:00 +00:00
Peter Steinberger
a48a3dbdda refactor(tests): dedupe tool, projector, and delivery fixtures 2026-03-03 01:06:00 +00:00
Peter Steinberger
1bd20dbdb6 fix(failover): treat stop reason error as timeout 2026-03-03 01:05:24 +00:00
Peter Steinberger
a2fdc3415f fix(failover): handle unhandled stop reason error 2026-03-03 01:05:24 +00:00
Peter Steinberger
ced267c5cb fix(moonshot): apply native thinking payload compatibility 2026-03-03 01:05:24 +00:00
Gustavo Madeira Santana
f26853f14c CLI: dedupe config validate errors and expose allowed values 2026-03-02 20:05:12 -05:00
Peter Steinberger
f3e6578e6c fix(test): tighten websocket and runner fixture typing 2026-03-03 00:55:01 +00:00
Peter Steinberger
47083460ea refactor: unify inbound debounce policy and split gateway/models helpers 2026-03-03 00:54:33 +00:00
Peter Steinberger
6649c22471 fix(agents): harden openai ws tool call id handling 2026-03-03 00:43:48 +00:00
Peter Steinberger
77ecef1fde feat(models): support minimax highspeed across onboarding 2026-03-03 00:40:15 +00:00
Peter Steinberger
1e8afa16f0 fix: apply config env vars before model discovery (#32295) (thanks @hsiaoa) 2026-03-03 00:25:24 +00:00
hsiaoa
65dc3ee76c models-config: apply config env vars before implicit provider discovery 2026-03-03 00:25:24 +00:00
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 c129a1a74b)

* 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 b7117384fc)

* 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 aad01edd3e)

* 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