Add files via upload

This commit is contained in:
公明
2026-04-24 11:04:55 +08:00
committed by GitHub
parent 88fd71e04c
commit 053534feaa
3 changed files with 142 additions and 23 deletions
+105 -9
View File
@@ -1144,12 +1144,18 @@ header {
.hitl-config-input {
width: 100%;
height: 38px;
border: 1px solid var(--border-color);
border: 1px solid #e2e8f0;
border-radius: 8px;
background: #fff;
padding: 0 10px;
padding: 0 12px;
font-size: 14px;
color: var(--text-primary);
transition: border-color 0.15s, box-shadow 0.15s;
}
.hitl-config-input:focus {
outline: none;
border-color: var(--accent-color, #0066ff);
box-shadow: 0 0 0 3px rgba(0, 102, 255, 0.1);
}
.hitl-pending-list {
@@ -1159,43 +1165,133 @@ header {
}
.hitl-pending-item {
border: 1px solid rgba(99, 102, 241, 0.25);
border: 1px solid #dbeafe;
border-radius: 10px;
padding: 12px;
background: rgba(15, 23, 42, 0.45);
padding: 16px;
background: #f8fbff;
transition: box-shadow 0.2s;
}
.hitl-pending-item:hover {
box-shadow: 0 2px 12px rgba(0, 102, 255, 0.08);
}
.hitl-pending-item-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.hitl-pending-item-title {
display: flex;
align-items: center;
gap: 8px;
}
.hitl-tool-badge {
display: inline-flex;
align-items: center;
padding: 3px 10px;
border-radius: 6px;
font-size: 13px;
font-weight: 600;
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
background: var(--accent-color, #0066ff);
color: #fff;
}
.hitl-mode-tag {
display: inline-flex;
align-items: center;
padding: 2px 8px;
border-radius: 10px;
font-size: 11px;
font-weight: 500;
background: #e0e7ff;
color: #4338ca;
}
.hitl-mode-tag--review_edit {
background: #fef3c7;
color: #92400e;
}
.hitl-pending-meta {
font-size: 12px;
color: #94a3b8;
margin-bottom: 8px;
word-break: break-all;
}
.hitl-pending-payload {
white-space: pre-wrap;
word-break: break-all;
max-height: 160px;
overflow: auto;
margin: 0 0 4px 0;
padding: 10px 12px;
border-radius: 8px;
background: #fff;
border: 1px solid #e2e8f0;
font-size: 12px;
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
color: #334155;
line-height: 1.5;
}
.hitl-pending-item-header-right {
display: flex;
align-items: center;
gap: 8px;
}
.hitl-dismiss-btn {
background: none;
border: none;
cursor: pointer;
font-size: 18px;
line-height: 1;
color: var(--text-secondary, #64748b);
padding: 2px 6px;
border-radius: 4px;
transition: background 0.15s, color 0.15s;
}
.hitl-dismiss-btn:hover {
background: rgba(239, 68, 68, 0.1);
color: #ef4444;
}
.hitl-pending-actions {
display: flex;
gap: 8px;
margin-top: 10px;
margin-top: 12px;
padding-top: 12px;
border-top: 1px solid #e2e8f0;
}
.hitl-edit-args {
width: 100%;
min-height: 76px;
margin-top: 8px;
border: 1px solid rgba(148, 163, 184, 0.35);
border: 1px solid #e2e8f0;
border-radius: 8px;
background: #ffffff;
color: #1f2937;
padding: 8px;
padding: 10px 12px;
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
font-size: 12px;
transition: border-color 0.15s, box-shadow 0.15s;
}
.hitl-edit-args:focus {
outline: none;
border-color: var(--accent-color, #0066ff);
box-shadow: 0 0 0 3px rgba(0, 102, 255, 0.1);
}
.hitl-input-help {
margin-top: 6px;
margin-bottom: 6px;
font-size: 12px;
color: #64748b;
color: var(--accent-color, #0066ff);
line-height: 1.4;
}
+34 -10
View File
@@ -282,21 +282,29 @@ async function refreshHitlPending() {
const preview = payload.length > 280 ? (payload.slice(0, 280) + '...') : payload;
const mode = String(item.mode || '').trim().toLowerCase();
const allowEdit = mode === 'review_edit';
var escId = escapeHtml(String(item.id || ''));
var qId = JSON.stringify(String(item.id || '')).replace(/"/g, '"');
var qConv = JSON.stringify(String(item.conversationId || '')).replace(/"/g, '"');
return (
'<div class="hitl-pending-item">' +
'<div class="hitl-pending-item-header">' +
'<strong>' + escapeHtml(item.toolName || '-') + '</strong>' +
'<span>' + escapeHtml(item.mode || '-') + '</span>' +
'<div class="hitl-pending-item-title">' +
'<span class="hitl-tool-badge">' + escapeHtml(item.toolName || '-') + '</span>' +
'<span class="hitl-mode-tag hitl-mode-tag--' + escapeHtml(mode) + '">' + escapeHtml(item.mode || '-') + '</span>' +
'</div>' +
'<div><small>conversation: ' + escapeHtml(item.conversationId || '-') + '</small></div>' +
'<pre style="white-space:pre-wrap;max-height:160px;overflow:auto;">' + escapeHtml(preview) + '</pre>' +
'<button class="hitl-dismiss-btn" title="忽略" onclick="dismissHitlItem(' + qId + ')">&times;</button>' +
'</div>' +
'<div class="hitl-pending-meta">会话:' + escapeHtml(item.conversationId || '-') + '</div>' +
'<pre class="hitl-pending-payload">' + escapeHtml(preview) + '</pre>' +
(allowEdit
? ('<div class="hitl-input-help">审查编辑模式:可填写 JSON 对象覆盖参数示例:{"command":"ls -la"}</div>' +
'<textarea id="hitl-edit-' + escapeHtml(String(item.id || '')) + '" class="hitl-edit-args" placeholder=\'{"command":"ls -la"}\'></textarea>')
? ('<div class="hitl-input-help">审查编辑模式:可填写 JSON 对象覆盖参数示例:{"command":"ls -la"}</div>' +
'<textarea id="hitl-edit-' + escId + '" class="hitl-edit-args" placeholder=\'{"command":"ls -la"}\'></textarea>')
: '<div class="hitl-input-help">审批模式:仅通过/拒绝,不支持改参。</div>') +
'<div class="hitl-input-help">备注(可选):建议写审批依据。</div>' +
'<input id="hitl-comment-' + escId + '" class="hitl-config-input hitl-inline-comment" type="text" placeholder="例如:允许只读命令">' +
'<div class="hitl-pending-actions">' +
'<button class="btn-primary" onclick="submitHitlDecision(' + JSON.stringify(String(item.id || '')) + ',\'approve\',' + JSON.stringify(String(item.conversationId || '')) + ')">通过</button>' +
'<button class="btn-secondary" onclick="submitHitlDecision(' + JSON.stringify(String(item.id || '')) + ',\'reject\',' + JSON.stringify(String(item.conversationId || '')) + ')">拒绝</button>' +
'<button class="btn-secondary" onclick="submitHitlDecision(' + qId + ',&quot;reject&quot;,' + qConv + ')">拒绝</button>' +
'<button class="btn-primary" onclick="submitHitlDecision(' + qId + ',&quot;approve&quot;,' + qConv + ')">通过</button>' +
'</div>' +
'</div>'
);
@@ -307,7 +315,8 @@ async function refreshHitlPending() {
}
async function submitHitlDecision(interruptId, decision, conversationIdOpt) {
const comment = prompt('审批备注(可选)') || '';
const commentBox = document.getElementById('hitl-comment-' + interruptId);
const comment = (commentBox && commentBox.value) ? commentBox.value.trim() : '';
let editedArguments = null;
const editBox = document.getElementById('hitl-edit-' + interruptId);
if (editBox && editBox.value && editBox.value.trim()) {
@@ -332,7 +341,7 @@ async function submitHitlDecisionWithPayload(interruptId, decision, comment, edi
if (!resp.ok) {
const errText = await readHitlApiError(resp);
if (resp.status === 409 && (errText.indexOf('already resolved') >= 0 || errText.indexOf('not found') >= 0)) {
refreshHitlPending();
await dismissHitlItem(interruptId, true);
return true;
}
alert('提交失败:' + errText);
@@ -363,9 +372,24 @@ async function readHitlApiError(resp) {
}
}
async function dismissHitlItem(interruptId, silent) {
try {
await hitlApiFetch('/api/hitl/dismiss', {
method: 'POST',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ interruptId: interruptId })
});
} catch (e) {
if (!silent) { console.warn('dismissHitlItem', e); }
}
refreshHitlPending();
}
window.refreshHitlPending = refreshHitlPending;
window.submitHitlDecision = submitHitlDecision;
window.submitHitlDecisionWithPayload = submitHitlDecisionWithPayload;
window.dismissHitlItem = dismissHitlItem;
window.followAgentRunAfterHitlDecision = followAgentRunAfterHitlDecision;
window.addEventListener('hitl-interrupt', function () {
+3 -4
View File
@@ -117,10 +117,9 @@
<div class="nav-item" data-page="hitl">
<div class="nav-item-content" data-title="人机协同" onclick="switchPage('hitl')">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="8" cy="7" r="3"></circle>
<circle cx="16" cy="7" r="3"></circle>
<path d="M2 20c0-3 2.5-5 6-5s6 2 6 5"></path>
<path d="M10 20h12"></path>
<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"></path>
<circle cx="9" cy="7" r="4"></circle>
<polyline points="16 11 18 13 22 9"></polyline>
</svg>
<span data-i18n="nav.hitl">人机协同</span>
</div>