feat(telegram): add AI agent bot with streaming and account context

- Add Telegram bot with long-polling and AI agent loop (api_call tool)
- SSE streaming with real-time message editing and  placeholder
- Account state injection at conversation start (models, exchanges,
  strategies, traders, per-trader PnL and statistics)
- Lane semaphore per chat serializes concurrent messages (60s timeout)
- Idle timeout watchdog (60s) prevents hung streaming connections
- Look-ahead buffer prevents partial <api_call> tag leaking to user
- Fix PUT /strategies/:id to merge config (read-then-merge pattern)
- Add route registry with full API schema for LLM documentation
- Add TelegramConfig store and Web UI config modal
- Add GetAnyEnabled to AIModel store for bot LLM client selection
This commit is contained in:
tinkle-community
2026-03-08 00:19:38 +08:00
parent 73f1fe105d
commit 3168a18c0d
28 changed files with 4673 additions and 118 deletions

View File

@@ -16,6 +16,7 @@ import { getModelIcon } from './ModelIcons'
import { TraderConfigModal } from './TraderConfigModal'
import { DeepVoidBackground } from './DeepVoidBackground'
import { ExchangeConfigModal } from './traders/ExchangeConfigModal'
import { TelegramConfigModal } from './traders/TelegramConfigModal'
import { PunkAvatar, getTraderAvatar } from './PunkAvatar'
import {
Bot,
@@ -31,6 +32,7 @@ import {
ExternalLink,
Copy,
Check,
MessageCircle,
} from 'lucide-react'
import { confirmToast } from '../lib/notify'
import { toast } from 'sonner'
@@ -148,6 +150,7 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) {
const [showEditModal, setShowEditModal] = useState(false)
const [showModelModal, setShowModelModal] = useState(false)
const [showExchangeModal, setShowExchangeModal] = useState(false)
const [showTelegramModal, setShowTelegramModal] = useState(false)
const [editingModel, setEditingModel] = useState<string | null>(null)
const [editingExchange, setEditingExchange] = useState<string | null>(null)
const [editingTrader, setEditingTrader] = useState<any>(null)
@@ -849,6 +852,16 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) {
</div>
</button>
<button
onClick={() => setShowTelegramModal(true)}
className="px-4 py-2 rounded text-xs font-mono uppercase tracking-wider transition-all border border-sky-900/50 bg-black/20 text-sky-500 hover:text-sky-300 hover:border-sky-700 whitespace-nowrap backdrop-blur-sm"
>
<div className="flex items-center gap-2">
<MessageCircle className="w-3 h-3" />
<span>TELEGRAM_BOT</span>
</div>
</button>
<button
onClick={() => setShowCreateModal(true)}
disabled={configuredModels.length === 0 || configuredExchanges.length === 0}
@@ -1379,6 +1392,14 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) {
language={language}
/>
)}
{/* Telegram Bot Modal */}
{showTelegramModal && (
<TelegramConfigModal
onClose={() => setShowTelegramModal(false)}
language={language}
/>
)}
</div>
</DeepVoidBackground>
)