Skip to content
Merged
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
28 changes: 0 additions & 28 deletions emrg/gui/renderer/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -401,17 +401,6 @@ <h2 data-i18n="help.title">/ 指令帮助</h2>
</dialog>

<!-- 会话列表对话框(/sessions /resume,GUI / 指令 P2) -->
<dialog id="sessions-dialog">
<div class="dialog-card" style="min-width:420px;">
<h2 data-i18n="sessions.title">切换对话</h2>
<p style="color:var(--text-2);font-size:var(--fs-secondary);margin:0 0 var(--sp-3);" data-i18n="sessions.desc">点击切换,或输入 /resume &lt;id&gt; 直接切换。</p>
<div id="sessions-list" class="help-list"></div>
<div class="dialog-actions">
<button type="button" id="sessions-close" class="btn btn-ghost" data-i18n="help.close">关闭</button>
</div>
</div>
</dialog>

<!-- P5:打开会话对话框(两步:选项目 → 选会话;跨项目) -->
<dialog id="open-session-dialog">
<div class="dialog-card" style="min-width:440px;">
Expand Down Expand Up @@ -491,23 +480,6 @@ <h2 data-i18n="settings.githubDeviceTitle">连接 GitHub</h2>
</dialog>

<!-- 进化对话框(/rant,GUI / 指令 P4) -->
<dialog id="rant-dialog">
<div class="dialog-card" style="min-width:460px;">
<h2 data-i18n="rant.title">🧬 进化 — 告诉 EMRG 往哪里走</h2>
<p style="color:var(--text-2);font-size:var(--fs-secondary);margin:0 0 var(--sp-3);" data-i18n="rant.desc">你的输入会驱动 EMRG 的自我进化——它会认真读,并据此改进自己。</p>
<label><span data-i18n="rant.project">项目(可选)</span>
<select id="rant-project"></select>
</label>
<label><span data-i18n="rant.message">你的想法</span>
<textarea id="rant-message" rows="4" maxlength="10000" placeholder="哪里不好用、想要什么新功能、或者希望它怎么改进…" data-i18n-placeholder="rant.placeholder"></textarea>
</label>
<div class="dialog-actions">
<button type="button" id="rant-cancel" class="btn btn-ghost" data-i18n="settings.cancel">取消</button>
<button type="button" id="rant-submit" class="btn btn-primary" data-i18n="rant.submit">驱动进化</button>
</div>
</div>
</dialog>

<!-- 进化完成 toast(WorkBuddy P3:进化发生时温和提示) -->
<div id="evolution-toast" class="evolution-toast hidden">
<div class="evolution-toast-title" data-i18n="copy.evolutionToastTitle">🌱 EMRG 刚刚完成一次自我进化!</div>
Expand Down
63 changes: 6 additions & 57 deletions emrg/gui/renderer/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,11 +222,11 @@ const App = (() => {
break;
case "/sessions":
case "/resume":
// P2:/resume <id> 直接切换;无参数 → 会话列表对话框
// P2:/resume <id> 直接切换;无参数 → 现代两步弹窗(rant 14:10:14 P6:sessions-dialog 移除,侧边栏会话区 + /open 已覆盖)
if (parsed.args.length > 0) {
await switchSession(parsed.args[0]);
} else {
showSessionsDialog();
Dialogs.showOpenSessionDialog();
}
break;
case "/open":
Expand Down Expand Up @@ -271,11 +271,12 @@ const App = (() => {
showSkillsDialog();
break;
case "/rant":
// P4:/rant 直接跟内容 → 快速提交;无参数 → 进化对话框
// P4:/rant 直接跟内容 → 快速提交;无参数 → 打开 Rant 面板 + 新建表单(rant 14:10:14 P6:rant-dialog 移除)
if (parsed.args.length > 0) {
await submitRant(parsed.args.join(" "), "");
} else {
showRantDialog();
await openRantsPanel();
Dialogs.openRantForm();
}
break;
case "/trigger":
Expand All @@ -294,31 +295,6 @@ const App = (() => {
}
}

// /sessions /resume:会话列表对话框(复用 help-list 样式)
async function showSessionsDialog() {
const list = $("sessions-list");
const dialog = $("sessions-dialog");
if (!list || !dialog) return;
await refreshSessions(); // 确保 state.sessions 最新
list.innerHTML = "";
if (state.sessions.length === 0) {
list.innerHTML = `<div class="help-row"><span class="help-hint">${_t("app.helpNoSessions")}</span></div>`;
}
state.sessions.forEach((s) => {
const row = el("button", { class: "help-row", type: "button", style: "width:100%;text-align:left;cursor:pointer;background:none;border:none;" });
const name = el("span", { class: "help-cmd" }, s.title || _t("app.unnamed"));
const hint = el("span", { class: "help-hint" }, s.session_id === state.sessionId ? _t("app.current") : "");
row.appendChild(name);
row.appendChild(hint);
row.addEventListener("click", async () => {
dialog.close();
await switchSession(s.session_id);
});
list.appendChild(row);
});
dialog.showModal();
}

// /rewind:历史消息点选择对话框(daemon list_history → 选择 → rewind_session)
async function showRewindDialog() {
const list = $("rewind-list");
Expand Down Expand Up @@ -446,26 +422,6 @@ const App = (() => {
}
}

// /rant:进化对话框(项目下拉 + 文本输入 → daemon rant 协议)
async function showRantDialog() {
const dialog = $("rant-dialog");
const msgInput = $("rant-message");
const projSel = $("rant-project");
if (!dialog || !msgInput) return;
// 加载项目列表填充下拉
try {
const projects = await window.emrg.listProjects();
projSel.innerHTML = `<option value="">${_t("app.globalAll")}</option>`;
for (const p of projects) {
const name = typeof p === "string" ? p : (p.name || "");
if (name) projSel.appendChild(el("option", { value: name }, name));
}
} catch { /* 项目加载失败则只留全局项 */ }
msgInput.value = "";
dialog.showModal();
msgInput.focus();
}

async function submitRant(message, project) {
const text = String(message || "").trim();
if (!text) {
Expand Down Expand Up @@ -1545,17 +1501,10 @@ const App = (() => {
$("confirm-cancel").addEventListener("click", Dialogs.closeConfirm);
$("confirm-ok").addEventListener("click", Dialogs.confirmOk);
$("help-close").addEventListener("click", () => $("help-dialog").close());
$("sessions-close").addEventListener("click", () => $("sessions-dialog").close());
$("rewind-close").addEventListener("click", () => $("rewind-dialog").close());
$("memory-close").addEventListener("click", () => $("memory-dialog").close());
$("skills-close").addEventListener("click", () => $("skills-dialog").close());
$("rant-cancel").addEventListener("click", () => $("rant-dialog").close());
$("rant-submit").addEventListener("click", async () => {
const msg = $("rant-message")?.value || "";
const proj = $("rant-project")?.value || "";
$("rant-dialog").close();
await submitRant(msg, proj);
});
// rant 14:10:14 P6:sessions-dialog / rant-dialog 已移除(侧边栏会话区 + /open + Rant 面板覆盖)

// rant 14:10:14 P2:设置面板 tab 切换(模型服务/工作目录/GitHub/外观/语言/关于)
document.querySelectorAll("#settings-tabs .panel-tab").forEach((tab) => {
Expand Down
15 changes: 11 additions & 4 deletions emrg/gui/test/app-commands.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ function makeEl(id) {
if (frag) this.innerHTML += frag;
},
removeChild() {},
setAttribute() {},
removeAttribute() {},
querySelectorAll: () => [],
getBoundingClientRect: () => ({ left: 0, right: 100, top: 0, bottom: 100, width: 100, height: 100 }),
showModal() { this.__open = true; },
Expand Down Expand Up @@ -207,24 +209,29 @@ test("P3:/skills 打开技能列表对话框并调用 listSkills", async () =>
assert.ok(els["skills-dialog"] && els["skills-dialog"].__open === true, "skills dialog opened");
});

test("P4:/rant 无参数打开进化对话框(项目下拉加载)", async () => {
test("P4:/rant 无参数打开 Rant 面板 + 新建表单(rant 14:10:14 P6:rant-dialog 移除)", async () => {
const { ctx, els } = makeSandbox({
listProjects: async () => [{ name: "emrg" }],
sendRant: async () => ({ ok: true, count: 5 }),
});
await tick();
vm.runInContext('document.getElementById("rant-form").classList.add("hidden")', ctx); // 镜像 index.html 初始态
await vm.runInContext("App.handleCommand({ type: 'command', cmd: '/rant', args: [] })", ctx);
assert.ok(els["rant-dialog"] && els["rant-dialog"].__open === true, "rant dialog opened");
await tick();
const panel = els["panel-rants"];
assert.ok(panel && !panel.classList.contains("hidden"), "rants panel should be open");
assert.ok(els["rant-form"] && !els["rant-form"].classList.contains("hidden"), "rant form should be open");
});

test("P4:/rant 直接跟内容快速提交(不打开对话框)", async () => {
test("P4:/rant 直接跟内容快速提交(不打开面板)", async () => {
const { ctx, els } = makeSandbox({
listProjects: async () => [{ name: "emrg" }],
sendRant: async () => ({ ok: true, count: 5 }),
});
await tick();
await vm.runInContext("App.handleCommand({ type: 'command', cmd: '/rant', args: ['希望支持主题切换'] })", ctx);
assert.ok(!(els["rant-dialog"] && els["rant-dialog"].__open), "direct rant submit should not open dialog");
const panel = els["panel-rants"];
assert.ok(!(panel && !panel.classList.contains("hidden")), "direct rant submit should not open panel");
});

test("P4:/trigger 无参数打开任务面板", async () => {
Expand Down
2 changes: 0 additions & 2 deletions emrg/gui/test/renderer.smoke.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,9 @@ const ELEMENT_IDS = [
"model-list", "add-model-btn", "model-form", "model-form-name", "model-form-id",
"model-form-vision", "model-form-save", "model-form-cancel", "back-to-bottom",
"cmd-menu", "help-dialog", "help-list", "help-close",
"sessions-dialog", "sessions-list", "sessions-close",
"rewind-dialog", "rewind-list", "rewind-close",
"memory-dialog", "memory-list", "memory-detail", "memory-close",
"skills-dialog", "skills-list", "skills-close",
"rant-dialog", "rant-message", "rant-project", "rant-cancel", "rant-submit",
"result-panel", "result-list", "result-toggle",
"result-tabs", "result-tab-files", "result-tab-artifacts", "result-tabbar", "result-files", "result-viewer", "result-resizer",
"growth-card", "growth-count", "about-recent",
Expand Down
Loading