Add AIServer, character art pipeline, and Art package boot integration.

Bring in MaleExplorer assets/shaders, model tooling and Hunyuan updates, plus boot/YooAsset Art package support.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
udx
2026-09-21 17:06:59 +08:00
co-authored by Cursor
parent b7a0bbcb89
commit 6550b8df4b
121 changed files with 313260 additions and 113 deletions
+40 -9
View File
@@ -33,6 +33,7 @@ from hunyuan_3d.auth import ( # noqa: E402
status,
)
from hunyuan_3d.client import FACE_LABEL, FACE_LABELS, generate_from_image # noqa: E402
from hunyuan_3d.errors import HunyuanQuotaExceeded, HunyuanReloginNeeded # noqa: E402
from hunyuan_3d.events import CallbackHub # noqa: E402
@@ -83,10 +84,11 @@ def run_generate(
output: str,
faces: str = FACE_LABEL,
interactive_login: bool = True,
login_timeout: int = 180,
login_timeout: int = 300,
callback_url: Optional[str] = None,
callback_file: Optional[str] = None,
quiet: bool = False,
max_login_retries: int = 3,
) -> Dict[str, Any]:
callbacks = CallbackHub(
callback_url=callback_url,
@@ -134,23 +136,43 @@ def run_generate(
attempts += 1
try:
mesh = generate_from_image(
image_path, work_dir, update, face_label=face_label
image_path,
work_dir,
update,
face_label=face_label,
headed=False,
)
break
except PermissionError as exc:
if not interactive_login or attempts >= 2:
except HunyuanReloginNeeded as exc:
reason = getattr(exc, "reason", "auth") or "auth"
if isinstance(exc, HunyuanQuotaExceeded):
reason = "quota"
if not interactive_login or attempts > max_login_retries:
raise GenerateError(str(exc)) from exc
update(
event="login_required",
stage="凭证失效,重新微信登录",
stage=(
"当前账号额度已满,打开登录页换号"
if reason == "quota"
else "凭证失效,重新微信登录"
),
progress=3,
error=str(exc),
reason=reason,
attempt=attempts,
)
print(
f"[hunyuan] {exc}\n"
f"[hunyuan] 即将打开浏览器登录页(原因={reason},第 {attempts}/{max_login_retries} 次)",
flush=True,
)
# 清掉失效会话再扫码
if is_logged_in():
logout()
start_wechat_login_blocking(
timeout_sec=login_timeout, update=update
timeout_sec=login_timeout,
update=update,
reason=reason,
clear_existing=True,
)
shutil.copy2(mesh, output_path)
@@ -203,8 +225,13 @@ def build_parser() -> argparse.ArgumentParser:
p.add_argument(
"--login-timeout",
type=int,
default=180,
help="微信扫码等待秒数,默认 180",
default=300,
help="微信扫码等待秒数,默认 300",
)
p.add_argument(
"--force-login",
action="store_true",
help="忽略本地凭证,强制弹出登录页(换号)",
)
p.add_argument("--callback-url", default=None, help="流程回调 URL:每个事件 POST JSON")
p.add_argument(
@@ -252,10 +279,14 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
quiet=quiet_events,
)
update = _make_update(callbacks)
force = bool(args.force_login or payload.get("force_login"))
reason = str(payload.get("reason") or ("quota" if force else "auth"))
try:
result = start_wechat_login_blocking(
timeout_sec=int(payload.get("login_timeout") or args.login_timeout),
update=update,
reason=reason,
clear_existing=force or reason == "quota",
)
except Exception as exc: # noqa: BLE001
err = {"ok": False, "error": str(exc)}