oclaw/gateway/server_methods/wizard.py
oliver ba3836f00f 初始化:独立 oclaw 仓库首提交
- 在 oclaw/ 下重新初始化 Git 仓库
- 补齐子仓库 .gitignore,避免提交本地运行态数据(_local、node_modules、logs 等)
- 提交当前工程代码与配置

Made-with: Cursor
2026-04-24 22:31:22 +08:00

170 lines
5 KiB
Python

from __future__ import annotations
from uuid import uuid4
from typing import Any
from .shared_types import GatewayRequestHandlers
from .validation import error_shape
def _ok(respond, payload: Any) -> None:
if callable(respond):
respond(True, payload, None, None)
def _bad(respond, message: str) -> None:
if callable(respond):
respond(False, None, error_shape("INVALID_REQUEST", message), None)
def _unavailable(respond, message: str) -> None:
if callable(respond):
respond(False, None, error_shape("UNAVAILABLE", message), None)
def _norm_str(v: Any) -> str | None:
if isinstance(v, str):
s = v.strip()
return s or None
return None
def _sessions(context: Any) -> dict[str, dict[str, Any]]:
if not isinstance(context, dict):
return {}
sessions = context.get("wizardSessions")
if isinstance(sessions, dict):
return sessions
created: dict[str, dict[str, Any]] = {}
context["wizardSessions"] = created
return created
def _find_running(context: Any) -> str | None:
for sid, session in _sessions(context).items():
if isinstance(session, dict) and session.get("status") == "running":
return sid
return None
def _wizard_start_handler(opts: dict[str, Any]) -> None:
respond = opts.get("respond")
params = opts.get("params")
context = opts.get("context")
if not isinstance(params, dict):
_bad(respond, "invalid wizard.start params")
return
mode = _norm_str(params.get("mode"))
if not mode:
_bad(respond, "invalid wizard.start params")
return
running = _find_running(context)
if running:
_unavailable(respond, "wizard already running")
return
session_id = str(uuid4())
session = {
"status": "running",
"error": None,
"mode": mode,
"workspace": _norm_str(params.get("workspace")),
"step": 0,
"history": [],
}
_sessions(context)[session_id] = session
_ok(
respond,
{
"sessionId": session_id,
"done": False,
"step": {"id": "step-1", "kind": "input", "prompt": "Provide first value"},
},
)
def _wizard_next_handler(opts: dict[str, Any]) -> None:
respond = opts.get("respond")
params = opts.get("params")
context = opts.get("context")
if not isinstance(params, dict):
_bad(respond, "invalid wizard.next params")
return
session_id = _norm_str(params.get("sessionId"))
if not session_id:
_bad(respond, "invalid wizard.next params")
return
session = _sessions(context).get(session_id)
if not isinstance(session, dict):
_bad(respond, "wizard not found")
return
answer = params.get("answer")
if answer is not None:
if session.get("status") != "running":
_bad(respond, "wizard not running")
return
session["history"].append(answer)
step = int(session.get("step") or 0) + 1
session["step"] = step
if step >= 2:
session["status"] = "done"
_sessions(context).pop(session_id, None)
_ok(respond, {"done": True, "result": {"ok": True}})
return
_ok(
respond,
{
"done": False,
"step": {"id": f"step-{step+1}", "kind": "input", "prompt": "Provide next value"},
},
)
def _wizard_cancel_handler(opts: dict[str, Any]) -> None:
respond = opts.get("respond")
params = opts.get("params")
context = opts.get("context")
if not isinstance(params, dict):
_bad(respond, "invalid wizard.cancel params")
return
session_id = _norm_str(params.get("sessionId"))
if not session_id:
_bad(respond, "invalid wizard.cancel params")
return
session = _sessions(context).get(session_id)
if not isinstance(session, dict):
_bad(respond, "wizard not found")
return
session["status"] = "cancelled"
_sessions(context).pop(session_id, None)
_ok(respond, {"status": "cancelled", "error": None})
def _wizard_status_handler(opts: dict[str, Any]) -> None:
respond = opts.get("respond")
params = opts.get("params")
context = opts.get("context")
if not isinstance(params, dict):
_bad(respond, "invalid wizard.status params")
return
session_id = _norm_str(params.get("sessionId"))
if not session_id:
_bad(respond, "invalid wizard.status params")
return
session = _sessions(context).get(session_id)
if not isinstance(session, dict):
_bad(respond, "wizard not found")
return
status = str(session.get("status") or "unknown")
out = {"status": status, "error": session.get("error")}
if status != "running":
_sessions(context).pop(session_id, None)
_ok(respond, out)
wizard_handlers: GatewayRequestHandlers = {
"wizard.start": _wizard_start_handler,
"wizard.next": _wizard_next_handler,
"wizard.cancel": _wizard_cancel_handler,
"wizard.status": _wizard_status_handler,
}