mirror of
https://github.com/hansjone/oclaw.git
synced 2026-10-09 03:30:48 +08:00
本次迁移将网关/通道/工具/技能/脚本与协议资源集中到新结构,统一路径常量与脚本转发机制,减少顶层噪音并保证运行与测试行为一致。 Made-with: Cursor
170 lines
5 KiB
Python
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,
|
|
}
|
|
|