mirror of https://github.com/Mai-with-u/MaiBot.git
Merge branch 'dev' of https://github.com/Mai-with-u/MaiBot into dev
commit
08ce18e0f4
|
|
@ -2,8 +2,7 @@ name: Docker Build and Push (Dev)
|
|||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
# push:
|
||||
- cron: '0 0 * * *' # every day at midnight UTC
|
||||
# branches:
|
||||
# - dev
|
||||
workflow_dispatch: # 允许手动触发工作流
|
||||
|
|
@ -28,11 +27,11 @@ jobs:
|
|||
fetch-depth: 0
|
||||
|
||||
# Clone required dependencies
|
||||
- name: Clone maim_message
|
||||
run: git clone https://github.com/MaiM-with-u/maim_message maim_message
|
||||
# - name: Clone maim_message
|
||||
# run: git clone https://github.com/MaiM-with-u/maim_message maim_message
|
||||
|
||||
- name: Clone lpmm
|
||||
run: git clone https://github.com/MaiM-with-u/MaiMBot-LPMM.git MaiMBot-LPMM
|
||||
run: git clone https://github.com/Mai-with-u/MaiMBot-LPMM.git MaiMBot-LPMM
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
|
@ -82,11 +81,11 @@ jobs:
|
|||
fetch-depth: 0
|
||||
|
||||
# Clone required dependencies
|
||||
- name: Clone maim_message
|
||||
run: git clone https://github.com/MaiM-with-u/maim_message maim_message
|
||||
# - name: Clone maim_message
|
||||
# run: git clone https://github.com/MaiM-with-u/maim_message maim_message
|
||||
|
||||
- name: Clone lpmm
|
||||
run: git clone https://github.com/MaiM-with-u/MaiMBot-LPMM.git MaiMBot-LPMM
|
||||
run: git clone https://github.com/Mai-with-u/MaiMBot-LPMM.git MaiMBot-LPMM
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
|
@ -147,8 +146,8 @@ jobs:
|
|||
with:
|
||||
images: ${{ secrets.DOCKERHUB_USERNAME }}/maibot
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=sha,prefix=${{ github.ref_name }}-,enable=${{ github.ref_type == 'branch' }}
|
||||
type=raw,value=dev
|
||||
type=schedule,pattern=dev-{{date 'YYMMDD'}}
|
||||
|
||||
- name: Create and Push Manifest
|
||||
run: |
|
||||
|
|
|
|||
|
|
@ -31,11 +31,11 @@ jobs:
|
|||
fetch-depth: 0
|
||||
|
||||
# Clone required dependencies
|
||||
- name: Clone maim_message
|
||||
run: git clone https://github.com/MaiM-with-u/maim_message maim_message
|
||||
# - name: Clone maim_message
|
||||
# run: git clone https://github.com/MaiM-with-u/maim_message maim_message
|
||||
|
||||
- name: Clone lpmm
|
||||
run: git clone https://github.com/MaiM-with-u/MaiMBot-LPMM.git MaiMBot-LPMM
|
||||
run: git clone https://github.com/Mai-with-u/MaiMBot-LPMM.git MaiMBot-LPMM
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
|
@ -84,11 +84,11 @@ jobs:
|
|||
fetch-depth: 0
|
||||
|
||||
# Clone required dependencies
|
||||
- name: Clone maim_message
|
||||
run: git clone https://github.com/MaiM-with-u/maim_message maim_message
|
||||
# - name: Clone maim_message
|
||||
# run: git clone https://github.com/MaiM-with-u/maim_message maim_message
|
||||
|
||||
- name: Clone lpmm
|
||||
run: git clone https://github.com/MaiM-with-u/MaiMBot-LPMM.git MaiMBot-LPMM
|
||||
run: git clone https://github.com/Mai-with-u/MaiMBot-LPMM.git MaiMBot-LPMM
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
|
|
|||
|
|
@ -271,7 +271,7 @@ def _to_emoji_objects(data: Any) -> Tuple[List["MaiEmoji"], int]:
|
|||
|
||||
emoji.description = emoji_data.description
|
||||
# Deserialize emotion string from DB to list
|
||||
emoji.emotion = emoji_data.emotion.split(",") if emoji_data.emotion else []
|
||||
emoji.emotion = emoji_data.emotion.replace(",",",").split(",") if emoji_data.emotion else []
|
||||
emoji.usage_count = emoji_data.usage_count
|
||||
|
||||
db_last_used_time = emoji_data.last_used_time
|
||||
|
|
@ -732,7 +732,7 @@ class EmojiManager:
|
|||
emoji_record = Emoji.get_or_none(Emoji.emoji_hash == emoji_hash)
|
||||
if emoji_record and emoji_record.emotion:
|
||||
logger.info(f"[缓存命中] 从数据库获取表情包情感标签: {emoji_record.emotion[:50]}...")
|
||||
return emoji_record.emotion.split(",")
|
||||
return emoji_record.emotion.replace(",",",").split(",")
|
||||
except Exception as e:
|
||||
logger.error(f"从数据库查询表情包情感标签时出错: {e}")
|
||||
|
||||
|
|
@ -993,7 +993,7 @@ class EmojiManager:
|
|||
)
|
||||
|
||||
# 处理情感列表
|
||||
emotions = [e.strip() for e in emotions_text.split(",") if e.strip()]
|
||||
emotions = [e.strip() for e in emotions_text.replace(",",",").split(",") if e.strip()]
|
||||
|
||||
# 根据情感标签数量随机选择 - 超过5个选3个,超过2个选2个
|
||||
if len(emotions) > 5:
|
||||
|
|
|
|||
|
|
@ -40,6 +40,90 @@ def is_webui_virtual_group(group_id: str) -> bool:
|
|||
return group_id and group_id.startswith(VIRTUAL_GROUP_ID_PREFIX)
|
||||
|
||||
|
||||
def parse_message_segments(segment) -> list:
|
||||
"""解析消息段,转换为 WebUI 可用的格式
|
||||
|
||||
参考 NapCat 适配器的消息解析逻辑
|
||||
|
||||
Args:
|
||||
segment: Seg 消息段对象
|
||||
|
||||
Returns:
|
||||
list: 消息段列表,每个元素为 {"type": "...", "data": ...}
|
||||
"""
|
||||
from maim_message import Seg
|
||||
|
||||
result = []
|
||||
|
||||
if segment is None:
|
||||
return result
|
||||
|
||||
if segment.type == "seglist":
|
||||
# 处理消息段列表
|
||||
if segment.data:
|
||||
for seg in segment.data:
|
||||
result.extend(parse_message_segments(seg))
|
||||
elif segment.type == "text":
|
||||
# 文本消息
|
||||
if segment.data:
|
||||
result.append({"type": "text", "data": segment.data})
|
||||
elif segment.type == "image":
|
||||
# 图片消息(base64)
|
||||
if segment.data:
|
||||
result.append({"type": "image", "data": f"data:image/png;base64,{segment.data}"})
|
||||
elif segment.type == "emoji":
|
||||
# 表情包消息(base64)
|
||||
if segment.data:
|
||||
result.append({"type": "emoji", "data": f"data:image/gif;base64,{segment.data}"})
|
||||
elif segment.type == "imageurl":
|
||||
# 图片链接消息
|
||||
if segment.data:
|
||||
result.append({"type": "image", "data": segment.data})
|
||||
elif segment.type == "face":
|
||||
# 原生表情
|
||||
result.append({"type": "face", "data": segment.data})
|
||||
elif segment.type == "voice":
|
||||
# 语音消息(base64)
|
||||
if segment.data:
|
||||
result.append({"type": "voice", "data": f"data:audio/wav;base64,{segment.data}"})
|
||||
elif segment.type == "voiceurl":
|
||||
# 语音链接
|
||||
if segment.data:
|
||||
result.append({"type": "voice", "data": segment.data})
|
||||
elif segment.type == "video":
|
||||
# 视频消息(base64)
|
||||
if segment.data:
|
||||
result.append({"type": "video", "data": f"data:video/mp4;base64,{segment.data}"})
|
||||
elif segment.type == "videourl":
|
||||
# 视频链接
|
||||
if segment.data:
|
||||
result.append({"type": "video", "data": segment.data})
|
||||
elif segment.type == "music":
|
||||
# 音乐消息
|
||||
result.append({"type": "music", "data": segment.data})
|
||||
elif segment.type == "file":
|
||||
# 文件消息
|
||||
result.append({"type": "file", "data": segment.data})
|
||||
elif segment.type == "reply":
|
||||
# 回复消息
|
||||
result.append({"type": "reply", "data": segment.data})
|
||||
elif segment.type == "forward":
|
||||
# 转发消息
|
||||
forward_items = []
|
||||
if segment.data:
|
||||
for item in segment.data:
|
||||
forward_items.append({
|
||||
"content": parse_message_segments(item.get("message_segment", {})) if isinstance(item, dict) else []
|
||||
})
|
||||
result.append({"type": "forward", "data": forward_items})
|
||||
else:
|
||||
# 未知类型,尝试作为文本处理
|
||||
if segment.data:
|
||||
result.append({"type": "unknown", "original_type": segment.type, "data": str(segment.data)})
|
||||
|
||||
return result
|
||||
|
||||
|
||||
async def _send_message(message: MessageSending, show_log=True) -> bool:
|
||||
"""合并后的消息发送函数,包含WS发送和日志记录"""
|
||||
message_preview = truncate_message(message.processed_plain_text, max_length=200)
|
||||
|
|
@ -56,11 +140,25 @@ async def _send_message(message: MessageSending, show_log=True) -> bool:
|
|||
import time
|
||||
from src.config.config import global_config
|
||||
|
||||
# 解析消息段,获取富文本内容
|
||||
message_segments = parse_message_segments(message.message_segment)
|
||||
|
||||
# 判断消息类型
|
||||
# 如果只有一个文本段,使用简单的 text 类型
|
||||
# 否则使用 rich 类型,包含完整的消息段
|
||||
if len(message_segments) == 1 and message_segments[0].get("type") == "text":
|
||||
message_type = "text"
|
||||
segments = None
|
||||
else:
|
||||
message_type = "rich"
|
||||
segments = message_segments
|
||||
|
||||
await chat_manager.broadcast(
|
||||
{
|
||||
"type": "bot_message",
|
||||
"content": message.processed_plain_text,
|
||||
"message_type": "text",
|
||||
"message_type": message_type,
|
||||
"segments": segments, # 富文本消息段
|
||||
"timestamp": time.time(),
|
||||
"group_id": group_id, # 包含群 ID 以便前端区分不同的聊天标签
|
||||
"sender": {
|
||||
|
|
|
|||
|
|
@ -143,10 +143,14 @@ def _convert_tool_options(tool_options: list[ToolOption]) -> list[FunctionDeclar
|
|||
:param tool_option_param: 工具参数对象
|
||||
:return: 转换后的工具参数字典
|
||||
"""
|
||||
# JSON Schema要求使用"boolean"而不是"bool"
|
||||
# JSON Schema 类型名称修正:
|
||||
# - 布尔类型使用 "boolean" 而不是 "bool"
|
||||
# - 浮点数使用 "number" 而不是 "float"
|
||||
param_type_value = tool_option_param.param_type.value
|
||||
if param_type_value == "bool":
|
||||
param_type_value = "boolean"
|
||||
elif param_type_value == "float":
|
||||
param_type_value = "number"
|
||||
|
||||
return_dict: dict[str, Any] = {
|
||||
"type": param_type_value,
|
||||
|
|
|
|||
|
|
@ -118,10 +118,14 @@ def _convert_tool_options(tool_options: list[ToolOption]) -> list[dict[str, Any]
|
|||
:param tool_option_param: 工具参数对象
|
||||
:return: 转换后的工具参数字典
|
||||
"""
|
||||
# JSON Schema要求使用"boolean"而不是"bool"
|
||||
# JSON Schema 类型名称修正:
|
||||
# - 布尔类型使用 "boolean" 而不是 "bool"
|
||||
# - 浮点数使用 "number" 而不是 "float"
|
||||
param_type_value = tool_option_param.param_type.value
|
||||
if param_type_value == "bool":
|
||||
param_type_value = "boolean"
|
||||
elif param_type_value == "float":
|
||||
param_type_value = "number"
|
||||
|
||||
return_dict: dict[str, Any] = {
|
||||
"type": param_type_value,
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,4 +1,4 @@
|
|||
import{r as c,R as P,b as Oe}from"./router-CWhjJi2n.js";function Rn(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return c.useMemo(()=>r=>{t.forEach(o=>o(r))},t)}const et=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function me(e){const t=Object.prototype.toString.call(e);return t==="[object Window]"||t==="[object global]"}function pt(e){return"nodeType"in e}function B(e){var t,n;return e?me(e)?e:pt(e)&&(t=(n=e.ownerDocument)==null?void 0:n.defaultView)!=null?t:window:window}function bt(e){const{Document:t}=B(e);return e instanceof t}function Be(e){return me(e)?!1:e instanceof B(e).HTMLElement}function Ut(e){return e instanceof B(e).SVGElement}function ye(e){return e?me(e)?e.document:pt(e)?bt(e)?e:Be(e)||Ut(e)?e.ownerDocument:document:document:document}const Q=et?c.useLayoutEffect:c.useEffect;function wt(e){const t=c.useRef(e);return Q(()=>{t.current=e}),c.useCallback(function(){for(var n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return t.current==null?void 0:t.current(...r)},[])}function Sn(){const e=c.useRef(null),t=c.useCallback((r,o)=>{e.current=setInterval(r,o)},[]),n=c.useCallback(()=>{e.current!==null&&(clearInterval(e.current),e.current=null)},[]);return[t,n]}function ke(e,t){t===void 0&&(t=[e]);const n=c.useRef(e);return Q(()=>{n.current!==e&&(n.current=e)},t),n}function Fe(e,t){const n=c.useRef();return c.useMemo(()=>{const r=e(n.current);return n.current=r,r},[...t])}function Ge(e){const t=wt(e),n=c.useRef(null),r=c.useCallback(o=>{o!==n.current&&t?.(o,n.current),n.current=o},[]);return[n,r]}function dt(e){const t=c.useRef();return c.useEffect(()=>{t.current=e},[e]),t.current}let at={};function $e(e,t){return c.useMemo(()=>{if(t)return t;const n=at[e]==null?0:at[e]+1;return at[e]=n,e+"-"+n},[e,t])}function Wt(e){return function(t){for(var n=arguments.length,r=new Array(n>1?n-1:0),o=1;o<n;o++)r[o-1]=arguments[o];return r.reduce((i,s)=>{const a=Object.entries(s);for(const[l,u]of a){const f=i[l];f!=null&&(i[l]=f+e*u)}return i},{...t})}}const we=Wt(1),ze=Wt(-1);function En(e){return"clientX"in e&&"clientY"in e}function mt(e){if(!e)return!1;const{KeyboardEvent:t}=B(e.target);return t&&e instanceof t}function Mn(e){if(!e)return!1;const{TouchEvent:t}=B(e.target);return t&&e instanceof t}function ft(e){if(Mn(e)){if(e.touches&&e.touches.length){const{clientX:t,clientY:n}=e.touches[0];return{x:t,y:n}}else if(e.changedTouches&&e.changedTouches.length){const{clientX:t,clientY:n}=e.changedTouches[0];return{x:t,y:n}}}return En(e)?{x:e.clientX,y:e.clientY}:null}const Je=Object.freeze({Translate:{toString(e){if(!e)return;const{x:t,y:n}=e;return"translate3d("+(t?Math.round(t):0)+"px, "+(n?Math.round(n):0)+"px, 0)"}},Scale:{toString(e){if(!e)return;const{scaleX:t,scaleY:n}=e;return"scaleX("+t+") scaleY("+n+")"}},Transform:{toString(e){if(e)return[Je.Translate.toString(e),Je.Scale.toString(e)].join(" ")}},Transition:{toString(e){let{property:t,duration:n,easing:r}=e;return t+" "+n+"ms "+r}}}),Ot="a,frame,iframe,input:not([type=hidden]):not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),*[tabindex]";function In(e){return e.matches(Ot)?e:e.querySelector(Ot)}const An={display:"none"};function On(e){let{id:t,value:n}=e;return P.createElement("div",{id:t,style:An},n)}function Tn(e){let{id:t,announcement:n,ariaLiveType:r="assertive"}=e;const o={position:"fixed",top:0,left:0,width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0 0 0 0)",clipPath:"inset(100%)",whiteSpace:"nowrap"};return P.createElement("div",{id:t,style:o,role:"status","aria-live":r,"aria-atomic":!0},n)}function Nn(){const[e,t]=c.useState("");return{announce:c.useCallback(r=>{r!=null&&t(r)},[]),announcement:e}}const Ht=c.createContext(null);function Ln(e){const t=c.useContext(Ht);c.useEffect(()=>{if(!t)throw new Error("useDndMonitor must be used within a children of <DndContext>");return t(e)},[e,t])}function kn(){const[e]=c.useState(()=>new Set),t=c.useCallback(r=>(e.add(r),()=>e.delete(r)),[e]);return[c.useCallback(r=>{let{type:o,event:i}=r;e.forEach(s=>{var a;return(a=s[o])==null?void 0:a.call(s,i)})},[e]),t]}const zn={draggable:`
|
||||
import{r as c,R as P,b as Oe}from"./router-Bz250laD.js";function Rn(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return c.useMemo(()=>r=>{t.forEach(o=>o(r))},t)}const et=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function me(e){const t=Object.prototype.toString.call(e);return t==="[object Window]"||t==="[object global]"}function pt(e){return"nodeType"in e}function B(e){var t,n;return e?me(e)?e:pt(e)&&(t=(n=e.ownerDocument)==null?void 0:n.defaultView)!=null?t:window:window}function bt(e){const{Document:t}=B(e);return e instanceof t}function Be(e){return me(e)?!1:e instanceof B(e).HTMLElement}function Ut(e){return e instanceof B(e).SVGElement}function ye(e){return e?me(e)?e.document:pt(e)?bt(e)?e:Be(e)||Ut(e)?e.ownerDocument:document:document:document}const Q=et?c.useLayoutEffect:c.useEffect;function wt(e){const t=c.useRef(e);return Q(()=>{t.current=e}),c.useCallback(function(){for(var n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];return t.current==null?void 0:t.current(...r)},[])}function Sn(){const e=c.useRef(null),t=c.useCallback((r,o)=>{e.current=setInterval(r,o)},[]),n=c.useCallback(()=>{e.current!==null&&(clearInterval(e.current),e.current=null)},[]);return[t,n]}function ke(e,t){t===void 0&&(t=[e]);const n=c.useRef(e);return Q(()=>{n.current!==e&&(n.current=e)},t),n}function Fe(e,t){const n=c.useRef();return c.useMemo(()=>{const r=e(n.current);return n.current=r,r},[...t])}function Ge(e){const t=wt(e),n=c.useRef(null),r=c.useCallback(o=>{o!==n.current&&t?.(o,n.current),n.current=o},[]);return[n,r]}function dt(e){const t=c.useRef();return c.useEffect(()=>{t.current=e},[e]),t.current}let at={};function $e(e,t){return c.useMemo(()=>{if(t)return t;const n=at[e]==null?0:at[e]+1;return at[e]=n,e+"-"+n},[e,t])}function Wt(e){return function(t){for(var n=arguments.length,r=new Array(n>1?n-1:0),o=1;o<n;o++)r[o-1]=arguments[o];return r.reduce((i,s)=>{const a=Object.entries(s);for(const[l,u]of a){const f=i[l];f!=null&&(i[l]=f+e*u)}return i},{...t})}}const we=Wt(1),ze=Wt(-1);function En(e){return"clientX"in e&&"clientY"in e}function mt(e){if(!e)return!1;const{KeyboardEvent:t}=B(e.target);return t&&e instanceof t}function Mn(e){if(!e)return!1;const{TouchEvent:t}=B(e.target);return t&&e instanceof t}function ft(e){if(Mn(e)){if(e.touches&&e.touches.length){const{clientX:t,clientY:n}=e.touches[0];return{x:t,y:n}}else if(e.changedTouches&&e.changedTouches.length){const{clientX:t,clientY:n}=e.changedTouches[0];return{x:t,y:n}}}return En(e)?{x:e.clientX,y:e.clientY}:null}const Je=Object.freeze({Translate:{toString(e){if(!e)return;const{x:t,y:n}=e;return"translate3d("+(t?Math.round(t):0)+"px, "+(n?Math.round(n):0)+"px, 0)"}},Scale:{toString(e){if(!e)return;const{scaleX:t,scaleY:n}=e;return"scaleX("+t+") scaleY("+n+")"}},Transform:{toString(e){if(e)return[Je.Translate.toString(e),Je.Scale.toString(e)].join(" ")}},Transition:{toString(e){let{property:t,duration:n,easing:r}=e;return t+" "+n+"ms "+r}}}),Ot="a,frame,iframe,input:not([type=hidden]):not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),*[tabindex]";function In(e){return e.matches(Ot)?e:e.querySelector(Ot)}const An={display:"none"};function On(e){let{id:t,value:n}=e;return P.createElement("div",{id:t,style:An},n)}function Tn(e){let{id:t,announcement:n,ariaLiveType:r="assertive"}=e;const o={position:"fixed",top:0,left:0,width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0 0 0 0)",clipPath:"inset(100%)",whiteSpace:"nowrap"};return P.createElement("div",{id:t,style:o,role:"status","aria-live":r,"aria-atomic":!0},n)}function Nn(){const[e,t]=c.useState("");return{announce:c.useCallback(r=>{r!=null&&t(r)},[]),announcement:e}}const Ht=c.createContext(null);function Ln(e){const t=c.useContext(Ht);c.useEffect(()=>{if(!t)throw new Error("useDndMonitor must be used within a children of <DndContext>");return t(e)},[e,t])}function kn(){const[e]=c.useState(()=>new Set),t=c.useCallback(r=>(e.add(r),()=>e.delete(r)),[e]);return[c.useCallback(r=>{let{type:o,event:i}=r;e.forEach(s=>{var a;return(a=s[o])==null?void 0:a.call(s,i)})},[e]),t]}const zn={draggable:`
|
||||
To pick up a draggable item, press the space bar.
|
||||
While dragging, use the arrow keys to move the item.
|
||||
Press space again to drop the item in its new position, or press escape to cancel.
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -7,21 +7,21 @@
|
|||
<link rel="icon" type="image/x-icon" href="/maimai.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>MaiBot Dashboard</title>
|
||||
<script type="module" crossorigin src="/assets/index-DHIER1DT.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/assets/react-vendor-Dtc2IqVY.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/router-CWhjJi2n.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/utils-CCeOswSm.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/radix-core-C3XKqQJw.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/radix-extra-DnIxMvW0.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/charts-Dhri-zxi.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/icons-BusT0Ku_.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/codemirror-BHeANvwm.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/misc-DyBU7ISD.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/dnd-Dyi3CnuX.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/uppy-DUr9_tfX.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/markdown-A1ShuLvG.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/reactflow-B3n3_Vkw.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DrsALSzA.css">
|
||||
<script type="module" crossorigin src="/assets/index-CgxOYrz-.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/assets/react-vendor-BmxF9s7Q.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/router-Bz250laD.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/utils-BXc2jIuz.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/radix-core-9dEfQl-6.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/radix-extra-DDK-u9dm.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/charts-DbiuC1q1.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/icons-CwAZotQh.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/codemirror-BEE0n9kQ.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/misc-CKjrIrIJ.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/dnd-CHfCzWUK.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/reactflow-DLoXAt4c.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/uppy-BMZiFQyG.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/markdown-kUhwkcQP.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-CWjV9Ftw.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root" class="notranslate"></div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue