Skip to content

feat: add WorkersResource + UsageResource (parity with /v1/workers + /v1/usage)#26

Merged
govindkavaturi-art merged 1 commit into
mainfrom
feat/sdk-workers-and-usage-resources
May 4, 2026
Merged

feat: add WorkersResource + UsageResource (parity with /v1/workers + /v1/usage)#26
govindkavaturi-art merged 1 commit into
mainfrom
feat/sdk-workers-and-usage-resources

Conversation

@mikemolinet
Copy link
Copy Markdown
Collaborator

Summary

Closes 2 entries from cueapi-python #24's endpoints_missing parity manifest plus a bonus DELETE that wasn't listed:

SDK Endpoint
client.workers.list() GET /v1/workers
client.workers.delete(worker_id) DELETE /v1/workers/{id}
client.usage.get() GET /v1/usage

New resource classes

  • cueapi/resources/workers.pyWorkersResource
  • cueapi/resources/usage.pyUsageResource

Both registered on the CueAPI client (client.workers, client.usage) and exported from cueapi.__init__ so callers can from cueapi import WorkersResource, UsageResource if they want to mock them in tests.

Skipped from manifest

POST /v1/worker/heartbeat (worker registration). The hosted endpoint is meant for cueapi-worker (which already wraps it correctly with heartbeat-loop semantics); direct SDK-driven registration would be redundant. Documented in WorkersResource's class docstring so future readers don't wonder why it's missing.

Tests

5 new (12 → 17 unit tests). Mock-based, mirrors the existing ExecutionsResource test pattern:

  • test_list_calls_get_workers — verifies path
  • test_list_passes_no_params — pinned bare-call shape (no params kwarg leakage)
  • test_delete_calls_delete_workers_id — verifies path + 204→None handling
  • test_get_calls_get_usage — verifies path + a representative response shape
  • test_get_returns_server_dict_unchanged — pinned no-transform behavior so a future refactor can't silently start coercing into a typed object

Pre-existing CI flake

The 14 errors on test_cues.py (ValueError: api_key is required) are pre-existing and unrelated to this PR. Captured in the Backlog row added when surveying cueapi-python earlier today (cueapi-python staging-cred test flake, tier-5-maintenance).

No hosted-PR dependency

All 3 endpoints already shipped on prod. Pure SDK catch-up.

Companion PR

#25mark_verified bug fix + replay() (sibling executions-resource changes from the same survey pass).

Test plan

  • python3 -m pytest tests/test_workers_resource.py tests/test_usage_resource.py -q → 5 passed
  • python3 -m pytest tests/test_executions_resource.py -q → 12 passed (unchanged)
  • Manual smoke against staging:
    • client.workers.list() → returns dict with workers + total
    • client.usage.get() → returns plan + cues + executions + rate_limit

Parity Impact

Closes 2 entries from endpoints_missing in cueapi-python #24's parity-manifest.json:

  • GET /v1/workers
  • GET /v1/usage

Plus the bonus DELETE /v1/workers/{id}. After this and #25 merge, remaining endpoints_missing is the messaging primitive (Phase 12.1.5 — large surface, separate PR) plus the deliberately-skipped destructive operations and POST /v1/worker/heartbeat.

🤖 Generated with Claude Code

…/v1/usage)

Closes 2 entries from cueapi-python #24's `endpoints_missing` parity manifest:

- GET /v1/workers           → client.workers.list()
- DELETE /v1/workers/{id}   → client.workers.delete(worker_id)
- GET /v1/usage             → client.usage.get()

(`DELETE /v1/workers/{id}` wasn't in the manifest but is part of the same
hosted surface — added for completeness.)

New resource classes:

- `cueapi/resources/workers.py`: WorkersResource — `.list()` + `.delete()`
- `cueapi/resources/usage.py`:   UsageResource — `.get()`

Both registered on the CueAPI client and exported from cueapi.__init__.

Skipped from manifest: POST /v1/worker/heartbeat (worker registration).
The hosted endpoint is meant for cueapi-worker (which already wraps it
correctly with heartbeat-loop semantics); direct SDK-driven registration
is redundant. Documented in WorkersResource's class docstring.

Tests: 5 new (12 → 17 unit tests). Mock-based, mirrors the existing
ExecutionsResource test pattern.

The 14 pre-existing staging-cred test_cues.py failures (`ValueError:
api_key is required`) are unrelated to this PR — same flake captured in
the Backlog row added when surveying cueapi-python earlier this session.

No hosted-PR dependency. All 3 endpoints already shipped on prod.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Copy link
Copy Markdown
Member

@govindkavaturi-art govindkavaturi-art left a comment

Choose a reason for hiding this comment

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

Clean parity port — WorkersResource + UsageResource just wrap GET endpoints. Approve.

@govindkavaturi-art govindkavaturi-art merged commit 4b37d97 into main May 4, 2026
3 of 4 checks passed
govindkavaturi-art pushed a commit that referenced this pull request May 4, 2026
Wraps the entire `/v1/agents` surface from the messaging primitive
(Phase 12.1.5). Closes the agents portion of the `Messaging primitive`
endpoints_missing entry in cueapi-python #24's parity manifest. The
companion `MessagesResource` (send/get/read/ack lifecycle) ships in a
follow-up PR.

New resource:

- `cueapi/resources/agents.py`: AgentsResource
  - .create(display_name, slug=None, webhook_url=None, metadata=None)
  - .list(status=None, include_deleted=False, limit=50, offset=0)
  - .get(ref, include_deleted=False)
  - .update(ref, display_name=None, webhook_url=None, clear_webhook_url=False,
           status=None, metadata=None)
  - .delete(ref)
  - .webhook_secret_get(ref)
  - .webhook_secret_regenerate(ref)  # sends X-Confirm-Destructive: true
  - .inbox(ref, state=None, limit=50, offset=0)
  - .sent(ref, limit=50, offset=0)

Client extension:

- `client._request` now accepts an optional `headers` kwarg, which
  extends (does not replace) the client's default Authorization +
  Content-Type + User-Agent headers. Used here for the destructive
  X-Confirm-Destructive guard; will also be used by the upcoming
  MessagesResource for X-Cueapi-From-Agent + Idempotency-Key.

Design notes pinned by tests:

- `--include-deleted` mirror: `include_deleted=True` sends `"true"`,
  `False` (default) omits. Same omit-when-default pattern as PR #26's
  `executions list --has-evidence`.

- `clear_webhook_url=True` sends literal JSON `null` (key present,
  value None), NOT field omission. Server uses `model_fields_set` to
  disambiguate "omitted = no change" from "explicit null = clear", so
  the SDK MUST send the key with explicit None. Pinned by
  test_clear_webhook_url_sends_explicit_null.

- `webhook_url` and `clear_webhook_url` mutex enforced with a clear
  ValueError before any HTTP call.

- `webhook_secret_regenerate` sends X-Confirm-Destructive: true in
  the header. The server requires it; the SDK adds it automatically
  so callers don't have to know about the header. Pinned by
  test_regenerate_sends_destructive_header.

Tests: 18 new across 9 test classes (12 → ~30 unit tests; total 46
passing across all unit-test files).

No hosted-PR dependency. All 9 endpoints already shipped on prod.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
govindkavaturi-art pushed a commit that referenced this pull request May 4, 2026
Wraps the entire `/v1/agents` surface from the messaging primitive
(Phase 12.1.5). Closes the agents portion of the `Messaging primitive`
endpoints_missing entry in cueapi-python #24's parity manifest. The
companion `MessagesResource` (send/get/read/ack lifecycle) ships in a
follow-up PR.

New resource:

- `cueapi/resources/agents.py`: AgentsResource
  - .create(display_name, slug=None, webhook_url=None, metadata=None)
  - .list(status=None, include_deleted=False, limit=50, offset=0)
  - .get(ref, include_deleted=False)
  - .update(ref, display_name=None, webhook_url=None, clear_webhook_url=False,
           status=None, metadata=None)
  - .delete(ref)
  - .webhook_secret_get(ref)
  - .webhook_secret_regenerate(ref)  # sends X-Confirm-Destructive: true
  - .inbox(ref, state=None, limit=50, offset=0)
  - .sent(ref, limit=50, offset=0)

Client extension:

- `client._request` now accepts an optional `headers` kwarg, which
  extends (does not replace) the client's default Authorization +
  Content-Type + User-Agent headers. Used here for the destructive
  X-Confirm-Destructive guard; will also be used by the upcoming
  MessagesResource for X-Cueapi-From-Agent + Idempotency-Key.

Design notes pinned by tests:

- `--include-deleted` mirror: `include_deleted=True` sends `"true"`,
  `False` (default) omits. Same omit-when-default pattern as PR #26's
  `executions list --has-evidence`.

- `clear_webhook_url=True` sends literal JSON `null` (key present,
  value None), NOT field omission. Server uses `model_fields_set` to
  disambiguate "omitted = no change" from "explicit null = clear", so
  the SDK MUST send the key with explicit None. Pinned by
  test_clear_webhook_url_sends_explicit_null.

- `webhook_url` and `clear_webhook_url` mutex enforced with a clear
  ValueError before any HTTP call.

- `webhook_secret_regenerate` sends X-Confirm-Destructive: true in
  the header. The server requires it; the SDK adds it automatically
  so callers don't have to know about the header. Pinned by
  test_regenerate_sends_destructive_header.

Tests: 18 new across 9 test classes (12 → ~30 unit tests; total 46
passing across all unit-test files).

No hosted-PR dependency. All 9 endpoints already shipped on prod.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mikemolinet added a commit that referenced this pull request May 9, 2026
…t recent ports (#36)

Manifest was 3 days stale; many endpoints listed as missing have
been ported since the last audit.

Moved from endpoints_missing → endpoints_covered (with PR refs):

  - POST /v1/cues/{id}/fire (PR #23; in-flight kwargs in #33)
  - POST /v1/executions/{id}/replay (PR #25)
  - GET /v1/executions/claimable (PR #23)
  - POST /v1/executions/{id}/claim (PR #23)
  - POST /v1/executions/claim (PR #23)
  - GET /v1/workers + DELETE /v1/workers/{id} (PR #26)
  - GET /v1/usage (PR #26)
  - POST /v1/agents + GET/PATCH/DELETE /v1/agents/{ref}
    + GET /v1/agents/{ref}/webhook-secret
    + GET /v1/agents/{ref}/inbox + /sent (PR #27)
  - POST /v1/messages + GET/read/ack (PR #28)

Added in-flight refs (open PRs):

  - GET /v1/agents/roster (in-flight PR #35; cueapi #630 parity)
  - GET /v1/agents/{ref}/presence (in-flight PR #35; cueapi #662 parity)
  - send_at + exit_criteria + idempotency_key kwargs on fire (PR #33)
  - send_at kwarg on messages.send (PR #34)

New endpoints_missing items (post-audit):

  - POST /v1/agents/{ref}/webhook-secret/regenerate (destructive; tracked)
  - DELETE /v1/messages bulk (cueapi #650; bounded by cueapi-cli upstream)
  - POST /v1/executions/{id}/live-claim (cueapi #664; handler-runtime, not SDK)

New "in_flight_ports_2026_05_07" section listing all 4 currently-open
SDK PRs with PR-overlap notes (PR #30/#33 lane-flagged with cueapi-main).

Bumped sdk_version_at_audit 0.1.3 → 0.2.x.

This refresh closes the Backlog row "Refresh cueapi-python parity-manifest.json"
filed earlier today (Self-flag 2026-05-07).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants