Commit Graph

5225 Commits

Author SHA1 Message Date
Tonic
08b7932df0 feat(agents) : Hugging Face Inference provider first-class support and Together API fix and Direct Injection Refactor Auths [AI-assisted] (#13472)
* initial commit

* removes assesment from docs

* resolves automated review comments

* resolves lint , type , tests , refactors , and submits

* solves : why do we have to lint the tests xD

* adds greptile fixes

* solves a type error

* solves a ci error

* refactors auths

* solves a failing test after i pulled from main lol

* solves a failing test after i pulled from main lol

* resolves token naming issue to comply with better practices when using hf / huggingface

* fixes curly lints !

* fixes failing tests for google api from main

* solve merge conflicts

* solve failing tests with a defensive check 'undefined' openrouterapi key

* fix: preserve Hugging Face auth-choice intent and token behavior (#13472) (thanks @Josephrp)

* test: resolve auth-choice cherry-pick conflict cleanup (#13472)

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 16:18:16 +01:00
Peter Steinberger
4169a4df79 perf(test): remove redundant status module reloads 2026-02-13 15:11:38 +00:00
Peter Steinberger
79f4c4c584 perf(test): trim module resets in config suites 2026-02-13 15:11:38 +00:00
Abdel Fane
c60780ba20 security: enforce 0o600 permissions on WhatsApp credential files (#10529)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 4f10b7dc635e4220b6357a36bd0a7a116442b507
Co-authored-by: abdelsfane <32418586+abdelsfane@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-13 16:02:15 +01:00
shayan919293
ab4adf7170 fix(macos): ensure exec approval prompt displays the command (#5042)
* fix(config): migrate audio.transcription with any CLI command

Two bugs fixed:
1. Removed CLI allowlist from mapLegacyAudioTranscription - the modern
   config format has no such restriction, so the allowlist only blocked
   legacy migration of valid configs like whisperx-transcribe.sh
2. Moved audio.transcription migration to a separate migration entry -
   it was nested inside routing.config-v2 which early-exited when no
   routing section existed

Closes #5017

* fix(macos): ensure exec approval prompt displays the command

The NSStackView and NSScrollView for the command text lacked proper
width constraints, causing the accessory view to collapse to zero
width in some cases. This fix:

1. Adds minimum width constraint (380px) to the root stack view
2. Adds minimum width constraint to the command scroll view
3. Enables vertical resizing and scrolling for long commands
4. Adds max height constraint to prevent excessively tall prompts

Closes #5038

* fix: validate legacy audio transcription migration input (openclaw#5042) thanks @shayan919293

* docs: add changelog note for legacy audio migration guard (openclaw#5042) thanks @shayan919293

* fix: satisfy lint on audio transcription migration braces (openclaw#5042) thanks @shayan919293

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 15:49:06 +01:00
Peter Steinberger
a7d6e44719 perf(test): reduce test startup overhead 2026-02-13 14:48:45 +00:00
Peter Steinberger
3bcde8df32 fix: finalize vLLM onboarding integration (#12577) (thanks @gejifeng) 2026-02-13 15:48:37 +01:00
gejifeng
513fd835a1 tests: fix vLLM onboarding selection 2026-02-13 15:48:37 +01:00
gejifeng
d44c118334 fix: avoid unused custom preferred provider 2026-02-13 15:48:37 +01:00
gejifeng
e6715bcb64 format: fix onboarding.ts wrapping 2026-02-13 15:48:37 +01:00
gejifeng
03c502ef31 lint: fix unused imports and onboarding preferred provider 2026-02-13 15:48:37 +01:00
gejifeng
94d5411f11 fix: remove duplicate TOGETHER_BASE_URL 2026-02-13 15:48:37 +01:00
gejifeng
3e7956b008 fix code review 2026-02-13 15:48:37 +01:00
gejifeng
0472dd68f0 fix code review 2026-02-13 15:48:37 +01:00
gejifeng
e73d881c50 Onboarding: add vLLM provider support 2026-02-13 15:48:37 +01:00
Yaxuan42
54bf5d0f41 feat(web-fetch): support Cloudflare Markdown for Agents (#15376)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: d0528dc429840b16bfcef4d921f3229653d38143
Co-authored-by: Yaxuan42 <184813557+Yaxuan42@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-13 15:46:20 +01:00
Abdel Fane
7467fcc529 security: use openFileWithinRoot for A2UI file serving (#10525)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 64547d6f904a7660c3f0f3565252d9098b6aa85a
Co-authored-by: abdelsfane <32418586+abdelsfane@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-13 15:37:10 +01:00
Harald Buerbaumer
30b6eccae5 feat(gateway): add auth rate-limiting & brute-force protection (#15035)
* feat(gateway): add auth rate-limiting & brute-force protection

Add a per-IP sliding-window rate limiter to Gateway authentication
endpoints (HTTP, WebSocket upgrade, and WS message-level auth).

When gateway.auth.rateLimit is configured, failed auth attempts are
tracked per client IP. Once the threshold is exceeded within the
sliding window, further attempts are blocked with HTTP 429 + Retry-After
until the lockout period expires. Loopback addresses are exempt by
default so local CLI sessions are never locked out.

The limiter is only created when explicitly configured (undefined
otherwise), keeping the feature fully opt-in and backward-compatible.

* fix(gateway): isolate auth rate-limit scopes and normalize 429 responses

---------

Co-authored-by: buerbaumer <buerbaumer@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 15:32:38 +01:00
Peter Steinberger
9131b22a28 test: migrate suites to e2e coverage layout 2026-02-13 14:28:22 +00:00
Peter Steinberger
f5160ca6be test: add browser evaluate gate trust-boundary regression 2026-02-13 15:19:05 +01:00
Ion Mudreac
25950bcbb8 fix(sessions): normalize absolute sessionFile paths for v2026.2.12 compatibility
Older OpenClaw versions stored absolute sessionFile paths in sessions.json.
v2026.2.12 added path traversal security that rejected these absolute paths,
breaking all Telegram group handlers with 'Session file path must be within
sessions directory' errors.

Changes:
- resolvePathWithinSessionsDir() now normalizes absolute paths that resolve
  within the sessions directory, converting them to relative before validation
- Added 3 tests for absolute path handling (within dir, with topic, outside dir)

Fixes #15283
Closes #15214, #15237, #15216, #15152, #15213
2026-02-13 15:13:58 +01:00
大猫子
edfdd12d37 TTS: add missing OpenAI voices (ballad, cedar, juniper, marin, verse) (openclaw#11020) thanks @lailoo
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: ${pr_author_login} <${coauthor_email}>
Co-authored-by: ${tak_name} <${tak_email}>
2026-02-13 07:54:00 -06:00
Peter Steinberger
ee31cd47b4 fix: close OC-02 gaps in ACP permission + gateway HTTP deny config (#15390) (thanks @aether-ai-agent) 2026-02-13 14:30:06 +01:00
aether-ai-agent
749e28dec7 fix(security): block dangerous tools from HTTP gateway and fix ACP auto-approval (OC-02)
Two critical RCE vectors patched:

Vector 1 - Gateway HTTP /tools/invoke:
- Add DEFAULT_GATEWAY_HTTP_TOOL_DENY blocking sessions_spawn,
  sessions_send, gateway, whatsapp_login from HTTP invocation
- Apply deny filter after existing policy cascade, before tool lookup
- Add gateway.tools.{allow,deny} config override in GatewayConfig

Vector 2 - ACP client auto-approval:
- Replace blind allow_once selection with danger-aware permission handler
- Dangerous tools (exec, sessions_spawn, etc.) require interactive confirmation
- Safe tools retain auto-approve behavior (backward compatible)
- Empty options array now denied (was hardcoded "allow")
- 30s timeout auto-denies to prevent hung sessions

CWE-78 | CVSS:3.1 9.8 Critical
2026-02-13 14:30:06 +01:00
Peter Steinberger
8899f9e94a perf(test): optimize heavy suites and stabilize lock timing 2026-02-13 13:29:07 +00:00
Harrington-bot
771c7ba14e test: add pickAsset unit tests for architecture-aware signal-cli install 2026-02-13 14:25:26 +01:00
Harrington-bot
eb4a0a84f2 fix: use Homebrew for signal-cli install on non-x64 architectures 2026-02-13 14:25:26 +01:00
Peter Steinberger
990413534a fix: land multi-agent session path fix + regressions (#15103) (#15448)
Co-authored-by: Josh Lehman <josh@martian.engineering>
2026-02-13 14:17:24 +01:00
JINNYEONG KIM
94763cd87d Fix OpenAI/Codex tool call id sanitization for transcript policy (#15279) 2026-02-13 11:39:51 +00:00
loiie45e
07faab6ac3 openai-codex: bridge OAuth profiles into pi auth.json for model discovery (#15184) 2026-02-13 11:39:37 +00:00
Lucky
e3cb2564d7 Agents: allow gpt-5.3-codex-spark in fallback and thinking (#14990)
* Agents: allow gpt-5.3-codex-spark in fallback and thinking

* Fix: model picker issue for openai-codex/gpt-5.3-codex-spark

Fixed an issue in the model picker.
2026-02-13 11:39:22 +00:00
Peter Steinberger
417509c539 test: stabilize local-timestamp assertion in session resets 2026-02-13 04:58:11 +00:00
青雲
fd076eb43a fix: /status shows incorrect context percentage — totalTokens clamped to contextTokens (#15114) (#15133)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: a489669fc7e86db03484ef5a0ae222d9360e72f7
Co-authored-by: echoVic <16428813+echoVic@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-12 23:52:19 -05:00
Masataka Shinohara
b93ad2cd48 fix(slack): populate thread session with existing thread history (#7610)
* feat(slack): populate thread session with existing thread history

When a new session is created for a Slack thread, fetch and inject
the full thread history as context. This preserves conversation
continuity so the bot knows what it previously said in the thread.

- Add resolveSlackThreadHistory() to fetch all thread messages
- Add ThreadHistoryBody to context payload
- Use thread history instead of just thread starter for new sessions

Fixes #4470

* chore: remove redundant comments

* fix: use threadContextNote in queue body

* fix(slack): address Greptile review feedback

- P0: Use thread session key (not base session key) for new-session check
  This ensures thread history is injected when the thread session is new,
  even if the base channel session already exists.

- P1: Fetch up to 200 messages and take the most recent N
  Slack API returns messages in chronological order (oldest first).
  Previously we took the first N, now we take the last N for relevant context.

- P1: Batch resolve user names with Promise.all
  Avoid N sequential API calls when resolving user names in thread history.

- P2: Include file-only messages in thread history
  Messages with attachments but no text are now included with a placeholder
  like '[attached: image.png, document.pdf]'.

- P2: Add documentation about intentional 200-message fetch limit
  Clarifies that we intentionally don't paginate; 200 covers most threads.

* style: add braces for curly lint rule

* feat(slack): add thread.initialHistoryLimit config option

Allow users to configure the maximum number of thread messages to fetch
when starting a new thread session. Defaults to 20. Set to 0 to disable
thread history fetching entirely.

This addresses the optional configuration request from #2608.

* chore: trigger CI

* fix(slack): ensure isNewSession=true on first thread turn

recordInboundSession() in prepare.ts creates the thread session entry
before session.ts reads the store, causing isNewSession to be false
on the very first user message in a thread. This prevented thread
context (history/starter) from being injected.

Add IsFirstThreadTurn flag to message context, set when
readSessionUpdatedAt() returns undefined for the thread session key.
session.ts uses this flag to force isNewSession=true.

* style: format prepare.ts for oxfmt

* fix: suppress InboundHistory/ThreadStarterBody when ThreadHistoryBody present (#13912)

When ThreadHistoryBody is fetched from the Slack API (conversations.replies),
it already contains pending messages and the thread starter. Passing both
InboundHistory and ThreadStarterBody alongside ThreadHistoryBody caused
duplicate content in the LLM context on new thread sessions.

Suppress InboundHistory and ThreadStarterBody when ThreadHistoryBody is
present, since it is a strict superset of both.

* remove verbose comment

* fix(slack): paginate thread history context fetch

* fix(slack): wire session file path options after main merge

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 05:51:04 +01:00
Peter Steinberger
78ec0a1edf fix: stabilize test runner and daemon-cli compat 2026-02-13 04:45:04 +00:00
Peter Steinberger
ba7dccc49d test: speed up test suite and trim redundant onboarding tests 2026-02-13 04:30:48 +00:00
Gustavo Madeira Santana
ac41176532 Auto-reply: fix non-default agent session transcript path resolution (#15154)
* Auto-reply: fix non-default agent transcript path resolution

* Auto-reply: harden non-default agent transcript lookups

* Auto-reply: harden session path resolution across agent stores
2026-02-12 23:23:12 -05:00
Peter Steinberger
79a38858ae fix: preserve off-mode semantics in auto reply threading (#14976) (thanks @Diaspar4u) 2026-02-13 05:22:14 +01:00
Andrey
3d89f0f14a fix(reply): auto-inject replyToCurrent for reply threading
replyToMode "first"/"all" only filters replyToId but never generates
it — that required the LLM to emit [[reply_to_current]] tags. Inject
replyToCurrent:true on all payloads so applyReplyTagsToPayload sets
replyToId=currentMessageId, then let the existing mode filter decide
which replies keep threading (first only, all, or off).

Covers both final reply path (reply-payloads.ts) and block streaming
path (agent-runner-execution.ts).
2026-02-13 05:22:14 +01:00
Marcus Castro
39ee708df6 fix(outbound): return error instead of silently redirecting to allowList[0] (#13578) 2026-02-13 05:20:03 +01:00
Peter Steinberger
a43136c85e fix: align slack thread footer metadata with reply semantics (#14625) (thanks @bennewton999) 2026-02-13 05:18:06 +01:00
Ben Newton
2b9d5e6e30 feat(slack): include thread metadata (thread_ts, parent_user_id) in agent context
Adds thread_ts and parent_user_id to the Slack message footer for thread
replies, giving agents awareness of thread context. Top-level messages
remain unchanged.

Includes tests verifying:
- Thread replies include thread_ts and parent_user_id in footer
- Top-level messages exclude thread metadata
2026-02-13 05:18:06 +01:00
seheepeak
23e4183608 fix(sandbox): force network bridge for browser container (#6961) 2026-02-13 05:17:17 +01:00
Kentaro Kuribayashi
c6ecd2a044 fix: replace file-based session store lock with in-process Promise chain mutex (#14498)
* fix: replace file-based session store lock with in-process Promise chain mutex

Node.js is single-threaded, so file-based locking (open('wx') + polling +
stale eviction) is unnecessary and causes timeouts under heavy session load.

Replace with a simple per-storePath Promise chain that serializes access
without any filesystem overhead.

In a 1159-session environment over 3 hours:
- Lock timeouts: 25
- Stuck sessions: 157 (max 1031s, avg 388s)
- Slow listeners: 39 (max 265s, avg 70s)

Root cause: during sessions.json file I/O, await yields control and other
lock requests hit the 10s timeout waiting for the .lock file to be released.

* test: add comprehensive tests for Promise chain mutex lock

- Concurrent access serialization (10 parallel writers, counter integrity)
- Error resilience (single & multiple consecutive throws don't poison queue)
- Independent storePath parallelism (different paths run concurrently)
- LOCK_QUEUES cleanup after completion and after errors
- No .lock file created on disk

Also fix: store caught promise in LOCK_QUEUES to avoid unhandled rejection
warnings when queued fn() throws.

* fix: add timeout to Promise chain mutex to prevent infinite hangs on Windows

* fix(session-store): enforce strict queue timeout + cross-process lock

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 05:12:59 +01:00
Marcus Castro
13bfd9da83 fix: thread replyToId and threadId through message tool send action (#14948)
* fix: thread replyToId and threadId through message tool send action

* fix: omit replyToId/threadId from gateway send params

* fix: add threading seam regression coverage (#14948) (thanks @mcaxtr)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 04:55:20 +01:00
Marcus Castro
e355f6e093 fix(security): distinguish webhooks from internal hooks in audit summary (#13474)
* fix(security): distinguish webhooks from internal hooks in audit summary

The attack surface summary reported a single 'hooks: disabled/enabled' line
that only checked the external webhook endpoint (hooks.enabled), ignoring
internal hooks (hooks.internal.enabled). Users who enabled internal hooks
(session-memory, command-logger, etc.) saw 'hooks: disabled' and thought
something was broken.

Split into two separate lines:
- hooks.webhooks: disabled/enabled
- hooks.internal: disabled/enabled

Fixes #13466

* test(security): move attack surface tests to focused test file

Move the 3 new hook-distinction tests from the monolithic audit.test.ts
(1,511 lines) into a dedicated audit-extra.sync.test.ts that tests
collectAttackSurfaceSummaryFindings directly. Avoids growing the
already-large test file and keeps tests focused on the changed unit.

* fix: add changelog entry for security audit hook split (#13474) (thanks @mcaxtr)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 04:46:27 +01:00
Marcus Castro
e90caa66d8 fix(exec): allow heredoc operator (<<) in allowlist security mode (#13811)
* fix(exec): allow heredoc operator (<<) in allowlist security mode

* fix: allow multiline heredoc parsing in exec approvals (#13811) (thanks @mcaxtr)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 04:41:51 +01:00
Peter Steinberger
7c25696ab0 fix(config): enforce default-free persistence in write path 2026-02-13 04:41:04 +01:00
Marcus Castro
2a9745c9a1 fix(config): redact resolved field in config snapshots
The newly added 'resolved' field contains secrets after ${ENV}
substitution. This commit ensures redactConfigSnapshot also redacts
the resolved field to prevent credential leaks in config.get responses.
2026-02-13 04:41:04 +01:00
Marcus Castro
3189e2f11b fix(config): add resolved field to ConfigFileSnapshot for pre-defaults config
The initial fix using snapshot.parsed broke configs with $include directives.
This commit adds a new 'resolved' field to ConfigFileSnapshot that contains
the config after $include and ${ENV} substitution but BEFORE runtime defaults
are applied. This is now used by config set/unset to avoid:
1. Breaking configs with $include directives
2. Leaking runtime defaults into the written config file

Also removes applyModelDefaults from writeConfigFile since runtime defaults
should only be applied when loading, not when writing.
2026-02-13 04:41:04 +01:00