Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions emrg/gui/renderer/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -471,8 +471,7 @@ async function handleEvent(evt) {
if (card.classList.contains("running")) {
card.classList.remove("running");
card.classList.add("failed");
const st = card.querySelector(".tool-status");
if (st) st.textContent = "结果未知——连接中断";
card.innerHTML = '<span class="tool-icon">⚠</span><span class="tool-text">连接中断,结果未知</span>';
}
}
break;
Expand Down Expand Up @@ -570,9 +569,11 @@ function handleToolStart(data) {
appendMsg(node);
state.groupNodes.set(rid, node);
}
// P2:友好状态行(设计 §4.2)——琥珀色转动圆点 + 动词短语,无技术黑话
const card = document.createElement("div");
card.className = "tool-card running";
card.innerHTML = `<span class="tool-icon">🔧</span> <span class="tool-name">${escapeHtml(data.tool_name)}</span> <span class="tool-status">运行中…</span>`;
const phrase = toolPhrase(data.tool_name, "doing");
card.innerHTML = `<span class="tool-spin"></span><span class="tool-text">${escapeHtml(phrase)}</span>`;
appendMsg(card);
state.toolCards.set(data.tool_call_id, card);
}
Expand All @@ -582,14 +583,21 @@ function handleToolEnd(data) {
if (!card) return;
const ok = !data.error;
card.className = "tool-card " + (ok ? "done" : "failed");
const phrase = toolPhrase(data.tool_name, ok ? "done" : "fail");
const elapsed = data.elapsed !== undefined ? `${data.elapsed.toFixed(1)}s` : "";
card.querySelector(".tool-status").textContent = ok ? `完成 ${elapsed}` : `失败 ${elapsed}`;
// G91/G131:content 默认截断 2000 字符 + 展开(textContent 纯文本,不做 marked)
const content = data.content || "";
const toggle = content ? '<span class="tool-toggle">展开 ⌄</span>' : "";
card.innerHTML =
`<span class="tool-icon">${ok ? "✓" : "⚠"}</span>` +
`<span class="tool-text">${escapeHtml(phrase)}</span>` +
(elapsed ? `<span class="tool-detail">${elapsed}</span>` : "") +
toggle;
// 原始输出默认折叠(渐进披露:点「展开」才看;G91/G131 保留 2000 字符截断)
if (content) {
const truncated = content.length > 2000 ? content.slice(0, 2000) + "…" : content;
const body = document.createElement("div");
body.className = "tool-output";
body.style.display = "none";
body.textContent = truncated;
card.appendChild(body);
if (content.length > 2000) {
Expand All @@ -602,6 +610,14 @@ function handleToolEnd(data) {
});
card.appendChild(btn);
}
const tg = card.querySelector(".tool-toggle");
if (tg) {
tg.addEventListener("click", () => {
const hidden = body.style.display === "none";
body.style.display = hidden ? "block" : "none";
tg.textContent = hidden ? "收起 ⌃" : "展开 ⌄";
});
}
}
scrollToBottom();
}
Expand Down
43 changes: 38 additions & 5 deletions emrg/gui/renderer/css/components.css
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
color: var(--text-1);
border-radius: var(--radius-bubble) var(--radius-bubble) 6px var(--radius-bubble);
}
/* EMRG:全宽无气泡,行首 ✦ 标识(P2 chat.js 渲染时加 ✦,P1 保留全宽样式) */
/* EMRG:全宽无气泡,行首 ✦ 品牌标识(设计 §3.3;remote 有标签不加) */
.msg.assistant {
align-self: flex-start;
max-width: 100%;
Expand All @@ -59,7 +59,9 @@
border-radius: 0;
white-space: normal;
}
.msg.assistant::before { content: "✦ "; color: var(--accent); font-weight: 600; }
.msg.assistant.remote { border-left: 3px solid var(--amber); padding-left: var(--space-3); }
.msg.assistant.remote::before { content: none; }
/* 系统提示:居中弱化小字 */
.msg.system {
align-self: center;
Expand All @@ -73,7 +75,7 @@
.remote-label { font-size: 11px; color: var(--amber); margin-bottom: var(--space-1); }
.msg-body { color: var(--text-1); }

/* ── 工具过程(P2 改折叠友好行;P1 保留卡片样式保证功能)── */
/* ── 工具过程:友好状态行(设计 §4.2 重点——折叠式,渐进披露)── */
.tool-card {
align-self: flex-start;
min-width: 320px;
Expand All @@ -86,14 +88,43 @@
font-size: var(--text-secondary);
margin: 2px 0;
box-shadow: var(--shadow-sm);
display: flex;
align-items: center;
gap: var(--space-2);
flex-wrap: wrap;
}
.tool-card.running { border-left-color: var(--amber); }
.tool-card.done { border-left-color: var(--accent); }
.tool-card.failed { border-left-color: var(--red); }
.tool-icon { }
.tool-name { font-family: var(--font-mono); font-weight: 600; }
.tool-status { color: var(--text-2); margin-left: var(--space-2); font-size: var(--text-aux); }
/* 进行中:琥珀色温和转动圆点(不刺眼) */
.tool-spin {
width: 12px;
height: 12px;
border-radius: 50%;
border: 2px solid var(--amber);
border-top-color: transparent;
animation: tool-spin 0.9s linear infinite;
flex-shrink: 0;
}
@keyframes tool-spin { to { transform: rotate(360deg); } }
/* 完成/失败图标 */
.tool-icon { flex-shrink: 0; }
.tool-card.done .tool-icon { color: var(--accent); font-weight: 600; }
.tool-card.failed .tool-icon { color: var(--red); font-weight: 600; }
.tool-text { flex-shrink: 0; }
.tool-detail { color: var(--text-3); font-size: var(--text-aux); }
.tool-toggle {
color: var(--blue);
cursor: pointer;
font-size: var(--text-aux);
margin-left: auto;
flex-shrink: 0;
padding: 2px 4px;
border-radius: 6px;
}
.tool-toggle:hover { background: var(--bg-soft); }
.tool-output {
flex-basis: 100%;
margin-top: var(--space-2);
background: var(--bg-soft);
border-radius: var(--radius-input);
Expand All @@ -106,13 +137,15 @@
word-break: break-all;
}
.tool-expand {
flex-basis: 100%;
margin-top: var(--space-1);
background: none;
border: none;
color: var(--blue);
cursor: pointer;
font-size: var(--text-aux);
padding: 0;
text-align: left;
}
.tool-expand:hover { text-decoration: underline; }

Expand Down
1 change: 1 addition & 0 deletions emrg/gui/renderer/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ <h2>欢迎使用 EMRG</h2>
<script src="../vendor/dompurify.min.js"></script>
<script src="../vendor/highlight.custom.js"></script>
<script src="markdown.js"></script>
<script src="js/copywriting.js"></script>
<script src="app.js"></script>
</body>
</html>
22 changes: 22 additions & 0 deletions emrg/gui/renderer/js/copywriting.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"use strict";
/**
* copywriting.js — 友好文案映射(docs/design/gui-redesign.md §4.2 工具过程 / §5.1 文案规范)
* 按 tool_name 映射动词短语(面向非开发者,零技术黑话)。
* 状态三态:doing(进行中)/ done(完成)/ fail(失败——统一鼓励性措辞,不责怪用户)。
*/
const TOOL_PHRASES = {
bash: { doing: "正在运行命令…", done: "命令已执行", fail: "这一步没成功,我换个方法试试" },
read: { doing: "正在读取文件…", done: "已读取文件", fail: "这一步没成功,我换个方法试试" },
write: { doing: "正在写入文件…", done: "文件已保存", fail: "这一步没成功,我换个方法试试" },
edit: { doing: "正在修改文件…", done: "文件已修改", fail: "这一步没成功,我换个方法试试" },
glob: { doing: "正在查找文件…", done: "文件查找完成", fail: "这一步没成功,我换个方法试试" },
grep: { doing: "正在搜索内容…", done: "搜索完成", fail: "这一步没成功,我换个方法试试" },
browser: { doing: "正在浏览网页…", done: "网页操作完成", fail: "这一步没成功,我换个方法试试" },
default: { doing: "正在处理…", done: "处理完成", fail: "这一步没成功,我换个方法试试" },
};

/** 取工具友好短语:toolPhrase(toolName, "doing" | "done" | "fail") */
function toolPhrase(toolName, kind) {
const p = TOOL_PHRASES[toolName] || TOOL_PHRASES.default;
return p[kind] || TOOL_PHRASES.default[kind];
}