mirror of
https://github.com/hansjone/oclaw.git
synced 2026-10-09 01:50:44 +08:00
Polish Admin/Chat UI: utilities, chat tokens, denser topbar.
Replace high-traffic inline styles with shared utility classes, retokenize chat chrome off white-mist hardcodes, and align the admin topbar to NetX 48px density. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
cbd9942b0b
commit
8ad4768476
5 changed files with 311 additions and 228 deletions
|
|
@ -2231,7 +2231,7 @@ async function renderStack() {
|
|||
.map((rid) => {
|
||||
const item = promptsMap[rid] && typeof promptsMap[rid] === "object" ? promptsMap[rid] : {};
|
||||
const finalSystem = String(item.system_prompt || "");
|
||||
return el("div", { class: "card", style: "margin-top:10px;" }, [
|
||||
return el("div", { class: "card u-mt-10" }, [
|
||||
el("div", { class: "card__title", text: `role: ${rid}` }),
|
||||
el("div", {}, [
|
||||
el("div", { class: "muted", text: "system_prompt" }),
|
||||
|
|
@ -2285,7 +2285,7 @@ async function renderStack() {
|
|||
el("div", { class: "card" }, [
|
||||
el("div", { class: "card__title", text: t("stack.title") }),
|
||||
el("div", { class: "row" }, [btnUp, btnDown]),
|
||||
el("div", { style: "height:10px" }),
|
||||
el("div", { class: "u-h-10" }),
|
||||
el("table", { class: "table" }, [
|
||||
el("thead", {}, [el("tr", {}, [el("th", { text: t("table.pid") }), el("th", { text: t("table.service") }), el("th", { text: "端口" }), el("th", { text: t("table.status") })])]),
|
||||
el("tbody", {}, items),
|
||||
|
|
@ -2934,7 +2934,7 @@ async function renderUserManagement() {
|
|||
await loadAccounts();
|
||||
|
||||
const tenantsListHint = allTenants.length > 1
|
||||
? el("div", { class: "muted", style: "margin-top:8px", text: t("tenants.allTenantsHint") })
|
||||
? el("div", { class: "muted u-mt-8", text: t("tenants.allTenantsHint") })
|
||||
: el("div", {});
|
||||
|
||||
return el("div", {}, [
|
||||
|
|
@ -2942,7 +2942,7 @@ async function renderUserManagement() {
|
|||
el("div", { class: "card__title", text: t("tenants.title") }),
|
||||
el("div", { class: "row" }, [createName, btnCreateTenant]),
|
||||
el("div", { class: "row" }, [el("label", { text: t("tenants.select") }), selector]),
|
||||
el("div", { class: "muted", style: "margin-top:6px", text: t("tenants.scopeHint") }),
|
||||
el("div", { class: "muted u-mt-6", text: t("tenants.scopeHint") }),
|
||||
el("table", { class: "table" }, [
|
||||
el("thead", {}, [el("tr", {}, [
|
||||
el("th", { text: t("tenants.colTenantName") }),
|
||||
|
|
@ -4004,7 +4004,7 @@ async function renderModels() {
|
|||
const bindingWrap = el("div", {});
|
||||
const opsAiSpecialistSelect = el("select", { class: "input", disabled: !canConfigureBindings });
|
||||
const opsAiProfileSelect = el("select", { class: "input", disabled: !canConfigureBindings });
|
||||
const modelsGrantsLinkRow = el("div", { class: "muted", style: "display:none" });
|
||||
const modelsGrantsLinkRow = el("div", { class: "muted u-hidden" });
|
||||
const newName = el("input", { class: "input", placeholder: t("models.createNamePlaceholder") });
|
||||
const newMode = el("select", { class: "input", disabled: !canMutateProfiles }, [
|
||||
el("option", { value: "openai", text: t("models.mode.openai") }),
|
||||
|
|
@ -4110,7 +4110,7 @@ async function renderModels() {
|
|||
|
||||
const secretsStatusMsg = el("div", { class: "muted", text: "" });
|
||||
const secretsMigrateBtn = el("button", { class: "btn", text: t("secrets.migrateBtn") });
|
||||
const secretsCard = el("div", { class: "card", style: "display:none" }, [
|
||||
const secretsCard = el("div", { class: "card u-hidden" }, [
|
||||
el("div", { class: "card__title", text: t("secrets.migrateTitle") }),
|
||||
el("div", { class: "muted", text: t("secrets.migrateHint") }),
|
||||
el("div", { class: "row" }, [secretsMigrateBtn]),
|
||||
|
|
@ -4788,7 +4788,7 @@ async function renderModels() {
|
|||
el("div", { class: "row" }, [btnDelete]),
|
||||
], { id: "models-api" }),
|
||||
renderSectionCard("Experts", "Runtime registry and workspace prompt files are split into two sections below.", [
|
||||
el("div", { class: "card", style: "margin:8px 0;padding:10px;" }, [
|
||||
el("div", { class: "card u-pad-block" }, [
|
||||
el("div", { class: "card__title", text: "Runtime Expert Registry" }),
|
||||
el("div", { class: "row" }, [el("label", { text: "Existing" }), expertsSelect]),
|
||||
el("div", { class: "row" }, [btnExpertDelete]),
|
||||
|
|
@ -4800,7 +4800,7 @@ async function renderModels() {
|
|||
el("div", { class: "row" }, [el("label", { text: "Name(zh)" }), expertNameZh]),
|
||||
el("div", { class: "row" }, [el("label", { text: "Role" }), expertRoleSel]),
|
||||
]),
|
||||
el("div", { class: "card", style: "margin:8px 0;padding:10px;" }, [
|
||||
el("div", { class: "card u-pad-block" }, [
|
||||
el("div", { class: "card__title", text: "Workspace Prompt Files" }),
|
||||
el("div", { class: "muted", text: "SOUL.md or ROLE_SYSTEM.md is required." }),
|
||||
el("div", { class: "row" }, [el("label", { text: "SOUL.md" }), expertSoul]),
|
||||
|
|
@ -4809,7 +4809,7 @@ async function renderModels() {
|
|||
]),
|
||||
expertsStatus,
|
||||
], { id: "models-experts" }),
|
||||
el("div", { class: "card section-card", id: "models-eval", style: "display:none" }, [evalDetails]),
|
||||
el("div", { class: "card section-card u-hidden", id: "models-eval" }, [evalDetails]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -5119,44 +5119,39 @@ async function renderPlugins() {
|
|||
const preflightFixWrap = el("div");
|
||||
const toolPolicyStatus = el("div", { class: "muted", text: "" });
|
||||
const turnMaxWorkersInput = el("input", {
|
||||
class: "input",
|
||||
class: "input u-max-w-120",
|
||||
type: "number",
|
||||
min: "1",
|
||||
max: "32",
|
||||
value: String(Number(toolPolicy.turn_max_tool_workers || 8)),
|
||||
style: "max-width:120px",
|
||||
});
|
||||
const turnMaxRoundsInput = el("input", {
|
||||
class: "input",
|
||||
class: "input u-max-w-120",
|
||||
type: "number",
|
||||
min: "1",
|
||||
max: "300",
|
||||
value: String(Number(toolPolicy.turn_max_tool_rounds || 100)),
|
||||
style: "max-width:120px",
|
||||
});
|
||||
const turnMaxCtxInput = el("input", {
|
||||
class: "input",
|
||||
class: "input u-max-w-120",
|
||||
type: "number",
|
||||
min: "10",
|
||||
max: "400",
|
||||
value: String(Number(toolPolicy.turn_max_context_messages || 80)),
|
||||
style: "max-width:120px",
|
||||
});
|
||||
const sseQueueMaxsizeInput = el("input", {
|
||||
class: "input",
|
||||
class: "input u-max-w-140",
|
||||
type: "number",
|
||||
min: "200",
|
||||
max: "50000",
|
||||
value: String(Number(toolPolicy.sse_queue_maxsize || 2000)),
|
||||
style: "max-width:140px",
|
||||
});
|
||||
const toolLogMaxCharsInput = el("input", {
|
||||
class: "input",
|
||||
class: "input u-max-w-140",
|
||||
type: "number",
|
||||
min: "20000",
|
||||
max: "2000000",
|
||||
value: String(Number(toolPolicy.tool_log_max_chars || 200000)),
|
||||
style: "max-width:140px",
|
||||
});
|
||||
const enableMcpToolsCb = el("input", { type: "checkbox" });
|
||||
enableMcpToolsCb.checked = !!toolPolicy.enable_mcp_tools;
|
||||
|
|
@ -5169,12 +5164,11 @@ async function renderPlugins() {
|
|||
const chatShowTtftDebugCb = el("input", { type: "checkbox" });
|
||||
chatShowTtftDebugCb.checked = !!toolPolicy.chat_show_ttft_debug;
|
||||
const toolLlmMessageMaxCharsInput = el("input", {
|
||||
class: "input",
|
||||
class: "input u-max-w-140",
|
||||
type: "number",
|
||||
min: "0",
|
||||
max: "500000",
|
||||
value: String(Number(toolPolicy.tool_llm_message_max_chars ?? 0)),
|
||||
style: "max-width:140px",
|
||||
});
|
||||
const mcpFilesystemExtraRootsInput = el("input", {
|
||||
class: "input",
|
||||
|
|
@ -5194,20 +5188,18 @@ async function renderPlugins() {
|
|||
const oclawRetryCodesStrictModeCb = el("input", { type: "checkbox" });
|
||||
oclawRetryCodesStrictModeCb.checked = !!toolPolicy.oclaw_retry_codes_strict_mode;
|
||||
const wecomLongconnWorkersInput = el("input", {
|
||||
class: "input",
|
||||
class: "input u-max-w-120",
|
||||
type: "number",
|
||||
min: "1",
|
||||
max: "8",
|
||||
value: String(Number(toolPolicy.wecom_longconn_workers || 2)),
|
||||
style: "max-width:120px",
|
||||
});
|
||||
const wecomLongconnInboundQueueInput = el("input", {
|
||||
class: "input",
|
||||
class: "input u-max-w-140",
|
||||
type: "number",
|
||||
min: "20",
|
||||
max: "5000",
|
||||
value: String(Number(toolPolicy.wecom_longconn_inbound_queue_maxsize || 200)),
|
||||
style: "max-width:140px",
|
||||
});
|
||||
const saveToolPolicyBtn = el("button", {
|
||||
class: "btn",
|
||||
|
|
@ -5735,7 +5727,7 @@ async function renderPlugins() {
|
|||
}
|
||||
},
|
||||
});
|
||||
const cliInstallModal = el("div", { class: "session-monitor-modal", style: "display:none;" });
|
||||
const cliInstallModal = el("div", { class: "session-monitor-modal u-hidden" });
|
||||
const cliInstallModalTitle = el("div", { class: "card__title", text: "MCP CLI install" });
|
||||
const cliInstallModalBody = el("pre", { class: "pre", text: "" });
|
||||
const closeCliInstallModal = () => {
|
||||
|
|
@ -5757,7 +5749,7 @@ async function renderPlugins() {
|
|||
el("div", { class: "card session-monitor-modal__card", style: "width:min(720px,96vw);" }, [
|
||||
cliInstallModalTitle,
|
||||
cliInstallModalBody,
|
||||
el("div", { class: "row", style: "justify-content:flex-end;margin-top:10px;" }, [
|
||||
el("div", { class: "row u-row-end" }, [
|
||||
el("button", { class: "btn", text: "Close", onclick: closeCliInstallModal }),
|
||||
]),
|
||||
]),
|
||||
|
|
@ -5916,13 +5908,13 @@ async function renderPlugins() {
|
|||
healthBtn.className = "chat-sess-menu-item";
|
||||
syncBtn.className = "chat-sess-menu-item";
|
||||
const actionMenuBtn = el("button", {
|
||||
class: "chat-sess-more",
|
||||
class: "chat-sess-more u-overlay-fixed",
|
||||
text: "⋯",
|
||||
title: "MCP actions",
|
||||
onclick: (ev) => {
|
||||
ev.stopPropagation();
|
||||
closeMcpActionMenu();
|
||||
const menu = el("div", { class: "chat-sess-menu-pop", style: "position:fixed;z-index:250;" }, [
|
||||
const menu = el("div", { class: "chat-sess-menu-pop" }, [
|
||||
toggleBtn,
|
||||
healthBtn,
|
||||
syncBtn,
|
||||
|
|
@ -6353,7 +6345,7 @@ pip install git+https://github.com/philschmid/code-sandbox-mcp.git && python -m
|
|||
]),
|
||||
]),
|
||||
usageSummaryPager.wrap,
|
||||
el("div", { class: "muted", text: "Recent MCP Calls", style: "margin-top:10px;" }),
|
||||
el("div", { class: "muted u-mt-10", text: "Recent MCP Calls" }),
|
||||
el("div", { class: "table-wrap" }, [
|
||||
el("table", { class: "table table--compact" }, [
|
||||
el("thead", {}, [el("tr", {}, [
|
||||
|
|
@ -6568,7 +6560,7 @@ async function renderSessionMonitor() {
|
|||
const detailStatus = el("div", { class: "muted", text: t("sessionMonitor.noMessages") });
|
||||
const detailPager = el("div", { class: "row" });
|
||||
const detailRoleFilter = el("select", { class: "input" });
|
||||
const detailModal = el("div", { class: "session-monitor-modal", style: "display:none;" });
|
||||
const detailModal = el("div", { class: "session-monitor-modal u-hidden" });
|
||||
const detailModalCard = el("div", { class: "session-monitor-modal__card" });
|
||||
const totalsWrap = el("div", { class: "row" });
|
||||
let selectedUserId = "";
|
||||
|
|
@ -6818,7 +6810,7 @@ async function renderSessionMonitor() {
|
|||
onclick: (ev) => {
|
||||
ev.stopPropagation();
|
||||
closeSessionMenu();
|
||||
const menu = el("div", { class: "chat-sess-menu-pop", style: "position:fixed;z-index:250;" }, [
|
||||
const menu = el("div", { class: "chat-sess-menu-pop u-overlay-fixed" }, [
|
||||
el("button", {
|
||||
class: "chat-sess-menu-item",
|
||||
text: t("sessionMonitor.viewDetail"),
|
||||
|
|
@ -7257,10 +7249,10 @@ async function renderWorkspacePaths() {
|
|||
el("div", { class: "muted", text: t("workspacePaths.help") }),
|
||||
];
|
||||
if (selfService) {
|
||||
cardParts.push(el("div", { class: "muted", style: "margin-top:6px;", text: t("workspacePaths.selfOnly") }));
|
||||
cardParts.push(el("div", { class: "muted u-mt-6", text: t("workspacePaths.selfOnly") }));
|
||||
}
|
||||
cardParts.push(
|
||||
el("div", { style: "height:10px" }),
|
||||
el("div", { class: "u-h-10" }),
|
||||
el("div", { class: "row" }, [
|
||||
el("label", { text: t("workspacePaths.tenant") }),
|
||||
tenantSel,
|
||||
|
|
@ -7275,14 +7267,14 @@ async function renderWorkspacePaths() {
|
|||
allowAnyCb,
|
||||
el("span", { text: t("workspacePaths.allowAny") }),
|
||||
]),
|
||||
el("div", { class: "muted", style: "margin-top:6px;line-height:1.45;", text: t("workspacePaths.allowAnyHint") }),
|
||||
el("div", { class: "muted u-muted-block", text: t("workspacePaths.allowAnyHint") }),
|
||||
el("label", { class: "row", style: "align-items:center;gap:8px;margin-top:10px;" }, [
|
||||
allowHighToolsCb,
|
||||
el("span", { text: t("workspacePaths.allowHighTools") }),
|
||||
]),
|
||||
el("div", { class: "muted", style: "margin-top:6px;line-height:1.45;", text: t("workspacePaths.allowHighToolsHint") }),
|
||||
el("div", { class: "muted u-muted-block", text: t("workspacePaths.allowHighToolsHint") }),
|
||||
el("div", { class: "row", style: "margin-top:10px;gap:8px;" }, [loadBtn, saveBtn]),
|
||||
el("div", { class: "muted", style: "margin-top:8px;" }, [el("span", { text: t("workspacePaths.status") + ": " }), status]),
|
||||
el("div", { class: "muted u-mt-8" }, [el("span", { text: t("workspacePaths.status") + ": " }), status]),
|
||||
);
|
||||
return el("div", { class: "card" }, cardParts);
|
||||
}
|
||||
|
|
@ -7488,16 +7480,16 @@ async function renderAttachments() {
|
|||
inputRow(t("attachments.toolModeMinRows"), toolMinRowsInput),
|
||||
inputRow(t("attachments.toolModeMaxBytes"), toolMaxBytesInput),
|
||||
inputRow(t("attachments.sqlTimeoutMs"), sqlTimeoutInput),
|
||||
el("div", { class: "muted", style: "margin-top:6px;line-height:1.45;", text: t("attachments.sqlTimeoutHint") }),
|
||||
el("div", { class: "muted u-muted-block", text: t("attachments.sqlTimeoutHint") }),
|
||||
], { id: "attach-table" }),
|
||||
renderSectionCard("图像与视频策略", "", [
|
||||
inputRow(t("attachments.imageReplayCapChars"), imageReplayCapInput),
|
||||
el("div", { class: "muted", style: "margin-top:6px;line-height:1.45;", text: t("attachments.imageReplayCapHint") }),
|
||||
el("div", { class: "muted u-muted-block", text: t("attachments.imageReplayCapHint") }),
|
||||
inputRow(t("attachments.videoReplayCapChars"), videoReplayCapInput),
|
||||
el("div", { class: "muted", style: "margin-top:6px;line-height:1.45;", text: t("attachments.videoReplayCapHint") }),
|
||||
el("div", { class: "muted u-muted-block", text: t("attachments.videoReplayCapHint") }),
|
||||
inputRow(t("attachments.videoTranscriptChunkSize"), videoTranscriptChunkSizeInput),
|
||||
inputRow(t("attachments.videoTranscriptChunkOverlap"), videoTranscriptChunkOverlapInput),
|
||||
el("div", { class: "muted", style: "margin-top:6px;line-height:1.45;", text: t("attachments.videoTranscriptChunkHint") }),
|
||||
el("div", { class: "muted u-muted-block", text: t("attachments.videoTranscriptChunkHint") }),
|
||||
], { id: "attach-media" }),
|
||||
]),
|
||||
renderSectionCard("压缩包预算策略", "", [
|
||||
|
|
@ -7505,8 +7497,8 @@ async function renderAttachments() {
|
|||
inputRow(t("attachments.archiveMaxFileCount"), archiveMaxFileCountInput),
|
||||
inputRow(t("attachments.archiveMaxEntryBytes"), archiveMaxEntryBytesInput),
|
||||
inputRow(t("attachments.archiveMaxTotalBytes"), archiveMaxTotalBytesInput),
|
||||
el("div", { class: "muted", style: "margin-top:6px;line-height:1.45;", text: t("attachments.archivePolicyHint") }),
|
||||
el("div", { style: "height:8px" }),
|
||||
el("div", { class: "muted u-muted-block", text: t("attachments.archivePolicyHint") }),
|
||||
el("div", { class: "u-h-8" }),
|
||||
status,
|
||||
], { id: "attach-archive" }),
|
||||
]);
|
||||
|
|
@ -7518,10 +7510,8 @@ async function renderProfile() {
|
|||
const metaUser = el("div", { class: "muted pre", text: "" });
|
||||
const metaIds = el("div", { class: "muted pre", text: "" });
|
||||
const avatarPreview = el("img", {
|
||||
class: "profile-avatar-preview",
|
||||
class: "profile-avatar-preview u-hidden u-avatar-chip",
|
||||
alt: "",
|
||||
style:
|
||||
"display:none;width:48px;height:48px;border-radius:999px;object-fit:contain;border:2px solid rgba(255,255,255,0.12);background:rgba(255,255,255,0.08);padding:5px;box-sizing:border-box;",
|
||||
});
|
||||
const avatarRow = el("div", { class: "row", style: "align-items:center;gap:16px;flex-wrap:wrap;" }, [
|
||||
el("div", {}, [avatarPreview]),
|
||||
|
|
@ -7530,7 +7520,7 @@ async function renderProfile() {
|
|||
el("div", { class: "muted", style: "margin-bottom:8px;font-size:12px;line-height:1.4;", text: t("profile.avatarHint") }),
|
||||
]),
|
||||
]);
|
||||
const fileInput = el("input", { type: "file", accept: "image/png,image/jpeg,image/jpg,image/webp,image/gif", style: "display:none" });
|
||||
const fileInput = el("input", { class: "u-hidden", type: "file", accept: "image/png,image/jpeg,image/jpg,image/webp,image/gif" });
|
||||
const chooseBtn = el("button", { class: "btn", type: "button", text: t("profile.chooseImage") });
|
||||
const removeBtn = el("button", { class: "btn", type: "button", text: t("profile.removeAvatar") });
|
||||
const saveBtn = el("button", { class: "btn btn--primary", type: "button", text: t("profile.save") });
|
||||
|
|
@ -7649,14 +7639,14 @@ async function renderProfile() {
|
|||
el("div", { class: "card__title", text: t("title.profile") }),
|
||||
el("div", { class: "muted", style: "margin-bottom:10px;line-height:1.45;", text: t("profile.help") }),
|
||||
el("div", { class: "row" }, [el("label", { text: t("profile.displayName") }), dnInput]),
|
||||
el("div", { style: "height:8px" }),
|
||||
el("div", { class: "u-h-8" }),
|
||||
avatarRow,
|
||||
el("div", { class: "row", style: "margin-top:10px;gap:8px;flex-wrap:wrap;" }, [fileInput, chooseBtn, removeBtn]),
|
||||
el("div", { class: "row", style: "margin-top:12px;gap:8px;flex-wrap:wrap;" }, [saveBtn, chatBtn]),
|
||||
el("div", { style: "height:8px" }),
|
||||
el("div", { class: "u-h-8" }),
|
||||
el("div", { style: "margin-top:14px" }, [metaUser]),
|
||||
el("div", { style: "margin-top:6px" }, [metaIds]),
|
||||
el("div", { class: "muted", style: "margin-top:10px;" }, [status]),
|
||||
el("div", { class: "u-mt-6" }, [metaIds]),
|
||||
el("div", { class: "muted u-mt-10" }, [status]),
|
||||
]);
|
||||
return el("div", {}, [profileCard]);
|
||||
}
|
||||
|
|
@ -7775,19 +7765,19 @@ async function renderSkills() {
|
|||
|
||||
const btnMarketSearch = el("button", { class: "btn", text: "Search", onclick: async () => await loadMarket(marketQ.value) });
|
||||
const btnMarketLatest = el("button", { class: "btn", text: "Latest", onclick: async () => await loadMarket("") });
|
||||
const marketBox = el("details", { style: "margin:10px 0 14px 0;" }, [
|
||||
el("summary", { text: "Skill market (ClawHub / CocoLoop)", style: "cursor:pointer;user-select:none;" }),
|
||||
el("div", { style: "height:8px" }),
|
||||
el("div", { class: "row", style: "gap:8px;flex-wrap:wrap;margin-bottom:8px;" }, [marketQ, marketLimitInp, btnMarketSearch, btnMarketLatest]),
|
||||
const marketBox = el("details", { class: "u-spacer-v" }, [
|
||||
el("summary", { class: "u-drag", text: "Skill market (ClawHub / CocoLoop)" }),
|
||||
el("div", { class: "u-h-8" }),
|
||||
el("div", { class: "row u-row-wrap-mb" }, [marketQ, marketLimitInp, btnMarketSearch, btnMarketLatest]),
|
||||
marketStatus,
|
||||
el("div", { style: "height:8px" }),
|
||||
el("div", { class: "u-h-8" }),
|
||||
el("div", { class: "table-wrap" }, [
|
||||
el("table", { class: "table table--compact" }, [
|
||||
el("thead", {}, [el("tr", {}, [el("th", { text: "slug" }), el("th", { text: "name" }), el("th", { text: "version" }), el("th", { text: "description" }), el("th", { text: "action" })])]),
|
||||
marketTbody,
|
||||
]),
|
||||
]),
|
||||
el("div", { style: "height:8px" }),
|
||||
el("div", { class: "u-h-8" }),
|
||||
el("div", { class: "muted", text: "Detail" }),
|
||||
marketDetailPre,
|
||||
]);
|
||||
|
|
@ -7840,13 +7830,13 @@ async function renderSkills() {
|
|||
const namesCell = names.length
|
||||
? el("details", {}, [
|
||||
el("summary", { text: previewText || "(empty)" }),
|
||||
el("div", { class: "muted", style: "margin-top:4px;white-space:normal;line-height:1.5;", text: names.join(", ") }),
|
||||
el("div", { class: "muted u-mt-4 u-wrap-lh", text: names.join(", ") }),
|
||||
])
|
||||
: el("span", { class: "muted", text: "-" });
|
||||
const docsOnlyCell = docsOnlyNames.length
|
||||
? el("details", {}, [
|
||||
el("summary", { text: docsOnlyNames.slice(0, 4).join(", ") }),
|
||||
el("div", { class: "muted", style: "margin-top:4px;white-space:normal;line-height:1.5;", text: docsOnlyNames.join(", ") }),
|
||||
el("div", { class: "muted u-mt-4 u-wrap-lh", text: docsOnlyNames.join(", ") }),
|
||||
])
|
||||
: el("span", { class: "muted", text: "-" });
|
||||
skillEffectiveTbody.appendChild(
|
||||
|
|
@ -7902,7 +7892,7 @@ async function renderSkills() {
|
|||
else prev.delete(nm);
|
||||
draft[current] = Array.from(prev);
|
||||
});
|
||||
skillBindingListWrap.appendChild(el("label", { class: "row", style: "gap:6px;align-items:center;" }, [cb, el("span", { text: nm })]));
|
||||
skillBindingListWrap.appendChild(el("label", { class: "row u-row-center" }, [cb, el("span", { text: nm })]));
|
||||
});
|
||||
};
|
||||
const loadSkillBinding = async () => {
|
||||
|
|
@ -7977,11 +7967,10 @@ async function renderSkills() {
|
|||
}
|
||||
},
|
||||
});
|
||||
const skillBindingBox = el("details", { style: "margin:10px 0 14px 0;" }, [
|
||||
el("summary", { text: "Skill role binding (specialists)", style: "cursor:pointer;user-select:none;" }),
|
||||
const skillBindingBox = el("details", { class: "u-spacer-v" }, [
|
||||
el("summary", { class: "u-drag", text: "Skill role binding (specialists)" }),
|
||||
el("div", {
|
||||
class: "muted",
|
||||
style: "margin:8px 0;line-height:1.5;",
|
||||
class: "muted u-muted-block-lg",
|
||||
text:
|
||||
"When enabled, the model skills catalog is filtered per role: each role sees only skills bound to that role, plus skills under skills/_workspace/public/. If nothing is bound yet, non-public skills are hidden until you assign them.",
|
||||
}),
|
||||
|
|
@ -7992,19 +7981,19 @@ async function renderSkills() {
|
|||
skillBindingEnabledCb,
|
||||
el("span", { text: "Enable role binding (AIA_SKILL_ROLE_BINDING_ENABLED)" }),
|
||||
]),
|
||||
el("div", { class: "row", style: "gap:8px;flex-wrap:wrap;margin-top:8px;align-items:center;" }, [
|
||||
el("div", { class: "row u-row-wrap-mt" }, [
|
||||
el("label", { text: "Role" }),
|
||||
skillRoleSelect,
|
||||
btnSaveSkillBinding,
|
||||
]),
|
||||
el("div", { class: "muted", style: "margin:8px 0 4px 0;", text: "Role binding dashboard" }),
|
||||
el("div", { class: "muted u-label-mt", text: "Role binding dashboard" }),
|
||||
el("div", { class: "table-wrap" }, [
|
||||
el("table", { class: "table table--compact" }, [
|
||||
el("thead", {}, [el("tr", {}, [el("th", { text: "role" }), el("th", { text: "direct skills" }), el("th", { text: "effective" })])]),
|
||||
skillBindingDashTbody,
|
||||
]),
|
||||
]),
|
||||
el("div", { class: "muted", style: "margin:8px 0 4px 0;", text: "Effective skills dashboard (binding + MCP + tools)" }),
|
||||
el("div", { class: "muted u-label-mt", text: "Effective skills dashboard (binding + MCP + tools)" }),
|
||||
el("div", { class: "table-wrap" }, [
|
||||
el("table", { class: "table table--compact" }, [
|
||||
el("thead", {}, [el("tr", {}, [
|
||||
|
|
@ -8079,11 +8068,11 @@ async function renderSkills() {
|
|||
text: "Preview",
|
||||
onclick: async () => await loadInternalToolsPreview(internalRoleSelect.value),
|
||||
});
|
||||
const internalToolsBox = el("details", { style: "margin:10px 0 14px 0;" }, [
|
||||
el("summary", { text: "Internal tools preview (public + expert)", style: "cursor:pointer;user-select:none;" }),
|
||||
el("div", { class: "muted", style: "margin:8px 0;line-height:1.5;", text: "Preview dynamically loaded builtin tools for a role (public shared + expert-scoped)." }),
|
||||
const internalToolsBox = el("details", { class: "u-spacer-v" }, [
|
||||
el("summary", { class: "u-drag", text: "Internal tools preview (public + expert)" }),
|
||||
el("div", { class: "muted u-muted-block-lg", text: "Preview dynamically loaded builtin tools for a role (public shared + expert-scoped)." }),
|
||||
internalToolsStatus,
|
||||
el("div", { class: "row", style: "gap:8px;flex-wrap:wrap;margin-top:8px;align-items:center;" }, [
|
||||
el("div", { class: "row u-row-wrap-mt" }, [
|
||||
el("label", { text: "Role" }),
|
||||
internalRoleSelect,
|
||||
btnInternalPreview,
|
||||
|
|
@ -8101,7 +8090,7 @@ async function renderSkills() {
|
|||
},
|
||||
}),
|
||||
]),
|
||||
el("div", { class: "table-wrap", style: "margin-top:8px" }, [
|
||||
el("div", { class: "table-wrap u-mt-8" }, [
|
||||
el("table", { class: "table table--compact" }, [
|
||||
el("thead", {}, [el("tr", {}, [
|
||||
el("th", { text: "source" }),
|
||||
|
|
@ -8114,7 +8103,7 @@ async function renderSkills() {
|
|||
internalToolsTbody,
|
||||
]),
|
||||
]),
|
||||
el("div", { class: "muted", style: "margin-top:8px", text: "Skipped modules / factory errors" }),
|
||||
el("div", { class: "muted u-mt-8", text: "Skipped modules / factory errors" }),
|
||||
internalSkippedPre,
|
||||
]);
|
||||
|
||||
|
|
@ -8127,7 +8116,7 @@ async function renderSkills() {
|
|||
const llmModeBadge = el("span", { class: "badge badge--mode-restricted", text: "restricted" });
|
||||
const llmDiffPre = el("pre", { class: "muted pre", text: "" });
|
||||
const llmDiffTbody = el("tbody");
|
||||
const llmDiffTableWrap = el("div", { class: "table-wrap", style: "margin-top:8px" }, [
|
||||
const llmDiffTableWrap = el("div", { class: "table-wrap u-mt-8" }, [
|
||||
el("table", { class: "table table--compact" }, [
|
||||
el("thead", {}, [el("tr", {}, [
|
||||
el("th", { text: "type" }),
|
||||
|
|
@ -8215,16 +8204,16 @@ async function renderSkills() {
|
|||
selfCheckStatus.textContent = `export failed: ${String(e && e.message ? e.message : e)}`;
|
||||
}
|
||||
};
|
||||
const selfCheckBox = el("details", { style: "margin:10px 0 14px 0;" }, [
|
||||
el("summary", { text: "Tools self-check", style: "cursor:pointer;user-select:none;" }),
|
||||
el("div", { class: "muted", style: "margin:8px 0;line-height:1.5;", text: "Run one-shot diagnostics across roles for internal/wired tools, role mode and permanent bans." }),
|
||||
const selfCheckBox = el("details", { class: "u-spacer-v" }, [
|
||||
el("summary", { class: "u-drag", text: "Tools self-check" }),
|
||||
el("div", { class: "muted u-muted-block-lg", text: "Run one-shot diagnostics across roles for internal/wired tools, role mode and permanent bans." }),
|
||||
selfCheckStatus,
|
||||
el("div", { class: "row", style: "gap:8px;align-items:center;margin-top:8px;" }, [
|
||||
el("div", { class: "row u-row-center-mt" }, [
|
||||
el("button", { class: "btn btn--primary", text: "Run self-check", onclick: runSelfCheck }),
|
||||
el("button", { class: "btn", text: "Export self-check JSON", onclick: exportSelfCheckJson }),
|
||||
selfCheckSummary,
|
||||
]),
|
||||
el("div", { class: "table-wrap", style: "margin-top:8px" }, [
|
||||
el("div", { class: "table-wrap u-mt-8" }, [
|
||||
el("table", { class: "table table--compact" }, [
|
||||
el("thead", {}, [el("tr", {}, [
|
||||
el("th", { text: "role" }),
|
||||
|
|
@ -8335,14 +8324,14 @@ async function renderSkills() {
|
|||
skillHealthStatus.textContent = `export failed: ${String(e && e.message ? e.message : e)}`;
|
||||
}
|
||||
};
|
||||
const skillHealthBox = el("details", { style: "margin:10px 0 14px 0;" }, [
|
||||
el("summary", { text: "Skills health self-check", style: "cursor:pointer;user-select:none;" }),
|
||||
el("div", { class: "muted", style: "margin:8px 0;line-height:1.5;", text: "Run executable skill diagnostics and show failure code distribution." }),
|
||||
const skillHealthBox = el("details", { class: "u-spacer-v" }, [
|
||||
el("summary", { class: "u-drag", text: "Skills health self-check" }),
|
||||
el("div", { class: "muted u-muted-block-lg", text: "Run executable skill diagnostics and show failure code distribution." }),
|
||||
skillHealthStatus,
|
||||
el("div", { class: "row", style: "gap:8px;align-items:center;margin-top:8px;" }, [
|
||||
el("div", { class: "row u-row-center-mt" }, [
|
||||
el("button", { class: "btn btn--primary", text: "Run skills self-check", onclick: runSkillHealthCheck }),
|
||||
el("button", { class: "btn", text: "Export skills self-check JSON", onclick: exportSkillHealthJson }),
|
||||
el("label", { class: "row", style: "gap:6px;align-items:center;" }, [
|
||||
el("label", { class: "row u-row-center" }, [
|
||||
skillHealthFailedOnlyCb,
|
||||
el("span", { class: "muted", text: "Only failed items" }),
|
||||
]),
|
||||
|
|
@ -8350,14 +8339,14 @@ async function renderSkills() {
|
|||
]),
|
||||
el("div", { class: "row", style: "gap:12px;align-items:flex-start;flex-wrap:wrap;margin-top:8px;" }, [
|
||||
el("div", { class: "table-wrap", style: "min-width:280px;flex:1;" }, [
|
||||
el("div", { class: "muted", style: "margin:0 0 6px 0;", text: "classification_counts" }),
|
||||
el("div", { class: "muted u-mb-6", text: "classification_counts" }),
|
||||
el("table", { class: "table table--compact" }, [
|
||||
el("thead", {}, [el("tr", {}, [el("th", { text: "code" }), el("th", { text: "count" })])]),
|
||||
skillHealthClassifyTbody,
|
||||
]),
|
||||
]),
|
||||
el("div", { class: "table-wrap", style: "min-width:360px;flex:2;" }, [
|
||||
el("div", { class: "muted", style: "margin:0 0 6px 0;", text: "execution_checks (top 30)" }),
|
||||
el("div", { class: "muted u-mb-6", text: "execution_checks (top 30)" }),
|
||||
el("table", { class: "table table--compact" }, [
|
||||
el("thead", {}, [el("tr", {}, [el("th", { text: "skill" }), el("th", { text: "status" }), el("th", { text: "error_code" }), el("th", { text: "output_truncated" }), el("th", { text: "action" })])]),
|
||||
skillHealthExecTbody,
|
||||
|
|
@ -8475,11 +8464,11 @@ async function renderSkills() {
|
|||
const p0 = a.parameters ? JSON.stringify(a.parameters, null, 2) : "";
|
||||
const p1 = b.parameters ? JSON.stringify(b.parameters, null, 2) : "";
|
||||
const box = el("details", {}, [
|
||||
el("summary", { text: "compare", style: "cursor:pointer;user-select:none;" }),
|
||||
el("div", { class: "muted", style: "margin-top:6px;" }, [el("div", { text: "raw.description" }), el("pre", { class: "muted pre", text: d0 })]),
|
||||
el("div", { class: "muted", style: "margin-top:6px;" }, [el("div", { text: "wired.description" }), el("pre", { class: "muted pre", text: d1 })]),
|
||||
el("div", { class: "muted", style: "margin-top:6px;" }, [el("div", { text: "raw.parameters" }), el("pre", { class: "muted pre", text: p0 })]),
|
||||
el("div", { class: "muted", style: "margin-top:6px;" }, [el("div", { text: "wired.parameters" }), el("pre", { class: "muted pre", text: p1 })]),
|
||||
el("summary", { class: "u-drag", text: "compare" }),
|
||||
el("div", { class: "muted u-mt-6" }, [el("div", { text: "raw.description" }), el("pre", { class: "muted pre", text: d0 })]),
|
||||
el("div", { class: "muted u-mt-6" }, [el("div", { text: "wired.description" }), el("pre", { class: "muted pre", text: d1 })]),
|
||||
el("div", { class: "muted u-mt-6" }, [el("div", { text: "raw.parameters" }), el("pre", { class: "muted pre", text: p0 })]),
|
||||
el("div", { class: "muted u-mt-6" }, [el("div", { text: "wired.parameters" }), el("pre", { class: "muted pre", text: p1 })]),
|
||||
]);
|
||||
return box;
|
||||
};
|
||||
|
|
@ -8534,11 +8523,11 @@ async function renderSkills() {
|
|||
btnLLMToggle.textContent = next === "wired" ? "Toggle raw/wired" : "Toggle raw/wired";
|
||||
},
|
||||
});
|
||||
const llmToolsBox = el("details", { style: "margin:10px 0 14px 0;" }, [
|
||||
el("summary", { text: "LLM tools preview (after wire policy)", style: "cursor:pointer;user-select:none;" }),
|
||||
el("div", { class: "muted", style: "margin:8px 0;line-height:1.5;", text: "Preview the final tools injected to the model for a role (internal + MCP + role_mode + MCP specialist binding)." }),
|
||||
const llmToolsBox = el("details", { class: "u-spacer-v" }, [
|
||||
el("summary", { class: "u-drag", text: "LLM tools preview (after wire policy)" }),
|
||||
el("div", { class: "muted u-muted-block-lg", text: "Preview the final tools injected to the model for a role (internal + MCP + role_mode + MCP specialist binding)." }),
|
||||
llmToolsStatus,
|
||||
el("div", { class: "row", style: "gap:8px;flex-wrap:wrap;margin-top:8px;align-items:center;" }, [
|
||||
el("div", { class: "row u-row-wrap-mt" }, [
|
||||
el("label", { text: "Role" }),
|
||||
llmRoleSelect,
|
||||
btnLLMPreview,
|
||||
|
|
@ -8558,21 +8547,21 @@ async function renderSkills() {
|
|||
}),
|
||||
el("span", { class: "muted", text: "role_mode:" }),
|
||||
llmModeBadge,
|
||||
el("label", { class: "row", style: "gap:6px;align-items:center;" }, [
|
||||
el("label", { class: "row u-row-center" }, [
|
||||
llmTracePlanCb,
|
||||
el("span", { class: "muted", text: "Trace exposure plan" }),
|
||||
]),
|
||||
el("button", { class: "btn", text: "Save trace setting", onclick: saveExposureTraceSetting }),
|
||||
]),
|
||||
el("div", { class: "table-wrap", style: "margin-top:8px" }, [
|
||||
el("div", { class: "table-wrap u-mt-8" }, [
|
||||
el("table", { class: "table table--compact" }, [
|
||||
el("thead", {}, [el("tr", {}, [el("th", { text: "name" }), el("th", { text: "description" }), el("th", { text: "kind" }), el("th", { text: "parameters" })])]),
|
||||
llmToolsTbody,
|
||||
]),
|
||||
]),
|
||||
el("div", { class: "muted", style: "margin-top:8px", text: "Diff / diagnostics" }),
|
||||
el("div", { class: "muted u-mt-8", text: "Diff / diagnostics" }),
|
||||
llmRemovedPre,
|
||||
el("div", { class: "muted", style: "margin-top:8px", text: "raw vs wired diff (added/removed/changed)" }),
|
||||
el("div", { class: "muted u-mt-8", text: "raw vs wired diff (added/removed/changed)" }),
|
||||
llmDiffPre,
|
||||
llmDiffTableWrap,
|
||||
]);
|
||||
|
|
@ -8587,10 +8576,10 @@ async function renderSkills() {
|
|||
}
|
||||
skillActionMenuEl = null;
|
||||
};
|
||||
const skillTestRunModal = el("div", { class: "session-monitor-modal", style: "display:none;" });
|
||||
const skillTestRunModal = el("div", { class: "session-monitor-modal u-hidden" });
|
||||
const skillTestRunTitle = el("div", { class: "card__title", text: "Skill test run" });
|
||||
const skillTestRunArgs = el("textarea", { class: "input", rows: "8", style: "width:100%;min-width:0;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;", placeholder: "{}" });
|
||||
const skillInstallModal = el("div", { class: "session-monitor-modal", style: "display:none;" });
|
||||
const skillInstallModal = el("div", { class: "session-monitor-modal u-hidden" });
|
||||
const skillInstallTitle = el("div", { class: "card__title", text: "Skill installation" });
|
||||
const skillInstallMsg = el("div", { class: "muted", style: "line-height:1.5;" });
|
||||
const closeSkillInstallModal = () => {
|
||||
|
|
@ -8614,7 +8603,7 @@ async function renderSkills() {
|
|||
const skillInstallCard = el("div", { class: "card session-monitor-modal__card", style: "width:min(560px,96vw);" }, [
|
||||
skillInstallTitle,
|
||||
skillInstallMsg,
|
||||
el("div", { class: "row", style: "justify-content:flex-end;margin-top:10px;" }, [
|
||||
el("div", { class: "row u-row-end" }, [
|
||||
el("button", { class: "btn", text: "Close", onclick: closeSkillInstallModal }),
|
||||
]),
|
||||
]);
|
||||
|
|
@ -8660,7 +8649,7 @@ async function renderSkills() {
|
|||
skillTestRunTitle,
|
||||
el("div", { class: "muted", style: "margin-bottom:8px;", text: "Input JSON args passed to the executable skill runtime." }),
|
||||
skillTestRunArgs,
|
||||
el("div", { class: "row", style: "gap:8px;justify-content:flex-end;margin-top:10px;" }, [skillTestRunCancelBtn, skillTestRunRunBtn]),
|
||||
el("div", { class: "row u-row-end" }, [skillTestRunCancelBtn, skillTestRunRunBtn]),
|
||||
]);
|
||||
skillTestRunModal.appendChild(skillTestRunCard);
|
||||
const retryableOnlyCb = el("input", { type: "checkbox" });
|
||||
|
|
@ -8768,13 +8757,13 @@ async function renderSkills() {
|
|||
},
|
||||
});
|
||||
const actionMenuBtn = el("button", {
|
||||
class: "chat-sess-more",
|
||||
class: "chat-sess-more u-overlay-fixed",
|
||||
text: "⋯",
|
||||
title: "Skill actions",
|
||||
onclick: (ev) => {
|
||||
ev.stopPropagation();
|
||||
closeSkillActionMenu();
|
||||
const menu = el("div", { class: "chat-sess-menu-pop", style: "position:fixed;z-index:250;" }, [
|
||||
const menu = el("div", { class: "chat-sess-menu-pop" }, [
|
||||
toggleBtn,
|
||||
testRunBtn,
|
||||
repairDepsBtn,
|
||||
|
|
@ -9022,7 +9011,7 @@ async function renderSkills() {
|
|||
return el("div", { class: "card" }, [
|
||||
el("div", { class: "card__title", text: t("title.skills") }),
|
||||
el("div", { class: "row", style: "gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:8px;" }, [
|
||||
el("label", { class: "row", style: "gap:6px;align-items:center;" }, [skillPromptModeCb, el("span", { text: "Prompt mode (inject SKILL.md)" })]),
|
||||
el("label", { class: "row u-row-center" }, [skillPromptModeCb, el("span", { text: "Prompt mode (inject SKILL.md)" })]),
|
||||
el("label", { class: "row", style: "gap:6px;align-items:center;flex-wrap:wrap;" }, [
|
||||
el("span", { text: "Market (AIA_SKILL_MARKET_PROVIDER)" }),
|
||||
skillMarketProviderSelect,
|
||||
|
|
@ -9032,25 +9021,25 @@ async function renderSkills() {
|
|||
]),
|
||||
docsHint,
|
||||
marketBox,
|
||||
el("details", { style: "margin:10px 0 14px 0;" }, [
|
||||
el("summary", { text: "Skill installation (local / registry)", style: "cursor:pointer;user-select:none;" }),
|
||||
el("div", { style: "height:8px" }),
|
||||
el("details", { class: "u-spacer-v" }, [
|
||||
el("summary", { class: "u-drag", text: "Skill installation (local / registry)" }),
|
||||
el("div", { class: "u-h-8" }),
|
||||
el("div", { class: "muted", style: "margin-bottom:8px;line-height:1.5;" }, [
|
||||
el("div", { text: "Local dir: 目录内必须包含 SKILL.md(支持绝对路径)。" }),
|
||||
el("div", { text: "Registry: zip/tar 的 URL(支持 file:// 本地 URI)。" }),
|
||||
]),
|
||||
el("div", { class: "row", style: "gap:8px;flex-wrap:wrap;margin-bottom:8px;" }, [regInp, btnInstallRegistry]),
|
||||
el("div", { class: "row", style: "gap:8px;flex-wrap:wrap;margin-bottom:8px;" }, [localDirInp, btnInstallLocal]),
|
||||
el("div", { class: "row u-row-wrap-mb" }, [regInp, btnInstallRegistry]),
|
||||
el("div", { class: "row u-row-wrap-mb" }, [localDirInp, btnInstallLocal]),
|
||||
]),
|
||||
skillBindingBox,
|
||||
selfCheckBox,
|
||||
skillHealthBox,
|
||||
internalToolsBox,
|
||||
llmToolsBox,
|
||||
el("div", { class: "row", style: "gap:8px;flex-wrap:wrap;margin-bottom:8px;" }, [nameInp, descInp]),
|
||||
el("div", { class: "row u-row-wrap-mb" }, [nameInp, descInp]),
|
||||
el("div", { style: "margin-bottom:8px;" }, [bodyInp]),
|
||||
el("div", { class: "row", style: "gap:8px;flex-wrap:wrap;margin-bottom:8px;" }, [btnCreate]),
|
||||
el("div", { class: "row", style: "gap:8px;flex-wrap:wrap;margin-bottom:8px;" }, [btnRefresh, btnRepairDepsAll]),
|
||||
el("div", { class: "row u-row-wrap-mb" }, [btnCreate]),
|
||||
el("div", { class: "row u-row-wrap-mb" }, [btnRefresh, btnRepairDepsAll]),
|
||||
el("div", { class: "table-wrap" }, [
|
||||
el("table", { class: "table table--compact" }, [
|
||||
el("thead", {}, [el("tr", {}, [
|
||||
|
|
@ -9065,10 +9054,10 @@ async function renderSkills() {
|
|||
tbody,
|
||||
]),
|
||||
]),
|
||||
el("div", { style: "height:10px" }),
|
||||
el("div", { class: "u-h-10" }),
|
||||
el("div", { class: "row", style: "gap:8px;align-items:center;" }, [
|
||||
el("div", { class: "muted", text: "Recent skill install audit" }),
|
||||
el("label", { class: "row", style: "gap:6px;align-items:center;" }, [
|
||||
el("label", { class: "row u-row-center" }, [
|
||||
retryableOnlyCb,
|
||||
el("span", { class: "muted", text: "Only retryable failures" }),
|
||||
]),
|
||||
|
|
@ -9135,7 +9124,7 @@ async function renderScheduledJobs() {
|
|||
const runsBox = el("pre", { class: "code", style: "max-height:220px;overflow:auto;white-space:pre-wrap;" });
|
||||
const msg = el("div", { class: "muted", text: "" });
|
||||
|
||||
const editModal = el("div", { class: "session-monitor-modal", style: "display:none;" });
|
||||
const editModal = el("div", { class: "session-monitor-modal u-hidden" });
|
||||
const editTitle = el("div", { class: "card__title", text: t("scheduledJobs.editTitle") });
|
||||
const editNameInput = el("input", { class: "input", placeholder: "name" });
|
||||
const editKindInput = el("select", {}, [
|
||||
|
|
@ -9206,11 +9195,11 @@ async function renderScheduledJobs() {
|
|||
editTitle,
|
||||
editWeixinInfo,
|
||||
editNameInput,
|
||||
el("div", { class: "row", style: "gap:8px;" }, [editKindInput, editExprInput]),
|
||||
el("div", { class: "row u-gap-8" }, [editKindInput, editExprInput]),
|
||||
editPromptInput,
|
||||
editSpecialistInput,
|
||||
editWaChatInput,
|
||||
el("div", { class: "row", style: "gap:8px;justify-content:flex-end;margin-top:10px;" }, [
|
||||
el("div", { class: "row u-row-end" }, [
|
||||
el("button", { class: "btn", text: t("scheduledJobs.cancel"), onclick: closeEditModal }),
|
||||
editSaveBtn,
|
||||
]),
|
||||
|
|
@ -9246,13 +9235,13 @@ async function renderScheduledJobs() {
|
|||
for (const job of resp.items || []) {
|
||||
const jobId = String(job.id || "");
|
||||
const btnMore = el("button", {
|
||||
class: "chat-sess-more",
|
||||
class: "chat-sess-more u-overlay-fixed",
|
||||
text: "⋯",
|
||||
title: t("scheduledJobs.menuTitle"),
|
||||
onclick: (ev) => {
|
||||
ev.stopPropagation();
|
||||
closeScheduledJobMenu();
|
||||
const menu = el("div", { class: "chat-sess-menu-pop", style: "position:fixed;z-index:250;" }, [
|
||||
const menu = el("div", { class: "chat-sess-menu-pop" }, [
|
||||
el("button", {
|
||||
class: "chat-sess-menu-item",
|
||||
text: t("scheduledJobs.viewRuns"),
|
||||
|
|
@ -9391,7 +9380,7 @@ async function renderScheduledJobs() {
|
|||
el("div", { class: "card__title", text: t("scheduledJobs.createTitle") }),
|
||||
weixinInfo,
|
||||
nameInput,
|
||||
el("div", { class: "row", style: "gap:8px;" }, [kindInput, exprInput]),
|
||||
el("div", { class: "row u-gap-8" }, [kindInput, exprInput]),
|
||||
promptInput,
|
||||
specialistInput,
|
||||
waChatInput,
|
||||
|
|
@ -9427,10 +9416,10 @@ async function renderScheduledJobs() {
|
|||
el("colgroup", {}, [
|
||||
el("col", { style: "width:14%" }),
|
||||
el("col", { style: "width:14%" }),
|
||||
el("col", { style: "width:12%" }),
|
||||
el("col", { class: "u-w-12p" }),
|
||||
el("col", { style: "width:8%" }),
|
||||
el("col", { style: "width:12%" }),
|
||||
el("col", { style: "width:12%" }),
|
||||
el("col", { class: "u-w-12p" }),
|
||||
el("col", { class: "u-w-12p" }),
|
||||
el("col", { style: "width:8%" }),
|
||||
el("col", { style: "width:10%" }),
|
||||
el("col", { style: "width:10%" }),
|
||||
|
|
|
|||
|
|
@ -982,12 +982,10 @@ async function openBackgroundJobsPanel() {
|
|||
}
|
||||
|
||||
const backdrop = el("div", {
|
||||
class: "chat-confirm-backdrop chat-jobs-backdrop",
|
||||
style: "z-index:9998;",
|
||||
class: "chat-confirm-backdrop chat-jobs-backdrop u-z-modal",
|
||||
});
|
||||
const card = el("div", {
|
||||
class: "chat-confirm-card chat-jobs-card",
|
||||
style: "max-width:920px;width:94vw;max-height:82vh;display:flex;flex-direction:column;gap:10px;",
|
||||
class: "chat-confirm-card chat-jobs-card u-jobs-card",
|
||||
});
|
||||
const title = el("div", { class: "card__title", text: t("chat.jobsTitle") });
|
||||
const closeBtn = el("button", { type: "button", class: "btn", text: t("chat.jobsClose") });
|
||||
|
|
@ -997,15 +995,14 @@ async function openBackgroundJobsPanel() {
|
|||
class: "btn btn--danger",
|
||||
text: t("chat.jobsKillAll"),
|
||||
});
|
||||
const head = el("div", { class: "row", style: "gap:8px;justify-content:space-between;align-items:center;flex-wrap:wrap;" }, [
|
||||
const head = el("div", { class: "row u-row-between" }, [
|
||||
title,
|
||||
el("div", { class: "row", style: "gap:8px;" }, [refreshBtn, killAllBtn, closeBtn]),
|
||||
el("div", { class: "row u-gap-8" }, [refreshBtn, killAllBtn, closeBtn]),
|
||||
]);
|
||||
const hint = el("div", { class: "muted", style: "font-size:12px;line-height:1.45;", text: t("chat.jobsHint") });
|
||||
const summary = el("div", { class: "muted", style: "font-size:12px;" });
|
||||
const hint = el("div", { class: "muted u-hint", text: t("chat.jobsHint") });
|
||||
const summary = el("div", { class: "muted u-fs-12" });
|
||||
const list = el("div", {
|
||||
class: "chat-jobs-list",
|
||||
style: "overflow:auto;flex:1;min-height:220px;max-height:58vh;display:flex;flex-direction:column;gap:8px;",
|
||||
class: "chat-jobs-list u-jobs-list",
|
||||
});
|
||||
|
||||
const close = () => {
|
||||
|
|
@ -1059,7 +1056,7 @@ async function openBackgroundJobsPanel() {
|
|||
}),
|
||||
],
|
||||
);
|
||||
const actions = el("div", { class: "chat-jobs-row__actions row", style: "gap:8px;" });
|
||||
const actions = el("div", { class: "chat-jobs-row__actions row u-gap-8" });
|
||||
if (runningJob) {
|
||||
const killBtn = el("button", {
|
||||
type: "button",
|
||||
|
|
@ -1163,16 +1160,14 @@ async function openWikiPreviewModal({ sessionId, path }) {
|
|||
const p = String(path || "").replace(/\\/g, "/").replace(/^\//, "");
|
||||
if (!sid || !p) return;
|
||||
const backdrop = el("div", {
|
||||
class: "chat-confirm-backdrop",
|
||||
style: "z-index:9998;",
|
||||
class: "chat-confirm-backdrop u-z-modal",
|
||||
});
|
||||
const card = el("div", {
|
||||
class: "chat-confirm-card",
|
||||
style: "max-width:980px;width:92vw;max-height:78vh;overflow:auto;",
|
||||
class: "chat-confirm-card u-profile-card",
|
||||
});
|
||||
const title = el("div", { class: "card__title", text: t("chat.wikiPreviewTitle", { path: p }) });
|
||||
const closeBtn = el("button", { type: "button", class: "btn", text: t("chat.wikiPreviewClose") });
|
||||
const head = el("div", { class: "row", style: "gap:8px;justify-content:space-between;align-items:center;" }, [
|
||||
const head = el("div", { class: "row u-row-between" }, [
|
||||
title,
|
||||
closeBtn,
|
||||
]);
|
||||
|
|
@ -1250,30 +1245,25 @@ async function openDispatchLabelsEditor(statusEl) {
|
|||
? JSON.stringify(cfg.overrides, null, 2)
|
||||
: "";
|
||||
const backdrop = el("div", {
|
||||
class: "chat-confirm-backdrop",
|
||||
style: "z-index:9999;",
|
||||
class: "chat-confirm-backdrop u-z-modal-top",
|
||||
});
|
||||
const card = el("div", {
|
||||
class: "card",
|
||||
style: "width:min(860px,96vw);max-height:86vh;overflow:auto;padding:12px;",
|
||||
class: "card u-json-card",
|
||||
});
|
||||
const title = el("div", { class: "card__title", text: t("chat.dispatchLabelsTitle") });
|
||||
const tip = el("div", { class: "muted", text: t("chat.dispatchLabelsPrompt") });
|
||||
const err = el("div", { class: "muted", style: "color:#dc2626;" });
|
||||
const err = el("div", { class: "muted u-text-danger" });
|
||||
const ta = el("textarea", {
|
||||
class: "input",
|
||||
style: "width:100%;min-height:320px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;",
|
||||
class: "input u-mono-area",
|
||||
});
|
||||
ta.value = initText;
|
||||
const previewTitle = el("div", { class: "muted", text: t("chat.dispatchLabelsEffectivePreview") });
|
||||
const diffOnlyWrap = el("label", { class: "muted", style: "display:flex;gap:6px;align-items:center;cursor:pointer;" });
|
||||
const diffOnlyWrap = el("label", { class: "muted u-check-row" });
|
||||
const diffOnlyCb = el("input", { type: "checkbox" });
|
||||
diffOnlyWrap.appendChild(diffOnlyCb);
|
||||
diffOnlyWrap.appendChild(el("span", { text: t("chat.dispatchLabelsDiffOnly") }));
|
||||
const preview = el("textarea", {
|
||||
class: "input",
|
||||
style:
|
||||
"width:100%;min-height:220px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;",
|
||||
class: "input u-mono-area-sm",
|
||||
readonly: "readonly",
|
||||
});
|
||||
const btnSave = el("button", { type: "button", class: "btn btn--primary", text: t("chat.dispatchLabelsSave") });
|
||||
|
|
@ -1282,7 +1272,7 @@ async function openDispatchLabelsEditor(statusEl) {
|
|||
const btnExport = el("button", { type: "button", class: "btn", text: t("chat.dispatchLabelsExport") });
|
||||
const btnImport = el("button", { type: "button", class: "btn", text: t("chat.dispatchLabelsImport") });
|
||||
const btnCancel = el("button", { type: "button", class: "btn", text: t("chat.dispatchLabelsCancel") });
|
||||
const fileInput = el("input", { type: "file", accept: "application/json,.json", style: "display:none" });
|
||||
const fileInput = el("input", { class: "u-hidden", type: "file", accept: "application/json,.json" });
|
||||
const close = () => backdrop.remove();
|
||||
const saveCurrent = async () => {
|
||||
const raw = String(ta.value || "").trim();
|
||||
|
|
@ -1395,16 +1385,16 @@ async function openDispatchLabelsEditor(statusEl) {
|
|||
|
||||
card.appendChild(title);
|
||||
card.appendChild(tip);
|
||||
card.appendChild(el("div", { style: "height:8px;" }));
|
||||
card.appendChild(el("div", { class: "u-h-8" }));
|
||||
card.appendChild(ta);
|
||||
card.appendChild(el("div", { style: "height:8px;" }));
|
||||
card.appendChild(el("div", { class: "u-h-8" }));
|
||||
card.appendChild(previewTitle);
|
||||
card.appendChild(diffOnlyWrap);
|
||||
card.appendChild(preview);
|
||||
card.appendChild(el("div", { style: "height:8px;" }));
|
||||
card.appendChild(el("div", { class: "u-h-8" }));
|
||||
card.appendChild(err);
|
||||
card.appendChild(
|
||||
el("div", { class: "row", style: "gap:8px;justify-content:flex-end;margin-top:8px;" }, [
|
||||
el("div", { class: "row u-row-end-sm" }, [
|
||||
btnDefaults,
|
||||
btnImport,
|
||||
btnExport,
|
||||
|
|
@ -1583,8 +1573,7 @@ function clearChatPageBlockers() {
|
|||
|
||||
function attachChatMenuDismiss(menu) {
|
||||
const scrim = el("div", {
|
||||
class: "chat-menu-scrim",
|
||||
style: "position:fixed;inset:0;z-index:250;background:transparent;",
|
||||
class: "chat-menu-scrim u-overlay-scrim",
|
||||
});
|
||||
const closeAll = () => {
|
||||
dismissChatMenus();
|
||||
|
|
@ -2707,10 +2696,9 @@ async function renderAttachmentsEl(raw) {
|
|||
if (String(typ || "") === "video_ref" && mime.toLowerCase().startsWith("video/")) {
|
||||
card.appendChild(
|
||||
el("video", {
|
||||
class: "chat-att-video",
|
||||
class: "chat-att-video u-media-preview",
|
||||
controls: true,
|
||||
preload: "metadata",
|
||||
style: "max-width:100%;max-height:420px;margin-top:8px;border-radius:8px;",
|
||||
src: url,
|
||||
}),
|
||||
);
|
||||
|
|
@ -2721,10 +2709,9 @@ async function renderAttachmentsEl(raw) {
|
|||
if (remote && String(typ || "") === "video_ref" && mime.toLowerCase().startsWith("video/")) {
|
||||
card.appendChild(
|
||||
el("video", {
|
||||
class: "chat-att-video",
|
||||
class: "chat-att-video u-media-preview",
|
||||
controls: true,
|
||||
preload: "metadata",
|
||||
style: "max-width:100%;max-height:420px;margin-top:8px;border-radius:8px;",
|
||||
src: remote,
|
||||
}),
|
||||
);
|
||||
|
|
@ -3012,11 +2999,10 @@ function syncAuthUserLabel() {
|
|||
];
|
||||
items.push(el("div", { class: "chat-sess-menu-sep" }));
|
||||
items.push(
|
||||
el("div", { class: "muted", style: "padding:6px 10px 2px;font-size:12px;", text: t("theme.label") }),
|
||||
el("div", { class: "muted u-menu-label", text: t("theme.label") }),
|
||||
);
|
||||
const themeSelMenu = el("select", {
|
||||
class: "input",
|
||||
style: "width:100%;margin:4px 8px 8px;max-width:calc(100% - 16px);",
|
||||
class: "input u-menu-select",
|
||||
});
|
||||
try {
|
||||
(window.OclawAdminTheme && window.OclawAdminTheme.THEMES ? window.OclawAdminTheme.THEMES : ["netx"]).forEach((tid) => {
|
||||
|
|
@ -3033,8 +3019,8 @@ function syncAuthUserLabel() {
|
|||
const bridge = window.__chatUserMenuPrefs;
|
||||
if (bridge && typeof bridge === "object") {
|
||||
items.push(el("div", { class: "chat-sess-menu-sep" }));
|
||||
items.push(el("div", { class: "muted", style: "padding:6px 10px 2px;font-size:12px;", text: t("chat.modeLabel") }));
|
||||
const modeSel = el("select", { class: "input", style: "width:100%;margin:4px 8px 8px;max-width:calc(100% - 16px);" });
|
||||
items.push(el("div", { class: "muted u-menu-label", text: t("chat.modeLabel") }));
|
||||
const modeSel = el("select", { class: "input u-menu-select" });
|
||||
try {
|
||||
const rows = Array.isArray(bridge.getModeOptions && bridge.getModeOptions()) ? bridge.getModeOptions() : [];
|
||||
rows.forEach((r) => modeSel.appendChild(el("option", { value: String(r.value || ""), text: String(r.label || r.value || "") })));
|
||||
|
|
@ -3052,7 +3038,7 @@ function syncAuthUserLabel() {
|
|||
}
|
||||
});
|
||||
items.push(modeSel);
|
||||
const reasonWrap = el("label", { class: "switch-wrap", style: "margin:2px 8px 8px;" }, [
|
||||
const reasonWrap = el("label", { class: "switch-wrap u-switch-menu" }, [
|
||||
el("input", { type: "checkbox", class: "switch-input" }),
|
||||
el("span", { class: "switch-slider" }),
|
||||
el("span", { class: "muted", text: t("chat.tools") }),
|
||||
|
|
@ -3087,8 +3073,7 @@ function syncAuthUserLabel() {
|
|||
}),
|
||||
);
|
||||
const menu = el("div", {
|
||||
class: "chat-sess-menu-pop",
|
||||
style: "position:fixed;min-width:220px;z-index:300;",
|
||||
class: "chat-sess-menu-pop u-pop-menu",
|
||||
}, items);
|
||||
const rect = moreBtn.getBoundingClientRect();
|
||||
attachChatMenuDismiss(menu);
|
||||
|
|
@ -3162,7 +3147,7 @@ async function renderLogin() {
|
|||
text: t("auth.login"),
|
||||
onclick: doLogin,
|
||||
});
|
||||
const card = el("div", { class: "card", style: "max-width:440px;width:100%" }, [
|
||||
const card = el("div", { class: "card u-modal-card-sm" }, [
|
||||
el("div", { class: "card__title", text: t("auth.login") }),
|
||||
el("div", { class: "chat-login-fields" }, [username, password]),
|
||||
el("div", { class: "row chat-login-actions" }, [btn]),
|
||||
|
|
@ -3271,7 +3256,7 @@ async function renderChatUi() {
|
|||
rows: "1",
|
||||
placeholder: t("chat.placeholder"),
|
||||
});
|
||||
const fileInput = el("input", { type: "file", multiple: "multiple", style: "display:none", accept: "*/*" });
|
||||
const fileInput = el("input", { class: "u-hidden", type: "file", multiple: "multiple", accept: "*/*" });
|
||||
const attachBtn = el("button", {
|
||||
type: "button",
|
||||
class: "chat-composer-iconbtn",
|
||||
|
|
@ -3301,16 +3286,14 @@ async function renderChatUi() {
|
|||
let specialistCatalog = [];
|
||||
/** Hidden: mode is global-only (⋯ menu). Kept for specialist option list in `publishUserMenuPrefsBridge`. */
|
||||
const modeSelect = el("select", {
|
||||
class: "input",
|
||||
style: "display:none;",
|
||||
class: "input u-hidden",
|
||||
"aria-hidden": "true",
|
||||
tabIndex: -1,
|
||||
});
|
||||
let globalMenuModeValue = String(localStorage.getItem(CHAT_USER_MENU_MODE_KEY) || MAIN_MODE_VALUE).toLowerCase();
|
||||
if (globalMenuModeValue === "comprehensive" || globalMenuModeValue === "main") globalMenuModeValue = MAIN_MODE_VALUE;
|
||||
const modelSelect = el("select", {
|
||||
class: "input",
|
||||
style: "min-width:150px;max-width:240px;padding:6px 8px;",
|
||||
class: "input u-select-mode",
|
||||
title: t("chat.activeModelLabel"),
|
||||
});
|
||||
let modelSelectNameToId = new Map();
|
||||
|
|
@ -3322,8 +3305,7 @@ async function renderChatUi() {
|
|||
normalizeExecutionMode(v) === EXECUTION_MODE_PLAN ? t("chat.execModePlan") : t("chat.execModeAgent");
|
||||
let currentExecutionMode = normalizeExecutionMode(localStorage.getItem(CHAT_EXECUTION_MODE_KEY) || EXECUTION_MODE_AGENT);
|
||||
const execSelect = el("select", {
|
||||
class: "input",
|
||||
style: "min-width:96px;max-width:140px;padding:6px 8px;",
|
||||
class: "input u-select-exec",
|
||||
});
|
||||
const refreshExecutionSelect = () => {
|
||||
const prev = normalizeExecutionMode(execSelect.value || currentExecutionMode);
|
||||
|
|
@ -3344,7 +3326,7 @@ async function renderChatUi() {
|
|||
});
|
||||
refreshExecutionSelect();
|
||||
execSelect.value = currentExecutionMode;
|
||||
const execSelectWrap = el("span", { class: "chat-exec-mode-wrap", style: "display:inline-flex;align-items:center;" }, [
|
||||
const execSelectWrap = el("span", { class: "chat-exec-mode-wrap u-inline-flex" }, [
|
||||
execSelect,
|
||||
]);
|
||||
const refreshExecUi = () => {
|
||||
|
|
@ -3584,13 +3566,12 @@ async function renderChatUi() {
|
|||
};
|
||||
await refreshActiveModelText();
|
||||
refreshExecUi();
|
||||
const composerMetaBar = el("div", { class: "row", style: "gap:8px;padding:2px 4px 6px;align-items:center;" }, [
|
||||
const composerMetaBar = el("div", { class: "row u-gap-8 u-composer-meta" }, [
|
||||
execSelectWrap,
|
||||
modelSelect,
|
||||
el("button", {
|
||||
type: "button",
|
||||
class: "btn",
|
||||
style: "padding:4px 8px;min-height:auto;font-size:12px;",
|
||||
class: "btn u-btn-compact",
|
||||
text: t("chat.compressHistory"),
|
||||
onclick: async () => {
|
||||
const sid = String(activeId || "");
|
||||
|
|
@ -3668,7 +3649,7 @@ async function renderChatUi() {
|
|||
if (ev.target === backdrop) close(false);
|
||||
});
|
||||
card.appendChild(text);
|
||||
card.appendChild(el("div", { class: "row", style: "gap:8px;justify-content:flex-end;margin-top:10px;" }, [btnCancel, btnOk]));
|
||||
card.appendChild(el("div", { class: "row u-row-end" }, [btnCancel, btnOk]));
|
||||
backdrop.appendChild(card);
|
||||
document.body.appendChild(backdrop);
|
||||
});
|
||||
|
|
@ -3678,10 +3659,9 @@ async function renderChatUi() {
|
|||
const card = el("div", { class: "chat-confirm-card" });
|
||||
const text = el("div", { class: "chat-confirm-text", text: String(message || "") });
|
||||
const input = el("input", {
|
||||
class: "input",
|
||||
class: "input u-w-full-mt-10",
|
||||
type: "text",
|
||||
value: String(initialValue || ""),
|
||||
style: "width:100%;margin-top:10px;",
|
||||
});
|
||||
const btnCancel = el("button", { type: "button", class: "btn", text: t("chat.dispatchLabelsCancel") });
|
||||
const btnOk = el("button", { type: "button", class: "btn btn--primary", text: t("chat.dispatchLabelsSave") });
|
||||
|
|
@ -3705,7 +3685,7 @@ async function renderChatUi() {
|
|||
});
|
||||
card.appendChild(text);
|
||||
card.appendChild(input);
|
||||
card.appendChild(el("div", { class: "row", style: "gap:8px;justify-content:flex-end;margin-top:10px;" }, [btnCancel, btnOk]));
|
||||
card.appendChild(el("div", { class: "row u-row-end" }, [btnCancel, btnOk]));
|
||||
backdrop.appendChild(card);
|
||||
document.body.appendChild(backdrop);
|
||||
setTimeout(() => {
|
||||
|
|
@ -3773,13 +3753,12 @@ async function renderChatUi() {
|
|||
const node = showToast(msg.text, { kind: msg.kind, ttlMs: 6500 });
|
||||
const acts = Array.isArray(msg.actions) ? msg.actions : [];
|
||||
if (acts.length) {
|
||||
const btnRow = el("div", { class: "row", style: "gap:8px;flex-wrap:wrap;margin-top:8px;" });
|
||||
const btnRow = el("div", { class: "row u-row-wrap-mt-loose" });
|
||||
for (const a of acts) {
|
||||
btnRow.appendChild(
|
||||
el("button", {
|
||||
type: "button",
|
||||
class: "btn",
|
||||
style: "padding:4px 8px;min-height:auto;font-size:12px;",
|
||||
class: "btn u-btn-compact",
|
||||
text: String(a.label || "View"),
|
||||
onclick: (e) => {
|
||||
e.stopPropagation();
|
||||
|
|
@ -3972,7 +3951,7 @@ async function renderChatUi() {
|
|||
loadMoreWrap.innerHTML = "";
|
||||
if (!sessions.length) {
|
||||
sessionsListEl.appendChild(
|
||||
el("div", { class: "muted", style: "padding:10px 0 10px 8px", text: t("chat.noSessions") }),
|
||||
el("div", { class: "muted u-empty-pad", text: t("chat.noSessions") }),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
|
@ -4025,8 +4004,7 @@ async function renderChatUi() {
|
|||
}
|
||||
if (sessions.length < sessionTotal) {
|
||||
const lm = el("button", {
|
||||
class: "btn",
|
||||
style: "width:100%;margin-top:8px",
|
||||
class: "btn u-w-full-mt-8",
|
||||
text: t("chat.loadMore"),
|
||||
onclick: async () => {
|
||||
try {
|
||||
|
|
@ -5687,7 +5665,7 @@ document.body.addEventListener("click", (e) => {
|
|||
if (!_statusReasonPairs.length) return;
|
||||
document.querySelectorAll(".chat-sess-menu-pop").forEach((n) => n.remove());
|
||||
const items = _statusReasonPairs.map(([k, n]) => `${reasonLabel(k)}: ${n}`).join("\n");
|
||||
const pop = el("div", { class: "chat-sess-menu-pop", style: "position:fixed;max-width:420px;white-space:pre-wrap;line-height:1.4;" }, [
|
||||
const pop = el("div", { class: "chat-sess-menu-pop u-pop-tip" }, [
|
||||
el("div", { class: "chat-sess-menu-item", text: t("chat.dynamicAllReasonsTitle") }),
|
||||
el("div", { class: "chat-sess-menu-item", text: items || "-" }),
|
||||
]);
|
||||
|
|
@ -5745,7 +5723,7 @@ async function boot() {
|
|||
} catch (err) {
|
||||
mount(
|
||||
el("div", { class: "chat-app--login" }, [
|
||||
el("div", { class: "card", style: "max-width:520px;width:100%" }, [
|
||||
el("div", { class: "card u-modal-card" }, [
|
||||
el("div", { class: "card__title", text: t("common.error") }),
|
||||
el("div", { class: "pre", text: String(err) }),
|
||||
]),
|
||||
|
|
@ -5817,7 +5795,7 @@ document.addEventListener("keydown", (ev) => {
|
|||
boot().catch((err) => {
|
||||
mount(
|
||||
el("div", { class: "chat-app--login" }, [
|
||||
el("div", { class: "card", style: "max-width:520px;width:100%" }, [
|
||||
el("div", { class: "card u-modal-card" }, [
|
||||
el("div", { class: "card__title", text: t("common.error") }),
|
||||
el("div", { class: "pre", text: String(err) }),
|
||||
]),
|
||||
|
|
|
|||
|
|
@ -95,9 +95,9 @@
|
|||
<div id="topTitle" class="topbar__title">Runtime</div>
|
||||
<div class="topbar__actions">
|
||||
<span id="authUser" class="muted"></span>
|
||||
<label class="admin-theme-wrap" style="display: inline-flex; align-items: center; gap: 6px; margin-right: 4px">
|
||||
<span class="muted" style="font-size: 12px" data-i18n="theme.label">配色</span>
|
||||
<select id="adminThemeSelect" class="input input--compact" style="min-width: 132px; max-width: 200px; padding: 6px 8px" aria-label="theme">
|
||||
<label class="admin-theme-wrap u-inline-flex u-row-center">
|
||||
<span class="muted u-fs-12" data-i18n="theme.label">配色</span>
|
||||
<select id="adminThemeSelect" class="input input--compact u-theme-select" aria-label="theme">
|
||||
<option value="netx" data-i18n="theme.netx">NetX</option>
|
||||
<option value="deepseek" data-i18n="theme.deepseek">DeepSeek</option>
|
||||
<option value="github" data-i18n="theme.github">GitHub</option>
|
||||
|
|
|
|||
|
|
@ -146,12 +146,30 @@ body {
|
|||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px 18px;
|
||||
height: 48px;
|
||||
min-height: 48px;
|
||||
padding: 0 20px;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 1px solid var(--ds-border, rgba(148, 163, 184, 0.18));
|
||||
background: var(--ds-topbar-bg, rgba(6, 10, 18, 0.94));
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
.topbar__title { color: var(--ds-text, #e2e8f0); font-weight: 650; }
|
||||
.topbar__title {
|
||||
color: var(--ds-text, #e2e8f0);
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
.topbar .row { align-items: center; gap: 8px; }
|
||||
.topbar .input--compact { height: 30px; padding: 4px 8px; font-size: 12px; }
|
||||
.topbar .btn { height: 30px; padding: 4px 10px; font-size: 12px; }
|
||||
.topbar__actions {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.admin-theme-wrap { margin-right: 4px; }
|
||||
.u-theme-select { min-width: 132px; max-width: 200px; padding: 6px 8px; }
|
||||
.btn {
|
||||
background: rgba(148, 163, 184, 0.1);
|
||||
border: 1px solid var(--ds-border, rgba(148, 163, 184, 0.25));
|
||||
|
|
@ -664,3 +682,101 @@ body.theme-ds-body[data-admin-theme="light"] {
|
|||
body.theme-ds-body[data-admin-theme="light"] .content {
|
||||
background: var(--ds-bg, #f1f5f9);
|
||||
}
|
||||
|
||||
/* ---- Utility classes (replace common JS inline styles) ---- */
|
||||
.u-mt-4 { margin-top: 4px; }
|
||||
.u-mt-6 { margin-top: 6px; }
|
||||
.u-mt-8 { margin-top: 8px; }
|
||||
.u-mt-10 { margin-top: 10px; }
|
||||
.u-mb-6 { margin: 0 0 6px 0; }
|
||||
.u-h-8 { height: 8px; }
|
||||
.u-h-10 { height: 10px; }
|
||||
.u-hidden { display: none !important; }
|
||||
.u-drag { cursor: pointer; user-select: none; }
|
||||
.u-wrap-lh { white-space: normal; line-height: 1.5; }
|
||||
.u-muted-block { margin-top: 6px; line-height: 1.45; }
|
||||
.u-muted-block-lg { margin: 8px 0; line-height: 1.5; }
|
||||
.u-spacer-v { margin: 10px 0 14px 0; }
|
||||
.u-label-mt { margin: 8px 0 4px 0; }
|
||||
.u-pad-block { margin: 8px 0; padding: 10px; }
|
||||
.u-row-wrap-mb { gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
|
||||
.u-row-wrap-mt,
|
||||
.u-row-wrap-mt-loose { gap: 8px; flex-wrap: wrap; margin-top: 8px; align-items: center; }
|
||||
.u-row-center { gap: 6px; align-items: center; }
|
||||
.u-row-center-mt { gap: 8px; align-items: center; margin-top: 8px; }
|
||||
.u-row-end { gap: 8px; justify-content: flex-end; margin-top: 10px; }
|
||||
.u-row-end-sm { gap: 8px; justify-content: flex-end; margin-top: 8px; }
|
||||
.u-row-between { gap: 8px; justify-content: space-between; align-items: center; flex-wrap: wrap; }
|
||||
.u-gap-8 { gap: 8px; }
|
||||
.u-max-w-120 { max-width: 120px; }
|
||||
.u-max-w-140 { max-width: 140px; }
|
||||
.u-w-12p { width: 12%; }
|
||||
.u-w-full-mt-8 { width: 100%; margin-top: 8px; }
|
||||
.u-w-full-mt-10 { width: 100%; margin-top: 10px; }
|
||||
.u-overlay-fixed { position: fixed; z-index: 250; }
|
||||
.u-overlay-scrim { position: fixed; inset: 0; z-index: 250; background: transparent; }
|
||||
.u-z-modal { z-index: 9998; }
|
||||
.u-z-modal-top { z-index: 9999; }
|
||||
.u-text-danger { color: #f87171; }
|
||||
.u-menu-label { padding: 6px 10px 2px; font-size: 12px; }
|
||||
.u-menu-select { width: 100%; margin: 4px 8px 8px; max-width: calc(100% - 16px); }
|
||||
.u-btn-compact { padding: 4px 8px; min-height: auto; font-size: 12px; }
|
||||
.u-modal-card { max-width: 520px; width: 100%; }
|
||||
.u-modal-card-sm { max-width: 440px; width: 100%; }
|
||||
.u-media-preview { max-width: 100%; max-height: 420px; margin-top: 8px; border-radius: 8px; }
|
||||
.u-mono-area,
|
||||
.u-mono-area-sm {
|
||||
width: 100%;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||
}
|
||||
.u-mono-area { min-height: 320px; }
|
||||
.u-mono-area-sm { min-height: 220px; }
|
||||
.u-check-row { display: flex; gap: 6px; align-items: center; cursor: pointer; }
|
||||
.u-hint { font-size: 12px; line-height: 1.45; }
|
||||
.u-fs-12 { font-size: 12px; }
|
||||
.u-jobs-card {
|
||||
max-width: 920px;
|
||||
width: 94vw;
|
||||
max-height: 82vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
.u-jobs-list {
|
||||
overflow: auto;
|
||||
flex: 1;
|
||||
min-height: 220px;
|
||||
max-height: 58vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
.u-profile-card { max-width: 980px; width: 92vw; max-height: 78vh; overflow: auto; }
|
||||
.u-json-card { width: min(860px, 96vw); max-height: 86vh; overflow: auto; padding: 12px; }
|
||||
.u-composer-meta { padding: 2px 4px 6px; align-items: center; }
|
||||
.u-select-mode { min-width: 150px; max-width: 240px; padding: 6px 8px; }
|
||||
.u-select-exec { min-width: 96px; max-width: 140px; padding: 6px 8px; }
|
||||
.u-inline-flex { display: inline-flex; align-items: center; }
|
||||
.u-switch-menu { margin: 2px 8px 8px; }
|
||||
.u-pop-menu { position: fixed; min-width: 220px; z-index: 300; }
|
||||
.u-pop-tip { position: fixed; max-width: 420px; white-space: pre-wrap; line-height: 1.4; }
|
||||
.u-empty-pad { padding: 10px 0 10px 8px; }
|
||||
.u-avatar-chip {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 999px;
|
||||
object-fit: contain;
|
||||
border: 2px solid var(--ds-border, rgba(148, 163, 184, 0.18));
|
||||
background: var(--ds-menu-hover-bg, rgba(148, 163, 184, 0.1));
|
||||
padding: 5px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Focus ring — NetX-like accent */
|
||||
.btn:focus-visible,
|
||||
.input:focus-visible,
|
||||
.nav__item:focus-visible,
|
||||
.page-shell__tocItem:focus-visible {
|
||||
outline: 2px solid var(--ds-accent, #3b82f6);
|
||||
outline-offset: 1px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -206,13 +206,13 @@ body.theme-ds-body .card {
|
|||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 50%;
|
||||
background-color: rgba(255, 255, 255, 0.14);
|
||||
background-color: var(--ds-menu-hover-bg, rgba(148, 163, 184, 0.14));
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.22);
|
||||
transition: background-color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.chat-nav__new:hover .chat-nav__newGlyph {
|
||||
background-color: rgba(255, 255, 255, 0.22);
|
||||
background-color: var(--ds-accent-soft, rgba(148, 163, 184, 0.22));
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
|
|
@ -220,7 +220,7 @@ body.theme-ds-body .card {
|
|||
.chat-nav__newGlyph::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
background-color: var(--ds-text, #fff);
|
||||
border-radius: 2px;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
|
|
@ -390,7 +390,7 @@ body.theme-ds-body .card {
|
|||
flex-direction: column;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
background: var(--ds-chat-main, #050505);
|
||||
background: var(--ds-chat-main, var(--ds-bg, #070b14));
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
|
@ -555,13 +555,13 @@ body.theme-ds-body .card {
|
|||
|
||||
/* 与助手侧 oliver.svg 一致:浅底 + 内边距,矢量用 contain(避免大 viewBox 在 flex 下撑开一行) */
|
||||
.chat-avatar--bot {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
background: var(--ds-menu-hover-bg, rgba(148, 163, 184, 0.1));
|
||||
padding: 5px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.chat-avatar--userBuiltin {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
background: var(--ds-menu-hover-bg, rgba(148, 163, 184, 0.1));
|
||||
padding: 5px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
|
@ -614,8 +614,8 @@ body.theme-ds-body .card {
|
|||
align-self: flex-start;
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
border: 1px solid var(--ds-border, rgba(255, 255, 255, 0.08));
|
||||
background: var(--ds-splash-bg, rgba(148, 163, 184, 0.06));
|
||||
border: 1px solid var(--ds-border, rgba(148, 163, 184, 0.18));
|
||||
}
|
||||
|
||||
.chat-msg__actions {
|
||||
|
|
@ -634,10 +634,10 @@ body.theme-ds-body .card {
|
|||
}
|
||||
|
||||
.chat-msg__action-btn {
|
||||
border: 1px solid rgba(148, 163, 184, 0.25);
|
||||
border: 1px solid var(--ds-border, rgba(148, 163, 184, 0.25));
|
||||
background: transparent;
|
||||
color: rgba(203, 213, 225, 0.92);
|
||||
border-radius: 999px;
|
||||
color: var(--ds-text-muted, rgba(203, 213, 225, 0.92));
|
||||
border-radius: 8px;
|
||||
font-size: 15px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
|
|
@ -649,7 +649,7 @@ body.theme-ds-body .card {
|
|||
}
|
||||
|
||||
.chat-msg__action-btn:hover {
|
||||
background: rgba(30, 41, 59, 0.45);
|
||||
background: var(--ds-menu-hover-bg, rgba(30, 41, 59, 0.45));
|
||||
}
|
||||
|
||||
.chat-msg__action-btn--danger {
|
||||
|
|
@ -861,15 +861,15 @@ body.theme-ds-body .card {
|
|||
.chat-msg__md .mermaid .mermaid-fallback pre {
|
||||
margin: 0;
|
||||
white-space: pre-wrap;
|
||||
color: #e5e7eb;
|
||||
color: var(--ds-text, #e5e7eb);
|
||||
}
|
||||
|
||||
.chat-msg--tool {
|
||||
align-self: flex-start;
|
||||
font-family: ui-monospace, monospace;
|
||||
font-size: 12px;
|
||||
background: rgba(0, 0, 0, 0.25);
|
||||
border: 1px dashed rgba(255, 255, 255, 0.12);
|
||||
background: var(--ds-surface, rgba(15, 23, 42, 0.55));
|
||||
border: 1px dashed var(--ds-border, rgba(148, 163, 184, 0.22));
|
||||
}
|
||||
|
||||
/* In-dialog progress (e.g. Core: analyzing request…) during stream; not the footer status line */
|
||||
|
|
@ -879,8 +879,8 @@ body.theme-ds-body .card {
|
|||
font-size: 12px;
|
||||
line-height: 1.45;
|
||||
color: var(--ds-text-muted, rgba(232, 232, 232, 0.72));
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
border: 1px dashed rgba(255, 255, 255, 0.14);
|
||||
background: var(--ds-splash-bg, rgba(148, 163, 184, 0.06));
|
||||
border: 1px dashed var(--ds-border, rgba(148, 163, 184, 0.22));
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
|
@ -890,16 +890,16 @@ body.theme-ds-body .card {
|
|||
gap: 10px;
|
||||
align-items: center;
|
||||
padding: 8px 10px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.12);
|
||||
border: 1px solid var(--ds-border, rgba(148, 163, 184, 0.18));
|
||||
border-radius: 12px;
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
background: var(--ds-splash-bg, rgba(148, 163, 184, 0.05));
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.chat-task-stage__toggle {
|
||||
margin-left: auto;
|
||||
border: 1px solid rgba(255, 255, 255, 0.12);
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
border: 1px solid var(--ds-border, rgba(148, 163, 184, 0.18));
|
||||
background: var(--ds-splash-bg, rgba(148, 163, 184, 0.06));
|
||||
color: var(--ds-text-muted, rgba(232, 232, 232, 0.72));
|
||||
border-radius: 8px;
|
||||
padding: 1px 6px;
|
||||
|
|
@ -908,7 +908,7 @@ body.theme-ds-body .card {
|
|||
}
|
||||
|
||||
.chat-task-stage__toggle:hover {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
background: var(--ds-menu-hover-bg, rgba(148, 163, 184, 0.12));
|
||||
}
|
||||
|
||||
/* Fold model reasoning blocks in assistant bubbles (same rules as Streamlit messages.py). */
|
||||
|
|
@ -927,9 +927,9 @@ body.theme-ds-body .card {
|
|||
.chat-msg__reasoning {
|
||||
align-self: stretch;
|
||||
margin: 4px 0 2px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
border: 1px solid var(--ds-border, rgba(148, 163, 184, 0.18));
|
||||
border-radius: 12px;
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
background: var(--ds-splash-bg, rgba(148, 163, 184, 0.05));
|
||||
padding: 4px 10px 6px;
|
||||
}
|
||||
|
||||
|
|
@ -963,7 +963,7 @@ body.theme-ds-body .card {
|
|||
word-break: break-word;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
border-radius: 10px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.05);
|
||||
border: 1px solid var(--ds-border, rgba(148, 163, 184, 0.12));
|
||||
}
|
||||
|
||||
.chat-msg__reasoning-block {
|
||||
|
|
@ -1001,7 +1001,7 @@ body.theme-ds-body .card {
|
|||
}
|
||||
|
||||
.chat-msg__process-caret {
|
||||
color: rgba(232, 232, 232, 0.6);
|
||||
color: var(--ds-text-muted, rgba(232, 232, 232, 0.6));
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
|
@ -1014,7 +1014,7 @@ body.theme-ds-body .card {
|
|||
|
||||
.chat-composer {
|
||||
flex-shrink: 0;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.05);
|
||||
border-top: 1px solid var(--ds-border, rgba(148, 163, 184, 0.12));
|
||||
padding: 10px 12px 12px;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue