Commit Graph

31620 Commits

Author SHA1 Message Date
Peter Steinberger
b31d243c57 fix: stabilize skills prompt ordering (#64198) (thanks @Bartok9) 2026-04-16 10:28:22 -07:00
Bartok
c4488d5ef5 fix: pin localeCompare to 'en' locale for cross-environment stability
Addresses review feedback: localeCompare without a fixed locale uses the
runtime default, which varies across servers. Pinning 'en' ensures
byte-identical prompts for cache stability. Applied at all three sort
points in workspace.ts.
2026-04-16 10:28:22 -07:00
Bartok Moltbot
a4b94f77b9 fix(skills): sort available_skills alphabetically for prompt cache stability
Sort the merged skill entries by name before rendering into the
available_skills prompt block. Previously the order depended on
Map insertion order which varies with skills.load.extraDirs config,
causing identical deployments to produce different prompts and bypass
LLM prompt caching.

Two sort points added:
1. loadSkillEntries — canonical ordering at the source
2. resolveWorkspaceSkillPromptState — ensures prompt stability even
   when callers pass pre-built entry arrays

Fixes #64167
2026-04-16 10:28:22 -07:00
Omar Shahine
77d9fd693f fix(bluebubbles): restore inbound image attachments and accept updated-message events (#67510)
* fix(bluebubbles): restore inbound image attachments and accept updated-message events

Four interconnected fixes for BlueBubbles inbound media:

1. Strip bundled-undici dispatcher from non-SSRF fetch path so attachment
   downloads no longer silently fail on Node 22+ (#64105, #61861)

2. Accept updated-message webhook events that carry attachments instead of
   filtering them as non-reaction events (#65430)

3. Include eventType in the persistent GUID dedup key so updated-message
   follow-ups are not rejected as duplicates of the original new-message (#52277)

4. Retry attachment fetch from BB API (2s delay) when the initial webhook
   arrives with an empty attachments array — image-only messages and
   updated-message events only (#67437)

Closes #64105, closes #61861, closes #65430.

* fix(bluebubbles): resolve review findings — SSRF policy, reuse extractAttachments, add tests

- F1 (BLOCKER): pass undefined instead of {} for SSRF policy when
  allowPrivateNetwork is false, so localhost BB servers are not blocked.
- F2 (IMPORTANT): reuse exported extractAttachments() from monitor-normalize
  instead of duplicating field extraction logic.
- F3 (IMPORTANT): simplify asRecord(asRecord(payload)?.data) to
  asRecord(payload.data) since payload is already Record<string, unknown>.
- F4 (NIT): bind retryMessageId before the guard to eliminate non-null assertion.
- F5 (IMPORTANT): add 4 tests for fetchBlueBubblesMessageAttachments covering
  success, non-ok HTTP, empty data, and guid-less entries.
- Add CHANGELOG entry for the user-facing fix.

* fix(ci): update raw-fetch allowlist line number after dispatcher strip

* fix(bluebubbles): resolve PR review findings (#67510)

- monitor-processing: move attachment retry into the !rawBody guard so
  image-only new-message events that arrive with empty attachments and
  empty text are recovered via a BB API refetch before being dropped.
  The existing retry block at the end of processMessageAfterDedupe was
  unreachable for this case because the !rawBody early-return fired
  first. (Greptile)
- monitor: derive isAttachmentUpdate from the normalized message shape
  instead of raw payload.data.attachments so updated-message webhooks
  with attachments under wrapper formats (payload.message, JSON-string
  payloads) are correctly routed through for processing instead of
  silently filtered. (Codex)
- types: use bundled-undici fetch when init.dispatcher is present so
  the SSRF guard's DNS-pinning dispatcher is preserved when this
  function is called as fetchImpl from guarded callers (e.g. the
  attachment download path via fetchRemoteMedia). Falls back to
  globalThis.fetch when no dispatcher is present so tests that stub
  globalThis.fetch keep working. (Codex)
- attachments: blueBubblesPolicy returns undefined for the non-private
  case (matching monitor-processing's helper) so sendBlueBubblesAttachment
  stops routing localhost BB through the SSRF guard. (Greptile)
- scripts/check-no-raw-channel-fetch: bump the types.ts allowlist line
  to match the restructured non-SSRF branch.

* fix(bluebubbles): move attachment retry before rawBody guard, fix stale log

Move the attachment retry block (2s BB API refetch for empty attachments)
before the !rawBody early-return guard. Previously, image-only messages
with text='' and attachments=[] would be dropped by the !rawBody check
before the retry could fire, making fix #4 dead code for its primary
use-case. Now the retry runs first and recomputes the placeholder from
resolved attachments so rawBody becomes non-empty when media is found.

Also fix stale log message that still said 'without reaction' after the
filter was expanded to pass through attachment updates.

* fix(bluebubbles): revert undici import, restore dispatcher-strip approach

Revert the @claude bot's undici import in types.ts — it introduced a
direct 'undici' dependency that is not declared in the BB extension's
package.json and would break isolated plugin installs. Restore the
original dispatcher-strip approach which is correct: the SSRF guard
already completed validation upstream before calling this function as
fetchImpl, so stripping the dispatcher does not weaken security.

* fix(bluebubbles): remove dead empty-body recovery block in !rawBody guard

The empty-body attachment-recovery block added in the earlier PR revision
is now redundant because the main retry block was moved above the rawBody
computation in 0d7d1c4208. Worse, that leftover block reassigned the
(now-const) placeholder variable, throwing `TypeError: Assignment to
constant variable` at runtime for image-only messages — breaking the very
recovery path it was meant to protect (flagged by Codex on 4bfc2777).

Remove the dead block; the up-front retry already handles the image-only
case by recovering attachments before the rawBody computation, so once we
reach the !rawBody guard with an empty body it is genuinely empty and
should drop as before.

* fix(ci): update raw-fetch allowlist line after dispatcher-strip revert

279dba17d2 reverted types.ts back to the dispatcher-strip approach,
which put the `fetch(url, ...)` call at line 189 instead of line 198.
Bump the allowlist entry to match so `lint:tmp:no-raw-channel-fetch`
stops failing check-additional.

* test(pdf-tool): update stale opus-4-6 constant to opus-4-7

`628b454eff feat: default Anthropic to Opus 4.7` bumped the bundled
anthropic image default to `claude-opus-4-7` but missed updating the
`ANTHROPIC_PDF_MODEL` constant in pdf-tool.model-config.test.ts. The
tests now fail on any PR that runs the `checks-node-agentic-agents-plugins`
shard because the resolver returns 4-7 while the test asserts 4-6.

Bump the constant to 4-7 to match the bundled default.

---------

Co-authored-by: Lobster <10343873+omarshahine@users.noreply.github.com>
2026-04-16 10:04:20 -07:00
Peter Steinberger
6429fa0a7f test: keep prompt cache PR gate green 2026-04-16 09:41:26 -07:00
Ted Li
eb10803691 fix(prompt): keep inbound chat ids out of system prefix 2026-04-16 09:41:26 -07:00
Peter Steinberger
1183832d4f fix: pin codex resume sandbox override 2026-04-16 17:31:41 +01:00
Peter Steinberger
d842ec4179 fix: tighten delivery mirror dedupe (#67185) (thanks @andyylin) 2026-04-16 09:20:01 -07:00
Andy
e95efa4373 fix(sessions): dedupe redundant delivery mirrors 2026-04-16 09:20:01 -07:00
Peter Steinberger
86f108401b fix: share agent harness runtime activation (#67474) 2026-04-16 09:06:45 -07:00
duqaXxX
f4bbd0122a test(plugins): remove useless spread in startup config fixture 2026-04-16 09:06:45 -07:00
duqaXxX
69ba924b53 fix(codex): activate harness plugin for forced runtime 2026-04-16 09:06:45 -07:00
Ayaan Zaidi
16c608e393 fix: harden cron announce NO_REPLY suppression (#65016) (thanks @BKF-Gitty) 2026-04-16 21:36:43 +05:30
Peter Steinberger
1d41ef724a test: isolate tts provider auto-selection env 2026-04-16 17:05:36 +01:00
Peter Steinberger
892baf2e81 test: align PDF tool expectations with Opus 4.7 2026-04-16 08:56:56 -07:00
Peter Steinberger
99dfc1b616 docs: add changelog for Codex Desktop user agents (#64666) (thanks @cyrusaf) 2026-04-16 08:56:56 -07:00
Cyrus Forbes
728295c046 Codex: parse Desktop app-server user agents 2026-04-16 08:56:56 -07:00
Gustavo Madeira Santana
d74533c718 Docs: remove QA Matrix changelog entry 2026-04-16 11:42:33 -04:00
Peter Steinberger
461d0050d9 fix: keep codex resume runs non-interactive (#67666) (thanks @plgonzalezrx8) 2026-04-16 08:41:57 -07:00
Pedro Gonzalez
4c66978591 security(codex): restore sandbox protections for resumed CLI sessions 2026-04-16 08:41:57 -07:00
Peter Steinberger
1a98090bf3 test: harden Parallels update smoke 2026-04-16 08:19:30 -07:00
Peter Steinberger
628b454eff feat: default Anthropic to Opus 4.7 2026-04-16 16:12:06 +01:00
Ayaan Zaidi
75c551e89e fix: harden node-host shell payload mutability checks 2026-04-16 20:34:17 +05:30
tmimmanuel
29919bb6e4 fix: land node-host approval binding for native binaries (#66731) (thanks @tmimmanuel)
* fix(node-host): allow absolute-path native binaries through approval binder

* test(node-host): cover binary binder edge cases

* test(node-host): use stable native binary fixture

* fix(ci): restore fail-closed race handling

* refactor(node-host): distill approval binding regressions

* fix(node-host): fail closed on unknown shell payload headers

* fix: land node-host approval binding for native binaries (#66731) (thanks @tmimmanuel)

* fix: keep relative shell binary payloads fail-closed (#66731) (thanks @tmimmanuel)

* fix: keep shell binary bypass on stable paths only (#66731) (thanks @tmimmanuel)

* fix: fail closed on symlinked shell binary targets (#66731) (thanks @tmimmanuel)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-04-16 20:30:09 +05:30
Mason Huang
69d25f5f16 CI: add daily schedule to CodeQL workflow (#67645)
* CI: add weekly schedule to CodeQL workflow

* CI: add daily schedule to CodeQL workflow and pin third-party actions
2026-04-16 21:27:45 +08:00
Chunyue Wang
8c11210fe5 fix(gateway): capture config hash after plugin auto-enable to prevent restart loop (#67557)
Merged via squash.

Prepared head SHA: 07250958a7
Co-authored-by: openperf <80630709+openperf@users.noreply.github.com>
Co-authored-by: openperf <80630709+openperf@users.noreply.github.com>
Reviewed-by: @openperf
2026-04-16 21:18:24 +08:00
stain lu
c3c7a9953f fix: repair sanitized replay tool results before send (#67620) (thanks @stainlu)
* fix(agents): preserve native Anthropic tool IDs for hybrid providers

Fixes #66892

MiniMax and other hybrid providers use api.minimaxi.com/anthropic
(modelApi: anthropic-messages), which generates and expects native
Anthropic tool_call_ids in toolu_* format. The hybrid replay policy
(buildHybridAnthropicOrOpenAIReplayPolicy) applied strict
sanitization that stripped underscores from these IDs, causing
MiniMax to reject them with error 2013.

The native Anthropic provider already preserved these IDs via
preserveNativeAnthropicToolUseIds (added in 4613f121ad). This
commit enables the same flag for the hybrid anthropic-messages
branch, so toolu_* IDs pass through unsanitized while other
synthetic IDs still get strict cleanup.

* fix(agents): repair sanitized replay tool results before send

* fix: repair sanitized replay tool results before send (#67620) (thanks @stainlu)

* fix: preserve aborted-span tool results during replay sanitize (#67620) (thanks @stainlu)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-04-16 18:38:57 +05:30
Ayaan Zaidi
de129a6530 fix: restrict HTML timeout short-circuit to transient statuses 2026-04-16 18:33:35 +05:30
Ayaan Zaidi
3525273930 fix: keep TUI watchdog bound to active run (#67401) (thanks @xantorres) 2026-04-16 18:31:56 +05:30
Xan Torres
d7f489f85e Gateway/skills: dedupe skills prefix-match + drop dead fallback on log 2026-04-16 18:31:56 +05:30
Xan Torres
b555214c96 Extensions/lmstudio: back off inference preload after consecutive failures 2026-04-16 18:31:56 +05:30
Xan Torres
f44ab20d4d TUI/streaming: add watchdog that resets the activity indicator after delta silence 2026-04-16 18:31:56 +05:30
Xan Torres
36ed36768c Agents/tool-loop: enable unknown-tool stream guard by default 2026-04-16 18:31:56 +05:30
Xan Torres
b23d59a522 Gateway/skills: invalidate session skills snapshot on config write 2026-04-16 18:31:56 +05:30
stain lu
e588e904a7 fix: classify HTML provider error pages correctly (#67642) (thanks @stainlu)
* fix(agents): classify Cloudflare/CDN HTML error pages as transport failures

Fixes #67517

When a provider endpoint returns an HTML error page (e.g. Cloudflare
502/503/520-524), the pattern-based message classifiers would scan
the HTML body and misinterpret embedded text like "Rate limit
exceeded" as a structured rate_limit API error. This caused
incorrect failover behavior (profile rotation instead of clean
retry/fallback) and left the TUI stuck.

Two fixes:
1. classifyFailoverSignal now short-circuits on HTML responses
   before running pattern matchers, returning "timeout" (transport
   failure) so retry/fallback handles them correctly.
2. classifyProviderRuntimeFailureKind now detects HTML errors at
   any status (not just 403), returning "upstream_html" for
   non-403 statuses with a clear user-facing message about
   CDN/gateway errors.

Adds regression tests covering Cloudflare 502/503 HTML with
embedded rate-limit text, 403 HTML (still classified as auth),
and JSON rate-limit responses (still classified correctly).

* fix: preserve auth and proxy HTML classification

* fix: classify HTML provider error pages correctly (#67642) (thanks @stainlu)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-04-16 18:19:53 +05:30
Mason Huang
55f05df77e fix(skills): remove unused model-usage import (#67641)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-16 19:56:34 +08:00
Nimrod Gutman
e485f24301 docs(changelog): credit codex fix superseded PRs 2026-04-16 14:33:19 +03:00
Nimrod Gutman
90801ba400 fix(openai-codex): normalize stale transport metadata in resolution and discovery (#67635)
Merged via squash.

Supersedes:
- #66969 by @saamuelng601-pixel
- #67159 by @hclsys

Co-authored-by: saamuelng601-pixel <274746699+saamuelng601-pixel@users.noreply.github.com>
Co-authored-by: hclsys <7755017+hclsys@users.noreply.github.com>
2026-04-16 14:30:05 +03:00
Mason Huang
f697b01747 CI: pin Docker-related GitHub Actions (#67632)
* CI: pin Docker-related GitHub Actions

* CI: pin docker build-push action
2026-04-16 19:23:03 +08:00
Mason Huang
44a6e50fcc Android: modernize WebView and discovery API usage (#67627)
* Android: modernize WebView and discovery API usage

* Android: narrow discovery API cleanup scope
2026-04-16 19:22:15 +08:00
Mason Huang
fbccc18e74 fix(deps): bump hono to 4.12.14 and @hono/node-server to 1.19.14 (GHSA-458j-xx4x-4375) (#67613) 2026-04-16 18:23:53 +08:00
Mason Huang
2c2dc00fb4 fix(deps): bump dompurify to 3.4.0 (#67614) 2026-04-16 18:18:55 +08:00
Mason Huang
01b7516a95 CI: add explicit permissions to all workflow jobs (fixes code-scanning #40-#57) (#67612) 2026-04-16 18:18:35 +08:00
stain lu
6ea3cddf0d fix: register bundled TTS providers and route overrides correctly (#62846) (thanks @stainlu)
* fix(microsoft,elevenlabs): add enabledByDefault so speech providers register at runtime

* fix(tts): route generic directive tokens to the explicitly declared provider

Addresses the P2 Codex review on #62846 that flagged auto-enabling
ElevenLabs as a product regression for MiniMax users. Both providers
claim the generic `speed` token, and parseTtsDirectives walked
providers in autoSelectOrder with first-match-wins, so inputs like
`[[tts:provider=minimax speed=1.2]]` silently routed speed to
providerOverrides.elevenlabs once elevenlabs participated in every
parse pass.

The parser now pre-scans for `provider=` (honoring legacy last-wins
semantics) and routes generic tokens with the declared provider tried
first, falling back to autoSelectOrder when it doesn't handle the key.
Token order inside the directive no longer matters: `speed=1.2` before
or after `provider=minimax` both resolve to MiniMax.

Adds a regression test suite covering the exact ElevenLabs/MiniMax
speed collision plus fallback, mixed-token, last-wins, and
allowProvider-disabled cases. parseTtsDirectives had no prior test
coverage.

* fix(tts): prefer active provider for generic directives

* fix: register bundled TTS providers safely (#62846) (thanks @stainlu)

* fix: use exported TTS SDK seam (#62846) (thanks @stainlu)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-04-16 15:26:38 +05:30
stain lu
ecfaf64526 fix: align host tilde paths with OS home (#62804) (thanks @stainlu)
* fix(tools): expand tilde in host edit/write paths (non-workspace mode)

* test: use it.runIf for visible skip when tmpdir is not under home

* fix(tools): address Codex P2 review on tilde host edit/write

Responds to two P2 findings from chatgpt-codex-connector on #62804:

1. Tests never ran in CI. The it.runIf(tmpdirUnderHome) guard always
   skipped on Linux runners where os.tmpdir() is /tmp, outside $HOME, so
   the regression tests reported green without executing. Tmpdirs now use
   the test-isolated HOME (process.env.HOME from test/test-env.ts) so
   tests run in every environment and match what expandHomePrefix
   resolves, keeping them hermetic.

2. Edit recovery path resolution was inconsistent. resolveEditPath
   inlined os.homedir() for tilde expansion, bypassing OPENCLAW_HOME,
   while the write/edit operations use expandHomePrefix. Under a custom
   OPENCLAW_HOME, wrapEditToolWithRecovery's readback targeted a
   different file than the edit actually touched, so successful edits
   could be reported as failures. resolveEditPath now uses the same
   expandHomePrefix helper.

* test(tools): verify tilde expansion honors OPENCLAW_HOME override

The prior tests covered tilde expansion but only under the default test
home, which matches os.homedir(). That passed whether the production code
used expandHomePrefix() or inlined os.homedir() — the behaviors only
diverge when OPENCLAW_HOME is set to a path outside $HOME.

Adds four tests that set OPENCLAW_HOME to a temp dir explicitly outside
$HOME and verify that write/mkdir/read/access tilde operations resolve
against OPENCLAW_HOME, not os.homedir(). These would fail if
pi-tools.read.ts or pi-tools.host-edit.ts reverted to os.homedir(),
directly covering the Codex P2 feedback about OPENCLAW_HOME consistency.

Uses the same env snapshot/restore pattern as test/helpers/temp-home.ts.

* Agents: resolve host tilde paths against OS home

* fix: align host tilde paths with OS home (#62804) (thanks @stainlu)

* fix: keep the changelog entry in the active block (#62804) (thanks @stainlu)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-04-16 14:37:55 +05:30
Gustavo Madeira Santana
05cac5b980 QA: fix private dist freshness check 2026-04-16 03:44:40 -04:00
Gustavo Madeira Santana
4db162db7f QA: split lab runtime and extend Matrix coverage (#67430)
Merged via squash.

Prepared head SHA: 790418b93b
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-04-16 03:08:39 -04:00
Gustavo Madeira Santana
8ecb6bbb12 QA: accept nodejs as Node runtime 2026-04-16 02:39:52 -04:00
Gustavo Madeira Santana
51b5d16faf CI: cap parity gate concurrency 2026-04-16 02:27:44 -04:00
Barron Roth
bf59917cd1 fix: add Google Gemini TTS provider (#67515) (thanks @barronlroth)
* Add Google Gemini TTS provider

* Remove committed planning artifact

* Explain Google media provider type shape

* google: distill Gemini TTS provider

* fix: add Google Gemini TTS provider (#67515) (thanks @barronlroth)

* fix: honor cfg-backed Google TTS selection (#67515) (thanks @barronlroth)

* fix: narrow Google TTS directive aliases (#67515) (thanks @barronlroth)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-04-16 11:54:35 +05:30