UNPKG

starchild-widget

Version:

Starchild Widget

1,805 lines (1,804 loc) 609 kB
var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); import * as React from "react"; import React__default, { createContext, useContext, useCallback, useMemo, memo, useEffect, useState, Fragment, useRef, forwardRef, useReducer } from "react"; import { createRoot } from "react-dom/client"; import { jsxs, jsx, Fragment as Fragment$1 } from "react/jsx-runtime"; import styled, { css, keyframes, useTheme as useTheme$1, ThemeProvider as ThemeProvider$1, StyleSheetManager } from "styled-components"; import { T as Trans, u as usePopper, i as i18n, c as copy, M as Markdown$1, r as remarkGfm, b as bs58, s as signAsync, d as dayjs, I as I18nProvider } from "./vendor-CSKZtZSl.mjs"; import { createPortal } from "react-dom"; var Locale = /* @__PURE__ */ ((Locale2) => { Locale2["EN_US"] = "en-US"; Locale2["ZH_CN"] = "zh-CN"; return Locale2; })(Locale || {}); var ThemeMode = /* @__PURE__ */ ((ThemeMode2) => { ThemeMode2["LIGHT"] = "light"; ThemeMode2["DARK"] = "dark"; return ThemeMode2; })(ThemeMode || {}); var InputType = /* @__PURE__ */ ((InputType2) => { InputType2["SEARCH"] = "SEARCH"; InputType2["TEXT"] = "TEXT"; return InputType2; })(InputType || {}); var MoveType = /* @__PURE__ */ ((MoveType2) => { MoveType2["LINE"] = "line"; MoveType2["BG"] = "bg"; return MoveType2; })(MoveType || {}); var TriggerMethod = /* @__PURE__ */ ((TriggerMethod2) => { TriggerMethod2[TriggerMethod2["CLICK"] = 0] = "CLICK"; TriggerMethod2[TriggerMethod2["HOVER"] = 1] = "HOVER"; return TriggerMethod2; })(TriggerMethod || {}); var RootActionType = /* @__PURE__ */ ((RootActionType2) => { RootActionType2["COMMON"] = "COMMON"; RootActionType2["AUTH"] = "AUTH"; RootActionType2["CHAT"] = "CHAT"; RootActionType2["SEARCH"] = "SEARCH"; RootActionType2["POSITION_CACHE"] = "POSITION_CACHE"; RootActionType2["TRADE"] = "TRADE"; RootActionType2["RESET_ALL"] = "RESET_ALL"; RootActionType2["CHAT_CACHE"] = "CHAT_CACHE"; return RootActionType2; })(RootActionType || {}); class ApiError extends Error { constructor(message, status, statusText) { super(message); __publicField(this, "status"); __publicField(this, "statusText"); this.name = "ApiError"; this.status = status; this.statusText = statusText; } } var ComponentType = /* @__PURE__ */ ((ComponentType2) => { ComponentType2["CHAT"] = "CHAT"; ComponentType2["SEARCH"] = "SEARCH"; return ComponentType2; })(ComponentType || {}); const getDefaultComponentPosition = (componentType) => { const padding = 12; const viewportWidth = window.innerWidth || document.documentElement.clientWidth || 1200; const viewportHeight = window.innerHeight || document.documentElement.clientHeight || 800; if (componentType === ComponentType.CHAT) { return { x: viewportWidth - padding, // button右边距离屏幕右边界12px y: viewportHeight - padding // button下边距离屏幕下边界12px }; } else if (componentType === ComponentType.SEARCH) { const inputWidth = 640; return { x: Math.max(padding, (viewportWidth - inputWidth) / 2), // 水平居中 y: 80 // 距离顶部80px }; } return { x: padding, y: padding }; }; const constrainToViewport = (position, elementSize) => { const padding = 12; const maxX = Math.max(0, window.innerWidth - elementSize.width - padding); const maxY = Math.max(0, window.innerHeight - elementSize.height - padding); return { x: Math.max(padding, Math.min(position.x, maxX)), y: Math.max(padding, Math.min(position.y, maxY)) }; }; const getDefaultSearchSize = () => ({ width: 640, height: 240 }); const getSearchSizeConstraints = () => { const viewportWidth = window.innerWidth || document.documentElement.clientWidth || 1200; const viewportHeight = window.innerHeight || document.documentElement.clientHeight || 800; return { minWidth: 420, minHeight: 228, maxWidth: Math.min(980, viewportWidth - 40), // 不超过页面宽度,留出40px边距 maxHeight: viewportHeight - 160 // 上下各留80px距离 }; }; const constrainSize = (size) => { const constraints = getSearchSizeConstraints(); return { width: Math.max(constraints.minWidth, Math.min(size.width, constraints.maxWidth)), height: Math.max(constraints.minHeight, Math.min(size.height, constraints.maxHeight)) }; }; const API_LANG_MAP = { "zh-CN": "zh", "en-US": "en" }; class ApiClient { constructor(config) { __publicField(this, "config"); this.config = { retries: 3, retryDelay: 1e3, timeout: 1e4, headers: {}, ...config }; } /** * GET request */ async get(endpoint, options = {}) { return this.request(endpoint, "GET", void 0, options); } /** * POST request */ async post(endpoint, data, options = {}) { return this.request(endpoint, "POST", data, options); } /** * DELETE request */ async delete(endpoint, data, options = {}) { return this.request(endpoint, "DELETE", data, options); } /** * PUT request */ async put(endpoint, data, options = {}) { return this.request(endpoint, "PUT", data, options); } setAccountId(accountId) { this.config.headers["account-id"] = accountId; } setAiChatKey(aiChatKey) { this.config.headers["account-api-key"] = aiChatKey; } setLanguage(language) { this.config.headers["language"] = language; } clearAccountId() { delete this.config.headers["account-id"]; } clearAiChatKey() { delete this.config.headers["account-api-key"]; } /** * Base request method */ async request(endpoint, method, data, options = {}) { const url = this.buildUrl(endpoint); const headers = { ...this.config.headers, ...options.headers }; const requestInit = { method, headers }; if ((method === "POST" || method === "PUT" || method === "DELETE") && data !== void 0) { if (data instanceof FormData) { requestInit.body = data; delete headers["Content-Type"]; } else if (data instanceof URLSearchParams) { requestInit.body = data.toString(); headers["Content-Type"] = "application/x-www-form-urlencoded"; } else { requestInit.body = JSON.stringify(data); headers["Content-Type"] = "application/json"; } } try { const response = await fetch(url, requestInit); if (!response.ok) { throw new ApiError(`HTTP ${response.status}: ${response.statusText}`, response.status, response.statusText); } const contentType = response.headers.get("content-type"); let responseData; if (contentType && contentType.includes("application/json")) { responseData = await response.json(); } else { responseData = await response.text(); } return { data: responseData, status: response.status, statusText: response.statusText }; } catch (error) { if (error instanceof ApiError) { throw error; } throw new ApiError(error instanceof Error ? error.message : "Unknown error", 0, "Network Error"); } } /** * Build complete URL */ buildUrl(endpoint) { const baseURL = this.config.baseURL.replace(/\/$/, ""); const cleanEndpoint = endpoint.replace(/^\//, ""); return `${baseURL}/${cleanEndpoint}`; } } function createApiClient(config) { return new ApiClient(config); } const WidgetContext = createContext(null); const useWidget = () => { const context = useContext(WidgetContext); if (!context) { throw new Error("useWidget must be used within WidgetProvider"); } return context; }; const initialAuthState = { secretKey: "", accountId: "", orderlyKey: "", aiChatKey: "", telegramUserId: "", error: null }; const authActionHandlers = { setSecretKeyAction: { action: (secretKey) => ({ type: RootActionType.AUTH, payload: { actionType: "setSecretKeyAction", data: secretKey } }), reducer: (state, data) => ({ ...state, secretKey: data, error: null }) }, setAccountIdAction: { action: (accountId) => ({ type: RootActionType.AUTH, payload: { actionType: "setAccountIdAction", data: accountId } }), reducer: (state, data) => ({ ...state, accountId: data, error: null }) }, setOrderlyKeyAction: { action: (orderlyKey) => ({ type: RootActionType.AUTH, payload: { actionType: "setOrderlyKeyAction", data: orderlyKey } }), reducer: (state, data) => ({ ...state, orderlyKey: data, error: null }) }, setAiChatKeyAction: { action: (aiChatKey) => ({ type: RootActionType.AUTH, payload: { actionType: "setAiChatKeyAction", data: aiChatKey } }), reducer: (state, data) => ({ ...state, aiChatKey: data, error: null }) }, setTelegramUserIdAction: { action: (telegramUserId) => ({ type: RootActionType.AUTH, payload: { actionType: "setTelegramUserIdAction", data: telegramUserId } }), reducer: (state, data) => ({ ...state, telegramUserId: data, error: null }) }, setCredentialsAction: { action: (credentials) => ({ type: RootActionType.AUTH, payload: { actionType: "setCredentialsAction", data: credentials } }), reducer: (state, data) => ({ ...state, ...data, error: null }) }, setErrorAction: { action: (error) => ({ type: RootActionType.AUTH, payload: { actionType: "setErrorAction", data: error } }), reducer: (state, data) => ({ ...state, error: data }) }, clearAction: { action: () => ({ type: RootActionType.AUTH, payload: { actionType: "clearAction", data: null } }), reducer: () => ({ ...initialAuthState }) }, destroyAction: { action: () => ({ type: RootActionType.AUTH, payload: { actionType: "destroyAction", data: null } }), reducer: () => ({ ...initialAuthState }) } }; const setAiChatKeyAction = authActionHandlers.setAiChatKeyAction.action; const setTelegramUserIdAction = authActionHandlers.setTelegramUserIdAction.action; const setCredentialsAction = authActionHandlers.setCredentialsAction.action; function authReducer(state = initialAuthState, action) { if (!action.payload || !action.payload.actionType) { return state; } const handler = authActionHandlers[action.payload.actionType]; if (handler) { return handler.reducer(state, action.payload.data); } return state; } function useAiChatKey() { const { state, dispatch } = useWidget(); const aiChatKey = state.auth.aiChatKey; const setAiChatKey = useCallback((aiChatKey2) => { dispatch(setAiChatKeyAction(aiChatKey2)); }, [dispatch]); return [aiChatKey, setAiChatKey]; } function useTelegramUserId() { const { state, dispatch } = useWidget(); const telegramUserId = state.auth.telegramUserId; const setTelegramUserId = useCallback((telegramUserId2) => { dispatch(setTelegramUserIdAction(telegramUserId2)); }, [dispatch]); return [telegramUserId, setTelegramUserId]; } let currentEnvironment = "testnet"; function setEnvironment(env) { currentEnvironment = env; } function getEnvironment() { return currentEnvironment; } const chatDomainOrigin = { // 测试环境 testnet: { restfulDomain: "https://tg-api-testnet-899f9ba9abd5.herokuapp.com" }, // 主网 mainnet: { restfulDomain: "https://tg-api-mainnet-a4ecd0c9d145.herokuapp.com" } }; const chatDomain = new Proxy({}, { get: (_, prop) => { const env = getEnvironment(); return chatDomainOrigin[env][prop]; } }); const orderlyDomainOrigin = { // 测试环境 testnet: { restfulDomain: "https://testnet-api.orderly.org" }, // 主网 mainnet: { restfulDomain: "https://api.orderly.org" } }; const orderlyDomain = new Proxy({}, { get: (_, prop) => { const env = getEnvironment(); return orderlyDomainOrigin[env][prop]; } }); const starChildDomainOrigin = { // 测试环境 testnet: { pageDomain: "https://testnet.iamstarchild.com" }, // 主网 mainnet: { pageDomain: "https://iamstarchild.com" } }; const starChildDomain = new Proxy({}, { get: (_, prop) => { const env = getEnvironment(); return starChildDomainOrigin[env][prop]; } }); const initialCommonState = { mounted: false, themeMode: ThemeMode.DARK, locale: Locale.EN_US, environment: "testnet", error: null, isWindowVisible: true }; const commonActionHandlers = { setMountedAction: { action: (mounted) => ({ type: RootActionType.COMMON, payload: { actionType: "setMountedAction", data: mounted } }), reducer: (state, data) => ({ ...state, mounted: data }) }, setThemeModeAction: { action: (themeMode) => ({ type: RootActionType.COMMON, payload: { actionType: "setThemeModeAction", data: themeMode } }), reducer: (state, data) => ({ ...state, themeMode: data }) }, setLocaleAction: { action: (locale) => ({ type: RootActionType.COMMON, payload: { actionType: "setLocaleAction", data: locale } }), reducer: (state, data) => ({ ...state, locale: data }) }, setEnvironmentAction: { action: (environment) => ({ type: RootActionType.COMMON, payload: { actionType: "setEnvironmentAction", data: environment } }), reducer: (state, data) => ({ ...state, environment: data }) }, setErrorAction: { action: (error) => ({ type: RootActionType.COMMON, payload: { actionType: "setErrorAction", data: error } }), reducer: (state, data) => ({ ...state, error: data }) }, setIsWindowVisibleAction: { action: (isWindowVisible) => ({ type: RootActionType.COMMON, payload: { actionType: "setIsWindowVisibleAction", data: isWindowVisible } }), reducer: (state, data) => ({ ...state, isWindowVisible: data }) }, destroyAction: { action: () => ({ type: RootActionType.COMMON, payload: { actionType: "destroyAction", data: null } }), reducer: () => ({ ...initialCommonState }) } }; const setMountedAction = commonActionHandlers.setMountedAction.action; const setThemeModeAction = commonActionHandlers.setThemeModeAction.action; const setLocaleAction = commonActionHandlers.setLocaleAction.action; const setEnvironmentAction = commonActionHandlers.setEnvironmentAction.action; const setErrorAction = commonActionHandlers.setErrorAction.action; const setIsWindowVisibleAction = commonActionHandlers.setIsWindowVisibleAction.action; function commonReducer(state = initialCommonState, action) { if (!action.payload || !action.payload.actionType) { return state; } const handler = commonActionHandlers[action.payload.actionType]; if (handler) { return handler.reducer(state, action.payload.data); } return state; } const defaultThemeTokens = {}; const darkThemeTokens = { ...defaultThemeTokens }; const lightTheme = { mode: ThemeMode.LIGHT, ...defaultThemeTokens, // Dark Neutral 完整色系 dn1: "#535E7B", dn2: "#4A5369", dn3: "#394155", dn4: "#333948", dn5: "#282E3A", dn6: "#20252F", dn7: "#1B2028", dn8: "#181C23", dn9: "#131519", dn10: "#07080A", // Brand 完整色系 brand1: "#B9D1FF", brand2: "#97B9FD", brand3: "#779DFF", brand4: "#608CFF", brand5: "#4774F6", brand6: "#335FFC", brand7: "#3347FD", brand8: "#283BEE", brand9: "#1D30DF", brand10: "#1728C1", // Brand/🏈 Brand-4-15 brand4_15: "rgba(96, 140, 255, 0.15)", brand100: "#F84600", // 文本透明度系列 textDark20: "rgba(255, 255, 255, 0.20)", textDark36: "rgba(255, 255, 255, 0.36)", textDark54: "rgba(255, 255, 255, 0.54)", textDark80: "rgba(255, 255, 255, 0.80)", textDark98: "rgba(255, 255, 255, 0.98)", // 线条透明度系列 lineDark4: "rgba(255, 255, 255, 0.04)", lineDark6: "rgba(255, 255, 255, 0.06)", lineDark8: "rgba(255, 255, 255, 0.08)", lineDark12: "rgba(255, 255, 255, 0.12)", lineDark16: "rgba(255, 255, 255, 0.16)", // Success/🏈 Success-1 success1: "#65ECD3", // Success/🏈 Success-2 success2: "#27DEC8", // Success/🏈 Success-3 success3: "#0FCBB4", // Success/🏈 Success-4 success4: "#00B49E", // Success/🏈 Success-5 success5: "#039886", // Success/🏈 Success-6 success6: "#008676", // Success/🏈 Success-7 success7: "#007769", // Success/🏈 Success-8 success8: "#00685C", // Success/🏈 Success-9 success9: "#0054AF", // Success/🏈 Success-10 success10: "#00433B", // Success/🏈 Success-4-15 success4_15: "rgba(0, 180, 158, 0.15)", // Danger/🏈 Danger-1 danger1: "#FFD0DE", // Danger/🏈 Danger-2 danger2: "#FFA5C0", // Danger/🏈 Danger-3 danger3: "#FF608F", // Danger/🏈 Danger-4 danger4: "#FF447C", // Danger/🏈 Danger-5 danger5: "#E93E71", // Danger/🏈 Danger-6 danger6: "#D92D6B", // Danger/🏈 Danger-7 danger7: "#AC2D58", // Danger/🏈 Danger-8 danger8: "#9D2D4D", // Danger/🏈 Danger-9 danger9: "#791438", // Danger/🏈 Danger-10 danger10: "#640B2B", // Danger/🏈 Danger-4-15 danger4_15: "rgba(255,68,124,0.15)", // Warning/🏈 Warning-1 warning1: "#FFF7E8", // Warning/🏈 Warning-2 warning2: "#FFE4BA", // Warning/🏈 Warning-3 warning3: "#FFCF8B", // Warning/🏈 Warning-4 warning4: "#FFB65D", // Warning/🏈 Warning-5 warning5: "#FF9A2E", // Warning/🏈 Warning-6 warning6: "#FF7D00", // Warning/🏈 Warning-7 warning7: "#D25F00", // Warning/🏈 Warning-8 warning8: "#A64500", // Warning/🏈 Warning-9 warning9: "#792E00", // Warning/🏈 Warning-10 warning10: "#4D1B00", // Link/🏈 Link-1 link1: "#FAEDFF", // Link/🏈 Link-2 link2: "#EDC4FF", // Link/🏈 Link-3 link3: "#D998FA", // Link/🏈 Link-4 link4: "#BD6BED", // Link/🏈 Link-5 link5: "#A141E0", // Link/🏈 Link-6 link6: "#831BD3", // Link/🏈 Link-7 link7: "#630EAD", // Link/🏈 Link-8 link8: "#460487", // Link/🏈 Link-9 link9: "#2D0061", // Link/🏈 Link-10 link10: "#19003B", // --Gradients-WOOFi gradient: "linear-gradient(270deg, #59B0FE 0%, #26FEFE 100%)", red100: "#FF375B", black600: "#2F3133", black700: "#232527", black800: "#1A1C1E", black900: "#121315", textLight88: "rgba(0, 0, 0, 0.88)", white: "#FFFFFF" }; const darkTheme = { mode: ThemeMode.DARK, ...darkThemeTokens, // Dark Neutral 完整色系 dn1: "#535E7B", dn2: "#4A5369", dn3: "#394155", dn4: "#333948", dn5: "#282E3A", dn6: "#20252F", dn7: "#1B2028", dn8: "#181C23", dn9: "#131519", dn10: "#07080A", // Brand 完整色系 brand1: "#B9D1FF", brand2: "#97B9FD", brand3: "#779DFF", brand4: "#608CFF", brand5: "#4774F6", brand6: "#335FFC", brand7: "#3347FD", brand8: "#283BEE", brand9: "#1D30DF", brand10: "#1728C1", // Brand/🏈 Brand-4-15 brand4_15: "rgba(96, 140, 255, 0.15)", brand100: "#F84600", // 文本透明度系列 textDark20: "rgba(255, 255, 255, 0.20)", textDark36: "rgba(255, 255, 255, 0.36)", textDark54: "rgba(255, 255, 255, 0.54)", textDark80: "rgba(255, 255, 255, 0.80)", textDark98: "rgba(255, 255, 255, 0.98)", // 线条透明度系列 lineDark4: "rgba(255, 255, 255, 0.04)", lineDark6: "rgba(255, 255, 255, 0.06)", lineDark8: "rgba(255, 255, 255, 0.08)", lineDark12: "rgba(255, 255, 255, 0.12)", lineDark16: "rgba(255, 255, 255, 0.16)", // Success/🏈 Success-1 success1: "#65ECD3", // Success/🏈 Success-2 success2: "#27DEC8", // Success/🏈 Success-3 success3: "#0FCBB4", // Success/🏈 Success-4 success4: "#00B49E", // Success/🏈 Success-5 success5: "#039886", // Success/🏈 Success-6 success6: "#008676", // Success/🏈 Success-7 success7: "#007769", // Success/🏈 Success-8 success8: "#00685C", // Success/🏈 Success-9 success9: "#0054AF", // Success/🏈 Success-10 success10: "#00433B", // Success/🏈 Success-4-15 success4_15: "rgba(0, 180, 158, 0.15)", // Danger/🏈 Danger-1 danger1: "#FFD0DE", // Danger/🏈 Danger-2 danger2: "#FFA5C0", // Danger/🏈 Danger-3 danger3: "#FF608F", // Danger/🏈 Danger-4 danger4: "#FF447C", // Danger/🏈 Danger-5 danger5: "#E93E71", // Danger/🏈 Danger-6 danger6: "#D92D6B", // Danger/🏈 Danger-7 danger7: "#AC2D58", // Danger/🏈 Danger-8 danger8: "#9D2D4D", // Danger/🏈 Danger-9 danger9: "#791438", // Danger/🏈 Danger-10 danger10: "#640B2B", // Danger/🏈 Danger-4-15 danger4_15: "rgba(255,68,124,0.15)", // Warning/🏈 Warning-1 warning1: "#FFF7E8", // Warning/🏈 Warning-2 warning2: "#FFE4BA", // Warning/🏈 Warning-3 warning3: "#FFCF8B", // Warning/🏈 Warning-4 warning4: "#FFB65D", // Warning/🏈 Warning-5 warning5: "#FF9A2E", // Warning/🏈 Warning-6 warning6: "#FF7D00", // Warning/🏈 Warning-7 warning7: "#D25F00", // Warning/🏈 Warning-8 warning8: "#A64500", // Warning/🏈 Warning-9 warning9: "#792E00", // Warning/🏈 Warning-10 warning10: "#4D1B00", // Link/🏈 Link-1 link1: "#FAEDFF", // Link/🏈 Link-2 link2: "#EDC4FF", // Link/🏈 Link-3 link3: "#D998FA", // Link/🏈 Link-4 link4: "#BD6BED", // Link/🏈 Link-5 link5: "#A141E0", // Link/🏈 Link-6 link6: "#831BD3", // Link/🏈 Link-7 link7: "#630EAD", // Link/🏈 Link-8 link8: "#460487", // Link/🏈 Link-9 link9: "#2D0061", // Link/🏈 Link-10 link10: "#19003B", // --Gradients-WOOFi gradient: "linear-gradient(270deg, #59B0FE 0%, #26FEFE 100%)", red100: "#FF375B", black600: "#2F3133", black700: "#232527", black800: "#1A1C1E", black900: "#121315", textLight88: "rgba(0, 0, 0, 0.88)", white: "#FFFFFF" }; const mergeTheme = (baseTheme, customTheme) => { return { ...baseTheme, ...customTheme }; }; const parseThemeConfig = (mode, themeConfig) => { if (!themeConfig) return void 0; const modeSpecificTheme = mode === ThemeMode.DARK ? themeConfig.dark : themeConfig.light; const commonTheme = themeConfig.common; if (commonTheme && modeSpecificTheme) { return { ...commonTheme, ...modeSpecificTheme }; } else if (commonTheme) { return commonTheme; } else if (modeSpecificTheme) { return modeSpecificTheme; } return void 0; }; const getTheme = (mode, themeConfig) => { const baseTheme = mode === ThemeMode.DARK ? darkTheme : lightTheme; const customTheme = parseThemeConfig(mode, themeConfig); return customTheme ? mergeTheme(baseTheme, customTheme) : baseTheme; }; const generateCSSVariables = (theme) => { return { // Dark Neutral 完整色系 (DN-1 到 DN-10) "--starchild-dn-1": theme.dn1, "--starchild-dn-2": theme.dn2, "--starchild-dn-3": theme.dn3, "--starchild-dn-4": theme.dn4, "--starchild-dn-5": theme.dn5, "--starchild-dn-6": theme.dn6, "--starchild-dn-7": theme.dn7, "--starchild-dn-8": theme.dn8, "--starchild-dn-9": theme.dn9, "--starchild-dn-10": theme.dn10, // Brand 完整色系 (Brand-1 到 Brand-10) "--starchild-brand-1": theme.brand1, "--starchild-brand-2": theme.brand2, "--starchild-brand-3": theme.brand3, "--starchild-brand-4": theme.brand4, "--starchild-brand-5": theme.brand5, "--starchild-brand-6": theme.brand6, "--starchild-brand-7": theme.brand7, "--starchild-brand-8": theme.brand8, "--starchild-brand-9": theme.brand9, "--starchild-brand-10": theme.brand10, "--starchild-brand-4-15": theme.brand4_15, "--starchild-brand-100": theme.brand100, // 文本透明度系列 "--starchild-text-dark-20": theme.textDark20, "--starchild-text-dark-36": theme.textDark36, "--starchild-text-dark-54": theme.textDark54, "--starchild-text-dark-80": theme.textDark80, "--starchild-text-dark-98": theme.textDark98, // 线条透明度系列 "--starchild-line-dark-6": theme.lineDark6, "--starchild-line-dark-8": theme.lineDark8, "--starchild-line-dark-12": theme.lineDark12, "--starchild-line-dark-16": theme.lineDark16, // Success 完整色系 (Success-1 到 Success-10) "--starchild-success-1": theme.success1, "--starchild-success-2": theme.success2, "--starchild-success-3": theme.success3, "--starchild-success-4": theme.success4, "--starchild-success-5": theme.success5, "--starchild-success-6": theme.success6, "--starchild-success-7": theme.success7, "--starchild-success-8": theme.success8, "--starchild-success-9": theme.success9, "--starchild-success-10": theme.success10, "--starchild-success-4-15": theme.success4_15, // Danger 完整色系 (Danger-1 到 Danger-10) "--starchild-danger-1": theme.danger1, "--starchild-danger-2": theme.danger2, "--starchild-danger-3": theme.danger3, "--starchild-danger-4": theme.danger4, "--starchild-danger-5": theme.danger5, "--starchild-danger-6": theme.danger6, "--starchild-danger-7": theme.danger7, "--starchild-danger-8": theme.danger8, "--starchild-danger-9": theme.danger9, "--starchild-danger-10": theme.danger10, "--starchild-danger-4-15": theme.danger4_15, // Warning 完整色系 (Warning-1 到 Warning-10) "--starchild-warning-1": theme.warning1, "--starchild-warning-2": theme.warning2, "--starchild-warning-3": theme.warning3, "--starchild-warning-4": theme.warning4, "--starchild-warning-5": theme.warning5, "--starchild-warning-6": theme.warning6, "--starchild-warning-7": theme.warning7, "--starchild-warning-8": theme.warning8, "--starchild-warning-9": theme.warning9, "--starchild-warning-10": theme.warning10, // Link 完整色系 (Link-1 到 Link-10) "--starchild-link-1": theme.link1, "--starchild-link-2": theme.link2, "--starchild-link-3": theme.link3, "--starchild-link-4": theme.link4, "--starchild-link-5": theme.link5, "--starchild-link-6": theme.link6, "--starchild-link-7": theme.link7, "--starchild-link-8": theme.link8, "--starchild-link-9": theme.link9, "--starchild-link-10": theme.link10, // --Gradients-WOOFi "--starchild-gradient": theme.gradient, "--starchild-red-100": theme.red100, "--starchild-black-600": theme.black600, "--starchild-black-700": theme.black700, "--starchild-black-800": theme.black800, "--starchild-black-900": theme.black900, "--starchild-text-light-88": theme.textLight88, "--starchild-white": theme.white }; }; function useMounted() { const { state, dispatch } = useWidget(); const isMounted = state.common.mounted; const setMounted = useCallback((mounted) => { dispatch(setMountedAction(mounted)); }, [dispatch]); return [isMounted, setMounted]; } function useThemeMode() { const { state, dispatch } = useWidget(); const themeMode = state.common.themeMode; const setTheme = useCallback((themeMode2) => { dispatch(setThemeModeAction(themeMode2)); }, [dispatch]); return [themeMode, setTheme]; } function useTheme() { const [themeMode] = useThemeMode(); return getTheme(themeMode); } function useLocale() { const { state, dispatch } = useWidget(); const locale = state.common.locale; const setLocale = useCallback((locale2) => { dispatch(setLocaleAction(locale2)); }, [dispatch]); return [locale, setLocale]; } function useError() { const { state, dispatch } = useWidget(); const error = state.common.error; const setError = useCallback((error2) => { dispatch(setErrorAction(error2)); }, [dispatch]); return [error, setError]; } function useIsWindowVisible() { const { state, dispatch } = useWidget(); const isWindowVisible = state.common.isWindowVisible; const setIsWindowVisible = useCallback((isWindowVisible2) => { dispatch(setIsWindowVisibleAction(isWindowVisible2)); }, [dispatch]); return [isWindowVisible, setIsWindowVisible]; } let apiClient$1 = null; function getApiClient$1() { if (!apiClient$1) { apiClient$1 = createApiClient({ baseURL: chatDomain["restfulDomain"], timeout: 1e4 }); } return apiClient$1; } function useSetAuthHeaders() { const [telegramUserId] = useTelegramUserId(); const [aiChatKey] = useAiChatKey(); const [locale] = useLocale(); const client = getApiClient$1(); client.setAccountId(telegramUserId); client.setAiChatKey(aiChatKey); client.setLanguage(API_LANG_MAP[locale]); } function useGetChatThreadsQuery() { useSetAuthHeaders(); return useCallback(async ({ telegramUserId }) => { try { const client = getApiClient$1(); const response = await client.get(`/threads?user_id=${telegramUserId}`); return response.data; } catch (error) { console.error("GET chat threads request failed:", error); throw error; } }, []); } function useDeleteThreadQuery() { useSetAuthHeaders(); return useCallback(async ({ threadIds, telegramUserId }) => { try { const client = getApiClient$1(); const response = await client.delete(`/batch_threads?user_id=${telegramUserId}&thread_ids=${threadIds.join(",")}`); return response.data; } catch (error) { console.error("DELETE thread request failed:", error); throw error; } }, []); } function useGetAiBotChatContentsQuery() { useSetAuthHeaders(); return useCallback(async ({ threadId, telegramUserId }) => { try { const client = getApiClient$1(); const response = await client.get(`/chat_content?thread_id=${threadId}&user_id=${telegramUserId}`); return response.data; } catch (error) { console.error("GET chat threads request failed:", error); throw error; } }, []); } function useDeleteAiBotChatContentQuery() { useSetAuthHeaders(); return useCallback(async ({ threadId, masgId, telegramUserId }) => { try { const client = getApiClient$1(); const response = await client.delete(`/chat_content?msg_id=${masgId}&thread_id=${threadId}&user_id=${telegramUserId}`); return response; } catch (error) { console.error("DELETE chat content request failed:", error); throw error; } }, []); } function useChatFeedQuery() { useSetAuthHeaders(); return useCallback(async ({ chatId, messageId, feedbackType, dislikeReason, originalMessage, telegramUserId }) => { try { const client = getApiClient$1(); const response = await client.post(`/feedback`, { user_id: telegramUserId, chat_id: chatId, message_id: messageId, feedback_type: feedbackType, dislike_reason: dislikeReason, original_message: originalMessage }); return response.data; } catch (error) { console.error("GET chat feed request failed:", error); throw error; } }, []); } function useGetChatRecommendationsQuery() { useSetAuthHeaders(); return useCallback(async ({ telegramUserId }) => { try { const client = getApiClient$1(); const response = await client.get(`/chat_recommendations?user_id=${telegramUserId}&count=5`); return response.data; } catch (error) { console.error("GET chat recommendations request failed:", error); throw error; } }, []); } function useUpdateChatOrderParamsQuery() { useSetAuthHeaders(); return useCallback(async ({ threadId, msgId, telegramUserId, orderParams }) => { try { const client = getApiClient$1(); const response = await client.put("/chat_order_params", { thread_id: threadId, msg_id: msgId, user_id: telegramUserId, order_params: orderParams }); return response.data; } catch (error) { console.error("PUT chat order params request failed:", error); throw error; } }, []); } const initialChatcacheState = { currentAiThreadId: "", searchSize: null, isShowVoiceTooltip: true }; const chatcacheActionHandlers = { setCurrentAiThreadIdAction: { action: (currentAiThreadId) => ({ type: RootActionType.CHAT_CACHE, payload: { actionType: "setCurrentAiThreadIdAction", data: currentAiThreadId } }), reducer: (state, data) => ({ ...state, currentAiThreadId: data }) }, setSearchSizeAction: { action: (searchSize) => ({ type: RootActionType.CHAT_CACHE, payload: { actionType: "setSearchSizeAction", data: searchSize } }), reducer: (state, data) => ({ ...state, searchSize: data }) }, loadAction: { action: (persistedState) => ({ type: RootActionType.CHAT_CACHE, payload: { actionType: "loadAction", data: persistedState } }), reducer: (state, data) => ({ ...state, ...data }) }, setIsShowVoiceTooltipAction: { action: (isShowVoiceTooltip) => ({ type: RootActionType.CHAT_CACHE, payload: { actionType: "setIsShowVoiceTooltipAction", data: isShowVoiceTooltip } }), reducer: (state, data) => ({ ...state, isShowVoiceTooltip: data }) }, resetAllAction: { action: () => ({ type: RootActionType.CHAT_CACHE, payload: { actionType: "resetAllAction", data: null } }), reducer: (state) => ({ ...state, currentAiThreadId: "", searchSize: null, isShowVoiceTooltip: true }) } }; const setCurrentAiThreadIdAction = chatcacheActionHandlers.setCurrentAiThreadIdAction.action; const setSearchSizeAction = chatcacheActionHandlers.setSearchSizeAction.action; const loadAction$1 = chatcacheActionHandlers.loadAction.action; function chatcacheReducer(state = initialChatcacheState, action) { if (!action.payload || !action.payload.actionType) { return state; } const handler = chatcacheActionHandlers[action.payload.actionType]; if (handler) { return handler.reducer(state, action.payload.data); } return state; } function useCurrentAiThreadId() { const { state, dispatch } = useWidget(); const currentAiThreadId = state.chatcache.currentAiThreadId; const setCurrentAiThreadId = useCallback((currentAiThreadId2) => { dispatch(setCurrentAiThreadIdAction(currentAiThreadId2)); }, [dispatch]); return [currentAiThreadId, setCurrentAiThreadId]; } function useSearchSize() { const { state, dispatch } = useWidget(); const searchSize = state.chatcache.searchSize; const setSearchSize = useCallback((searchSize2) => { dispatch(setSearchSizeAction(searchSize2)); }, [dispatch]); return [searchSize, setSearchSize]; } var ROLE_TYPE = /* @__PURE__ */ ((ROLE_TYPE2) => { ROLE_TYPE2["USER"] = "USER"; ROLE_TYPE2["ASSISTANT"] = "ASSISTANT"; return ROLE_TYPE2; })(ROLE_TYPE || {}); var STREAM_DATA_TYPE = /* @__PURE__ */ ((STREAM_DATA_TYPE2) => { STREAM_DATA_TYPE2["FINAL_ANSWER"] = "final_answer"; STREAM_DATA_TYPE2["TEMP"] = "temp"; STREAM_DATA_TYPE2["END_THINKING"] = "end_thinking"; STREAM_DATA_TYPE2["ERROR"] = "error"; STREAM_DATA_TYPE2["SOURCE_LIST_DETAILS"] = "source_list_details"; STREAM_DATA_TYPE2["ORDER_PARAMS"] = "order_params"; return STREAM_DATA_TYPE2; })(STREAM_DATA_TYPE || {}); function generateRandomString(length = 8) { const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; let result = ""; for (let i = 0; i < length; i++) { const randomIndex = Math.floor(Math.random() * chars.length); result += chars[randomIndex]; } return result; } function goOutPageDirect(url) { const _open = window.open(); if (_open) { _open.opener = null; _open.location = url; } } const getDomain = (url) => { if (!url) return ""; try { const urlObj = new URL(url.startsWith("http") ? url : `https://${url}`); const hostname = urlObj.hostname; const parts = hostname.split("."); if (parts.length >= 2) { return parts[parts.length - 2]; } return hostname; } catch { return ""; } }; const getFaviconUrl = (id) => { if (!id) return ["", ""]; try { const urlPattern = /(https?:\/\/[^\s?]+)/; const match = id.match(urlPattern); const url = match ? match[1] : id.split("?")[0]; const urlObj = new URL(url); const hostParts = urlObj.hostname.split("."); const mainDomain = hostParts.length >= 2 ? `${hostParts[hostParts.length - 2]}.${hostParts[hostParts.length - 1]}` : urlObj.hostname; const origin = `https://${mainDomain}`; return [origin, `https://www.google.com/s2/favicons?domain=${origin}&sz=32`]; } catch (e) { return ["", ""]; } }; const getCoinUrl = (symbol) => { return `https://oss.orderly.network/static/symbol_logo/${symbol}.png`; }; function getCutdownTextByMiliSeconds(cutdown) { let hours = Math.floor(cutdown / 36e5); let minutes = Math.floor((cutdown - hours * 36e5) / 6e4); let seconds = Math.floor((cutdown - hours * 36e5 - minutes * 6e4) / 1e3); hours = hours > 9 ? hours : `0${hours}`; minutes = minutes > 9 ? minutes : `0${minutes}`; seconds = seconds > 9 ? seconds : `0${seconds}`; return `${hours}:${minutes}:${seconds}`; } function formatNumber(num) { const value = Number(num); if (isNaN(value)) return "0"; const absValue = Math.abs(value); const sign = value < 0 ? "-" : ""; if (absValue >= 1e9) { return `${sign}${(absValue / 1e9).toFixed(2)}B`; } else if (absValue >= 1e6) { return `${sign}${(absValue / 1e6).toFixed(2)}M`; } else if (absValue >= 1e3) { return `${sign}${(absValue / 1e3).toFixed(2)}K`; } else { return `${sign}${absValue.toFixed(2)}`; } } function formatPriceWithTick(price, tick) { const value = Number(price); const tickValue = Number(tick); if (isNaN(value)) return "0"; if (isNaN(tickValue) || tickValue <= 0) return value.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 }); const decimals = Math.max(0, -Math.floor(Math.log10(tickValue))); return value.toLocaleString("en-US", { minimumFractionDigits: decimals, maximumFractionDigits: decimals }); } const initialChatState = { visible: false, disabled: false, aiResponseContentList: [], tempAiContentData: { id: "", feedback: null, role: ROLE_TYPE.ASSISTANT, thoughtContentList: [], sourceListDetails: [], content: "", timestamp: 0, agentRecommendationList: [] }, isFocus: false, inputValue: "", isLoadingData: false, isChatModalOpen: false, isRenderingData: false, threadsList: [], currentLoadingThreadId: "", currentRenderingId: "", isAnalyzeContent: false, analyzeContentList: [], currentAiContentDeepThinkData: { id: "", feedback: null, role: ROLE_TYPE.ASSISTANT, thoughtContentList: [], sourceListDetails: [], content: "", timestamp: 0, agentRecommendationList: [] }, chatRecommendationList: [], isShowThreadList: false, isShowDeepThinkSources: false, isShowDeepThink: false, isRecording: false, isHandleRecord: false, realtimeText: "", userSetting: { searchbarShortcut: "", voiceShortcut: "" }, shouldTriggerVoiceRecording: false }; const chatActionHandlers = { setVisibleAction: { action: (visible) => ({ type: RootActionType.CHAT, payload: { actionType: "setVisibleAction", data: visible } }), reducer: (state, data) => ({ ...state, visible: data }) }, setIsChatModalOpenAction: { action: (isChatModalOpen) => ({ type: RootActionType.CHAT, payload: { actionType: "setIsChatModalOpenAction", data: isChatModalOpen } }), reducer: (state, data) => ({ ...state, isChatModalOpen: data }) }, setDisabledAction: { action: (disabled) => ({ type: RootActionType.CHAT, payload: { actionType: "setDisabledAction", data: disabled } }), reducer: (state, data) => ({ ...state, disabled: data }) }, getAiSteamDataAction: { action: (aiSteamData) => ({ type: RootActionType.CHAT, payload: { actionType: "getAiSteamDataAction", data: aiSteamData } }), reducer: (state, data) => { const tempAiContentData = state.tempAiContentData; const { id, type, content } = data; const newState = { ...state }; if (type === STREAM_DATA_TYPE.ERROR) { newState.tempAiContentData = { id, thoughtContentList: [], sourceListDetails: [], content: tempAiContentData.content + content, feedback: null, role: ROLE_TYPE.ASSISTANT, timestamp: (/* @__PURE__ */ new Date()).getTime(), agentRecommendationList: [] }; } else { if (tempAiContentData.id !== id) { if (type === STREAM_DATA_TYPE.TEMP) { const data2 = JSON.parse(content); newState.tempAiContentData = { id, feedback: null, thoughtContentList: tempAiContentData.thoughtContentList.concat({ id: data2.id, tool_name: data2.tool_name, tool_type: data2.tool_type, tool_description: data2.description }), sourceListDetails: tempAiContentData.sourceListDetails, content: tempAiContentData.content ? tempAiContentData.content : "", role: ROLE_TYPE.ASSISTANT, timestamp: (/* @__PURE__ */ new Date()).getTime(), agentRecommendationList: [] }; } else if (type === STREAM_DATA_TYPE.SOURCE_LIST_DETAILS) { const list = JSON.parse(content); newState.tempAiContentData = { id, feedback: null, thoughtContentList: tempAiContentData.thoughtContentList, sourceListDetails: list, content: tempAiContentData.content, role: ROLE_TYPE.ASSISTANT, timestamp: (/* @__PURE__ */ new Date()).getTime(), agentRecommendationList: [] }; } else if (type === STREAM_DATA_TYPE.FINAL_ANSWER) { newState.tempAiContentData = { id, feedback: null, thoughtContentList: tempAiContentData.thoughtContentList, sourceListDetails: tempAiContentData.sourceListDetails, content, role: ROLE_TYPE.ASSISTANT, timestamp: (/* @__PURE__ */ new Date()).getTime(), agentRecommendationList: [] }; } } else { if (type === STREAM_DATA_TYPE.TEMP) { const data2 = JSON.parse(content); const { tool_name, tool_type, description, id: id2 } = data2; const isExist = tempAiContentData.thoughtContentList.some((item) => item.id === id2); let newThoughtContentList = [...tempAiContentData.thoughtContentList]; if (isExist) { newThoughtContentList = newThoughtContentList.map((item) => { if (item.id === id2) { return { ...item, tool_description: item.tool_description + description }; } return item; }); } else { newThoughtContentList.push({ id: id2, tool_name, tool_type, tool_description: description }); } newState.tempAiContentData = { ...tempAiContentData, thoughtContentList: newThoughtContentList }; } else if (type === STREAM_DATA_TYPE.SOURCE_LIST_DETAILS) { const list = JSON.parse(content); const newSourceListDetails = tempAiContentData.sourceListDetails.concat(list); newState.tempAiContentData = { ...tempAiContentData, sourceListDetails: newSourceListDetails }; } else if (type === STREAM_DATA_TYPE.FINAL_ANSWER) { const newContent = tempAiContentData.content + content; newState.tempAiContentData = { ...tempAiContentData, content: newContent }; } } } return newState; } }, combineResponseDataAction: { action: () => ({ type: RootActionType.CHAT, payload: { actionType: "combineResponseDataAction", data: null } }), reducer: (state) => { const newState = { ...state }; const tempAiContentData = { ...state.tempAiContentData, extraData: { done: true } }; if (!tempAiContentData.id) { tempAiContentData.id = String(generateRandomString()); } newState.aiResponseContentList.push(tempAiContentData); newState.tempAiContentData = initialChatState.tempAiContentData; return newState; } }, changeAiResponseContentListAction: { action: (aiResponseContentList) => ({ type: RootActionType.CHAT, payload: { actionType: "changeAiResponseContentListAction", data: aiResponseContentList } }), reducer: (state, data) => { return { ...state, aiResponseContentList: data }; } }, changeIsFocusAction: { action: (isFocus) => ({ type: RootActionType.CHAT, payload: { actionType: "changeIsFocusAction", data: isFocus } }), reducer: (state, data) => ({ ...state, isFocus: data }) }, changeInputValueAction: { action: (inputValue) => ({ type: RootActionType.CHAT, payload: { actionType: "changeInputValueAction", data: inputValue } }), reducer: (state, data) => ({ ...state, inputValue: data }) }, changeIsLoadingDataAction: { action: (isLoadingData) => ({ type: RootActionType.CHAT, payload: { actionType: "changeIsLoadingDataAction", data: isLoadingData } }), reducer: (state, data) => ({ ...state, isLoadingData: data }) }, changeIsRenderingDataAction: { action: (isRenderingData) => ({ type: RootActionType.CHAT, payload: { actionType: "changeIsRenderingDataAction", data: isRenderingData } }), reducer: (state, data) => ({ ...state, isRenderingData: data }) }, changeThreadsListAction: { action: (threadsList) => ({ type: RootActionType.CHAT, payload: { actionType: "changeThreadsListAction", data: threadsList } }), reducer: (state, data) => ({ ...state, threadsList: data }) }, changeCurrentRenderingIdAction: { action: (currentRenderingId) => ({ type: RootActionType.CHAT, payload: { actionType: "changeCurrentRenderingIdAction", data: currentRenderingId } }), reducer: (state, data) => ({ ...state, currentRenderingId: data }) }, changeCurrentLoadingThreadIdAction: { action: (currentLoadingThreadId) => ({ type: RootActionType.CHAT, payload: { actionType: "changeCurrentLoadingThreadIdAction", data: currentLoadingThreadId } }), reducer: (state, data) => ({ ...state, currentLoadingThreadId: data }) }, resetTempAiContentDataAction: { action: () => ({ type: RootActionType.CHAT, payload: { actionType: "resetTempAiContentDataAction", data: null } }), reducer: (state) => ({ ...state, tempAiContentData: initialChatState.tempAiContentData }) }, changeIsAnalyzeContentAction: { action: (isAnalyzeContent) => ({ type: RootActionType.CHAT, payload: { actionType: "changeIsAnalyzeContentAction", data: isAnalyzeContent } }), reducer: (state, data) => ({ ...state, isAnalyzeContent: data }) }, changeAnalyzeContentListAction: { action: (analyzeContentList) => ({ type: RootActionType.CHAT, payload: { actionType: "changeAnalyzeContentListAction", data: analyzeContentList } }), reducer: (state, data) => ({ ...state, analyzeContentList: data }) }, changeCurrentAiContentDeepThinkDataAction: { action: (currentAiContentDeepThinkData) => ({ type: RootActionType.CHAT, payload: { actionType: "changeCurrentAiContentDeepThinkDataAction", data: currentAiContentDeepThinkData } }), reducer: (state, data) => ({ ...state, currentAiContentDeepThinkData: data }) }, changeChatRecommendationListAction: { action: (chatRecommendationList) => ({ type: RootActionType.CHAT, payload: { actionType: "changeChatRecommendationListAction", data: chatRecommendationList } }), reducer: (state, data) => ({ ...state, chatRecommendationList: data }) }, changeIsShowThreadListAction: { action: (isShowThreadList) => ({ type: RootActionType.CHAT, payload: { actionType: "changeIsShowThreadListAction", data: isShowThreadList } }), reducer: (state, data) => ({