Files
hermes-agent-home/hermes-agent-web/templates/index.html
T
carlandCursor 5341a7617b Initial commit: Hermes Agent 多实例管理与 Web 控制台
基于官方 nousresearch/hermes-agent 镜像的 CLI、Docker Compose 与 Web 管理界面,支持多实例部署;敏感配置与实例数据由 .gitignore 排除。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-17 13:56:04 +08:00

107 lines
5.6 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.
{% extends "base.html" %}
{% block title %}实例 · Hermes Agent Web{% endblock %}
{% block body %}
<h2 style="margin-top:0;">实例</h2>
<p class="muted">
数据目录:<code>{{ data_root }}</code> ·
合计 <strong>{{ total }}</strong> 个实例 ·
网关运行中 <strong>{{ running_n }}</strong> 个
· 列表「所属人」记在每台目录下的 <code>web-meta.json</code>(与 <code>data/config.yaml</code> 分离)
</p>
<p class="muted" style="max-width:52rem;">
首次配置请点 <strong>「Hermes 引导」</strong>(<code>setup</code> → 启动 gateway → 容器 shell)。
Docker 项目名 <code>hermes-&lt;序号&gt;</code>,服务 <code>gateway</code>(NousResearch/hermes-agent)。
</p>
{% if compose_error %}
<div class="flash error">Compose 配置错误:{{ compose_error }}</div>
{% endif %}
<form method="post" action="{{ url_for('instance_create') }}" style="margin:1rem 0;">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<button type="submit" class="primary">新建实例</button>
<span class="muted">将分配新序号、创建目录并执行 <code>bootstrap</code>;之后可点「启动」拉起网关。</span>
</form>
{% if not rows %}
<p class="muted">暂无实例。点击「新建实例」开始。</p>
{% else %}
<table>
<thead>
<tr>
<th>#</th>
<th>状态</th>
<th>所属人</th>
<th>端口</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for r in rows %}
<tr>
<td><strong>{{ r.id }}</strong></td>
<td>
{% if r.status.running %}
<span class="badge ok">运行中</span>
{% elif r.status.state == 'not_created' %}
<span class="badge off">未创建容器</span>
{% elif r.status.state in ('exited', 'dead') %}
<span class="badge off">已停止</span> <span class="muted">{{ r.status.state }}</span>
{% else %}
<span class="badge err">{{ r.status.state }}</span>
{% endif %}
{% if r.status.name %}
<div class="muted" style="margin-top:0.35rem;"><code>{{ r.status.name }}</code></div>
{% endif %}
{% if r.status.detail %}
<div class="muted" style="margin-top:0.25rem;">{{ r.status.detail }}</div>
{% endif %}
{% if not r.has_config %}
<div class="muted" style="margin-top:0.25rem;">未配置(无 config.yaml / .env)</div>
{% endif %}
</td>
<td style="min-width:12rem;vertical-align:middle;">
<form method="post" action="{{ url_for('instance_set_owner', iid=r.id) }}" style="margin:0;display:flex;flex-direction:column;gap:0.45rem;align-items:stretch;">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input type="text" name="owner" value="{{ r.metadata_owner }}" placeholder="未设置" maxlength="128" autocomplete="off" style="width:50%;box-sizing:border-box;padding:0.4rem 0.5rem;border-radius:6px;border:1px solid var(--border);background:#0c1017;color:var(--text);font:inherit;">
<button type="submit" class="btn" style="align-self:flex-start;">保存</button>
</form>
</td>
<td>
<span class="muted">网关</span> <code>{{ r.gateway_port }}</code>
<br>
<span class="muted">Dashboard</span> <code>{{ r.dashboard_port }}</code>
</td>
<td>
<div class="row-actions">
<form method="post" action="{{ url_for('instance_compose_build', iid=r.id) }}" style="margin:0;display:inline;">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<button type="submit" title="从 Docker Hub 拉取官方镜像 nousresearch/hermes-agent">拉取镜像</button>
</form>
<form method="post" action="{{ url_for('instance_run', iid=r.id) }}" style="margin:0;display:inline;">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<button type="submit" class="primary">启动</button>
</form>
<a href="{{ url_for('instance_guide', iid=r.id) }}" class="btn primary" style="display:inline-block;padding:0.35rem 0.65rem;text-decoration:none;background:#1a4d7a;border:1px solid #2563a8;border-radius:6px;color:#e7edf4;font:inherit;">Hermes 引导</a>
<a href="{{ url_for('instance_docker_terminal', iid=r.id) }}" class="btn" style="display:inline-block;padding:0.35rem 0.65rem;text-decoration:none;background:#111827;border:1px solid #374151;border-radius:6px;color:#e7edf4;font:inherit;">终端</a>
<form method="post" action="{{ url_for('instance_stop', iid=r.id) }}" style="margin:0;display:inline;">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<button type="submit">停止</button>
</form>
<form method="post" action="{{ url_for('instance_restart', iid=r.id) }}" style="margin:0;display:inline;">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<button type="submit">重启</button>
</form>
<form method="post" action="{{ url_for('instance_destroy', iid=r.id) }}" style="margin:0;display:inline;" onsubmit="return confirm('确定销毁该实例?将执行 compose down,并永久删除宿主机上该序号的配置与工作区目录(不可恢复)。');">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<button type="submit" class="danger">销毁</button>
</form>
<a href="{{ url_for('instance_config', iid=r.id) }}">编辑配置</a>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% endblock %}