349 lines
17 KiB
HTML
349 lines
17 KiB
HTML
<!doctype html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<title>HWLAB 云工作台</title>
|
|
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
|
<link rel="stylesheet" href="/styles.css" />
|
|
<script type="module" src="/app.js"></script>
|
|
</head>
|
|
<body data-auth-state="checking">
|
|
<section class="login-shell" id="login-shell" data-auth-login aria-labelledby="login-title">
|
|
<div class="login-panel">
|
|
<div class="login-heading">
|
|
<p class="eyebrow">HWLAB</p>
|
|
<h1 id="login-title">云工作台登录</h1>
|
|
<p>请输入账号和密码。</p>
|
|
</div>
|
|
<form class="login-form" id="login-form" autocomplete="on">
|
|
<label>
|
|
<span>用户名</span>
|
|
<input id="login-username" name="username" type="text" autocomplete="username" inputmode="text" required />
|
|
</label>
|
|
<label>
|
|
<span>密码</span>
|
|
<input id="login-password" name="password" type="password" autocomplete="current-password" required />
|
|
</label>
|
|
<p class="login-error" id="login-error" role="alert" hidden></p>
|
|
<button class="login-submit" id="login-submit" type="submit">登录</button>
|
|
</form>
|
|
</div>
|
|
</section>
|
|
|
|
<main class="workbench-shell" data-app-shell data-help-route-policy="non-default-internal-help" data-internal-help-path="/help.md" hidden aria-hidden="true">
|
|
<aside class="activity-rail" id="activity-rail" aria-label="工作台活动栏">
|
|
<button class="rail-button active" type="button" data-route="workspace" title="工作台" aria-label="工作台">工作台</button>
|
|
<button class="rail-button" type="button" data-route="skills" title="Skills" aria-label="Skills">Skills</button>
|
|
<button class="rail-button" type="button" data-route="gate" title="内部复核" aria-label="内部复核">内部复核</button>
|
|
<button class="rail-button" type="button" data-route="help" title="使用说明" aria-label="使用说明">使用说明</button>
|
|
<span class="rail-spacer" aria-hidden="true"></span>
|
|
<button
|
|
class="rail-button sidebar-toggle"
|
|
id="left-sidebar-toggle"
|
|
type="button"
|
|
aria-controls="activity-rail"
|
|
aria-expanded="true"
|
|
aria-label="折叠左侧导航"
|
|
title="折叠左侧导航"
|
|
>收起</button>
|
|
</aside>
|
|
<div
|
|
class="resize-handle left-sidebar-resize"
|
|
id="left-sidebar-resize"
|
|
role="separator"
|
|
tabindex="0"
|
|
aria-label="拖拽调整左侧导航宽度"
|
|
aria-controls="activity-rail"
|
|
aria-orientation="vertical"
|
|
aria-valuemin="72"
|
|
aria-valuemax="180"
|
|
aria-valuenow="92"
|
|
title="拖拽调整左侧导航宽度;用左右方向键微调,Home/End 到最小或最大。"
|
|
></div>
|
|
|
|
<aside class="session-sidebar" id="session-sidebar" aria-label="Code Agent sessions">
|
|
<header class="session-sidebar-head">
|
|
<div>
|
|
<p class="eyebrow">Sessions</p>
|
|
<h2>Agent Sessions</h2>
|
|
</div>
|
|
<button class="session-icon-button" id="session-create" type="button" aria-label="创建 session" title="创建 session">+</button>
|
|
</header>
|
|
<div class="session-tabs" id="session-tabs" role="tablist" aria-label="Code Agent sessions"></div>
|
|
<div class="session-sidebar-foot">
|
|
<span class="session-status" id="session-status">等待 workspace</span>
|
|
<button class="session-delete-button" id="session-delete" type="button" disabled>删除当前</button>
|
|
</div>
|
|
</aside>
|
|
|
|
<section class="center-workspace">
|
|
<section class="view workbench-view" id="workspace" data-view="workspace" aria-labelledby="workspace-title">
|
|
<div class="conversation-column">
|
|
<div class="workspace-panel conversation-panel">
|
|
<div class="panel-title-row">
|
|
<div>
|
|
<p class="eyebrow">Agent 工作区</p>
|
|
<h2 id="workspace-title">Agent 对话</h2>
|
|
</div>
|
|
<span class="state-tag tone-source" id="agent-chat-status">等待输入</span>
|
|
</div>
|
|
<details class="code-agent-summary tone-border-pending" id="code-agent-summary">
|
|
<summary>
|
|
<span class="code-agent-summary-icon tone-pending" id="code-agent-summary-icon" aria-hidden="true">○</span>
|
|
<strong class="code-agent-summary-label tone-pending" id="code-agent-summary-label">探测中</strong>
|
|
<span class="code-agent-summary-capability" id="code-agent-summary-capability">未观测</span>
|
|
<span class="code-agent-summary-trace" id="code-agent-summary-trace">trace 未观测</span>
|
|
</summary>
|
|
<div class="code-agent-summary-detail" id="code-agent-summary-detail"></div>
|
|
</details>
|
|
<div class="session-tabs" id="session-tabs" role="tablist" aria-label="Code Agent sessions"></div>
|
|
<div class="conversation-list" id="conversation-list" aria-live="polite"></div>
|
|
</div>
|
|
|
|
</div>
|
|
</section>
|
|
|
|
<section class="view help-view" id="help" data-view="help" aria-labelledby="help-title" hidden>
|
|
<div class="workspace-panel help-panel">
|
|
<div class="panel-title-row">
|
|
<div>
|
|
<p class="eyebrow">内部说明</p>
|
|
<h2 id="help-title">使用说明</h2>
|
|
</div>
|
|
<span class="state-tag tone-dry-run" id="help-status">加载中</span>
|
|
</div>
|
|
<div id="help-content" class="help-content" aria-live="polite"></div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="view skills-view" id="skills" data-view="skills" aria-labelledby="skills-title" hidden>
|
|
<div class="workspace-panel skills-panel">
|
|
<div class="panel-title-row">
|
|
<div>
|
|
<p class="eyebrow">Skills</p>
|
|
<h2 id="skills-title">Skill 管理</h2>
|
|
</div>
|
|
<div class="skills-actions">
|
|
<span class="state-tag tone-source" id="skill-status">未加载</span>
|
|
<button class="command-button secondary" id="skill-refresh" type="button">刷新</button>
|
|
</div>
|
|
</div>
|
|
<div class="skills-layout">
|
|
<section class="skill-upload-panel" aria-label="上传 skill">
|
|
<form id="skill-upload-form" class="skill-upload-form">
|
|
<label class="skill-upload-drop">
|
|
<span>选择目录</span>
|
|
<input id="skill-upload-input" type="file" multiple webkitdirectory directory />
|
|
</label>
|
|
<button class="command-button" id="skill-upload-button" type="submit">上传</button>
|
|
</form>
|
|
<div id="skill-assembly" class="skill-assembly" aria-live="polite"></div>
|
|
<div id="skill-list" class="skill-list" aria-label="Skill 列表" aria-live="polite"></div>
|
|
</section>
|
|
<section class="skill-detail-panel" aria-label="Skill 文件">
|
|
<div class="panel-title-row skill-detail-head">
|
|
<div>
|
|
<p class="eyebrow">Skill Files</p>
|
|
<h3 id="skill-detail-title">未选择 skill</h3>
|
|
</div>
|
|
</div>
|
|
<div id="skill-tree" class="skill-tree" aria-label="Skill 文件树"></div>
|
|
</section>
|
|
<section class="skill-preview-panel" aria-label="SKILL.md 预览">
|
|
<div id="skill-preview" class="skill-preview" aria-live="polite">等待 SKILL.md。</div>
|
|
</section>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="view gate-view" id="gate" data-view="gate" aria-labelledby="gate-title" hidden>
|
|
<header class="gate-header">
|
|
<div>
|
|
<p class="eyebrow">内部二级入口</p>
|
|
<h2 id="gate-title">内部复核</h2>
|
|
</div>
|
|
<span class="state-tag tone-source" id="gate-source-status">等待 live 后端</span>
|
|
</header>
|
|
<div class="gate-controls" aria-label="内部复核过滤控件">
|
|
<label>
|
|
<span>状态</span>
|
|
<select id="gate-status-filter">
|
|
<option value="all">全部</option>
|
|
<option value="通过">通过</option>
|
|
<option value="阻塞">阻塞</option>
|
|
<option value="失败">失败</option>
|
|
<option value="待验证">待验证</option>
|
|
<option value="信息">信息</option>
|
|
</select>
|
|
</label>
|
|
<label>
|
|
<span>搜索</span>
|
|
<input id="gate-search" type="search" placeholder="按类别、检查项、对象或 trace 搜索" autocomplete="off" />
|
|
</label>
|
|
<button class="command-button secondary" id="gate-refresh" type="button">刷新</button>
|
|
</div>
|
|
<div class="gate-table-wrap">
|
|
<table class="gate-table" aria-describedby="gate-source-status">
|
|
<thead>
|
|
<tr>
|
|
<th>类别</th>
|
|
<th>检查项</th>
|
|
<th>状态</th>
|
|
<th>归因对象</th>
|
|
<th>关键细节</th>
|
|
<th>证据/trace</th>
|
|
<th>更新时间</th>
|
|
<th>下一步</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="gate-review-body">
|
|
<tr>
|
|
<td colspan="8">正在读取 live 后端聚合。</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</section>
|
|
|
|
<form class="command-bar" id="command-form" aria-label="Agent 输入">
|
|
<label class="agent-timeout-control" for="code-agent-provider-profile">
|
|
<span>模型通道</span>
|
|
<select id="code-agent-provider-profile" aria-label="Code Agent 模型通道">
|
|
<option value="deepseek" selected>DeepSeek</option>
|
|
<option value="codex-api">Codex API</option>
|
|
<option value="minimax-m3">MiniMax-M3</option>
|
|
</select>
|
|
</label>
|
|
<label class="agent-timeout-control" for="code-agent-timeout">
|
|
<span>无新事件超时</span>
|
|
<select id="code-agent-timeout" aria-label="Code Agent 无新事件超时">
|
|
<option value="180000">3 分钟</option>
|
|
<option value="300000">5 分钟</option>
|
|
<option value="600000">10 分钟</option>
|
|
<option value="900000">15 分钟</option>
|
|
<option value="1200000">20 分钟</option>
|
|
<option value="1800000" selected>30 分钟</option>
|
|
<option value="2400000">40 分钟</option>
|
|
</select>
|
|
</label>
|
|
<label class="agent-timeout-control" for="gateway-shell-timeout">
|
|
<span>Gateway 命令超时</span>
|
|
<select id="gateway-shell-timeout" aria-label="PC gateway shell 命令超时">
|
|
<option value="60000">1 分钟</option>
|
|
<option value="120000" selected>2 分钟</option>
|
|
<option value="180000">3 分钟</option>
|
|
<option value="300000">5 分钟</option>
|
|
<option value="600000">10 分钟</option>
|
|
</select>
|
|
</label>
|
|
<div class="input-shell">
|
|
<span class="prompt-mark">hwlab</span>
|
|
<textarea
|
|
id="command-input"
|
|
autocomplete="off"
|
|
rows="1"
|
|
placeholder="输入要发送给 Code Agent 的消息;不会直接触发硬件变更。"
|
|
></textarea>
|
|
</div>
|
|
<button class="command-button" id="command-send" type="submit">发送</button>
|
|
<button class="command-button secondary" id="command-clear" type="button">清空</button>
|
|
</form>
|
|
</section>
|
|
|
|
<aside class="right-sidebar" id="device-pod-sidebar" aria-label="Device Pod 摘要看板">
|
|
<div class="right-sidebar-control-row">
|
|
<button
|
|
class="right-sidebar-toggle"
|
|
id="right-sidebar-toggle"
|
|
type="button"
|
|
aria-controls="device-pod-sidebar"
|
|
aria-expanded="true"
|
|
aria-label="折叠右侧 Device Pod 看板"
|
|
title="折叠右侧 Device Pod 看板"
|
|
>收起看板</button>
|
|
<button class="logout-button" id="logout-button" type="button">退出</button>
|
|
</div>
|
|
<header class="sidebar-workbench-header">
|
|
<p class="eyebrow">用户工作台</p>
|
|
<h2>Agent 对话与 Device Pod 看板</h2>
|
|
<p id="route-path" class="route-path">当前浏览器会话只保存任务草稿,Device Pod 操作需通过受控后端流程。</p>
|
|
</header>
|
|
<div class="probe-card user-card" aria-live="polite">
|
|
<span class="metric-label">工作区状态</span>
|
|
<strong id="live-status" class="tone-pending">等待验证</strong>
|
|
<small id="live-detail">正在验证 hwlab-cloud-api /health/live、/v1、/v1/agent/chat 与 /v1/device-pods;未完成前不标为通过。</small>
|
|
<div class="live-build-summary" id="live-build-summary">
|
|
<button class="live-build-toggle" id="live-build-toggle" type="button" aria-haspopup="dialog" aria-expanded="false">
|
|
<span class="live-build-summary-label" id="live-build-latest">最新镜像构建时间:等待实时元数据</span>
|
|
</button>
|
|
</div>
|
|
<div class="live-build-list live-build-list-template" id="live-build-list" hidden aria-label="live HWLAB 微服务构建时间明细"></div>
|
|
</div>
|
|
<div
|
|
class="resize-handle right-sidebar-resize"
|
|
id="right-sidebar-resize"
|
|
role="separator"
|
|
tabindex="0"
|
|
aria-label="拖拽调整右侧 Device Pod 看板宽度"
|
|
aria-controls="device-pod-sidebar"
|
|
aria-orientation="vertical"
|
|
aria-valuemin="560"
|
|
aria-valuemax="740"
|
|
aria-valuenow="728"
|
|
title="拖拽调整右侧 Device Pod 看板宽度;用左右方向键微调,Home/End 到最小或最大。"
|
|
></div>
|
|
<section class="device-pod-status" aria-labelledby="device-pod-title">
|
|
<div class="panel-title-row">
|
|
<div>
|
|
<p class="eyebrow">Device Pod</p>
|
|
<h2 id="device-pod-title">设备目标看板</h2>
|
|
</div>
|
|
<span class="state-tag tone-source" id="device-pod-status-tag">未验证</span>
|
|
</div>
|
|
<div class="device-pod-selector-row">
|
|
<label for="device-pod-select">当前 Pod</label>
|
|
<select id="device-pod-select" aria-label="选择 Device Pod">
|
|
<option value="device-pod-71-freq">device-pod-71-freq</option>
|
|
</select>
|
|
</div>
|
|
<div id="device-pod-summary" class="device-pod-summary" data-static-source-fallback="FAKE">
|
|
<article class="summary-tile" data-device-detail="pod" data-device-title="Pod Summary" role="button" tabindex="0" aria-label="查看 Device Pod 摘要详情">
|
|
<span class="summary-title">Pod Summary</span>
|
|
<dl class="kv-list">
|
|
<div><dt>devicePodId</dt><dd id="device-pod-id">等待 /v1/device-pods</dd></div>
|
|
<div><dt>targetId</dt><dd id="device-pod-target">未观测</dd></div>
|
|
<div><dt>profile</dt><dd id="device-pod-profile">未观测</dd></div>
|
|
<div><dt>freshness</dt><dd id="device-pod-freshness">未观测</dd></div>
|
|
</dl>
|
|
</article>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="device-pod-workspace">
|
|
<div id="device-pod-interfaces" class="device-pod-interfaces" aria-label="Device Pod 四要素摘要"></div>
|
|
<section class="device-event-panel" aria-labelledby="device-event-title">
|
|
<div class="event-toolbar">
|
|
<span id="device-event-title">事件流</span>
|
|
<button id="device-event-follow" type="button" aria-pressed="true">跟随</button>
|
|
<button id="device-event-jump" type="button" hidden>有 0 条新事件</button>
|
|
</div>
|
|
<div id="device-event-scroll" class="device-event-scroll" tabindex="0" aria-label="Device Pod 纯文本事件流">
|
|
<pre id="device-event-text">等待 /v1/device-pods 事件流。</pre>
|
|
</div>
|
|
</section>
|
|
</section>
|
|
<dialog class="device-detail-dialog" id="device-detail-dialog" aria-labelledby="device-detail-title">
|
|
<form method="dialog" class="device-detail-shell">
|
|
<header class="device-detail-head">
|
|
<h2 id="device-detail-title">Device Pod 详情</h2>
|
|
<button class="command-button secondary" value="close" type="submit">关闭</button>
|
|
</header>
|
|
<pre id="device-detail-body" class="device-detail-body"></pre>
|
|
</form>
|
|
</dialog>
|
|
</aside>
|
|
</main>
|
|
</body>
|
|
</html>
|