Skip to content

Merge develop: fix /bsc CORS + wallet reconnect#7843

Merged
lalalune merged 1 commit into
mainfrom
develop
May 20, 2026
Merged

Merge develop: fix /bsc CORS + wallet reconnect#7843
lalalune merged 1 commit into
mainfrom
develop

Conversation

@lalalune
Copy link
Copy Markdown
Member

@lalalune lalalune commented May 20, 2026

Summary

Two regressions Shaw hit live-testing /bsc:

  1. CORS preflight on /api/credits/balance — CreditsProvider was sending Pragma: no-cache alongside Cache-Control: no-cache, no-store, must-revalidate. Cross-origin call to api.elizacloud.ai, preflight rejected (Request header field pragma is not allowed). Dropped the redundant Pragma header.

  2. Wallet stuck on "Connect Wallet" after a successful MetaMask connectStewardWalletProviders had reconnectOnMount={false} on the WagmiProvider. With that flag, when the BSC page swaps the AttachWalletCard for the DirectCryptoCreditCard after a successful attach, the new component's useAccount / ConnectButton.Custom boots with account = undefined and refuses to reflect the live MetaMask connection. Pay button bails with "Connect your BSC wallet first". Removed the flag — wagmi default (true) is what every consumer of these providers wants, and the login surface already gates SIWE on an explicit user click so auto-reconnect can't accidentally fire a signature.

Test plan

  • After prod deploy, /bsc with an OAuth account that has wallet attached: clicking Connect Wallet → MetaMask connect → button shows the address, Pay button enables.
  • Credits sidebar polls without CORS errors in DevTools console.

🤖 Generated with Claude Code

Greptile Summary

This PR adds unit test coverage to several packages/examples sub-packages (agent-console, autonomous, chat, telegram, text-adventure, twitter-xai) by exporting previously private helpers, moving dynamic plugin imports inside main(), and guarding entry-point execution with import.meta.main. Despite the title referencing a CORS header fix and a wagmi reconnectOnMount change, none of those changes appear in the diff — only example package improvements are present.

  • Testability refactor: Internal helpers (parseDecision, isCommandAllowed, requireEnv, validateEnvironment, etc.) are exported and entry points are gated behind import.meta.main, enabling isolated unit tests without side effects.
  • New test suites: Six new *.test.ts files are added with deterministic, no-network test coverage for provider detection, environment validation, game engine logic, and action scanning.

Confidence Score: 4/5

Safe to merge — all changes are confined to example packages and add test coverage without touching any production runtime code.

The refactoring is clean and the new tests are well-isolated. The only tangible concern is that both requireEnv (twitter-xai) and readRequiredEnv (telegram) validate presence using .trim() but return the raw, un-trimmed string — a whitespace-padded API key would pass the guard and silently fail at the provider. The test for requireEnv even enshrines the untrimmed behavior with a misleading description. Nothing here breaks existing behavior, but the pattern could cause hard-to-diagnose auth errors for users with .env files that have trailing spaces.

packages/examples/twitter-xai/agent.ts and packages/examples/telegram/telegram-agent.ts — both expose helper functions that accept but do not trim env var values.

Important Files Changed

Filename Overview
packages/examples/autonomous/autonomous.ts Dynamic plugin imports moved inside main(); parseDecision, isCommandAllowed, and decisionPrompt exported; import.meta.main guard added — clean refactor for testability.
packages/examples/chat/chat.ts LLM_PROVIDERS, hasValidApiKey, detectLLMPlugin, printAvailableProviders exported; main() guarded by import.meta.main — straightforward export-for-testing refactor.
packages/examples/telegram/telegram-agent.ts readRequiredEnv and createTelegramCharacter extracted and exported; main() restructured to use these helpers and guarded by import.meta.main.
packages/examples/twitter-xai/agent.ts requireEnv and validateEnvironment exported; import.meta.main guard added. Test name claims the function "trims present values" but the implementation returns the raw untrimmed value.
packages/examples/twitter-xai/agent.test.ts Comprehensive env validation tests; test description for requireEnv is misleading — says "trims present values" but the assertion preserves leading/trailing spaces.
packages/examples/text-adventure/game.test.ts Deterministic no-LLM dungeon playthrough test; scripted action sequence is tightly coupled to game balance constants but exercises end-to-end engine logic well.
packages/examples/agent-console/action-scanner.test.ts Creates a temporary git repo fixture to test action discovery, metadata extraction, and subaction linking — well-isolated and deterministic.
packages/examples/autonomous/autonomous.test.ts Tests parseDecision (including sleep clamping), isCommandAllowed (shell metacharacter blocking), and decisionPrompt content — good coverage without any runtime or network dependencies.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Module imported by test runner] -->|import.meta.main = false| B[Export helpers only\nNo side effects]
    A -->|import.meta.main = true\nDirect execution| C[Run main]

    B --> D[Unit tests call exported functions]
    D --> E1[parseDecision / isCommandAllowed\nautonomous.ts]
    D --> E2[hasValidApiKey / detectLLMPlugin\nchat.ts]
    D --> E3[readRequiredEnv / createTelegramCharacter\ntelegram-agent.ts]
    D --> E4[requireEnv / validateEnvironment\nagent.ts]
    D --> E5[AdventureGame / playScriptedAdventure\ngame.ts]
    D --> E6[scanRepoActions\naction-scanner.ts]

    C --> F[Dynamic plugin imports\ne.g. @elizaos/plugin-inmemorydb\n@elizaos/plugin-local-inference]
    F --> G[Start runtime / agent loop]
Loading

Comments Outside Diff (2)

  1. packages/examples/twitter-xai/agent.ts, line 930-936 (link)

    P2 requireEnv validates with .trim() but returns the untrimmed value. If a user's .env file has XAI_API_KEY= sk-abc (accidental leading/trailing whitespace), the function accepts it as present but hands the padded string to the API client, causing authentication errors that are hard to diagnose. The same pattern appears in readRequiredEnv in telegram-agent.ts. Returning value.trim() instead of value would align the validation check with what's actually used downstream.

  2. packages/examples/text-adventure/game.test.ts, line 697-701 (link)

    P2 Misleading variable name blocked. game.executeAction("go north") here succeeds and returns a message containing "Torch-lit Hallway" (the player has moved there), yet the result is stored in a variable named blocked. The second call to go north is the one that is actually blocked. Consider renaming to moveResult or hallwayEntry to avoid confusing readers of this test.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Reviews (1): Last reviewed commit: "fix(cloud): unblock credits-balance CORS..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

…n /bsc

Two visible regressions on the live BSC flow:

1) CORS preflight rejection on `/api/credits/balance`

   CreditsProvider was sending `Pragma: no-cache` alongside `Cache-Control:
   no-cache, no-store, must-revalidate`. The `Cache-Control` value already
   disables caching for any modern proxy; `Pragma` is HTTP/1.0-era cruft
   kept "just in case". Sending it on a cross-origin call to
   `api.elizacloud.ai` forces a CORS preflight to list `pragma` in
   `Access-Control-Allow-Headers`, which the Worker's CORS config doesn't,
   so the actual GET was rejected with `Request header field pragma is not
   allowed`. Dropping the header from the request is the correct fix —
   no protocol semantics change, and the API CORS allowlist stays narrow.

2) Wallet stuck on "Connect Wallet" after a successful MetaMask connect

   `StewardWalletProviders` was setting `reconnectOnMount={false}` on the
   `WagmiProvider`. With that flag, wagmi refuses to restore an existing
   connector session when the provider mounts. On /bsc this surfaced as:
   the user connects via the RainbowKit modal, MetaMask shows "site
   connected", but as soon as React re-renders past the connect event
   (e.g. when the wallet attach flow swaps the AttachWalletCard for the
   DirectCryptoCreditCard), the new component's `useAccount` /
   `ConnectButton.Custom` boots with `account = undefined` and the button
   regresses to "Connect Wallet" with no clickable recovery. The pay
   handler then bails with "Connect your BSC wallet first" because
   `isConnected` is false.

   Default behavior (`reconnectOnMount: true`) is what the BSC promo,
   dashboard billing, and any return-visit flow want. The login surface
   already gates SIWE on an explicit user click via `pendingSignRef`, so
   auto-reconnect can't accidentally fire a signature prompt — flipping
   the default is safe across all consumers of these providers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 20, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 66b18d43-4375-496b-9347-0afbfb954e1f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch develop

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@lalalune lalalune merged commit abe8a74 into main May 20, 2026
30 of 33 checks passed
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 20, 2026

Claude encountered an error —— View job


I'll analyze this and get back to you.

Comment on lines +36 to +38
test("requireEnv trims present values and rejects missing values", () => {
process.env.XAI_API_KEY = " xai-test-key ";
expect(requireEnv("XAI_API_KEY")).toBe(" xai-test-key ");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 The test description says requireEnv "trims present values", but the assertion on the next line proves the opposite — the raw value " xai-test-key " (spaces intact) is returned. A developer reading this test description would expect whitespace to be stripped, which could mask silent authentication failures when an API key is copy-pasted with surrounding spaces into a .env file.

Suggested change
test("requireEnv trims present values and rejects missing values", () => {
process.env.XAI_API_KEY = " xai-test-key ";
expect(requireEnv("XAI_API_KEY")).toBe(" xai-test-key ");
test("requireEnv rejects missing or blank values but returns the raw value", () => {
process.env.XAI_API_KEY = " xai-test-key ";
expect(requireEnv("XAI_API_KEY")).toBe(" xai-test-key ");

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant