first commit
This commit is contained in:
@@ -0,0 +1,219 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>BLACK BEAN · 黑豆</title>
|
||||
<link rel="stylesheet" href="/static/style.css?v=20260814a">
|
||||
</head>
|
||||
<body>
|
||||
<div class="app">
|
||||
<!-- ===== 侧栏 ===== -->
|
||||
<aside class="sidebar" id="sidebar">
|
||||
<div class="brand">
|
||||
<div class="brand-mark">豆</div>
|
||||
<div class="brand-copy">
|
||||
<strong>BLACK BEAN</strong>
|
||||
<span>黑豆 · 智能体</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="new-chat-btn" id="new-chat-btn">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
||||
<path d="M12 5v14M5 12h14"/>
|
||||
</svg>
|
||||
新建任务
|
||||
</button>
|
||||
|
||||
<div class="sidebar-search">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="11" cy="11" r="7"/>
|
||||
<path d="m21 21-4.3-4.3"/>
|
||||
</svg>
|
||||
<input id="session-search" type="text" placeholder="搜索会话…" autocomplete="off" spellcheck="false">
|
||||
</div>
|
||||
|
||||
<div class="sidebar-label">会话</div>
|
||||
<nav class="session-list" id="session-list"></nav>
|
||||
|
||||
<div class="sidebar-footer">
|
||||
<span class="model-chip" id="model-chip">模型未配置</span>
|
||||
<div class="sidebar-footer-actions">
|
||||
<button class="icon-btn" id="refresh-btn" title="刷新">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
||||
<path d="M21 12a9 9 0 1 1-2.64-6.36M21 3v6h-6"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="icon-btn" id="settings-btn" title="设置">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="3"/>
|
||||
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- ===== 主区域 ===== -->
|
||||
<main class="main">
|
||||
<header class="topbar">
|
||||
<button class="icon-btn menu-btn" id="menu-btn" title="侧栏">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
||||
<path d="M4 6h16M4 12h16M4 18h16"/>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="topbar-title-wrap">
|
||||
<div class="topbar-title" id="session-title">新任务</div>
|
||||
<div class="topbar-sub" id="session-sub"></div>
|
||||
</div>
|
||||
<div class="topbar-right">
|
||||
<span class="ctx-chip hidden" id="ctx-chip"></span>
|
||||
<div class="topbar-status">
|
||||
<span class="status-dot" id="status-dot"></span>
|
||||
<span id="status-text">就绪</span>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- 协作任务实时状态 -->
|
||||
<div class="coop-panel hidden" id="coop-panel">
|
||||
<div class="coop-panel-header" id="coop-panel-header">
|
||||
<span class="coop-panel-title">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/>
|
||||
<circle cx="9" cy="7" r="4"/>
|
||||
<path d="M23 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75"/>
|
||||
</svg>
|
||||
worker 任务
|
||||
</span>
|
||||
<span class="coop-panel-count" id="coop-count"></span>
|
||||
</div>
|
||||
<div class="coop-list" id="coop-list"></div>
|
||||
</div>
|
||||
|
||||
<!-- 任务时间轴 -->
|
||||
<div class="timeline" id="chat">
|
||||
<div class="empty-state" id="empty-state">
|
||||
<div class="empty-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="3"/>
|
||||
<path d="M12 2v3M12 19v3M2 12h3M19 12h3M4.9 4.9l2.1 2.1M17 17l2.1 2.1M19.1 4.9 17 7M7 17l-2.1 2.1"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h1>黑豆 · 听君差遣</h1>
|
||||
<p>运行命令、读写文件、执行 Python、操作 Docker,并可调度 worker 任务处理复杂任务。工具皆于本地工作区真实执行。</p>
|
||||
<div class="examples">
|
||||
<button class="example" data-prompt="列出当前工作区目录结构,并说明每个文件的作用。">浏览工作区并说明结构</button>
|
||||
<button class="example" data-prompt="分析 sample_server.log,找出响应时间最长的 5 条请求并给出结论。">分析日志定位慢请求</button>
|
||||
<button class="example" data-prompt="写一个 Python 脚本统计 access 日志中每个 IP 的请求次数,并输出 Top 10。">用 Python 统计数据</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 返回底部 -->
|
||||
<button class="scroll-bottom hidden" id="scroll-bottom-btn" title="回到底部">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="m6 9 6 6 6-6"/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- 输入台 -->
|
||||
<div class="composer-wrap">
|
||||
<div class="composer">
|
||||
<textarea id="input" rows="1" placeholder="落笔命题,如:分析 server.log 中响应时间最长的 5 条请求..."></textarea>
|
||||
<div class="composer-actions">
|
||||
<span class="context-hint" id="context-hint"></span>
|
||||
<button class="stop-btn hidden" id="stop-btn" title="停止">
|
||||
<svg viewBox="0 0 24 24" fill="currentColor">
|
||||
<rect x="7" y="7" width="10" height="10" rx="2"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="send-btn" id="send-btn" title="投递">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="m5 12 14-7-4.5 14-3.5-6.5L5 12z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p class="disclaimer">工具调用于本地工作区真实执行 · Enter 投递 · Shift + Enter 换行</p>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<!-- ===== 设置弹窗 ===== -->
|
||||
<div class="modal-overlay hidden" id="settings-modal">
|
||||
<div class="modal">
|
||||
<div class="modal-header">
|
||||
<strong>设置</strong>
|
||||
<button class="icon-btn" id="close-settings-btn" title="关闭">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
||||
<path d="M6 6l12 12M18 6 6 18"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="settings-group">
|
||||
<div class="settings-group-title">模型 API</div>
|
||||
<label class="modal-label" for="provider-select">接口类型</label>
|
||||
<select id="provider-select">
|
||||
<option value="openai">OpenAI 兼容(SiliconFlow / OpenRouter / 中转站)</option>
|
||||
<option value="anthropic">Anthropic(Claude Messages API)</option>
|
||||
</select>
|
||||
<label class="modal-label" for="api-key-input">API Key</label>
|
||||
<input type="password" id="api-key-input" autocomplete="off" spellcheck="false" placeholder="未配置">
|
||||
<label class="modal-label" for="base-url-input">Base URL</label>
|
||||
<input type="text" id="base-url-input" autocomplete="off" spellcheck="false" placeholder="https://api.siliconflow.cn/v1/chat/completions">
|
||||
<label class="modal-label" for="model-input">模型</label>
|
||||
<input type="text" id="model-input" autocomplete="off" spellcheck="false" placeholder="Qwen/Qwen3-32B">
|
||||
<p class="modal-hint" id="provider-hint">OpenAI 兼容模式使用 Bearer Token 认证,Base URL 填写 /v1/chat/completions 地址。</p>
|
||||
<p class="modal-hint">字段留空表示不修改当前配置;API Key 输入新值即替换,保存后立即生效。</p>
|
||||
</div>
|
||||
<div class="settings-group">
|
||||
<div class="settings-group-title">Docker</div>
|
||||
<label class="modal-label" for="docker-socket-input">Docker Socket 地址</label>
|
||||
<input type="text" id="docker-socket-input" autocomplete="off" spellcheck="false" placeholder="npipe:////./pipe/docker_engine">
|
||||
<p class="modal-hint">默认操作本机 Docker。可填写远程 Docker 服务器的 socket 地址,例如 <code>unix:///var/run/docker.sock</code>、<code>npipe:////./pipe/docker_engine</code>、<code>tcp://192.168.1.10:2375</code>。保存后 Agent 的 Docker 工具立即生效。</p>
|
||||
<label class="modal-label" for="coop-engine-select">协作引擎</label>
|
||||
<select id="coop-engine-select">
|
||||
<option value="pi">pi(pi-coding-agent,支持 openai + anthropic)</option>
|
||||
<option value="pigo">pigo(pigo,支持 openai + anthropic)</option>
|
||||
<option value="claude">Claude Code(仅支持 anthropic 协议)</option>
|
||||
</select>
|
||||
<p class="modal-hint">协作任务的默认引擎。run_coop 未显式指定 engine 时使用此默认值。Claude Code 仅支持 Anthropic 协议端点;pi 与 pigo 同时支持 openai 与 anthropic。</p>
|
||||
<label class="modal-label" for="coop-mode-select">Worker 管理模式</label>
|
||||
<select id="coop-mode-select">
|
||||
<option value="local">本地子进程(无需 Docker,默认)</option>
|
||||
<option value="docker">Docker 容器(需本机/远程 Docker daemon)</option>
|
||||
</select>
|
||||
<p class="modal-hint">控制层对 worker 的管理方式。本地模式通过子进程直接运行 supervisor.sh,无需 Docker,适用于托管沙箱等环境;Docker 模式通过容器隔离运行,需 Docker daemon。</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn" id="reset-settings-btn">恢复默认</button>
|
||||
<button class="btn btn-primary" id="save-settings-btn">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ===== 授权弹窗(仅启用授权时展示) ===== -->
|
||||
<div class="modal-overlay hidden" id="auth-modal">
|
||||
<div class="modal">
|
||||
<div class="modal-header">
|
||||
<strong>授权验证</strong>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p class="modal-hint">此实例已启用访问授权。请输入部署时配置的授权码以继续使用。</p>
|
||||
<label class="modal-label" for="auth-code-input">授权码</label>
|
||||
<input type="password" id="auth-code-input" autocomplete="off" spellcheck="false" placeholder="请输入授权码">
|
||||
<p class="modal-hint auth-error hidden" id="auth-error"></p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-primary" id="auth-submit-btn">验证</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toast" id="toast"></div>
|
||||
<script src="/static/app.js?v=20260814a"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user