feat: multimodal image clients, workspaces, Tushare skill, test fixes

- Replace monolithic image_message_client with HTTP/OCR/legacy modules; tighten OpenAI transport + tool schemas for multimodal downgrade to OCR specialist path.
- Add image/stock workspace prompts (META/SOUL/ROLE_SYSTEM); register experts; tweak specialist agent/direct loop/query_image_attachment.
- Add bundled runtime/skills/tushare-finance (references, api_client, SKILL metadata).
- Document OCR-related env vars; admin chat tweaks; README; weixin_install Ensure-OfficialPluginRuntimeDeps helper.
- Tests: multimodal downgrade + OCR coverage, strict tool pairing in attachment replay guard, workspace contract skips _internal/_system dirs, router/trace/prompt guards.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-05-10 04:41:42 +08:00
parent 6307ade480
commit d1bcc4debe
266 changed files with 57024 additions and 839 deletions

View file

@ -42,11 +42,16 @@ def normalize_interaction_mode(raw: Any) -> InteractionMode:
def normalize_requested_specialist(raw: Any) -> SpecialistId:
specialist = str(raw or "").strip().lower()
if specialist == "ops":
return "ops"
if specialist == "memory":
return "memory"
return "generalist"
# Accept dynamic specialists discovered from workspaces (e.g. "stock").
# Fallback to "generalist" when unknown.
try:
from oclaw.runtime.agents.specialists import normalize_specialist_id
return normalize_specialist_id(specialist)
except Exception:
if specialist in {"ops", "memory", "generalist", "image"}:
return specialist
return "generalist"
@dataclass(frozen=True)