hf-cli admin list crashed on prod with `KeyError: 'Agent'` because the CLI bypassed main.py's startup() which is the only place that imports every model module — User has a relationship target (`Agent`) that SQLAlchemy can't resolve unless its module is imported. Load them all up front in __main__.py (mirrors the main.py import block). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
69 lines
2.3 KiB
Python
69 lines
2.3 KiB
Python
"""hf-cli entry point. Dispatches to subject-specific modules."""
|
|
import sys
|
|
|
|
|
|
def _load_all_models() -> None:
|
|
"""Import every model module so SQLAlchemy's declarative registry
|
|
resolves cross-table relationships (e.g. User.role, User.agent).
|
|
|
|
main.py's startup() does the same thing for the web server; the CLI
|
|
skips startup() but still queries User → would otherwise hit
|
|
`KeyError: 'Agent'` when SA tries to resolve relationship targets.
|
|
Keep this list in sync with main.py's startup import list.
|
|
"""
|
|
from app.models import ( # noqa: F401
|
|
models, webhook, apikey, activity, milestone, notification, worklog,
|
|
monitor, role_permission, task, support, meeting, proposal, propose,
|
|
essential, agent, calendar, minimum_workload, schedule_type,
|
|
schedule_type_special_slot, oidc_settings,
|
|
)
|
|
|
|
|
|
_load_all_models()
|
|
|
|
|
|
USAGE = """Usage:
|
|
hf-cli admin create-user --email <e> [--username <u>] [--full-name <n>]
|
|
[--password <p>] [--oidc-issuer <url> --oidc-subject <sub>]
|
|
hf-cli admin list
|
|
hf-cli admin set-role --username <u> --role <admin|mgr|dev|guest|account-manager>
|
|
hf-cli admin reset-password --username <u> --password <p>
|
|
hf-cli admin bind-oidc --username <u> --oidc-issuer <url> --oidc-subject <sub>
|
|
|
|
hf-cli config oidc [--issuer <url>] [--client-id <id>] [--client-secret <s>]
|
|
[--redirect-uri <url>] [--post-login-redirect <url>]
|
|
[--scopes "openid email profile"] [--admin-role <role>]
|
|
[--enabled true|false] [--show-secret]
|
|
|
|
Reads DATABASE_URL + SECRET_KEY from the same env as the backend. Run
|
|
inside the backend container: `docker exec hf-backend hf-cli ...`.
|
|
"""
|
|
|
|
|
|
def main() -> int:
|
|
args = sys.argv[1:]
|
|
if len(args) < 1:
|
|
sys.stderr.write(USAGE)
|
|
return 1
|
|
|
|
subject = args[0]
|
|
rest = args[1:]
|
|
|
|
if subject == "admin":
|
|
from app.cli import admin
|
|
return admin.dispatch(rest)
|
|
if subject == "config":
|
|
from app.cli import config
|
|
return config.dispatch(rest)
|
|
if subject in ("-h", "--help", "help"):
|
|
sys.stdout.write(USAGE)
|
|
return 0
|
|
|
|
sys.stderr.write(f"unknown subject: {subject}\n\n")
|
|
sys.stderr.write(USAGE)
|
|
return 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|