Commit Graph

939 Commits

Author SHA1 Message Date
Peter Steinberger
ee8d8be2e3 fix(chutes): accept manual OAuth code input 2026-02-14 22:01:11 +01:00
Peter Steinberger
d2857fbea9 refactor(test): reuse doctor e2e harness 2026-02-14 20:12:47 +00:00
Peter Steinberger
ffcf37f8c1 fix(doctor): avoid no-op legacy dmPolicy conflict notes 2026-02-14 21:04:27 +01:00
Peter Steinberger
52ad64f8f9 test(doctor): migrate Slack/Discord dmPolicy aliases 2026-02-14 21:04:27 +01:00
Peter Steinberger
bf76452b43 fix(doctor): migrate Slack/Discord dm.policy keys to aliases 2026-02-14 21:04:27 +01:00
Bin Deng
b9d14855d0 Fix: Force dashboard command to use localhost URL (#16434)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 3c03b4cc9b1dec96e0541df37910a697493ca285
Co-authored-by: BinHPdev <219093083+BinHPdev@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-14 15:00:58 -05:00
Peter Steinberger
994bcbf670 refactor: clarify restoreTerminalState stdin resume option 2026-02-14 20:47:00 +01:00
Bin Deng
4734f99108 Fix: Add type safety to models status command (#16395)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 1554137ae34b8183a924d48e3894e9d60c4e2dde
Co-authored-by: BinHPdev <219093083+BinHPdev@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-14 14:07:38 -05:00
Vincent Koc
a042b32d2f fix: Docker installation keeps hanging on MacOS (#12972)
* Onboarding: avoid stdin resume after wizard finish

* Changelog: remove Docker hang entry from PR

* Terminal: make stdin resume behavior explicit at call sites

* CI: rerun format check

* Onboarding: restore terminal before cancel exit

* test(onboard): align restoreTerminalState expectation

* chore(format): align onboarding restore test with updated oxfmt config

* chore(format): enforce updated oxfmt on restore test

* chore(format): apply updated oxfmt spacing to restore test

* fix: avoid stdin resume after onboarding (#12972) (thanks @vincentkoc)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 19:46:07 +01:00
Peter Steinberger
4133f4bd37 refactor(tui): clarify searchable select list width layout (#16378)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: fecbade822f8163f12b7da441b567acb42e6f809
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-14 19:15:38 +01:00
Peter Steinberger
fc5d147d1b fix(test-harness): annotate vitest mocks to avoid TS2742 2026-02-14 18:26:46 +01:00
Peter Steinberger
571c195c54 fix: support moltbot legacy state dir 2026-02-14 17:14:21 +00:00
Peter Steinberger
ae97f8f798 refactor(test): share doctor e2e harness 2026-02-14 17:13:24 +00:00
Steve
69ba9a0562 fix: add memory search health check to openclaw doctor (openclaw#16294) thanks @superlowburn
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test (noted unrelated local flakes)

Co-authored-by: superlowburn <24779772+superlowburn@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-14 11:09:51 -06:00
Peter Steinberger
684c18458a perf(test): speed up line, models list, and memory batch 2026-02-14 16:36:15 +00:00
Peter Steinberger
d583782ee3 fix(security): harden discovery routing and TLS pins 2026-02-14 17:18:14 +01:00
Peter Steinberger
9e147f00b4 fix(doctor): resolve telegram allowFrom usernames 2026-02-14 16:48:07 +01:00
Peter Steinberger
8d1a1d9e86 refactor(commands): share vllm setup 2026-02-14 15:39:46 +00:00
Peter Steinberger
64df787448 refactor(channels): share account summary helpers 2026-02-14 15:39:46 +00:00
Peter Steinberger
3150ece95a refactor(channels): pass setup input to mutator 2026-02-14 15:39:45 +00:00
Peter Steinberger
4c74a2f06e refactor(channels): reuse setup input types 2026-02-14 15:39:45 +00:00
Peter Steinberger
a1fc6a6ea6 refactor(daemon): share runtime status formatter 2026-02-14 15:39:45 +00:00
Peter Steinberger
1b03eb71aa refactor(health): share channel line styling 2026-02-14 15:39:45 +00:00
Aether AI
3967ece625 fix(security): OC-25 — Validate OAuth state parameter to prevent CSRF attacks (#16058)
* fix(security): validate OAuth state parameter to prevent CSRF attacks (OC-25)

The parseOAuthCallbackInput() function in the Chutes OAuth flow had two
critical bugs that completely defeated CSRF state validation:

1. State extracted from callback URL was never compared against the
   expected cryptographic nonce, allowing attacker-controlled state values
2. When URL parsing failed (bare authorization code input), the catch block
   fabricated a matching state using expectedState, making the caller's
   CSRF check always pass

## Attack Flow

1. Victim runs `openclaw login chutes --manual`
2. System generates cryptographic state: randomBytes(16).toString("hex")
3. Browser opens: https://api.chutes.ai/idp/authorize?state=abc123...
4. Attacker obtains their OWN OAuth authorization code (out of band)
5. Attacker tricks victim into pasting just "EVIL_CODE" (not full URL)
6. parseOAuthCallbackInput("EVIL_CODE", "abc123...") is called
7. new URL("EVIL_CODE") throws → catch block executes
8. catch returns { code: "EVIL_CODE", state: "abc123..." } ← FABRICATED
9. Caller checks: parsed.state !== state → "abc123..." !== "abc123..." → FALSE
10. CSRF check passes! System calls exchangeChutesCodeForTokens()
11. Attacker's code exchanged for access + refresh tokens
12. Victim's account linked to attacker's OAuth session

Fix:
- Add explicit state validation against expectedState before returning
- Remove state fabrication from catch block; always return error for
  non-URL input
- Add comprehensive unit tests for state validation

Remediated by Aether AI Agent security analysis.

* fix(security): harden chutes manual oauth state check (#16058) (thanks @aether-ai-agent)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 15:28:52 +01:00
Peter Steinberger
3aa94afcfd fix(security): harden archive extraction (#16203)
* fix(browser): confine upload paths for file chooser

* fix(browser): sanitize suggested download filenames

* chore(lint): avoid control regex in download sanitizer

* test(browser): cover absolute escape paths

* docs(browser): update upload example path

* refactor(browser): centralize upload path confinement

* fix(infra): harden tmp dir selection

* fix(security): harden archive extraction

* fix(infra): harden tar extraction filter
2026-02-14 14:42:08 +01:00
Peter Steinberger
1ba266a8e8 refactor: split minimax-cn provider 2026-02-14 13:37:47 +01:00
Peter Steinberger
83248f7603 Merge remote-tracking branch 'origin/main' 2026-02-14 13:30:22 +01:00
Peter Steinberger
0cfea46293 fix: wire minimax-api-key-cn onboarding (#15191) (thanks @liuy) 2026-02-14 13:25:54 +01:00
Liu Yuan
9bb099736b feat: add minimax-api-key-cn option for China API endpoint
- Add 'minimax-api-key-cn' auth choice for Chinese users
- Reuse existing --minimax-api-key CLI option
- Use MINIMAX_CN_API_BASE_URL (https://api.minimaxi.com/anthropic)
- Similar to how moonshot supports moonshot-api-key-cn

Tested: build , check , test 
2026-02-14 13:25:54 +01:00
Peter Steinberger
6dd6bce997 fix(security): enforce sandbox bridge auth 2026-02-14 13:17:41 +01:00
Peter Steinberger
eb4215d570 perf(test): speed up Vitest bootstrap 2026-02-14 12:13:27 +00:00
Nicholas
f8ba8f7699 fix(docs): update outdated hooks documentation URLs (#16165)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 8ed13fb02fae2cb6dd3cacdb3cd1ef37a5cdd4d8
Co-authored-by: nicholascyh <188132635+nicholascyh@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-14 13:05:37 +01:00
Peter Steinberger
3b56a6252b chore!: remove moltbot legacy state/config support 2026-02-14 12:40:47 +01:00
Nick Taylor
1fb52b4d7b feat(gateway): add trusted-proxy auth mode (#15940)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 279d4b304f83186fda44dfe63a729406a835dafa
Co-authored-by: nickytonline <833231+nickytonline@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-14 12:32:17 +01:00
Peter Steinberger
d8beddc8b7 refactor(onboard): unify auth-choice aliases and provider flags 2026-02-14 05:58:26 +01:00
Peter Steinberger
eab9dc538a refactor(onboard): unify auth-choice catalog for CLI help 2026-02-14 05:51:17 +01:00
AI-Reviewer-QS
28431b84cc fix(gateway): prune expired entries instead of clearing all hook auth failure state (#15848)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 188a40e8a35112b9ea2df23dd0a940b9be1eac1d
Co-authored-by: AI-Reviewer-QS <255312808+AI-Reviewer-QS@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
2026-02-14 01:46:12 +01:00
Peter Steinberger
e7c3c27fd0 perf(test): trim browser and models suite overhead 2026-02-14 00:38:55 +00:00
Shadril Hassan Shifat
1c928e493d fix(hooks): replace console logging with proper subsystem logging in loader (openclaw#11029) thanks @shadril238
Verified:
- pnpm build
- pnpm check
- pnpm test

Co-authored-by: shadril238 <63901551+shadril238@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-13 18:21:11 -06:00
Peter Steinberger
05524bb5ef perf(test): remove duplicate models list e2e suite 2026-02-14 00:20:47 +00:00
Peter Steinberger
ec4da3aca9 perf(test): lighten models list e2e registry mock 2026-02-14 00:17:49 +00:00
Peter Steinberger
fecb3f326e perf(test): trim models/browser suite overhead 2026-02-14 00:08:02 +00:00
Peter Steinberger
cf2524b8b9 refactor(models): share auth helpers and forward-compat list fallbacks 2026-02-14 01:07:35 +01:00
Vincent Koc
a0cbf9002d fix(models): antigravity opus 4.6 availability follow-up (#12845)
* fix(models): antigravity opus 4.6 availability follow-up

* chore(format): apply updated oxfmt config to models files

* fix(models): retain zai glm-5 forward-compat fallback after extraction

* chore(format): apply updated oxfmt config

* fix(models): fail fast on unknown auth login provider

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 00:54:46 +01: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
2086cdfb9b perf(test): reduce hot-suite import and setup overhead 2026-02-13 20:26:39 +00:00
Peter Steinberger
08725270e2 perf: honor low timeout budgets in health telegram probes 2026-02-13 19:22:25 +00:00
Marcus Castro
eed8cd383f fix(agent): search all agent stores when resolving --session-id (#13579)
* fix(agent): search all agent stores when resolving --session-id

When `--session-id` was provided without `--to` or `--agent`, the reverse
lookup only searched the default agent's session store. Sessions created
under a specific agent (e.g. `--agent mybot`) live in that agent's store
file, so the lookup silently failed and the session was not reused.

Now `resolveSessionKeyForRequest` iterates all configured agent stores
when the primary store doesn't contain the requested sessionId.

Fixes #12881

* fix: search other agent stores when --to key does not match --session-id

When --to derives a session key whose stored sessionId doesn't match the
requested --session-id, the cross-store search now also runs. This handles
the case where a user provides both --to and --session-id targeting a
session in a different agent's store.
2026-02-13 18:46:54 +01:00
Peter Steinberger
fdfc34fa1f perf(test): stabilize e2e harness and reduce flaky gateway coverage 2026-02-13 17:32:14 +00:00
Mariano Belinky
86e4fe0a7a Auth: land codex oauth onboarding flow (#15406) 2026-02-13 17:18:49 +00:00