Commit Graph

19120 Commits

Author SHA1 Message Date
ShengtongZhu a19f3890b8 fix(guardian): remove unused import, align pi-ai version with root
- Remove unused PluginRuntime import, consolidate import lines
- Bump @mariozechner/pi-ai from 0.55.3 to 0.58.0 to match root

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 22:43:38 +08:00
ShengtongZhu e55c4c4044 fix(guardian): resolve well-known provider baseUrl from pi-ai model database
When a provider (e.g. anthropic, openai) is not explicitly configured in
openclaw.json, fall back to pi-ai's built-in model database to resolve
baseUrl and api type. This avoids requiring users to manually configure
well-known providers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 19:33:14 +08:00
ShengtongZhu 474a41a3ee fix(guardian): use openclaw/plugin-sdk/core instead of monolithic import
Bundled plugins must use scoped plugin-sdk imports (e.g. /core, /compat)
instead of the monolithic openclaw/plugin-sdk entry point.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 14:11:46 +08:00
ShengtongZhu 9fbbc97e9a fix(guardian): use runtime.modelAuth instead of runtime.models
Align with main's PluginRuntime interface: use `modelAuth` (not `models`)
for API key resolution. Remove dependency on `resolveProviderInfo` (not
available on main) — provider info is now resolved from config at
registration time via `resolveModelFromConfig`.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 14:06:59 +08:00
ShengtongZhu 400787110c fix: restore core files to match main (rebase artifact cleanup)
The rebase left stale versions of src/plugin-sdk/index.ts,
src/agents/model-auth.ts, src/plugins/runtime/*, and
src/cli/daemon-cli/lifecycle.test.ts. These are not guardian changes —
restore them to match origin/main exactly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 13:47:28 +08:00
ShengtongZhu 39b0ae7cc1 chore(guardian): update pnpm-lock.yaml for guardian extension
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:47:54 +08:00
ShengtongZhu 2e2eed339a refactor(guardian): replace async instruction extraction with full system prompt caching
Remove the LLM-based standingInstructions and availableSkills extraction
pipeline. Instead, cache the main agent's full system prompt on the first
llm_input and pass it as-is to the guardian as "Agent context".

This eliminates two async LLM calls per session, simplifies the codebase
(~340 lines removed), and gives the guardian MORE context (the complete
system prompt including tool definitions, memory, and skills) rather than
a lossy LLM-extracted summary.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:33:28 +08:00
ShengtongZhu 8f0c1cb85f docs(guardian): add model selection guidance to README
Recommend instruction-following models (sonnet, haiku, gpt-4o-mini) and
warn against coding-specific models that tend to ignore the strict
ALLOW/BLOCK output format.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:32:47 +08:00
ShengtongZhu 8a2c15f9bc fix(guardian): detect system triggers from historyMessages, not just currentPrompt
Heartbeat prompts may arrive via historyMessages (as the last user message)
rather than via currentPrompt, depending on the agent loop stage. Check both
sources for system trigger detection so heartbeat tool calls are consistently
skipped regardless of how the prompt is delivered.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:32:47 +08:00
ShengtongZhu 13b4a0bbeb fix(guardian): preserve isSystemTrigger across agent loop continuations
During a heartbeat cycle, llm_input fires multiple times: first with the
heartbeat prompt (isSystemTrigger=true), then without a prompt as the agent
loop continues after tool results. Previously the flag was unconditionally
rewritten on each llm_input, resetting to false when currentPrompt was
undefined — causing heartbeat tool calls to reach the guardian LLM
unnecessarily.

Now preserves the existing isSystemTrigger value when currentPrompt is
empty/undefined, and only resets it when a real user message arrives.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:32:47 +08:00
ShengtongZhu 31ed78ef28 fix(guardian): remove trailing comma in plugin manifest JSON
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:32:47 +08:00
ShengtongZhu f4488a73ff fix(guardian): stricter ALLOW/BLOCK verdict parsing in guardian response
Require a delimiter (colon, space, or end of line) after ALLOW/BLOCK keywords.
Previously `startsWith("ALLOW")` would match words like "ALLOWING" or
"ALLOWANCE", potentially causing a false ALLOW verdict if the model's
response started with such a word.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:32:47 +08:00
ShengtongZhu 8972213aee docs(guardian): improve README with quick start, default config values, and block behavior
- Replace Enable/Config sections with Quick start (bundled plugin, no npm install)
- Show all default values in config example
- Add "When a tool call is blocked" section explaining user flow
- Remove Model selection section
- Fix dead anchor link

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:32:47 +08:00
ShengtongZhu 6a3220b0c6 feat(guardian): enhance context awareness and add conversation summarization
- Add rolling conversation summary generation to provide long-term context without token waste
- Extract standing instructions and available skills from system prompt for better decision context
- Support thinking block extraction for reasoning model responses (e.g. kimi-coding)
- Add config options for context tools, recent turns, and tool result length
- Implement lazy context extraction with live message array reference
- Skip guardian review for system triggers (heartbeat, cron)
- Improve error handling for abort race conditions and timeout scenarios
- Normalize headers in model-auth to handle secret inputs consistently
- Update documentation with comprehensive usage guide and security model
2026-03-15 12:32:47 +08:00
Albert 7be93f981b fix(guardian): include trailing assistant messages in conversation context
When the main model is iterating autonomously (tool call → response →
tool call → ...) without new user input, assistant messages after the
last user message were being discarded. The guardian couldn't see what
the model had been doing, leading to potential misjudgments.

Now trailing assistant messages are appended to the last conversation
turn, giving the guardian full visibility into the model's recent
actions and reasoning during autonomous iteration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 12:32:34 +08:00
Albert 1c6b5d7b72 refactor(guardian): use pi-ai completeSimple, improve prompt and logging
- Replace 3 raw fetch() API call functions (OpenAI, Anthropic, Google)
  with a single pi-ai completeSimple() call, ensuring consistent HTTP
  behavior (User-Agent, auth, retry) with the main model
- Remove authMode field — pi-ai auto-detects OAuth from API key prefix
- Rewrite system prompt for strict single-line output format, add
  "Do NOT change your mind" and "Do NOT output reasoning" constraints
- Move decision guidelines to system prompt, add multi-step workflow
  awareness (intermediate read steps should be ALLOWed)
- Simplify user prompt — remove inline examples and criteria
- Use forward scanning in parseGuardianResponse for security (model's
  verdict appears first, attacker-injected text appears after)
- Add prominent BLOCK logging via logger.error with full conversation
  context dump (████ banner, all turns, tool arguments)
- Remove 800-char assistant message truncation limit
- Increase default max_user_messages from 3 to 10

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 12:32:34 +08:00
Albert ba28dbc016 feat(guardian): add LLM-based intent-alignment guardian plugin
Guardian intercepts tool calls via before_tool_call hook and sends them
to a separate LLM for review — blocks actions the user never requested,
defending against prompt injection attacks.

Key design decisions:
- Conversation turns (user + assistant pairs) give guardian context to
  understand confirmations like "yes" / "go ahead"
- Assistant replies are explicitly marked as untrusted in the prompt to
  prevent poisoning attacks from propagating
- Provider resolution uses SDK (not hardcoded list) with 3-layer
  fallback: explicit config → models.json → pi-ai built-in database
- Lazy resolution pattern for async provider/auth lookup in sync register()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 12:32:34 +08:00
Ayaan Zaidi 37c79f84ba
fix(android): theme popup surfaces 2026-03-15 09:48:08 +05:30
Sebastian Schubotz db20141993
feat(android): add dark theme (#46249)
* Android: add mobile dark theme

* Android: fix remaining dark mode card surfaces

* Android: address dark mode review comments

* fix(android): theme onboarding flow

* fix: add Android dark theme coverage (#46249) (thanks @sibbl)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-03-15 08:35:04 +05:30
Tak Hoffman 29fec8bb9f
fix(gateway): harden health monitor account gating (#46749)
* gateway: harden health monitor account gating

* gateway: tighten health monitor account-id guard
2026-03-14 21:58:28 -05:00
Vincent Koc 8aaafa045a
docker: add lsof to runtime image (#46636) 2026-03-14 19:40:29 -07:00
rstar327 ba6064cc22
feat(gateway): make health monitor stale threshold and max restarts configurable (openclaw#42107)
Verified:
- pnpm exec vitest --run src/config/config-misc.test.ts -t "gateway.channelHealthCheckMinutes"
- pnpm exec vitest --run src/gateway/server-channels.test.ts -t "health monitor"
- pnpm exec vitest --run src/gateway/channel-health-monitor.test.ts src/gateway/server/readiness.test.ts
- pnpm exec vitest --run extensions/feishu/src/outbound.test.ts
- pnpm exec tsc --noEmit

Co-authored-by: rstar327 <114364448+rstar327@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-14 21:21:56 -05:00
Tak Hoffman f00db91590
fix(plugins): prefer explicit installs over bundled duplicates (#46722)
* fix(plugins): prefer explicit installs over bundled duplicates

* test(feishu): mock structured card sends in outbound tests

* fix(plugins): align duplicate diagnostics with loader precedence
2026-03-14 21:08:32 -05:00
Radek Sienkiewicz e3b7ff2f1f
Docs: fix MDX markers blocking page refreshes (#46695)
Merged via squash.

Prepared head SHA: 56b25a9fb3
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Reviewed-by: @velvet-shark
2026-03-15 02:58:59 +01:00
songlei df3a247db2
feat(feishu): structured cards with identity header, note footer, and streaming enhancements (openclaw#29938)
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: nszhsl <512639+nszhsl@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-14 20:31:46 -05:00
Tak Hoffman f4dbd78afd
Add Feishu reactions and card action support (#46692)
* Add Feishu reactions and card action support

* Tighten Feishu action handling
2026-03-14 20:25:02 -05:00
Hiago Silva 946c24d674
fix: validate edge tts output file is non-empty before reporting success (#43385) thanks @Huntterxx
Merged after review.\n\nSmall, scoped fix: treat 0-byte Edge TTS output as failure so provider fallback can continue.
2026-03-14 20:22:09 -05:00
Tomsun28 c57b750be4
feat(provider): support new model zai glm-5-turbo, performs better for openclaw (openclaw#46670)
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: tomsun28 <24788200+tomsun28@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-14 20:19:41 -05:00
Radek Sienkiewicz 4c6a7f84a4
docs: remove dead security README nav entry (#46675)
Merged via squash.

Prepared head SHA: 63331a54b8
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Reviewed-by: @velvet-shark
2026-03-15 01:40:00 +01:00
Tak Hoffman 774b40467b
fix(zalouser): stop inheriting dm allowlist for groups (#46663) 2026-03-14 19:10:11 -05:00
nmccready f4aff83c51
feat(webchat): add toggle to hide tool calls and thinking blocks (#20317) thanks @nmccready
Merged via maintainer override after review.\n\nRed required checks are unrelated to this PR; local inspection found no blocker in the diff.
2026-03-14 19:03:04 -05:00
Tak Hoffman e5a42c0bec
fix(feishu): keep sender-scoped thread bootstrap across id types (#46651) 2026-03-14 18:47:05 -05:00
Andrew Demczuk 92fc8065e9
fix(gateway): remove re-introduced auth.mode=none pairing bypass
The revert of #43478 (commit 39b4185d0b) was silently undone by
3704293e6f which was based on a branch that included the original
change. This removes the auth.mode=none skipPairing condition again.

The blanket skip was too broad - it disabled pairing for ALL websocket
clients, not just Control UI behind reverse proxies.
2026-03-15 00:46:24 +01:00
Tomáš Dinh b5b589d99d
fix(zalo): use plugin-sdk export for webhook client IP resolution (openclaw#46549)
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: Tomáš Dinh <82420070+No898@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-14 18:37:56 -05:00
Gugu-sugar c1a0196826
Fix Codex CLI auth profile sync (#45353)
Merged via squash.

Prepared head SHA: e5432ec4e1
Co-authored-by: Gugu-sugar <201366873+Gugu-sugar@users.noreply.github.com>
Co-authored-by: grp06 <1573959+grp06@users.noreply.github.com>
Reviewed-by: @grp06
2026-03-14 16:36:09 -07:00
Andrew Demczuk b202ac2ad1
revert: restore supportsUsageInStreaming=false default for non-native endpoints
Reverts #46500. Breaks Ollama, LM Studio, TGI, LocalAI, Mistral API -
these backends reject stream_options with 400/422.

This reverts commit bb06dc7cc9.
2026-03-15 00:34:04 +01:00
George Zhang 2806f2b878
Heartbeat: add isolatedSession option for fresh session per heartbeat run (#46634)
Reuses the cron isolated session pattern (resolveCronSession with forceNew)
to give each heartbeat a fresh session with no prior conversation history.
Reduces per-heartbeat token cost from ~100K to ~2-5K tokens.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 16:28:01 -07:00
day253 9e8df16732
feat(feishu): add reasoning stream support to streaming cards (openclaw#46029)
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: day253 <9634619+day253@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-14 18:23:03 -05:00
ufhy 3928b4872a
fix: persist context-engine auto-compaction counts (#42629)
Merged via squash.

Prepared head SHA: df8f292039
Co-authored-by: uf-hy <41638541+uf-hy@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-03-14 16:22:10 -07:00
Brian Qu 8a607d7553
fix(feishu): fetch thread context so AI can see bot replies in topic threads (#45254)
* fix(feishu): fetch thread context so AI can see bot replies in topic threads

When a user replies in a Feishu topic thread, the AI previously could only
see the quoted parent message but not the bot's own prior replies in the
thread. This made multi-turn conversations in threads feel broken.

- Add `threadId` (omt_xxx) to `FeishuMessageInfo` and `getMessageFeishu`
- Add `listFeishuThreadMessages()` using `container_id_type=thread` API
  to fetch all messages in a thread including bot replies
- In `handleFeishuMessage`, fetch ThreadStarterBody and ThreadHistoryBody
  for topic session modes and pass them to the AI context
- Reuse quoted message result when rootId === parentId to avoid redundant
  API calls; exclude root message from thread history to prevent duplication
- Fall back to inbound ctx.threadId when rootId is absent or API fails
- Fetch newest messages first (ByCreateTimeDesc + reverse) so long threads
  keep the most recent turns instead of the oldest

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

* fix(feishu): skip redundant thread context injection on subsequent turns

Only inject ThreadHistoryBody on the first turn of a thread session.
On subsequent turns the session already contains prior context, so
re-injecting thread history (and starter) would waste tokens.

The heuristic checks whether the current user has already sent a
non-root message in the thread — if so, the session has prior turns
and thread context injection is skipped entirely.

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

* fix(feishu): handle thread_id-only events in prior-turn detection

When ctx.rootId is undefined (thread_id-only events), the starter
message exclusion check `msg.messageId !== ctx.rootId` was always
true, causing the first follow-up to be misclassified as a prior
turn. Fall back to the first message in the chronologically-sorted
thread history as the starter.

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

* fix(feishu): bootstrap topic thread context via session state

* test(memory): pin remote embedding hostnames in offline suites

* fix(feishu): use plugin-safe session runtime for thread bootstrap

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-14 18:01:59 -05:00
George Zhang 3704293e6f
browser: drop headless/remote MCP attach modes, simplify existing-session to autoConnect-only (#46628) 2026-03-14 15:54:22 -07:00
Josh Lehman 2f7e548a57
chore: regenerate config baseline (#46598) 2026-03-14 15:44:13 -07:00
George Zhang b1d8737017
browser: drop chrome-relay auto-creation, simplify to user profile only (#46596)
Merged via squash.

Prepared head SHA: 74becc8f7d
Co-authored-by: odysseus0 <8635094+odysseus0@users.noreply.github.com>
Co-authored-by: odysseus0 <8635094+odysseus0@users.noreply.github.com>
Reviewed-by: @odysseus0
2026-03-14 15:40:02 -07:00
Vincent Koc 39b4185d0b revert: 9bffa3422c 2026-03-14 15:09:22 -07:00
Vincent Koc 173fe3cb54
feat(browser): add headless existing-session MCP support esp for Linux/Docker/VPS (#45769)
* fix(browser): prefer managed default profile in headless mode

* test(browser): cover headless default profile fallback

* feat(browser): support headless MCP profile resolution

* feat(browser): add headless and target-url Chrome MCP modes

* feat(browser): allow MCP target URLs in profile creation

* docs(browser): document headless MCP existing-session flows

* fix(browser): restore playwright browser act helpers

* fix(browser): preserve strict selector actions

* docs(changelog): add existing-session MCP note
2026-03-14 14:59:30 -07:00
Vincent Koc 92834c8440 fix(deps): update package yauzl 2026-03-14 14:35:17 -07:00
Vincent Koc 39377b7a20
UI: surface gateway restart reasons in dashboard disconnect state (#46580)
* UI: surface gateway shutdown reason

* UI: add gateway restart disconnect tests

* Changelog: add dashboard restart reason fix

* UI: cover reconnect shutdown state
2026-03-14 14:31:26 -07:00
Vincent Koc cbec476b6b
Docs: add config drift baseline statefile (#45891)
* Docs: add config drift statefile generator

* Docs: generate config drift baseline

* CI: move config docs drift runner into workflow sanity

* Docs: emit config drift baseline json

* Docs: commit config drift baseline json

* Docs: wire config baseline into release checks

* Config: fix baseline drift walker coverage

* Docs: regenerate config drift baselines
2026-03-14 14:23:30 -07:00
Vincent Koc 432ea11248
Security: add secops ownership for sensitive paths (#46440)
* Meta: add secops ownership for sensitive paths

* Docs: restrict Codeowners-managed security edits

* Meta: guide agents away from secops-owned paths

* Meta: broaden secops CODEOWNERS coverage

* Meta: narrow secops workflow ownership
2026-03-14 14:16:14 -07:00
Tak Hoffman e81442ac80 Fix full local gate on main 2026-03-14 15:52:11 -05:00