Files
writing-agent/web/settings.html
T
chenmoranzhiandCursor 26328751ee 设置页接入用户角色管理与预设采样编辑。
并把指令目录接口一并挂上,供输入框补全拉取。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-14 01:15:36 +08:00

214 lines
9.1 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" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>设置 · Writing Agent</title>
<link rel="stylesheet" href="/settings.css" />
</head>
<body class="settings-page">
<header class="st-top">
<a class="st-brand" href="/">Writing Agent</a>
<nav class="st-nav" aria-label="主导航">
<a href="/">对话</a>
<a href="/modules.html">技能</a>
<a href="/shells.html">呈现壳</a>
<a href="/stats.html">Token</a>
<a href="/settings.html" aria-current="page">设置</a>
</nav>
</header>
<div class="st-shell">
<aside class="st-rail" aria-label="设置分类">
<p class="st-rail-label">设置</p>
<button type="button" class="st-rail-item active" data-section="api">API</button>
<button type="button" class="st-rail-item" data-section="persona">用户角色</button>
<button type="button" class="st-rail-item" data-section="preset">预设</button>
<button type="button" class="st-rail-item" data-section="storage">上下文</button>
<p class="st-rail-note">保存在本机 <code>~/.writing-agent/</code>,明文、不同步。</p>
</aside>
<main class="st-main">
<header class="st-main-head">
<div>
<h1 id="panel-title">API</h1>
<p class="st-sub" id="panel-subtitle">管理 LLM 连接</p>
</div>
<div class="st-main-actions" id="panel-actions"></div>
</header>
<div class="st-status" id="active-settings-bar"></div>
<div class="settings-toast" id="settings-toast" hidden></div>
<div class="st-body">
<section class="settings-section" id="section-api">
<div id="profiles-list" class="card-list"></div>
</section>
<section class="settings-section hidden" id="section-persona">
<div class="settings-card storage-card">
<h3>用户角色</h3>
<p class="settings-help">
游玩时,对话里 <code>@玩家</code> / <code>{{user}}</code> 会换成当前选中角色的名字;
<code>@人设</code> 与预设的 persona 洞用其正文。可在输入框旁快速切换。
创作阶段不用当前选用,而用下方勾选的「创作默认」填入预设用户设定。
建议把创作默认的名称写成 <code>@玩家</code>:模型会按这个称呼写开场白,替换后仍是占位,进游玩再换成当前角色。
</p>
</div>
<div id="personas-list" class="card-list"></div>
</section>
<section class="settings-section hidden" id="section-preset">
<div id="presets-list" class="card-list"></div>
<pre id="import-report" class="import-report" hidden></pre>
</section>
<section class="settings-section hidden" id="section-storage">
<div class="settings-card storage-card">
<h3>LLM 请求上下文</h3>
<p class="settings-help">
每次模型调用可保存完整 prompt。默认每个对话只保留最新若干条;更早消息仍在,但去掉上下文痕迹。可在对话里查看上下文。
</p>
<label class="field">
每个对话保留最新条数
<input
type="number"
id="context-trace-keep"
min="0"
max="50"
step="1"
value="5"
/>
</label>
<p class="settings-help muted">0 = 不保存;最大 50。保存后对新回复立即生效。</p>
<div class="storage-actions">
<button type="button" class="btn-primary" id="btn-save-context-keep">保存</button>
<button type="button" class="btn-secondary" id="btn-prune-context">修剪已打开会话</button>
<button type="button" class="btn-secondary danger-outline" id="btn-clear-context">清除全部痕迹</button>
</div>
</div>
</section>
</div>
</main>
</div>
<dialog id="preset-probe-dialog" class="probe-dialog">
<header class="probe-head">
<div>
<h3>试跑预设</h3>
<p class="probe-sub" id="probe-preset-name"></p>
</div>
<button type="button" class="btn-secondary" id="probe-close">关闭</button>
</header>
<div class="probe-body">
<section class="probe-composer">
<label>
本轮输入
<textarea id="probe-message" rows="4" placeholder="发给模型的这一轮"></textarea>
</label>
<details class="probe-extras">
<summary>试跑用设定 / 历史</summary>
<label>
历史前(设定)
<textarea id="probe-lore-before" rows="3"></textarea>
</label>
<label>
对话历史
<textarea id="probe-history" rows="4"></textarea>
</label>
<label>
历史后(状态)
<textarea id="probe-lore-after" rows="3"></textarea>
</label>
<label>
本轮后(可选)
<textarea id="probe-post-turn" rows="2"></textarea>
</label>
</details>
<div class="probe-composer-actions">
<button type="button" class="btn-primary" id="probe-send">发送一轮</button>
<p class="probe-status" id="probe-status" hidden></p>
</div>
</section>
<section class="probe-inspect" aria-live="polite">
<h4>发出的上下文</h4>
<div id="probe-messages" class="probe-messages">
<p class="probe-empty">发送后显示实际拼进请求的消息。</p>
</div>
<div id="probe-reply-wrap" class="probe-reply" hidden>
<h4>模型回复</h4>
<pre id="probe-reply"></pre>
</div>
</section>
</div>
</dialog>
<dialog id="profile-dialog" class="profile-dialog">
<form id="profile-form" method="dialog">
<h3 id="profile-dialog-title">新增 API</h3>
<label>
名称
<input name="name" required placeholder="例如 DeepSeek" autocomplete="off" />
</label>
<label>
Base URL
<input name="baseUrl" required placeholder="https://api.deepseek.com" />
</label>
<label>
API Key
<input name="apiKey" type="password" placeholder="sk-…" autocomplete="off" />
</label>
<label>
Model
<input name="model" required placeholder="deepseek-chat" />
</label>
<label>
思考强度
<select name="reasoningEffort">
<option value="">默认(不发送)</option>
<option value="none">none · 关闭思考(带 tools 时自动用)</option>
<option value="low">low · 轻量</option>
<option value="medium">medium</option>
<option value="high">high · 增强</option>
<option value="max">max · 深度</option>
</select>
<span class="field-hint">写入请求的思考参数。GLM-5.3:仅 low/high/max(none 会映射为 low),并附带 thinking.enabled;旧 GLM 只用 thinking、不发 reasoning_effort。探测始终用 low。带 function tools 时:非 GLM 强制 none;GLM-5.3 保留合法档。</span>
</label>
<div class="dialog-actions">
<button type="button" id="profile-cancel" class="btn-secondary">取消</button>
<button type="button" id="profile-save" class="btn-secondary">仅保存</button>
<button type="submit" class="btn-primary">保存并选用</button>
</div>
</form>
</dialog>
<dialog id="persona-dialog" class="profile-dialog">
<form id="persona-form" method="dialog">
<h3 id="persona-dialog-title">新增用户角色</h3>
<label>
名称
<input name="name" required placeholder="例如 林晚,或创作默认用 @玩家" autocomplete="off" />
</label>
<label>
人设
<textarea name="description" rows="6" placeholder="性格、外貌、背景……(可空)"></textarea>
</label>
<label class="check-label">
<input type="checkbox" name="creationDefault" />
<span>
作为创作默认用户设定
<span class="field-hint">创作阶段填入预设的用户设定洞。建议名称写成 @玩家,这样开场白会自然用该占位,进游玩再换成当前角色。</span>
</span>
</label>
<div class="dialog-actions">
<button type="button" id="persona-cancel" class="btn-secondary">取消</button>
<button type="submit" class="btn-primary">保存并选用</button>
</div>
</form>
</dialog>
<input type="file" id="preset-file" accept=".json,application/json" hidden />
<script src="/settings.js" type="module"></script>
</body>
</html>