Files
GenericAgent/frontends/desktop/static/index.html
T

515 lines
31 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>GenericAgent</title>
<link rel="stylesheet" href="styles.css?v=72">
<!-- KaTeX: LaTeX 公式渲染 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css" crossorigin="anonymous">
<!-- highlight.js: 代码高亮 -->
<link id="hljs-theme" rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/styles/github.min.css" crossorigin="anonymous">
<!-- DEV 脚手架(标注模式):删本行 + 下方 annot.js 一行即可彻底移除 -->
<link rel="stylesheet" href="annot.css">
<script>
(function(){
var t=localStorage.getItem('ga_theme'); if(t) document.documentElement.dataset.theme=t;
var l=localStorage.getItem('ga_lang'); if(l==='en') document.documentElement.lang='en';
var legacy=localStorage.getItem('ga_style');
var app=localStorage.getItem('ga_appearance');
if(!app&&legacy){
if(legacy==='dark') app='dark';
else{ app='light'; if(legacy==='classic') localStorage.setItem('ga_plain','1'); }
localStorage.setItem('ga_appearance',app);
localStorage.removeItem('ga_style');
}
app=app||'light';
document.documentElement.dataset.appearance=app;
if(app==='light'&&localStorage.getItem('ga_plain')==='1') document.documentElement.dataset.plain='1';
var LEGACY_FONT={sm:12,md:14,lg:16};
function chatFontPx(v){
if(v&&LEGACY_FONT[v]) return LEGACY_FONT[v];
var n=parseInt(v,10); if(!isNaN(n)&&n>=10&&n<=20) return n;
return 14;
}
var fs=localStorage.getItem('ga_font_size');
var cfp=chatFontPx(fs);
document.documentElement.dataset.chatFont=String(cfp);
document.documentElement.style.setProperty('--chat-font',cfp+'px');
var hljs=document.getElementById('hljs-theme');
if(hljs&&app==='dark') hljs.href='https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/styles/github-dark.min.css';
try{ var sraw=localStorage.getItem('ga_sessions'); if(sraw && JSON.parse(sraw).length) document.documentElement.dataset.bootHasSessions='1'; }catch(_){}
})();
</script>
</head>
<body>
<div id="app">
<div class="body">
<!-- ① 左侧边栏 -->
<aside class="sidebar">
<div class="brand">
<div class="brand-logo">GA</div>
<div class="brand-text">
<div class="brand-name">GenericAgent</div>
<div class="brand-sub" data-i18n="brand.sub"></div>
</div>
</div>
<nav class="nav" id="nav">
<a class="nav-item active" data-page="chat">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.4 8.4 0 0 1-8.5 8.5 8.4 8.4 0 0 1-3.8-.9L3 21l1.9-5.7A8.4 8.4 0 0 1 3.5 11.5 8.5 8.5 0 0 1 12 3a8.5 8.5 0 0 1 9 8.5z"/></svg>
<span data-i18n="nav.chat"></span>
</a>
<a class="nav-item" data-page="channels">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 3 21 3 21 8"/><line x1="4" y1="20" x2="21" y2="3"/><polyline points="21 16 21 21 16 21"/><line x1="15" y1="15" x2="21" y2="21"/><line x1="4" y1="4" x2="9" y2="9"/></svg>
<span data-i18n="nav.channels"></span>
</a>
<a class="nav-item" data-page="status">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="6" y1="20" x2="6" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="18" y1="20" x2="18" y2="14"/></svg>
<span data-i18n="nav.status"></span>
</a>
<a class="nav-item" data-page="collab">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
<span data-i18n="nav.collab"></span>
<span id="collab-badge" class="collab-nav-badge" hidden></span>
</a>
<a class="nav-item" data-page="token">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v10M9.5 9.6c0-1 1.1-1.7 2.5-1.7s2.5.7 2.5 1.7-1.1 1.5-2.5 1.5-2.5.7-2.5 1.7 1.1 1.8 2.5 1.8 2.5-.7 2.5-1.7"/></svg>
<span data-i18n="nav.token"></span>
</a>
</nav>
<div class="sidebar-foot">
<a class="foot-row" id="settings-btn">
<span class="fr-l">
<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
<span data-i18n="foot.settings"></span>
</span>
<svg class="chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>
</a>
<div class="foot-ver" data-i18n="foot.ver"></div>
</div>
</aside>
<div class="sb-resize" id="sb-resize"></div>
<button class="sb-toggle" id="sb-toggle" aria-label="toggle sidebar">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
</button>
<!-- 中间主区 -->
<main class="main">
<div class="topbar">
<div class="tb-left">
<button class="run-state" id="run-toggle"
>
<i class="dot"></i> <span class="rs-label"></span>
</button>
</div>
</div>
<div id="pages">
<!-- 聊天 -->
<section class="page active" data-page="chat"
>
<div class="msg-area">
<div class="chat-start">
<div class="feature-head">
<div class="page-title" data-i18n="chat.startTitle"></div>
<div class="page-sub" data-i18n="chat.startSub"></div>
</div>
<div class="feature-grid"></div>
</div>
<div class="msg-loading" id="msg-loading" hidden aria-live="polite">
<span class="ga-spin" aria-hidden="true"></span>
<span data-i18n="chat.interrupting"></span>
</div>
</div>
<div class="composer">
<div class="composer-top">
<button class="ic-btn" id="upload-btn" data-i18n-title="upload.button" title="">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.44 11.05 12 20.5a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"/></svg>
</button>
<button class="ic-btn" id="preset-btn">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 10 14 9 22 21 10 14 10 13 2"/></svg>
</button>
</div>
<textarea class="input" data-i18n-ph="composer.placeholder" placeholder=""></textarea>
<input type="file" id="img-input" multiple hidden>
<div class="thumb-strip" id="thumb-strip" hidden></div>
<div class="composer-bot">
<div class="cb-left">
<button class="chip" id="model-chip" data-i18n-title="model.menuLabel" title=""><span class="model-name"></span> <svg class="chip-ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg></button>
<button class="chip sm" id="plan-chip"><span data-i18n="chip.plan"></span></button>
<button class="chip sm" id="auto-chip">
<svg class="chip-ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 10 14 9 22 21 10 14 10 13 2"/></svg>
<span data-i18n="chip.auto"></span>
</button>
</div>
<button class="send" id="send-btn" type="button">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
</button>
</div>
<div class="ga-menu" id="model-menu" hidden></div>
</div>
</section>
<!-- 消息通道 -->
<section class="page" data-page="channels">
<div class="page-pad">
<div class="page-title" data-i18n="page.channels.title"></div>
<div class="list" id="chan-list"></div>
<div class="list-empty" id="chan-empty" hidden data-i18n="ch.empty"></div>
</div>
</section>
<!-- 状态面板 -->
<section class="page" data-page="status">
<div class="page-pad">
<div class="page-title" data-i18n="page.status.title"></div>
<div class="list" id="status-list"></div>
</div>
</section>
<!-- Conductor -->
<section class="page" data-page="collab">
<div class="collab-offline" id="collab-offline" hidden>
<span data-i18n="collab.offline"></span>
<button type="button" class="chip sm" id="collab-retry" data-i18n="collab.retry"></button>
</div>
<div class="collab-reconnect" id="collab-reconnect" hidden data-i18n="collab.reconnect"></div>
<div class="collab-sticky" id="collab-sticky" hidden></div>
<div class="collab-body" id="collab-body">
<aside class="collab-progress">
<div class="collab-progress-stats" id="collab-progress-stats" hidden></div>
<div class="collab-progress-head" data-i18n="collab.progressTitle"></div>
<div class="collab-progress-empty" id="collab-progress-empty" data-i18n="collab.progressEmpty"></div>
<div id="collab-workers"></div>
</aside>
<div class="collab-chat">
<div class="collab-chat-head" id="collab-chat-head" hidden>
<span data-i18n="collab.chatTitle"></span>
<button type="button" class="ic-btn collab-progress-toggle" id="collab-progress-toggle" hidden data-i18n-title="collab.showProgressTitle" title="">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="3" width="7" height="18" rx="1"/><rect x="14" y="3" width="7" height="18" rx="1"/></svg>
</button>
</div>
<div class="msg-area collab-msgs" id="collab-msgs">
<div class="collab-guide" id="collab-welcome" hidden>
<div class="feature-head">
<div class="page-title" data-i18n="collab.guideTitle"></div>
<p class="page-sub" data-i18n="collab.guideWhen"></p>
</div>
<div class="collab-guide-steps">
<div class="collab-guide-step">
<span class="collab-guide-ic" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg></span>
<span class="collab-guide-txt"><span class="collab-guide-label" data-i18n="collab.guideStep1t"></span><span class="collab-guide-desc" data-i18n="collab.guideStep1d"></span></span>
</div>
<div class="collab-guide-step">
<span class="collab-guide-ic" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/></svg></span>
<span class="collab-guide-txt"><span class="collab-guide-label" data-i18n="collab.guideStep2t"></span><span class="collab-guide-desc" data-i18n="collab.guideStep2d"></span></span>
</div>
<div class="collab-guide-step">
<span class="collab-guide-ic" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><path d="M9 15l2 2 4-4"/></svg></span>
<span class="collab-guide-txt"><span class="collab-guide-label" data-i18n="collab.guideStep3t"></span><span class="collab-guide-desc" data-i18n="collab.guideStep3d"></span></span>
</div>
<div class="collab-guide-step">
<span class="collab-guide-ic" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"/></svg></span>
<span class="collab-guide-txt"><span class="collab-guide-label" data-i18n="collab.guideStep4t"></span><span class="collab-guide-desc" data-i18n="collab.guideStep4d"></span></span>
</div>
</div>
</div>
<div class="msgs" id="collab-msg-list" hidden></div>
</div>
<div class="composer collab-composer">
<div class="composer-top">
<button class="ic-btn" id="collab-upload-btn" type="button" data-i18n-title="upload.button" title="">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.44 11.05 12 20.5a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"/></svg>
</button>
<div class="collab-chips" id="collab-chips"></div>
</div>
<textarea class="input" id="collab-input" data-i18n-ph="collab.placeholder" rows="1"></textarea>
<input type="file" id="collab-img-input" multiple hidden>
<div class="thumb-strip" id="collab-thumb-strip" hidden></div>
<div class="composer-bot">
<div class="cb-left"></div>
<button class="send" id="collab-send" type="button" aria-label="send">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
</button>
</div>
</div>
</div>
</div>
</section>
<!-- Token 统计 -->
<section class="page" data-page="token">
<div class="page-pad">
<div class="page-title" data-i18n="page.token.title"></div>
<div class="tok-filter">
<label data-i18n="tok.from"></label>
<input type="datetime-local" id="tok-since">
<label data-i18n="tok.to"></label>
<input type="datetime-local" id="tok-until">
<button class="tok-reset" id="tok-reset" data-i18n="tok.reset"></button>
</div>
<div class="stat-row">
<div class="stat"><div class="s-n" id="tok-total-n">0</div><div class="s-l" data-i18n="tok.total"></div></div>
<div class="stat"><div class="s-n" id="tok-cost-n">¥ 0</div><div class="s-l" data-i18n="tok.cost"></div></div>
<div class="stat"><div class="s-n" id="tok-today-n">0</div><div class="s-l" data-i18n="tok.today"></div></div>
</div>
<table class="tok-table" id="tok-table">
<thead><tr>
<th data-i18n="tok.colSession"></th>
<th data-i18n="tok.colIn"></th>
<th data-i18n="tok.colOut"></th>
<th data-i18n="tok.colCacheW"></th>
<th data-i18n="tok.colCache"></th>
<th data-i18n="tok.cost"></th>
</tr></thead>
<tbody id="tok-tbody"></tbody>
</table>
<div class="tok-pager" id="tok-pager"></div>
</div>
</section>
</div>
</main>
<!-- ④ 右侧会话面板 -->
<button class="rp-toggle" id="rp-toggle" aria-label="toggle panel">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>
</button>
<div class="rp-resize" id="rp-resize"></div>
<aside class="rightpanel" id="rightpanel">
<div class="search">
<svg class="search-ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
<input data-i18n-ph="search.placeholder" placeholder="">
</div>
<button class="new-conv">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
<span data-i18n="conv.new"></span>
</button>
<div class="conv-list"></div>
<!-- 会话操作菜单 -->
<div class="ctx-menu" id="conv-menu" hidden>
<div class="ctx-item" data-act="pin">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="17" x2="12" y2="22"/><path d="M9 4h6l-1 6 3 3v2H7v-2l3-3-1-6z"/></svg>
<span data-i18n="ctx.pin"></span>
</div>
<div class="ctx-item danger" data-act="del">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>
<span data-i18n="ctx.del"></span>
</div>
</div>
</aside>
</div>
<!-- 预设功能 弹窗 -->
<div class="modal" id="preset-modal" hidden>
<div class="modal-backdrop" data-close></div>
<div class="modal-card" role="dialog">
<div class="modal-head">
<div class="modal-title" data-i18n="modal.preset"></div>
<button id="preset-restore-btn" class="preset-restore" type="button" data-i18n="builtinPreset.restoreBtn" hidden></button>
<button class="modal-x" data-close data-i18n-title="common.close" title="">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg>
</button>
</div>
<div class="modal-body preset-pop">
<div class="feature-grid"></div>
</div>
</div>
</div>
<!-- 添加模型 弹窗(模板,未实现)-->
<div class="modal" id="add-model-modal" hidden>
<div class="modal-backdrop" data-close></div>
<div class="modal-card" role="dialog">
<div class="modal-head">
<div class="modal-title" id="model-form-title" data-i18n="modal.addModel"></div>
<button class="modal-x" data-close data-i18n-title="common.close" title="">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg>
</button>
</div>
<div class="modal-body model-form-body">
<form id="add-model-form" class="model-form" autocomplete="off">
<label><span class="field-label"><span data-i18n="model.model"></span><span class="field-req" aria-hidden="true">*</span></span><input name="model" required data-i18n-ph="model.modelPh"><span class="field-hint" data-i18n="model.modelHint"></span></label>
<label id="model-apikey-label"><span class="field-label"><span data-i18n="model.apikey"></span><span class="field-req" aria-hidden="true">*</span></span><input name="apikey" type="password" data-i18n-ph="model.apikeyPh" id="model-apikey-input"></label>
<label><span class="field-label"><span data-i18n="model.apibase"></span><span class="field-req" aria-hidden="true">*</span></span><input name="apibase" required data-i18n-ph="model.apibasePh"></label>
<div class="model-form-field"><span class="field-label"><span data-i18n="model.protocol"></span><span class="field-req" aria-hidden="true">*</span></span>
<div class="seg-group" role="radiogroup">
<label class="seg-opt"><input type="radio" name="protocol" value="oai" required><span data-i18n="model.protocolOai"></span></label>
<label class="seg-opt"><input type="radio" name="protocol" value="claude" required><span data-i18n="model.protocolClaude"></span></label>
</div>
</div>
<label><span data-i18n="model.name"></span><input name="name" data-i18n-ph="model.namePh" data-optional-ph></label>
<div class="model-form-row">
<label class="model-form-mini"><span data-i18n="model.retries"></span><input name="max_retries" type="number" min="1" value="5"></label>
<label class="model-form-mini"><span data-i18n="model.connTimeout"></span><input name="connect_timeout" type="number" min="1" value="15"></label>
<label class="model-form-mini"><span data-i18n="model.readTimeout"></span><input name="read_timeout" type="number" min="5" value="300"></label>
</div>
<p class="model-form-err" id="add-model-err" hidden></p>
<div class="model-form-actions">
<button type="button" class="set-btn ghost" data-close data-i18n="common.cancel"></button>
<button type="submit" class="set-btn primary"><span data-i18n="model.save"></span></button>
</div>
</form>
</div>
</div>
</div>
<!-- 自定义预设 弹窗 -->
<div class="modal" id="custom-preset-modal" hidden>
<div class="modal-backdrop" data-close></div>
<div class="modal-card" role="dialog">
<div class="modal-head">
<div class="modal-title" data-i18n="modal.customPreset"></div>
<button class="modal-x" data-close data-i18n-title="common.close" title="">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg>
</button>
</div>
<div class="modal-body cp-body">
<input class="cp-input" id="cp-title" type="text" data-i18n-ph="customPreset.titlePh" placeholder="">
<textarea class="cp-textarea" id="cp-prompt" rows="6" data-i18n-ph="customPreset.promptPh" placeholder=""></textarea>
<div class="cp-error" id="cp-error" hidden></div>
<div class="cp-actions">
<button class="cp-btn" data-close data-i18n="common.cancel" type="button"></button>
<button class="cp-btn cp-btn-primary" id="cp-save" data-i18n="common.save" type="button"></button>
</div>
</div>
</div>
</div>
<!-- 渠道日志 弹窗 -->
<div class="modal" id="chan-log-modal" hidden>
<div class="modal-backdrop" data-close></div>
<div class="modal-card modal-card-wide modal-card-inset" role="dialog">
<div class="modal-head">
<div class="modal-title" id="chan-log-title" data-i18n="modal.channelLogs"></div>
<button class="modal-x" data-close data-i18n-title="common.close" title="">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg>
</button>
</div>
<div class="modal-body modal-body-inset">
<pre class="chan-log-pre" id="chan-log-pre"></pre>
</div>
</div>
</div>
<!-- mykey 配置 弹窗 -->
<div class="modal" id="chan-config-modal" hidden>
<div class="modal-backdrop" data-close></div>
<div class="modal-card modal-card-wide modal-card-inset" role="dialog">
<div class="modal-head">
<div class="modal-title" id="chan-config-title" data-i18n="modal.mykeyConfig"></div>
<button class="modal-x" data-close data-i18n-title="common.close" title="">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg>
</button>
</div>
<div class="modal-body modal-body-inset chan-config-body">
<textarea id="chan-config-editor" class="mykey-editor" spellcheck="false"></textarea>
<div class="chan-config-foot">
<button type="button" class="chan-config-save" id="chan-config-save" data-i18n="common.save"></button>
</div>
</div>
</div>
</div>
<!-- 配置 弹窗 -->
<div class="modal" id="settings-modal" hidden>
<div class="modal-backdrop" data-close></div>
<div class="modal-card" role="dialog">
<div class="modal-head">
<div class="modal-title" data-i18n="modal.settings"></div>
<button class="modal-x" data-close data-i18n-title="common.close" title="">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg>
</button>
</div>
<div class="modal-body set-body">
<div class="set-block">
<div class="set-sec-t" data-i18n="set.appearance"></div>
<div class="appear-cards" id="appearance-seg" role="radiogroup">
<button class="appear-card sel" type="button" data-appearance="light" role="radio" aria-checked="true">
<span class="appear-preview appear-preview-light" aria-hidden="true"></span>
<span class="appear-name" data-i18n="appearance.light"></span>
</button>
<button class="appear-card" type="button" data-appearance="dark" role="radio" aria-checked="false">
<span class="appear-preview appear-preview-dark" aria-hidden="true"></span>
<span class="appear-name" data-i18n="appearance.dark"></span>
</button>
</div>
<div class="set-toggle-row" id="plain-ui-row" hidden>
<span class="set-toggle-label" data-i18n="set.plainUi"></span>
<button class="set-switch" type="button" id="plain-ui-switch" role="switch" aria-checked="false">
<span class="set-switch-knob" aria-hidden="true"></span>
</button>
</div>
</div>
<div class="set-block">
<div class="set-sec-t" id="chat-font-label" data-i18n="set.fontSize"></div>
<div class="chat-font-panel">
<div class="chat-font-stepper" id="chat-font-stepper" role="slider"
aria-valuemin="10" aria-valuemax="20" aria-valuenow="14"
aria-valuetext="14px" aria-labelledby="chat-font-label" tabindex="0">
<div class="chat-font-segments" id="chat-font-segments"></div>
</div>
<span class="chat-font-value" id="chat-font-value" aria-hidden="true">14px</span>
<div class="chat-font-scale" aria-hidden="true">
<span class="chat-font-scale-min">10</span>
<span class="chat-font-scale-max">20</span>
</div>
</div>
</div>
<div class="set-block">
<div class="set-sec-t" data-i18n="set.theme"></div>
<div class="color-grid" id="theme-swatches">
<span class="swatch sel" data-theme="1" role="button" tabindex="0" aria-label="1"></span>
<span class="swatch" data-theme="2" role="button" tabindex="0" aria-label="2"></span>
<span class="swatch" data-theme="3" role="button" tabindex="0" aria-label="3"></span>
<span class="swatch" data-theme="4" role="button" tabindex="0" aria-label="4"></span>
<span class="swatch" data-theme="5" role="button" tabindex="0" aria-label="5"></span>
<span class="swatch" data-theme="6" role="button" tabindex="0" aria-label="6"></span>
<span class="swatch" data-theme="7" role="button" tabindex="0" aria-label="7"></span>
<span class="swatch" data-theme="8" role="button" tabindex="0" aria-label="8"></span>
</div>
</div>
<div class="set-block">
<div class="set-sec-t" data-i18n="set.lang"></div>
<div class="model-list lang-list" id="lang-list"></div>
</div>
<div>
<div class="set-sec-t" data-i18n="set.model"></div>
<div class="model-list" id="model-list"></div>
<button class="set-btn" id="add-model-btn" type="button">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
<span data-i18n="set.addModel"></span>
</button>
</div>
</div>
</div>
</div>
</div>
<!-- 图片预览 lightbox -->
<div class="lightbox" id="lightbox" hidden>
<div class="lightbox-backdrop" data-close></div>
<button class="lightbox-x" data-close data-i18n-title="lightbox.closeTitle" title="">×</button>
<img class="lightbox-img" id="lightbox-img" alt="">
</div>
<div id="toast-root" class="toast-root" aria-live="polite"></div>
<script src="vendor/marked.min.js"></script>
<!-- KaTeX JS -->
<script src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js" crossorigin="anonymous"></script>
<!-- highlight.js -->
<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/highlight.min.js" crossorigin="anonymous"></script>
<script src="app.js?v=43"></script>
<script src="annot.js"></script><!-- DEV 脚手架,可删 -->
</body>
</html>