Skip to content

feat: fetch a job's execution log on demand with get_logs() - #122

Draft
guill wants to merge 1 commit into
mainfrom
jacob/be-9479-add-devplat-execution-logs-support-to-sdk
Draft

feat: fetch a job's execution log on demand with get_logs()#122
guill wants to merge 1 commit into
mainfrom
jacob/be-9479-add-devplat-execution-logs-support-to-sdk

Conversation

@guill

@guill guill commented Sep 1, 2026

Copy link
Copy Markdown
Member

Summary

Adds Job.get_logs() and AsyncJob.get_logs(), which fetch what a run printed and return a JobLogs (text, truncated, captured_at, complete) or None.

The log is a resource of its own rather than a field on the job, so submitting and polling never download one — run() to terminal issues zero log requests, and a caller pays only when it asks. Nothing is cached, so an early None on a job that has not finished cannot mask the log it goes on to produce; read again after a terminal status.

None is an ordinary answer, not an error. It covers every reason there is nothing to read — the deployment captures no logs at all, the job has not finished, it predates capture, the run was killed before the worker could report an outcome, capture failed, or the log is withheld from anonymous callers — and the API deliberately does not distinguish them.

A surface that captures no logs omits urls.logs entirely. The SDK answers from that absence without a request, rather than building the path itself, which would 404 as though the job were missing.

Consumer impact

Purely additive. Nothing is removed or narrowed, and existing code keeps working:

  • New: Job.get_logs(), AsyncJob.get_logs(), ComfyLow.get_job_logs(), AsyncComfyLow.get_job_logs(), and the exported JobLogs model.
  • New JobUrls.logs, optional — a server that does not send it still validates.
  • Output.node_id gained a description in the generated model. Documentation only; its type and requiredness are unchanged.

The vendored spec is synced from the canonical contract and the models regenerated.

Testing

  • pytest — 731 passed, 4 skipped. New behavioural coverage: 200 yields a typed value, 204 yields None, three calls make three requests, run() to terminal issues none, a missing urls.logs short-circuits without a request, an empty urls.logs is treated the same way, and the SDK follows the link rather than rebuilding the path.
  • ruff check, ruff format --check, mypy src — clean.
  • scripts/check_drift.py — models in sync with the vendored spec.
  • scripts/check_public_repo_hygiene.py — clean.

Also verified end to end by driving the real SDK against a live HTTP server, not only the test doubles.

Opened as a draft: the server side of this contract is not released yet.

`Job.get_logs()` / `AsyncJob.get_logs()` return what a run printed as a
`JobLogs` (`text`, `truncated`, `captured_at`, `complete`), or `None`.

The log is a resource of its own rather than a field on the job, so
submitting and polling never download one — `run()` to terminal issues zero
log requests, and a caller pays only when it asks. Nothing is cached, so an
early `None` on a job that has not finished cannot mask the log it goes on
to produce; read again after a terminal status.

`None` is an ordinary answer, not an error, covering every reason there is
nothing to read — the contract deliberately does not distinguish them. A
surface that captures no logs omits `urls.logs` entirely, and the SDK
answers from its absence without a request rather than building the path
itself, which would 404 as though the job were missing.

Spec synced from the canonical contract and models regenerated.
@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Comment @coderabbitai help to get the list of available commands.

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.

1 participant