Skip to content

[CLI] Parse initiator field on jobs API responses#4212

Merged
Wauplin merged 6 commits into
huggingface:mainfrom
davanstrien:cli-jobs-initiator-field
May 18, 2026
Merged

[CLI] Parse initiator field on jobs API responses#4212
Wauplin merged 6 commits into
huggingface:mainfrom
davanstrien:cli-jobs-initiator-field

Conversation

@davanstrien

@davanstrien davanstrien commented May 8, 2026

Copy link
Copy Markdown
Member

Independent of #4211 (off main, no merge-order dependency).

Summary

Parses the initiator field the Hub returns on jobs API responses. Adds a
JobInitiator dataclass + JobInfo.initiator field. Pure data-layer
addition — no ps table column in this PR.

  • _jobs_api.py: new JobInitiator dataclass + new JobInfo.initiator field
  • __init__.py: re-export JobInitiator alongside the existing job dataclasses

Variants the Hub returns:

  • user / org — ad-hoc runs (name populated)
  • scheduled-job — cron-triggered runs (id only)
  • duplicated-job — runs created via POST /duplicate (id only)

All share type and id; name is only set for user/org. Matches the
lightweight shape of the existing JobOwner (no avatar_url — keeps
inspect output tight). The server-side avatarUrl is dropped at the
call site rather than absorbed into the dataclass, matching how
JobOwner / JobStatus are constructed in this file.

Why

Useful for both human users (knowing at-a-glance what triggered a job in
inspect output) and agents inspecting a user's job history programmatically.
When scanning many jobs from the same user, initiator is the only way to
disambiguate manual runs from automated/scheduled ones. The data was already
available server-side; the Python library was silently dropping it on parse.

Where it surfaces

CLI surface Visible?
hf jobs inspect <id> ✅ full block
hf jobs ps --format json ✅ full block (JSON-parseable for agents)
hf jobs ps (default table) ❌ no column added

Sample output

Two real jobs run by the same user — one ad-hoc, one cron-triggered. Note how
initiator disambiguates them while owner is identical:

$ hf jobs inspect 6a01d697aff1cd33e8f33a64
[
    {
        "id": "6a01d697aff1cd33e8f33a64",
        "status": {"stage": "COMPLETED", "message": null},
        ...
        "owner": {"id": "60107b385ac3e86b3ea4fc34", "name": "davanstrien", "type": "user"},
        "initiator": {"type": "user", "id": "60107b385ac3e86b3ea4fc34", "name": "davanstrien"}
        ...
    }
]

$ hf jobs inspect 6a01c8c2aff1cd33e8f339d4
[
    {
        "id": "6a01c8c2aff1cd33e8f339d4",
        "status": {"stage": "COMPLETED", "message": null},
        ...
        "owner": {"id": "60107b385ac3e86b3ea4fc34", "name": "davanstrien", "type": "user"},
        "initiator": {"type": "scheduled-job", "id": "69c4179671691dc46f166314", "name": null}
        ...
    }
]

For cron-triggered runs, initiator.type == "scheduled-job" and
initiator.id points at the schedule definition. Agents can filter the full
list directly off --format json:

$ hf jobs ps -a --format json | jq '[.[] | select(.initiator.type == "scheduled-job")] | length'
63

Open question for reviewers

Should we add an INITIATOR column to the default hf jobs ps table?

  • For: glance-scan UX — "which of these are cron vs manual?"
  • Against: column-count creep — ps is already 5 cols (6 if [CLI] Surface job runtime fields in ps + inspect #4211 lands),
    150+ chars wide on standard terminals
  • Adjacent UX problem: active runs buried under historical ERROR/COMPLETED
    rows — better addressed by a --sort status flag or --active-only shortcut

Kept this PR minimal so the display decision can have its own discussion.

Test plan

  • Parametrized parse tests for all four variants (user / org / scheduled-job / duplicated-job)
  • Default-None test (when initiator field absent)
  • Smoke-tested locally against real jobs — user and scheduled-job initiators both parse; server-side avatarUrl extra is silently filtered

🤖 Generated with Claude Code


Note

Low Risk
Low risk: adds an optional parsed field to JobInfo and re-exports a new dataclass, with minimal impact on existing job APIs unless callers rely on strict attribute sets/serialization.

Overview
Adds support for the Jobs API initiator field by introducing a new JobInitiator dataclass and wiring it into JobInfo as an optional initiator attribute during response parsing.

Updates public exports in __init__.py (lazy/static imports and __all__) so JobInitiator is available at the package top level.

Reviewed by Cursor Bugbot for commit 460db26. Bugbot is set up for automated code reviews on this repo. Configure here.

Adds a `JobInitiator` dataclass and `JobInfo.initiator` field, surfacing the
`initiator` object the Hub returns on jobs responses. Variants: user/org
(ad-hoc runs), scheduled-job (cron-triggered runs), duplicated-job
(`POST /duplicate` runs). All share `type` and `id`; `name` is only set for
user/org. Mirrors the lightweight shape of the existing `JobOwner`.

`hf jobs inspect --json` and `hf jobs ps --json` auto-surface the new field
via `asdict`. No `ps` table column added — kept minimal; column or filter
flag is a separate UX decision.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bot-ci-comment

bot-ci-comment Bot commented May 8, 2026

Copy link
Copy Markdown

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

@codecov

codecov Bot commented May 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 77.09%. Comparing base (1daa48b) to head (460db26).
⚠️ Report is 338 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4212      +/-   ##
==========================================
+ Coverage   75.00%   77.09%   +2.09%     
==========================================
  Files         145      171      +26     
  Lines       13978    19493    +5515     
==========================================
+ Hits        10484    15028    +4544     
- Misses       3494     4465     +971     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

davanstrien and others added 2 commits May 11, 2026 14:34
- Drop the custom JobInitiator.__init__ in favour of a plain @DataClass
  with `name: str | None = None`. Switch the call site in JobInfo to
  explicit kwargs (matches the JobOwner / JobStatus construction style
  in this file), which also drops server-side extras like `avatarUrl`
  without needing to absorb them inside the dataclass.
- Re-export JobInitiator from huggingface_hub.__init__ alongside the
  existing job dataclasses, so users can type-annotate `job.initiator`
  without reaching into the private _jobs_api module.
- Bring the JobInfo docstring example up to date with the new
  `initiator=...` field.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@davanstrien davanstrien marked this pull request as ready for review May 11, 2026 13:53

@hanouticelina hanouticelina left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

Comment thread src/huggingface_hub/_jobs_api.py
Comment thread tests/test_cli.py Outdated
davanstrien and others added 3 commits May 15, 2026 11:17
Co-authored-by: célina <hanouticelina@gmail.com>
Removes test_job_info_parses_initiator_variants and
test_job_info_initiator_default_none from tests/test_cli.py: they
weren't CLI tests, and the parametrized variants exercised the same
constructor line with different strings rather than meaningful behavior.

Also applies ruff format to the JobInitiator docstring whitespace.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

@Wauplin Wauplin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@Wauplin Wauplin merged commit ed29b27 into huggingface:main May 18, 2026
16 of 17 checks passed
davanstrien added a commit to davanstrien/huggingface_hub that referenced this pull request May 20, 2026
Resolve JobInfo conflict from huggingface#4212 (initiator) by keeping both the
runtime fields (started_at/finished_at/durations + JobDurations) and
the new initiator field/dataclass.

Add JobStage.SCHEDULING (+ docstring) per review — fixtures rely on it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@huggingface-hub-bot

Copy link
Copy Markdown
Contributor

This PR has been shipped as part of the v1.16.0 release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants