Files
2026-07-13 13:04:19 +08:00

680 lines
38 KiB
HTML
Raw Permalink 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="assets/fonts/fonts.css?v=2">
<link rel="stylesheet" href="styles.css?v=181">
<!-- 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">
<!-- Flatpickr: 日期选择器 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr@4.6.13/dist/flatpickr.min.css" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/flatpickr@4.6.13/dist/flatpickr.min.js" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/flatpickr@4.6.13/dist/l10n/zh.js" crossorigin="anonymous"></script>
<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-text">
<div class="brand-name ga-wordmark">Generic Agent</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">
<span class="ic" data-ga-icon="chatTeardropText"></span>
<span data-i18n="nav.chat"></span>
</a>
<a class="nav-item" data-page="collab">
<span class="ic" data-ga-icon="gitFork"></span>
<span data-i18n="nav.collab"></span>
<span id="collab-badge" class="collab-nav-badge" hidden></span>
</a>
<a class="nav-item" data-page="services">
<span class="ic" data-ga-icon="broadcast"></span>
<span data-i18n="nav.services"></span>
</a>
<a class="nav-item" data-page="token">
<span class="ic" data-ga-icon="coins"></span>
<span data-i18n="nav.token"></span>
</a>
</nav>
<!-- 快速接入官方模型(DeepSeek / 通义千问):填好 API Key 即可使用 -->
<div class="provider-quickstart" id="provider-quickstart">
<div class="pq-head" id="pq-toggle" role="button" tabindex="0" aria-expanded="true">
<span class="fr-l">
<span class="ic" data-ga-icon="lightning"></span>
<span class="pq-title" data-i18n="pq.title"></span>
</span>
<span class="pq-collapse chev" data-ga-icon="caretRight" aria-hidden="true"></span>
</div>
<div class="pq-body">
<button type="button" class="pq-btn" data-provider="deepseek">
<span class="pq-logo" style="background:rgba(77,107,254,.12)" aria-hidden="true"><svg viewBox="0 0 24 24" fill="#4D6BFE" xmlns="http://www.w3.org/2000/svg"><path d="M23.748 4.651c-.254-.124-.364.113-.512.233-.051.04-.094.09-.137.137-.372.397-.806.657-1.373.626-.829-.046-1.537.214-2.163.848-.133-.782-.575-1.248-1.247-1.548-.352-.155-.708-.311-.955-.65-.172-.24-.219-.509-.305-.774-.055-.16-.11-.323-.293-.35-.2-.031-.278.136-.356.276-.313.572-.434 1.202-.422 1.84.027 1.436.633 2.58 1.838 3.393.137.094.172.187.129.323-.082.28-.18.553-.266.833-.055.179-.137.218-.328.14a5.5 5.5 0 0 1-1.737-1.179c-.857-.828-1.631-1.743-2.597-2.46a12 12 0 0 0-.689-.47c-.985-.957.13-1.743.387-1.836.27-.098.094-.433-.778-.428-.872.003-1.67.295-2.687.685a3 3 0 0 1-.465.136 9.6 9.6 0 0 0-2.883-.101c-1.885.21-3.39 1.1-4.497 2.622C.082 8.776-.231 10.854.152 13.02c.403 2.284 1.568 4.175 3.36 5.653 1.857 1.533 3.997 2.284 6.438 2.14 1.482-.085 3.132-.284 4.994-1.86.47.234.962.328 1.78.398.629.058 1.235-.031 1.705-.129.735-.155.684-.836.418-.961-2.155-1.004-1.682-.595-2.112-.926 1.095-1.295 2.768-3.598 3.284-6.733.05-.346.115-.834.108-1.114-.004-.171.035-.238.23-.257a4.2 4.2 0 0 0 1.545-.475c1.397-.763 1.96-2.016 2.093-3.517.02-.23-.004-.467-.247-.588M11.58 18.168c-2.088-1.642-3.101-2.183-3.52-2.16-.39.024-.32.472-.234.763.09.288.207.487.371.74.114.167.192.416-.113.603-.673.416-1.842-.14-1.897-.168-1.361-.801-2.5-1.86-3.301-3.306-.775-1.393-1.225-2.888-1.299-4.482-.02-.385.094-.522.477-.592a4.7 4.7 0 0 1 1.53-.038c2.131.311 3.946 1.264 5.467 2.774.868.86 1.525 1.887 2.202 2.89.72 1.066 1.494 2.082 2.48 2.915.348.291.626.513.892.677-.802.09-2.14.109-3.055-.615zm1.001-6.44a.306.306 0 0 1 .415-.287.3.3 0 0 1 .113.074.3.3 0 0 1 .086.214c0 .17-.136.307-.308.307a.303.303 0 0 1-.306-.307m3.11 1.596c-.2.081-.4.151-.591.16a1.25 1.25 0 0 1-.798-.254c-.274-.23-.47-.358-.551-.758a1.7 1.7 0 0 1 .015-.588c.07-.327-.007-.537-.238-.727-.188-.156-.426-.199-.689-.199a.6.6 0 0 1-.254-.078.253.253 0 0 1-.114-.358 1 1 0 0 1 .192-.21c.356-.202.767-.136 1.146.016.352.144.618.408 1.001.782.392.451.462.576.685.915.176.264.336.536.446.848.066.194-.02.353-.25.45"/></svg></span>
<span class="pq-btn-text">
<span class="pq-btn-name">DeepSeek</span>
<span class="pq-btn-desc" data-i18n="pq.deepseekDesc"></span>
</span>
<span class="pq-arrow" data-ga-icon="caretRight"></span>
</button>
<button type="button" class="pq-btn" data-provider="qwen">
<span class="pq-logo" style="background:rgba(97,92,237,.12)" aria-hidden="true"><svg viewBox="0 0 24 24" fill="#615CED" xmlns="http://www.w3.org/2000/svg"><path d="M23.919 14.545 20.817 9.17l1.47-2.544a.56.56 0 0 0 0-.566l-1.633-2.83a.57.57 0 0 0-.49-.283h-6.207L12.487.402a.57.57 0 0 0-.49-.284H8.732a.56.56 0 0 0-.49.284L5.139 5.775h-2.94a.56.56 0 0 0-.49.284L.077 8.887a.56.56 0 0 0 0 .567L3.18 14.83l-1.47 2.545a.56.56 0 0 0 0 .566l1.634 2.83a.57.57 0 0 0 .49.283h6.205l1.47 2.545a.57.57 0 0 0 .49.284h3.266a.57.57 0 0 0 .49-.284l3.104-5.375h2.94a.57.57 0 0 0 .49-.283l1.634-2.828a.55.55 0 0 0-.004-.568M8.733.686l1.634 2.828-1.634 2.828H21.8L20.164 9.17H7.425L5.63 6.06Zm1.306 19.801-6.205-.002 1.634-2.83h3.265L2.201 6.344h3.267q3.182 5.517 6.367 11.032zm10.124-5.66L18.53 12l-6.532 11.315-1.634-2.83c2.129-3.673 4.25-7.351 6.373-11.028h3.592l3.102 5.374z"/></svg></span>
<span class="pq-btn-text">
<span class="pq-btn-name">通义千问</span>
<span class="pq-btn-desc" data-i18n="pq.qwenDesc"></span>
</span>
<span class="pq-arrow" data-ga-icon="caretRight"></span>
</button>
</div>
</div>
<div class="sidebar-foot">
<a class="foot-row" id="settings-btn">
<span class="fr-l">
<span class="ic" data-ga-icon="gear"></span>
<span data-i18n="foot.settings"></span>
</span>
<span class="chev" data-ga-icon="caretRight"></span>
</a>
<div class="foot-ver" data-i18n="foot.ver"></div>
</div>
</aside>
<div class="sb-resize" id="sb-resize"></div>
<!-- 中间主区 -->
<main class="main">
<div id="pages">
<!-- 聊天 -->
<section class="page active page--chat-ui" data-page="chat">
<div class="page-top">
<button type="button" class="pt-icon pt-sb-toggle" aria-label="toggle sidebar">
<span data-ga-icon="caretLeft"></span>
</button>
<button class="run-state" id="run-toggle" type="button">
<i class="dot"></i> <span class="rs-label"></span>
</button>
<button type="button" class="pt-icon pt-rp-toggle" aria-label="toggle conversations">
<span data-ga-icon="caretRight"></span>
</button>
</div>
<div class="chat-shell">
<div class="chat-panel">
<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="session-loading" id="session-loading" hidden aria-live="polite">
<span class="ga-spin" aria-hidden="true"></span>
<span data-i18n="chat.sessionLoading"></span>
</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-anchor" id="chat-composer-anchor">
<div class="composer" id="chat-composer" data-composer-ctx="chat">
<div class="composer-slot">
<div class="plan-card" id="plan-bar" hidden aria-live="polite"></div>
<div class="composer-inset">
<div class="thumb-strip" id="thumb-strip" hidden></div>
<div class="input" id="chat-input" contenteditable="true" role="textbox" aria-multiline="true" data-i18n-ph="composer.placeholder"></div>
<div class="composer-bot">
<div class="composer-plus-wrap">
<button type="button" class="ic-btn composer-plus" id="chat-plus-btn" aria-haspopup="menu" aria-expanded="false" data-i18n-title="collab.plusMenu" title="">
<span data-ga-icon="plus"></span>
</button>
<div class="ga-menu composer-menu" id="chat-menu" hidden role="menu">
<button type="button" class="ga-menu-item" data-composer-action="upload" role="menuitem">
<span data-ga-icon="paperclip"></span>
<span data-i18n="upload.button"></span>
</button>
<button type="button" class="ga-menu-item" data-composer-action="preset" role="menuitem">
<span data-ga-icon="lightning"></span>
<span data-i18n="modal.preset"></span>
</button>
</div>
</div>
<span class="spacer"></span>
<button type="button" class="chip" id="model-chip" data-i18n-title="model.menuLabel" title=""><span class="model-name"></span> <span class="chip-ic" data-ga-icon="caretDown"></span></button>
<button type="button" class="send" id="send-btn" aria-label="send">
<span data-ga-icon="paperPlaneTilt"></span>
</button>
</div>
</div>
</div>
<div class="ga-menu" id="model-menu" hidden></div>
<input type="file" id="chat-file-input" multiple hidden>
</div>
</div>
</div>
</div>
</section>
<!-- 后台服务:消息通道 + 状态面板 -->
<section class="page" data-page="services">
<div class="page-top">
<button type="button" class="pt-icon pt-sb-toggle" aria-label="toggle sidebar">
<span data-ga-icon="caretLeft"></span>
</button>
<span class="pt-spacer"></span>
<button type="button" class="pt-icon pt-rp-toggle" aria-label="toggle conversations">
<span data-ga-icon="caretRight"></span>
</button>
</div>
<div class="page-pad">
<div class="page-title" data-i18n="page.services.title"></div>
<div class="svc-tabs" id="svc-tabs">
<button type="button" class="svc-tab active" data-tab="channels" data-i18n="page.channels.title"></button>
<button type="button" class="svc-tab" data-tab="status" data-i18n="page.status.title"></button>
</div>
<div class="svc-panel active" data-svc-panel="channels">
<div class="list" id="chan-list"></div>
<div class="list-empty" id="chan-empty" hidden data-i18n="ch.empty"></div>
</div>
<div class="svc-panel" data-svc-panel="status">
<div class="list" id="status-list"></div>
</div>
</div>
</section>
<!-- 指挥家 Conductor(对话区结构复用 page--chat-ui / chat-shell -->
<section class="page page--chat-ui" data-page="collab">
<div class="page-top">
<button type="button" class="pt-icon pt-sb-toggle" aria-label="toggle sidebar">
<span data-ga-icon="caretLeft"></span>
</button>
<div class="page-top-center">
<button class="run-state" id="collab-run-toggle" type="button">
<i class="dot"></i> <span class="rs-label"></span>
</button>
<button type="button" class="pt-icon collab-retry-btn" id="collab-retry" hidden data-i18n-aria-label="collab.retry" aria-label="retry">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="23 4 23 10 17 10"/><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"/></svg>
</button>
</div>
<button type="button" class="pt-icon pt-rp-toggle" aria-label="toggle conversations">
<span data-ga-icon="caretRight"></span>
</button>
</div>
<div class="chat-shell">
<div class="chat-panel">
<div class="msg-area collab-msgs" id="collab-msgs">
<div class="collab-scroll">
<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"><span data-ga-icon="chatTeardropText"></span></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"><span data-ga-icon="gridFour"></span></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"><span data-ga-icon="listChecks"></span></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"><span data-ga-icon="pencilSimple"></span></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="collab-overlay">
<div class="collab-rail" id="collab-rail" hidden>
<button type="button" class="collab-rail-handle" id="collab-rail-toggle" data-i18n-title="collab.showProgressTitle" title="">
<span class="collab-rail-grip" aria-hidden="true"></span>
<svg class="collab-rail-chev" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" aria-hidden="true"><path d="M181.66,133.66l-80,80a8,8,0,0,1-11.32-11.32L164.69,128,90.34,53.66a8,8,0,0,1,11.32-11.32l80,80A8,8,0,0,1,181.66,133.66Z"/></svg>
<span class="collab-rail-badge collab-rail-run" id="collab-rail-run" hidden>
<span class="collab-rail-spin" aria-hidden="true"></span>
<span class="n" id="collab-rail-run-n">0</span>
</span>
<span class="collab-rail-badge collab-rail-done" id="collab-rail-done" hidden>
<span class="collab-rail-dot" aria-hidden="true"></span>
<span class="n" id="collab-rail-done-n">0</span>
</span>
<span class="collab-rail-badge collab-rail-issue" id="collab-rail-issue" hidden>
<span class="collab-rail-dot collab-rail-dot--danger" aria-hidden="true"></span>
<span class="n" id="collab-rail-issue-n">0</span>
</span>
</button>
</div>
<aside class="collab-prog-panel" id="collab-prog-panel">
<div class="collab-prog-panel-head">
<span data-i18n="collab.progressTitle"></span>
<button type="button" class="ic-btn collab-prog-close" id="collab-prog-close" aria-label="close">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" aria-hidden="true"><path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"/></svg>
</button>
</div>
<div class="collab-prog-stats" id="collab-progress-stats" hidden></div>
<div class="collab-progress-empty" id="collab-progress-empty" data-i18n="collab.progressEmpty"></div>
<div id="collab-workers"></div>
</aside>
</div>
</div>
<div class="collab-quick" id="collab-quick">
<button type="button" class="pill" data-prompt-key="collab.chipProgress" data-i18n="collab.chipProgress"></button>
<button type="button" class="pill" data-prompt-key="collab.chipPause" data-i18n="collab.chipPause"></button>
<button type="button" class="pill" data-prompt-key="collab.chipSummary" data-i18n="collab.chipSummary"></button>
</div>
<div class="composer-anchor" id="cdb-composer-anchor">
<div class="composer" id="cdb-composer" data-composer-ctx="collab">
<div class="composer-slot">
<div class="composer-inset">
<div class="thumb-strip" id="cdb-thumb-strip" hidden></div>
<div class="input" id="cdb-input" contenteditable="true" role="textbox" aria-multiline="true" data-i18n-ph="collab.placeholder"></div>
<div class="composer-bot">
<div class="composer-plus-wrap">
<button type="button" class="ic-btn composer-plus" id="cdb-plus-btn" aria-haspopup="menu" aria-expanded="false" data-i18n-title="collab.plusMenu" title="">
<span data-ga-icon="plus"></span>
</button>
<div class="ga-menu composer-menu" id="cdb-menu" hidden role="menu">
<button type="button" class="ga-menu-item" data-composer-action="upload" role="menuitem">
<span data-ga-icon="paperclip"></span>
<span data-i18n="upload.button"></span>
</button>
</div>
</div>
<span class="spacer"></span>
<button type="button" class="chip" id="cdb-model-chip" data-i18n-title="model.menuLabel" title="">
<span class="model-name"></span>
<span class="chip-ic" data-ga-icon="caretDown"></span>
</button>
<button type="button" class="send" id="cdb-send" aria-label="send">
<span data-ga-icon="paperPlaneTilt"></span>
</button>
</div>
</div>
</div>
<div class="ga-menu" id="cdb-model-menu" hidden></div>
<input type="file" id="cdb-file-input" multiple hidden>
</div>
</div>
</div>
</div>
</section>
<!-- Token 统计 -->
<section class="page" data-page="token">
<div class="page-top">
<button type="button" class="pt-icon pt-sb-toggle" aria-label="toggle sidebar">
<span data-ga-icon="caretLeft"></span>
</button>
<span class="pt-spacer"></span>
<button type="button" class="pt-icon pt-rp-toggle" aria-label="toggle conversations">
<span data-ga-icon="caretRight"></span>
</button>
</div>
<div class="page-pad">
<div class="page-title" data-i18n="page.token.title"></div>
<div class="tok-tabs" id="tok-tabs">
<button class="tok-tab active" data-tab="chat" data-i18n="tok.tabAll"></button>
<button class="tok-tab" data-tab="conductor" data-i18n="tok.tabConductor"></button>
</div>
<div class="tok-filter">
<label data-i18n="tok.from"></label>
<input type="text" id="tok-since" class="tok-date" readonly>
<label data-i18n="tok.to"></label>
<input type="text" id="tok-until" class="tok-date" readonly>
<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>
<!-- ④ 右侧会话面板 -->
<div class="rp-resize" id="rp-resize"></div>
<aside class="rightpanel" id="rightpanel">
<div class="rp-head">
<div class="search">
<span class="search-ic" data-ga-icon="magnifyingGlass"></span>
<input data-i18n-ph="search.placeholder" placeholder="" maxlength="50">
</div>
</div>
<button type="button" class="new-conv">
<span data-ga-icon="plus"></span>
<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">
<span data-ga-icon="pushPinSimple"></span>
<span data-i18n="ctx.pin"></span>
</div>
<div class="ctx-item" data-act="rename">
<span data-ga-icon="pencilSimple"></span>
<span data-i18n="ctx.rename"></span>
</div>
<div class="ctx-item danger" data-act="del">
<span data-ga-icon="trash"></span>
<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="">
<span data-ga-icon="x"></span>
</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="">
<span data-ga-icon="x"></span>
</button>
</div>
<div class="modal-body model-form-body">
<div class="model-guide" id="model-guide" hidden>
<div class="model-guide-head">
<span class="model-guide-logo" id="model-guide-logo" aria-hidden="true"></span>
<span class="model-guide-name" id="model-guide-name"></span>
</div>
<ol class="model-guide-steps">
<li data-i18n="guide.step1"></li>
<li data-i18n="guide.step2"></li>
<li data-i18n="guide.step3"></li>
</ol>
<div class="model-guide-link-row">
<a class="model-guide-link" id="model-guide-link" href="#" target="_blank" rel="noopener noreferrer"></a>
<button type="button" class="model-guide-copy" id="model-guide-copy" data-i18n-title="guide.copy" title="" aria-label="copy">
<span data-ga-icon="copy"></span>
</button>
</div>
<p class="model-guide-tip" data-i18n="guide.prefillTip"></p>
</div>
<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" maxlength="50"><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" maxlength="200"></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" maxlength="200"></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>
<div class="model-form-field"><span class="field-label"><span data-i18n="model.stream"></span></span>
<div class="seg-group" role="radiogroup">
<label class="seg-opt"><input type="radio" name="stream" value="true" checked><span data-i18n="model.streamOn"></span></label>
<label class="seg-opt"><input type="radio" name="stream" value="false"><span data-i18n="model.streamOff"></span></label>
</div>
</div>
<label><span data-i18n="model.name"></span><input name="name" data-i18n-ph="model.namePh" data-optional-ph maxlength="50"></label>
<div class="model-form-row">
<label class="model-form-mini"><span data-i18n="model.retries"></span><input name="max_retries" type="text" inputmode="numeric" pattern="[0-9]*" min="1" max="20" value="5"></label>
<label class="model-form-mini"><span data-i18n="model.connTimeout"></span><input name="connect_timeout" type="text" inputmode="numeric" pattern="[0-9]*" min="1" max="300" value="15"></label>
<label class="model-form-mini"><span data-i18n="model.readTimeout"></span><input name="read_timeout" type="text" inputmode="numeric" pattern="[0-9]*" min="5" max="3600" 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="confirm-modal" hidden>
<div class="modal-backdrop" data-close></div>
<div class="modal-card confirm-card" role="dialog" aria-modal="true" aria-labelledby="confirm-title">
<div class="modal-head">
<div class="modal-title" id="confirm-title"></div>
<button class="modal-x" data-close data-i18n-title="common.close" title="">
<span data-ga-icon="x"></span>
</button>
</div>
<div class="modal-body confirm-body">
<div class="confirm-message" id="confirm-message"></div>
<div class="confirm-actions">
<button type="button" class="set-btn ghost" id="confirm-cancel"></button>
<button type="button" class="set-btn primary" id="confirm-ok"></button>
</div>
</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="">
<span data-ga-icon="x"></span>
</button>
</div>
<div class="modal-body cp-body">
<input class="cp-input" id="cp-title" type="text" data-i18n-ph="customPreset.titlePh" placeholder="" maxlength="50">
<textarea class="cp-textarea" id="cp-prompt" rows="6" data-i18n-ph="customPreset.promptPh" placeholder="" maxlength="10000"></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="">
<span data-ga-icon="x"></span>
</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="">
<span data-ga-icon="x"></span>
</button>
</div>
<div class="modal-body modal-body-inset chan-config-body">
<textarea id="chan-config-editor" class="mykey-editor" spellcheck="false" maxlength="1000000"></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="">
<span data-ga-icon="x"></span>
</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.lang"></div>
<div class="model-list lang-list" id="lang-list"></div>
</div>
<div class="set-block">
<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">
<span data-ga-icon="plus"></span>
<span data-i18n="set.addModel"></span>
</button>
</div>
<div class="set-block">
<div class="set-sec-t" data-i18n="set.features"></div>
<button class="set-btn" id="import-mykey-btn" type="button">
<span data-ga-icon="fileText"></span>
<span data-i18n="set.importMykey"></span>
</button>
<input type="file" id="import-mykey-input" accept=".py,text/plain" hidden>
<button class="set-btn set-btn-follow" id="export-mykey-btn" type="button">
<span data-ga-icon="folderSimple"></span>
<span data-i18n="set.exportMykey"></span>
</button>
<button class="set-btn set-btn-follow" id="settings-services-btn" type="button">
<span data-ga-icon="broadcast"></span>
<span data-i18n="set.serviceManager"></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="phosphor-icons.js?v=2"></script>
<script src="app.js?v=208"></script>
</body>
</html>