diff --git a/apps/playground-web/src/app/ai/api/chat.ts b/apps/playground-web/src/app/ai/api/chat.ts index 322ae696fc4..2c5aec9ad44 100644 --- a/apps/playground-web/src/app/ai/api/chat.ts +++ b/apps/playground-web/src/app/ai/api/chat.ts @@ -22,7 +22,9 @@ export async function promptNebula(params: { body.context = { chain_ids: params.context.chainIds?.map(Number) || [], session_id: params.context.sessionId ?? undefined, - wallet_address: params.context.walletAddress, + from: params.context.walletAddress ?? undefined, + auto_execute_transactions: + params.context.autoExecuteTransactions || false, }; } diff --git a/apps/playground-web/src/app/ai/api/types.ts b/apps/playground-web/src/app/ai/api/types.ts index 7d51d317167..a2c4782cf38 100644 --- a/apps/playground-web/src/app/ai/api/types.ts +++ b/apps/playground-web/src/app/ai/api/types.ts @@ -34,6 +34,7 @@ export type NebulaContext = { chainIds: string[] | null; walletAddress: string | null; sessionId: string | null; + autoExecuteTransactions?: boolean; }; export type NebulaSwapData = { diff --git a/apps/playground-web/src/app/ai/components/ChatPageContent.tsx b/apps/playground-web/src/app/ai/components/ChatPageContent.tsx index b4f30441f6c..dcb4318181b 100644 --- a/apps/playground-web/src/app/ai/components/ChatPageContent.tsx +++ b/apps/playground-web/src/app/ai/components/ChatPageContent.tsx @@ -49,6 +49,18 @@ export function ChatPageContent(props: { const connectionStatus = useActiveWalletConnectionStatus(); const connectedWallets = useConnectedWallets(); const setActiveWallet = useSetActiveWallet(); + const [chatAbortController, setChatAbortController] = useState< + AbortController | undefined + >(); + + const [isChatStreaming, setIsChatStreaming] = useState(false); + const [enableAutoScroll, setEnableAutoScroll] = useState(false); + const [showConnectModal, setShowConnectModal] = useState(false); + + // User-configurable context options + const [userWalletAddress, setUserWalletAddress] = useState(""); + const [userChainIds, setUserChainIds] = useState(""); + const [userAutoExecute, setUserAutoExecute] = useState(false); const [userHasSubmittedMessage, setUserHasSubmittedMessage] = useState(false); const [messages, setMessages] = useState>(() => { @@ -68,12 +80,32 @@ export function ChatPageContent(props: { }); const contextFilters = useMemo(() => { + // Parse user-entered chain IDs + const userChainIdArray = userChainIds + .split(",") + .map((id) => id.trim()) + .filter((id) => id !== "" && !isNaN(Number(id))); + return { - chainIds: _contextFilters?.chainIds || [], + chainIds: + userChainIdArray.length > 0 + ? userChainIdArray + : _contextFilters?.chainIds || [], sessionId: _contextFilters?.sessionId || null, - walletAddress: address || _contextFilters?.walletAddress || null, + walletAddress: + userWalletAddress.trim() || + address || + _contextFilters?.walletAddress || + null, + autoExecuteTransactions: userAutoExecute, } satisfies NebulaContext; - }, [_contextFilters, address]); + }, [ + _contextFilters, + address, + userWalletAddress, + userChainIds, + userAutoExecute, + ]); const setContextFilters = useCallback((v: NebulaContext | undefined) => { _setContextFilters(v); @@ -107,14 +139,6 @@ export function ChatPageContent(props: { }); }, []); - const [chatAbortController, setChatAbortController] = useState< - AbortController | undefined - >(); - - const [isChatStreaming, setIsChatStreaming] = useState(false); - const [enableAutoScroll, setEnableAutoScroll] = useState(false); - const [showConnectModal, setShowConnectModal] = useState(false); - const handleSendMessage = useCallback( async (message: NebulaUserMessage) => { setUserHasSubmittedMessage(true); @@ -227,6 +251,14 @@ export function ChatPageContent(props: { {/* Chat input - anchored at bottom (same as chat state) */}
+ { chatAbortController?.abort(); @@ -279,6 +311,14 @@ export function ChatPageContent(props: { {/* Chat input - anchored at bottom */}
+ { chatAbortController?.abort(); @@ -708,6 +748,73 @@ function RenderMessage(props: { ); } +function ContextOptionsBar(props: { + walletAddress: string; + chainIds: string; + autoExecute: boolean; + onWalletAddressChange: (value: string) => void; + onChainIdsChange: (value: string) => void; + onAutoExecuteChange: (value: boolean) => void; +}) { + return ( +
+
+
+ + props.onWalletAddressChange(e.target.value)} + placeholder="0x..." + className="px-2 py-1 text-sm border border-border rounded focus:outline-none focus:ring-1 focus:ring-ring focus:border-ring bg-background" + style={{ width: "200px" }} + /> +
+ +
+ + props.onChainIdsChange(e.target.value)} + placeholder="1, 8453" + className="px-2 py-1 text-sm border border-border rounded focus:outline-none focus:ring-1 focus:ring-ring focus:border-ring bg-background" + style={{ width: "100px" }} + /> +
+ +
+ props.onAutoExecuteChange(e.target.checked)} + className="w-4 h-4 text-primary border-border rounded focus:ring-ring" + /> + +
+
+
+ ); +} + const NEBULA_LAST_USED_CHAIN_IDS_KEY = "nebula-last-used-chain-ids"; function saveLastUsedChainIds(chainIds: string[] | undefined) {