101 lines
3.2 KiB
Python
101 lines
3.2 KiB
Python
"""轻量任务编排:校验输入 → 选 adapter → 提交批次。"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import os
|
||
import tempfile
|
||
import uuid
|
||
from typing import Any, Dict, List, Optional
|
||
|
||
from service.adapter import BatchItem, select_adapter
|
||
from util.logging import get_logger
|
||
|
||
logger = get_logger(__name__)
|
||
|
||
|
||
def _validate_items(items: List[Dict[str, Any]]) -> tuple[List[BatchItem], Optional[str]]:
|
||
if not items:
|
||
return [], "items 不能为空"
|
||
parsed: List[BatchItem] = []
|
||
for idx, raw in enumerate(items, start=1):
|
||
name = str(raw.get("name") or "").strip()
|
||
account = str(raw.get("account") or "").strip()
|
||
note = str(raw.get("note") or "").strip()
|
||
try:
|
||
amount = float(raw.get("amount"))
|
||
except (TypeError, ValueError):
|
||
return [], f"第 {idx} 行 amount 无效"
|
||
if amount <= 0:
|
||
return [], f"第 {idx} 行 amount 必须大于 0"
|
||
if not name or not account:
|
||
return [], f"第 {idx} 行 name/account 不能为空"
|
||
parsed.append(
|
||
BatchItem(
|
||
row_index=int(raw.get("row_index") or idx),
|
||
name=name,
|
||
account=account,
|
||
amount=amount,
|
||
note=note,
|
||
)
|
||
)
|
||
return parsed, None
|
||
|
||
|
||
async def run_batch_submit(
|
||
target: str,
|
||
items: List[Dict[str, Any]],
|
||
*,
|
||
force: bool = False,
|
||
artifacts_dir: Optional[str] = None,
|
||
) -> Dict[str, Any]:
|
||
"""
|
||
最小编排示例。
|
||
|
||
真实 skill 中还应:写业务表、entitlement、RpaVideoSession 等。
|
||
账号 pick / lease 在 adapter 内完成,编排层不直接碰 account-manager。
|
||
"""
|
||
del force # 示例占位;真实 skill 可用于跳过确认
|
||
|
||
target_key = (target or "").strip()
|
||
if not target_key:
|
||
return {"success": False, "error": {"code": "INVALID_TARGET", "message": "target 不能为空"}}
|
||
|
||
batch_items, err = _validate_items(items)
|
||
if err:
|
||
return {"success": False, "error": {"code": "INVALID_ITEMS", "message": err}}
|
||
|
||
art_dir = artifacts_dir or os.path.join(
|
||
tempfile.gettempdir(),
|
||
"openclaw-simulator-rpa-artifacts",
|
||
uuid.uuid4().hex[:8],
|
||
)
|
||
os.makedirs(art_dir, exist_ok=True)
|
||
logger.info(
|
||
"batch_submit_start target=%s item_count=%s artifacts_dir=%s",
|
||
target_key,
|
||
len(batch_items),
|
||
art_dir,
|
||
)
|
||
|
||
adapter = select_adapter(artifacts_dir=art_dir)
|
||
result = await adapter.submit_batch(target_key, batch_items)
|
||
summary: Dict[str, Any] = {
|
||
"success": result.ok,
|
||
"target": target_key,
|
||
"adapter": result.artifacts.get("adapter") or adapter.name,
|
||
"submitted_count": result.submitted_count,
|
||
"submitted_amount": result.submitted_amount,
|
||
"batch_id": result.batch_id,
|
||
"artifacts": result.artifacts,
|
||
"artifacts_dir": art_dir,
|
||
}
|
||
if not result.ok:
|
||
summary["error"] = {"code": "BATCH_SUBMIT_FAILED", "message": result.error_msg or "提交失败"}
|
||
logger.info(
|
||
"batch_submit_done success=%s batch_id=%s adapter=%s",
|
||
result.ok,
|
||
result.batch_id,
|
||
adapter.name,
|
||
)
|
||
return summary
|