Simplify oclaw product surface: drop niche specialists and admin noise.

Remove stock/image/video specialists, Gmail watcher, CocoLoop market, desktop packaging, and extra memory plugins; disable dynamic agents and hide Session Monitor / API grants / Admin Audit from nav.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-08-11 01:34:10 +08:00
parent efa72df362
commit cf31fd104d
290 changed files with 127 additions and 64576 deletions

View file

@ -4479,7 +4479,7 @@ def build_admin_router() -> APIRouter:
_require_permission(ctx, "admin:memory:write")
store.set_setting("MEMORY_VECTOR_ENABLED", "1" if str(payload.get("enabled") or "").lower() in ("1", "true", "yes", "on") else "0")
backend = str(payload.get("backend") or "sqlite").strip().lower()
if backend not in {"sqlite", "chroma", "qdrant"}:
if backend != "sqlite":
backend = "sqlite"
store.set_setting("MEMORY_VECTOR_BACKEND", backend)
store.set_setting("MEMORY_VECTOR_TOPK", str(payload.get("top_k") or 5))

View file

@ -3552,8 +3552,6 @@ async function renderMemory() {
const enabled = el("input", { type: "checkbox" });
const backend = el("select", { class: "input" }, [
el("option", { value: "sqlite", text: "sqlite" }),
el("option", { value: "chroma", text: "chroma" }),
el("option", { value: "qdrant", text: "qdrant" }),
]);
const topk = el("input", { class: "input", type: "number", value: "5", min: "1", max: "20" });
const writerEnabled = el("input", { type: "checkbox" });
@ -4847,7 +4845,7 @@ async function renderModels() {
]),
expertsStatus,
], { id: "models-experts" }),
el("div", { class: "card section-card", id: "models-eval" }, [evalDetails]),
el("div", { class: "card section-card", id: "models-eval", style: "display:none" }, [evalDetails]),
]);
}
@ -8237,7 +8235,6 @@ async function renderSkills() {
const skillPromptModeCb = el("input", { type: "checkbox" });
const skillMarketProviderSelect = el("select", { class: "input", style: "min-width:160px;" }, [
el("option", { value: "clawhub", text: "clawhub (ClawHub)" }),
el("option", { value: "cocoloop", text: "cocoloop (CocoLoop)" }),
]);
const marketQ = el("input", { class: "input", placeholder: "search skills (keyword)" });
const marketLimitInp = el("input", { class: "input", placeholder: "limit", value: "40", style: "max-width:120px;" });
@ -8249,8 +8246,7 @@ async function renderSkills() {
try {
const r = await apiGet("/admin/api/skills/mode");
skillPromptModeCb.checked = !!r.prompt_in_system;
const mp = String(r.market_provider || "clawhub").trim().toLowerCase();
skillMarketProviderSelect.value = mp === "cocoloop" ? "cocoloop" : "clawhub";
skillMarketProviderSelect.value = "clawhub";
skillModeStatus.textContent = "";
} catch (e) {
skillModeStatus.textContent = `mode: ${String(e && e.message ? e.message : e)}`;
@ -8261,12 +8257,11 @@ async function renderSkills() {
try {
const r = await apiPost("/admin/api/skills/mode", {
prompt_in_system: !!skillPromptModeCb.checked,
market_provider: String(skillMarketProviderSelect.value || "clawhub").trim(),
market_provider: "clawhub",
});
skillPromptModeCb.checked = !!r.prompt_in_system;
const mp = String(r.market_provider || "clawhub").trim().toLowerCase();
skillMarketProviderSelect.value = mp === "cocoloop" ? "cocoloop" : "clawhub";
skillModeStatus.textContent = `saved: prompt=${String(!!r.prompt_in_system)} market=${String(skillMarketProviderSelect.value)}`;
skillMarketProviderSelect.value = "clawhub";
skillModeStatus.textContent = `saved: prompt=${String(!!r.prompt_in_system)} market=clawhub`;
} catch (e) {
skillModeStatus.textContent = `mode: ${String(e && e.message ? e.message : e)}`;
}
@ -10101,11 +10096,15 @@ async function router() {
view = hasPermission("admin:user:read") ? await renderUserManagement() : forbiddenCard();
} else if (page === "memory") view = await renderMemory();
else if (page === "models") view = await renderModels();
else if (page === "api-grants") view = await renderApiGrants();
else if (page === "audit") view = await renderAudit(route.params.get("session_id") || "");
else if (page === "session-monitor") {
else if (page === "api-grants" || page === "session-monitor" || page === "admin-audit") {
view = el("div", { class: "card" }, [
el("div", { class: "card__title", text: t("common.notFound") }),
el("div", { class: "muted", text: "This admin page was removed in the product simplification pass." }),
]);
} else if (page === "audit") view = await renderAudit(route.params.get("session_id") || "");
else if (false && page === "session-monitor") {
view = isAdministratorUsername() ? await renderSessionMonitor() : el("div", { class: "card" }, [el("div", { class: "card__title", text: t("sessionMonitor.onlyAdministrator") })]);
} else if (page === "admin-audit") {
} else if (false && page === "admin-audit") {
view = hasPermission("admin:user:write") ? await renderAdminAudit() : forbiddenCard();
} else if (page === "plugins") {
mount(

View file

@ -66,14 +66,12 @@
<div class="nav__groupTitle">系统与运行</div>
<a class="nav__item" data-page="stack" href="#/stack" data-i18n="nav.stack">Runtime</a>
<a class="nav__item" data-page="scheduled-jobs" href="#/scheduled-jobs" data-i18n="nav.scheduledJobs">定时任务</a>
<a class="nav__item" data-page="session-monitor" href="#/session-monitor" data-i18n="nav.sessionMonitor">会话监控</a>
<a class="nav__item" data-page="workspace-paths" href="#/workspace-paths" data-i18n="nav.workspacePaths">工作区路径</a>
<a class="nav__item" data-page="attachments" href="#/attachments" data-i18n="nav.attachments">附件</a>
</div>
<div class="nav__group">
<div class="nav__groupTitle">模型与插件</div>
<a class="nav__item" data-page="models" href="#/models" data-i18n="nav.models">模型管理</a>
<a class="nav__item" data-page="api-grants" href="#/api-grants" data-i18n="nav.apiGrants">API 使用授权</a>
<a class="nav__item" data-page="plugins" href="#/plugins" data-i18n="nav.plugins">Plugins</a>
<a class="nav__item" data-page="skills" href="#/skills" data-i18n="nav.skills">Skills</a>
</div>
@ -81,7 +79,6 @@
<div class="nav__groupTitle">治理与审计</div>
<a class="nav__item" data-page="memory" href="#/memory" data-i18n="nav.memory">Memory</a>
<a class="nav__item" data-page="audit" href="#/audit" data-i18n="nav.audit">Audit & Trace</a>
<a class="nav__item" data-page="admin-audit" href="#/admin-audit" data-i18n="nav.adminAudit">Admin Audit</a>
</div>
<div class="nav__group">
<div class="nav__groupTitle">用户与配置</div>

View file

@ -36,13 +36,14 @@ def _resolve_gateway_startup_plugin_ids(
out = [str(x).strip() for x in plugins if str(x).strip()]
slot_cfg = ((config.get("plugins") or {}).get("slots") or {}) if isinstance(config, dict) else {}
memory_slot = str(slot_cfg.get("memory") or "").strip()
memory_plugin_ids = {"memory-core", "memory-wiki", "memory-lancedb"}
memory_plugin_ids = {"memory-wiki"}
skip_plugin_ids = {"telegram", "memory-core", "memory-lancedb"}
if out:
if memory_slot:
out = [x for x in out if x not in memory_plugin_ids]
if memory_slot.lower() != "none":
out = [x for x in out if x not in {"memory-core", "memory-wiki", "memory-lancedb"}]
if memory_slot.lower() != "none" and memory_slot not in skip_plugin_ids:
out.append(memory_slot)
return out
return [x for x in out if x not in skip_plugin_ids]
# Auto-discover local plugins when explicit list is absent.
roots = [
runtime_extensions_root(),
@ -62,10 +63,10 @@ def _resolve_gateway_startup_plugin_ids(
seen.add(pid)
out.append(pid)
if memory_slot:
out = [x for x in out if x not in memory_plugin_ids]
if memory_slot.lower() != "none":
out = [x for x in out if x not in {"memory-core", "memory-wiki", "memory-lancedb"}]
if memory_slot.lower() != "none" and memory_slot not in skip_plugin_ids:
out.append(memory_slot)
return out
return [x for x in out if x not in skip_plugin_ids]
def _load_oclaw_plugins(