Skip to content

Commit 8e8792e

Browse files
Shawclaude
andcommitted
wip: parallel agent changes (on main)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 7768619 commit 8e8792e

12 files changed

Lines changed: 138 additions & 34 deletions

File tree

packages/cloud-frontend/public/_headers

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@
1919
X-XSS-Protection: 1; mode=block
2020
Permissions-Policy: camera=(), microphone=(self), geolocation=()
2121
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
22+
Cache-Control: no-cache
23+
24+
# Hashed assets under /assets/* are content-addressed and immutable. Pin
25+
# them to a long cache so they survive the no-cache rule on /* above. This
26+
# pair (no-cache HTML + immutable assets) is the standard cache discipline
27+
# for hashed-bundle SPAs: deploys propagate instantly without re-fetching
28+
# unchanged JS/CSS.
29+
/assets/*
30+
Cache-Control: public, max-age=31536000, immutable
2231

2332
# OAuth/popup callback pages need a relaxed COOP so window.closed works
2433
/app-auth/*

packages/cloud-frontend/public/_redirects

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@
1717
/docs https://docs.elizaos.ai/cloud 301
1818
/docs/* https://docs.elizaos.ai/cloud/:splat 301
1919

20+
# Hashed-asset 404s must NOT fall through to the SPA index.html. When a
21+
# stale browser HTML references an asset hash that no longer exists, the
22+
# catch-all below would otherwise return index.html with status 200 for
23+
# the missing .js, and the browser would fail strict MIME checking with
24+
# "Expected a JavaScript-or-Wasm module script but the server responded
25+
# with a MIME type of text/html". Returning a real 404 lets the chunk-load
26+
# error boundary in src/providers/ConditionalWalletProviders.tsx catch it
27+
# and self-heal via a single hard reload.
28+
/assets/* /index.html 404
29+
2030
# SPA fallback — every other path falls through to index.html so React
2131
# Router can resolve client-side routes.
2232
/* /index.html 200

packages/cloud-frontend/src/components/landing/hero-section.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ export default function HeroSection() {
3131
</h1>
3232
<p className="mt-6 max-w-2xl text-xl font-medium leading-snug text-black/80 sm:text-2xl">
3333
{t("cloud.landing.heroSubtitle", {
34-
defaultValue:
35-
"Hosting, APIs and commerce tools for agents.",
34+
defaultValue: "Hosting, APIs and commerce tools for agents.",
3635
})}
3736
</p>
3837
<div className="mt-10 flex w-full flex-col gap-3 sm:w-auto sm:flex-row sm:flex-wrap">

packages/cloud-frontend/src/dashboard/admin/rpc-status/Page.tsx

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
/** /dashboard/admin/rpc-status — verify the worker can reach each chain's RPC. */
22

3-
import { Badge, Button, Card, CardContent, CardHeader, CardTitle } from "@elizaos/ui";
3+
import {
4+
Badge,
5+
Button,
6+
Card,
7+
CardContent,
8+
CardHeader,
9+
CardTitle,
10+
} from "@elizaos/ui";
411
import { useQuery } from "@tanstack/react-query";
512
import { Loader2, RefreshCw } from "lucide-react";
613
import { Helmet } from "react-helmet-async";
@@ -66,7 +73,9 @@ export default function AdminRpcStatusPage() {
6673
{error && (
6774
<Card className="border-destructive">
6875
<CardContent className="p-4 text-destructive">
69-
{error instanceof Error ? error.message : "Failed to load RPC status"}
76+
{error instanceof Error
77+
? error.message
78+
: "Failed to load RPC status"}
7079
</CardContent>
7180
</Card>
7281
)}
@@ -84,7 +93,11 @@ export default function AdminRpcStatusPage() {
8493
<CardHeader>
8594
<CardTitle className="flex items-center gap-2">
8695
Treasury hot wallet
87-
<Badge variant={payload.hotWalletAddress ? "default" : "destructive"}>
96+
<Badge
97+
variant={
98+
payload.hotWalletAddress ? "default" : "destructive"
99+
}
100+
>
88101
{payload.hotWalletAddress ? "configured" : "missing"}
89102
</Badge>
90103
</CardTitle>
@@ -99,7 +112,10 @@ export default function AdminRpcStatusPage() {
99112

100113
<div className="grid grid-cols-1 gap-3 md:grid-cols-3">
101114
{payload.evm.map((p) => (
102-
<Card key={p.network} className={p.reachable ? "" : "border-destructive"}>
115+
<Card
116+
key={p.network}
117+
className={p.reachable ? "" : "border-destructive"}
118+
>
103119
<CardHeader>
104120
<CardTitle className="flex items-center justify-between text-base">
105121
<span className="capitalize">{p.network}</span>
@@ -115,15 +131,18 @@ export default function AdminRpcStatusPage() {
115131
<div>latency: {p.latencyMs ?? "—"} ms</div>
116132
<div>latest block: {p.latestBlock ?? "—"}</div>
117133
<div>
118-
ELIZA balance: {p.hotWalletBalance?.toLocaleString() ?? "—"}
134+
ELIZA balance:{" "}
135+
{p.hotWalletBalance?.toLocaleString() ?? "—"}
119136
</div>
120137
{p.error && (
121-
<div className="break-all text-destructive">error: {p.error}</div>
138+
<div className="break-all text-destructive">
139+
error: {p.error}
140+
</div>
122141
)}
123142
{p.rpcSource === "public_default" && (
124143
<div className="text-amber-500">
125-
Using chain's public RPC — set a dedicated provider URL for
126-
production.
144+
Using chain's public RPC — set a dedicated provider URL
145+
for production.
127146
</div>
128147
)}
129148
</CardContent>

packages/cloud-frontend/src/dashboard/billing/_components/direct-crypto-credit-card.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,22 @@ import { useConnection, useWallet } from "@solana/wallet-adapter-react";
1111
import { useWalletModal } from "@solana/wallet-adapter-react-ui";
1212
import { PublicKey, Transaction } from "@solana/web3.js";
1313
import { Coins, Loader2, ShieldCheck, Wallet } from "lucide-react";
14-
import { type CSSProperties, useEffect, useMemo, useRef, useState } from "react";
14+
import {
15+
type CSSProperties,
16+
useEffect,
17+
useMemo,
18+
useRef,
19+
useState,
20+
} from "react";
1521
import { Link } from "react-router-dom";
1622
import { toast } from "sonner";
1723
import { erc20Abi } from "viem";
1824
import { useAccount, useConfig, useSwitchChain } from "wagmi";
19-
import { sendTransaction, waitForTransactionReceipt, writeContract } from "wagmi/actions";
25+
import {
26+
sendTransaction,
27+
waitForTransactionReceipt,
28+
writeContract,
29+
} from "wagmi/actions";
2030
import type {
2131
CryptoStatusResponse,
2232
CryptoStatusTokenOption,
@@ -183,6 +193,7 @@ export function DirectCryptoCreditCard({
183193

184194
// When the network changes (or the underlying token list does), reset the
185195
// selected token to the network's default so we don't carry a stale BSC
196+
// biome-ignore lint/correctness/useExhaustiveDependencies: selected?.network is the intentional reset signal here
186197
// selection into Base/Solana.
187198
useEffect(() => {
188199
setTokenSymbol(null);
@@ -269,7 +280,10 @@ export function DirectCryptoCreditCard({
269280
value: BigInt(payment.instructions.amountUnits),
270281
chainId: cfg.chainId,
271282
});
272-
await waitForTransactionReceipt(wagmiConfig, { hash, chainId: cfg.chainId });
283+
await waitForTransactionReceipt(wagmiConfig, {
284+
hash,
285+
chainId: cfg.chainId,
286+
});
273287
return hash;
274288
}
275289
if (!payment.instructions.tokenAddress) {

packages/cloud-frontend/src/dashboard/billing/_components/payment-waiting-overlay.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,9 @@ export function PaymentWaitingOverlay({
116116
<p className="mt-2 text-sm text-white/65">
117117
{isConfirmed
118118
? `Added $${data?.creditsToAdd ?? "—"} in cloud credit${
119-
data?.bonusCredits ? ` (incl. $${data.bonusCredits} bonus)` : ""
119+
data?.bonusCredits
120+
? ` (incl. $${data.bonusCredits} bonus)`
121+
: ""
120122
}.`
121123
: isFailed
122124
? (data?.error ??

packages/cloud-frontend/src/dashboard/security/permissions/_components/plugin-permissions-page-client.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
import { Puzzle } from "lucide-react";
99
import { useCallback, useEffect, useState } from "react";
1010
import { toast } from "sonner";
11-
import { ApiError, api, apiFetch } from "@/lib/api-client";
11+
import { api, apiFetch } from "@/lib/api-client";
1212
import { emitAuditEvent } from "@/lib/security/audit-client";
1313

1414
interface PluginGrant {
@@ -56,6 +56,7 @@ export function PluginPermissionsPageClient() {
5656
}
5757
};
5858

59+
// biome-ignore lint/correctness/useExhaustiveDependencies: load is stable scope function; running on mount only is intentional
5960
useEffect(() => {
6061
void load();
6162
}, []);

packages/cloud-frontend/src/pages/login/wallet-buttons.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,7 @@ import { useWallet } from "@solana/wallet-adapter-react";
33
import { useWalletModal } from "@solana/wallet-adapter-react-ui";
44
import type { StewardAuth, StewardAuthResult } from "@stwd/sdk";
55
import { useCallback, useEffect, useRef } from "react";
6-
import {
7-
type Connector,
8-
useAccount,
9-
useConnect,
10-
useSignMessage,
11-
} from "wagmi";
6+
import { type Connector, useAccount, useConnect, useSignMessage } from "wagmi";
127
import { useT } from "@/providers/I18nProvider";
138

149
// Phantom injects itself as an Ethereum provider but must never be used for

packages/cloud-frontend/src/providers/ConditionalWalletProviders.tsx

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { lazy, type ReactNode, Suspense, useMemo } from "react";
1+
import { Component, lazy, type ReactNode, Suspense, useMemo } from "react";
22
import { matchPath, useLocation } from "react-router-dom";
33

44
/**
@@ -34,6 +34,48 @@ const LazyStewardWalletProviders = lazy(async () => {
3434
return { default: mod.StewardWalletProviders };
3535
});
3636

37+
const CHUNK_RELOAD_FLAG = "eliza:chunk-reload-attempted";
38+
39+
function isChunkLoadError(error: unknown): boolean {
40+
if (!(error instanceof Error)) return false;
41+
const message = error.message ?? "";
42+
return (
43+
error.name === "ChunkLoadError" ||
44+
message.includes("Failed to fetch dynamically imported module") ||
45+
message.includes("Importing a module script failed") ||
46+
message.includes("error loading dynamically imported module") ||
47+
/Expected a JavaScript-or-Wasm module script/.test(message)
48+
);
49+
}
50+
51+
class ChunkLoadErrorBoundary extends Component<
52+
{ children: ReactNode; fallback: ReactNode },
53+
{ failed: boolean }
54+
> {
55+
state = { failed: false };
56+
57+
static getDerivedStateFromError(error: unknown) {
58+
if (isChunkLoadError(error)) {
59+
if (typeof window !== "undefined") {
60+
const alreadyTried =
61+
window.sessionStorage.getItem(CHUNK_RELOAD_FLAG) === "1";
62+
if (!alreadyTried) {
63+
window.sessionStorage.setItem(CHUNK_RELOAD_FLAG, "1");
64+
window.location.reload();
65+
return { failed: true };
66+
}
67+
}
68+
return { failed: true };
69+
}
70+
throw error;
71+
}
72+
73+
render() {
74+
if (this.state.failed) return this.props.fallback;
75+
return this.props.children;
76+
}
77+
}
78+
3779
function isWalletRoute(pathname: string): boolean {
3880
if (pathname === "/payment/success") {
3981
return false;

packages/cloud-frontend/tests/e2e/direct-crypto-flow.spec.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,10 @@ async function installBscMocks(
195195

196196
if (path === "/api/crypto/direct-payments") {
197197
createPaymentCalls += 1;
198-
const body = await route.request().postDataJSON().catch(() => ({}));
198+
const body = await route
199+
.request()
200+
.postDataJSON()
201+
.catch(() => ({}));
199202
const requestedSymbol: string =
200203
typeof body?.tokenSymbol === "string" ? body.tokenSymbol : "USDT";
201204
const token =
@@ -346,7 +349,9 @@ test("/bsc shows BNB/USDT/$U token selector and $5 bonus is per-purchase, token-
346349
await expect(tokenSelect).toBeVisible();
347350
// The three BSC tokens are selectable; USDC must NOT appear.
348351
for (const value of ["BNB", "USDT", "U"]) {
349-
await expect(tokenSelect.locator(`option[value="${value}"]`)).toHaveCount(1);
352+
await expect(tokenSelect.locator(`option[value="${value}"]`)).toHaveCount(
353+
1,
354+
);
350355
}
351356
await expect(tokenSelect.locator('option[value="USDC"]')).toHaveCount(0);
352357

@@ -455,7 +460,7 @@ test("Login with Ethereum (SIWE) excludes Phantom from the injected-provider pat
455460
await ethereumButton.click();
456461
// Brief wait for any async injected-provider call to fire.
457462
await page.waitForTimeout(750);
458-
expect(errors.some((m) => m.includes("unexpected_phantom_account_request"))).toBe(
459-
false,
460-
);
463+
expect(
464+
errors.some((m) => m.includes("unexpected_phantom_account_request")),
465+
).toBe(false);
461466
});

0 commit comments

Comments
 (0)