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

@ -280,11 +280,6 @@ def build_ops_agent(
)
# `default_registry` treats empty allow_tags + empty allow_tools as "no filter". Use an impossible
# tool name so image/video specialists get an empty tool surface (dedicated HTTP lanes).
_IMAGE_SPECIALIST_TOOL_ALLOWLIST: tuple[str, ...] = ("__oclaw_image_specialist_no_tools__",)
def build_gateway_executor(
store: SqliteStore,
*,
@ -328,8 +323,6 @@ def build_gateway_executor(
"path_policy_user_id": path_policy_user_id,
"store": store,
}
if prof.name in {"image", "video"}:
reg_kw["allow_tools"] = list(_IMAGE_SPECIALIST_TOOL_ALLOWLIST)
tools = default_registry(**reg_kw)
return Agent(
store=store,

View file

@ -13,6 +13,10 @@ AgentRoleId = str
MANAGER_AGENT_ID: AgentRoleId = "manager"
AGENT_PROFILE_BINDINGS_KEY = "agent_profile_bindings"
# Product simplification: media/stock specialists removed from the surface.
_REMOVED_SPECIALIST_IDS: frozenset[str] = frozenset({"image", "video", "stock"})
_BASE_SPECIALIST_ORDER: tuple[str, ...] = ("generalist", "ops", "memory")
@dataclass(frozen=True)
class SpecialistConfig:
@ -46,22 +50,18 @@ SPECIALISTS: dict[SpecialistId, SpecialistConfig] = {
expert_name="memory",
default_tool_tags=None,
),
"image": SpecialistConfig(
specialist_id="image",
# Vision turns attach pixels in-message; gateway executor exposes no tools (see factory).
expert_name="image",
default_tool_tags=None,
),
"video": SpecialistConfig(
specialist_id="video",
expert_name="video",
default_tool_tags=None,
),
}
def discover_specialist_ids() -> tuple[SpecialistId, ...]:
rows = specialist_registry_snapshot(base_order=("generalist", "ops", "memory", "image", "video"))
return tuple(str(x.get("id") or "").strip().lower() for x in rows if str(x.get("id") or "").strip())
rows = specialist_registry_snapshot(base_order=_BASE_SPECIALIST_ORDER)
out: list[str] = []
for x in rows:
sid = str(x.get("id") or "").strip().lower()
if not sid or sid in _REMOVED_SPECIALIST_IDS:
continue
out.append(sid)
return tuple(out)
def specialist_ids() -> tuple[SpecialistId, ...]:
@ -101,6 +101,8 @@ def model_role_for_specialist(specialist_id: SpecialistId) -> AgentRoleId:
def normalize_specialist_id(specialist_id: SpecialistId | None) -> SpecialistId:
sid = (specialist_id or "").strip().lower()
if sid in _REMOVED_SPECIALIST_IDS:
return "generalist"
if sid in SPECIALISTS:
return sid
if sid in discover_specialist_ids():