feat(agent): surface the AI500 index board in chat, tools, and sidebar

- provider/nofxos: GetAI500ListCached — 5min TTL cache with stale
  fallback on upstream failure; ResolveClient routes through the claw402
  gateway when a wallet key is configured (user's claw402 model key ->
  CLAW402_WALLET_KEY env -> direct nofxos)
- new GET /api/ai500 endpoint serving the score-sorted board
- new get_ai500_list agent tool + prompt rule: when the user wants coin
  picks or creates a strategy without naming coins, consult AI500's
  high-scoring entries by default
- web: AI500 sidebar panel (rank, score badge, gain since entry,
  5min auto-refresh); clicking an entry asks the agent to analyze it
This commit is contained in:
tinkle-community
2026-06-11 22:11:03 +08:00
parent 953240565f
commit 2c6e2827e8
12 changed files with 666 additions and 2 deletions

View File

@@ -8,6 +8,7 @@ import {
Bot,
Bookmark,
Zap,
Sparkles,
ChevronDown,
ChevronRight,
} from 'lucide-react'
@@ -21,6 +22,8 @@ import { ChatMessages } from '../components/agent/ChatMessages'
import { ChatInput, type ChatInputHandle } from '../components/agent/ChatInput'
import { UserPreferencesPanel } from '../components/agent/UserPreferencesPanel'
import { HyperliquidSymbolsPanel } from '../components/agent/HyperliquidSymbolsPanel'
import { AI500Panel } from '../components/agent/AI500Panel'
import type { AI500Coin } from '../lib/api/data'
import { createHyperliquidQuickTrader } from '../lib/hyperliquidQuickTrade'
import { useAgentChatStore } from '../stores/agentChatStore'
import type { AgentMessage as Message, AgentStep } from '../types/agent'
@@ -467,6 +470,7 @@ export function AgentChatPage() {
// Sidebar section collapse state
const [sections, setSections] = useState({
market: true,
ai500: true,
positions: true,
traders: false,
preferences: true,
@@ -582,6 +586,15 @@ export function AgentChatPage() {
chatInputRef.current?.focus()
}
const analyzeAI500Symbol = (coin: AI500Coin) => {
const display = coin.pair.replace(/USDT$/i, '')
const text =
language === 'zh'
? `分析一下 AI500 里的 ${display}(当前 AI 评分 ${coin.score.toFixed(1)}),给出趋势判断和交易建议`
: `Analyze ${display} from the AI500 index (current AI score ${coin.score.toFixed(1)}) and give me a trend read plus a trading suggestion`
void send(text)
}
const tradeHyperliquidSymbol = async (symbol: { symbol: string; display?: string; category?: string }) => {
const label = symbol.display || symbol.symbol
const time = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
@@ -720,6 +733,18 @@ export function AgentChatPage() {
title: language === 'zh' ? '市场行情' : 'Market',
component: <MarketTicker />,
},
{
key: 'ai500' as const,
icon: <Sparkles size={14} />,
title: language === 'zh' ? 'AI500 精选' : 'AI500 Picks',
component: (
<AI500Panel
language={language}
disabled={loading}
onAnalyzeSymbol={analyzeAI500Symbol}
/>
),
},
{
key: 'hyperliquid' as const,
icon: <Zap size={14} />,