--- /dev/null
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
+<title>Codebuddy Web Console · 设计说明</title>
+<style>
+ * { margin: 0; padding: 0; box-sizing: border-box; }
+ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Microsoft YaHei", sans-serif;
+ color: #222; line-height: 1.7; background: #f5f6fa; padding: 32px 16px; }
+ .wrap { max-width: 920px; margin: 0 auto; background: #fff; border-radius: 14px; padding: 36px 40px; box-shadow: 0 4px 24px rgba(0,0,0,0.06); }
+ header { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; border-bottom: 2px solid #4ecca3; padding-bottom: 16px; margin-bottom: 8px; }
+ h1 { font-size: 24px; color: #1a1a2e; }
+ .sub { color: #888; font-size: 13px; margin-top: 4px; }
+ .btn-pdf { flex-shrink: 0; background: #4ecca3; color: #06281f; border: none; border-radius: 8px; padding: 8px 14px; cursor: pointer; font-size: 13px; font-weight: 600; }
+ .btn-pdf:hover { background: #6fd9b4; }
+ h2 { font-size: 19px; color: #1a1a2e; margin: 28px 0 10px; padding-left: 10px; border-left: 4px solid #4ecca3; }
+ h3 { font-size: 16px; color: #157a5e; margin: 18px 0 6px; }
+ p { margin: 6px 0; color: #333; }
+ ul, ol { margin: 6px 0 6px 22px; }
+ li { margin: 4px 0; }
+ code { background: #eef6f2; color: #157a5e; padding: 1px 6px; border-radius: 5px; font-size: 13px; font-family: "Cascadia Code", Menlo, Consolas, monospace; }
+ .tag { display: inline-block; background: #1a1a2e; color: #4ecca3; border-radius: 6px; padding: 2px 8px; font-size: 12px; margin: 2px 4px 2px 0; }
+ table { width: 100%; border-collapse: collapse; margin: 10px 0; font-size: 14px; }
+ th, td { text-align: left; padding: 8px 10px; border-bottom: 1px solid #e3e6ee; vertical-align: top; }
+ th { background: #f0f3f8; color: #1a1a2e; }
+ .note { background: #fff8e6; border: 1px solid #ffe08a; border-radius: 8px; padding: 10px 14px; margin: 10px 0; font-size: 13px; color: #6b5a1f; }
+ .page { background: #f0f3ff; border: 1px solid #c9d4ff; border-radius: 8px; padding: 12px 16px; margin: 10px 0; }
+ footer { margin-top: 32px; padding-top: 14px; border-top: 1px solid #eee; color: #aaa; font-size: 12px; text-align: center; }
+ a { color: #157a5e; }
+ @media print {
+ body { background: #fff; padding: 0; }
+ .wrap { box-shadow: none; max-width: 100%; padding: 0 8px; }
+ .btn-pdf { display: none; }
+ h2 { page-break-after: avoid; }
+ .page, .note { break-inside: avoid; }
+ }
+ @page { margin: 16mm; }
+</style>
+</head>
+<body>
+<div class="wrap">
+ <header>
+ <div>
+ <h1>Codebuddy Web Console · 设计说明</h1>
+ <div class="sub">通过浏览器远程使用 Codebuddy CLI 的 Web 控制台 · 多会话 / 全局技能 / 文件上传 / 移动端适配</div>
+ </div>
+ <button class="btn-pdf" onclick="window.print()">⬇ 下载 PDF</button>
+ </header>
+
+ <h2>一、整体架构</h2>
+ <ul>
+ <li><b>后端</b>:FastAPI + WebSocket PTY。每个“任务”对应一个独立运行的 <code>codebuddy</code> CLI 进程。</li>
+ <li><b>前端</b>:单文件原生 HTML(无前端框架)。通过 URL 参数区分页面:<code>/</code> 为任务列表页,<code>/?task=<任务ID></code> 为对应任务的终端页。</li>
+ <li><b>技能</b>:存储于全局目录 <code>~/.codebuddy/skills</code>。上传后对所有会话可见;运行中的会话可“热加载”即时生效,否则下次打开会话时由 codebuddy 自动发现。</li>
+ <li><b>上传文件</b>:统一存于服务端的 <code>data/pastes/</code> 目录,并可在“已上传文件”面板中集中管理。</li>
+ </ul>
+
+ <h2>二、页面与功能</h2>
+
+ <div class="page">
+ <h3>1. 登录页</h3>
+ <ul>
+ <li>输入访问密码进入控制台(密码保存在浏览器 <code>localStorage</code>)。</li>
+ </ul>
+ </div>
+
+ <div class="page">
+ <h3>2. 任务列表页(首页)</h3>
+ <p>默认展示“启用中”的任务,可勾选“显示全部任务”查看包括已暂停的全部任务。</p>
+ <h3>左侧 · 技能侧边栏(🧩 技能 全局)</h3>
+ <ul>
+ <li><b>上传</b>:选择 skill 的 zip(须以单个 skill 目录为顶层,内含 <code>SKILL.md</code>),上传后对所有会话全局可见。</li>
+ <li><b>技能列表卡片</b>:每张卡片提供 <span class="tag">更新</span><span class="tag">编辑</span><span class="tag">加载</span><span class="tag">删除</span>。
+ <ul>
+ <li><b>更新</b>:用新 zip 覆盖同名 skill(按 zip 内声明名匹配,避免产生重复目录)。</li>
+ <li><b>编辑</b>:直接修改 <code>SKILL.md</code> 内容。</li>
+ <li><b>加载</b>:选择“运行中的会话”注入热加载通知(可多选,或一键“全部运行中的会话”);若无运行会话则技能已全局就位,下次打开自动发现。</li>
+ <li><b>删除</b>:移除该全局 skill。</li>
+ </ul>
+ </li>
+ <li><b>📂 已上传文件</b>:打开“已上传文件”管理弹窗(详见第 4 节)。</li>
+ </ul>
+ <h3>主区 · 任务卡片</h3>
+ <ul>
+ <li>展示:任务名、工作目录、状态、最近使用时间。</li>
+ <li>状态指示:<span class="tag">● 前台已登录</span><span class="tag">⚙ 后台运行中</span><span class="tag">⏸ 后台等待中</span><span class="tag">⏳ 后台任务待确认</span><span class="tag">⏸ 已暂停</span><span class="tag">○ 空闲</span>。</li>
+ <li>操作:打开终端、重启会话、暂停/恢复、删除(可同时删除历史会话记录与工作目录)。</li>
+ </ul>
+ <p class="note">列表页每 5 秒自动刷新一次,实时反映各会话状态。</p>
+ </div>
+
+ <div class="page">
+ <h3>3. 终端页(<code>/?task=<ID></code>)</h3>
+ <h3>顶部栏</h3>
+ <ul>
+ <li>连接状态指示灯 + 文本、任务名、工作目录。</li>
+ <li>模型切换下拉(切换后重启会话以应用)。</li>
+ <li>按钮:<span class="tag">↻ 重启会话</span><span class="tag">≡ 列表</span><span class="tag">📋 粘贴</span><span class="tag">🧩 技能</span><span class="tag">❓ 帮助</span><span class="tag">✕ 关闭</span>。</li>
+ </ul>
+ <h3>终端输出区(xterm)</h3>
+ <ul>
+ <li>实时显示 CLI 输出;新输出自动滚动贴底。</li>
+ <li>手动上滑查看历史时,右下角出现 <span class="tag">↓ 回到底部</span> 按钮,点击即回到最新。</li>
+ </ul>
+ <h3>粘贴框(📋)</h3>
+ <ul>
+ <li>文本直接输入;<code>Ctrl+Enter</code> 发送到终端输入行(不自动提交,需自行回车)。</li>
+ <li><b>📎 附件</b>:支持上传 <b>图片 / 视频 / zip / 任意格式</b> 文件,单文件上限 <b>5MB</b>。</li>
+ <li>待发送文件以 chip 展示(图标区分 🖼 图片 / 🎬 视频 / 📦 压缩包 / 📄 其他)。</li>
+ <li>发送规则:图片包装为 <code><image_local_path>路径</image_local_path></code>;其它文件发送其本地路径文本,供命令行引用。</li>
+ <li>粘贴框内“已上传文件”区:列出本次/历史上传文件,可单独删除。</li>
+ </ul>
+ <h3>技能弹窗(🧩,终端页内)</h3>
+ <ul>
+ <li>功能与列表页左侧技能侧边栏一致(上传/更新/编辑/加载/删除)。</li>
+ </ul>
+ </div>
+
+ <div class="page">
+ <h3>4. 已上传文件弹窗</h3>
+ <p>从列表页「📂 已上传文件」按钮打开,以表格管理所有上传文件:</p>
+ <table>
+ <thead><tr><th>列</th><th>说明</th></tr></thead>
+ <tbody>
+ <tr><td>选择框</td><td>每行可勾选;表头“全选”一键勾选全部。</td></tr>
+ <tr><td>文件名</td><td>服务端存储的文件名。</td></tr>
+ <tr><td>上传时间</td><td>文件写入时间(本地时间)。</td></tr>
+ <tr><td>所属会话任务</td><td>上传时所在的终端会话名;历史文件(升级前上传)显示 <code>—</code>。</td></tr>
+ <tr><td>文件类型</td><td>按扩展名/格式显示,如 <code>.png</code> / <code>.zip</code> / <code>.mp4</code>。</td></tr>
+ <tr><td>操作</td><td>单条“删除”。</td></tr>
+ </tbody>
+ </table>
+ <ul>
+ <li><b>批量删除</b>:勾选多个后点“删除所选”(带二次确认)。</li>
+ <li>删除同时从服务端磁盘移除文件,并清理其会话归属索引。</li>
+ </ul>
+ </div>
+
+ <h2>三、移动端(iPad / 手机)适配</h2>
+ <ul>
+ <li><b>顶栏固定</b>:顶部菜单栏锁定在视口顶部,不随页面滚动;整页只有终端区内部滚动。</li>
+ <li><b>键盘适配</b>:软键盘弹起时,终端区自动缩小到键盘上方,输入内容始终可见。</li>
+ <li><b>自动滚动</b>:CLI 新输出自动贴底,无需手动下拉。</li>
+ <li><b>标签页标题</b>:浏览器标签页显示为 <code>会话名 - CLI</code>(如 <code>Words - CLI</code>),便于多标签区分。</li>
+ <li><b>安全区域</b>:适配刘海与底部指示条(<code>env(safe-area-inset)</code>)。</li>
+ </ul>
+
+ <h2>四、快捷操作</h2>
+ <ul>
+ <li><code>Ctrl+Enter</code>:在粘贴框发送内容。</li>
+ <li><code>Esc</code>:关闭弹窗(粘贴框 / 技能框 / 已上传文件框)。</li>
+ <li>多会话选择 + “全部运行中的会话”:一键把 skill 热加载到多个会话。</li>
+ </ul>
+
+ <h2>五、常见问题</h2>
+ <div class="note">
+ <b>Q:上传视频/zip 提示不支持或过大?</b><br>
+ 服务端已内置“任意格式 + 5MB”支持;若仍报错,多为服务端尚未重启生效,重启 <code>codebuddy-web.service</code> 即可。
+ </div>
+ <div class="note">
+ <b>Q:已上传文件的“所属会话任务”是空/—?</b><br>
+ 仅“升级后、从终端页新上传”的文件会记录所属会话;升级前上传的历史文件因当时未记录归属,故显示 <code>—</code>,无法反查。
+ </div>
+
+ <footer>
+ Codebuddy Web Console · 设计说明(随仓库 <code>frontend/help.html</code> 提供) · 在应用内点「❓ 帮助」可随时打开
+ </footer>
+</div>
+</body>
+</html>