Skip to content

feat: generate status-specific action attempt subclasses - #486

Merged
razor-x merged 5 commits into
mainfrom
claude/action-attempt-status-annotations-f216kn
Aug 27, 2026
Merged

feat: generate status-specific action attempt subclasses#486
razor-x merged 5 commits into
mainfrom
claude/action-attempt-status-annotations-f216kn

Conversation

@razor-x

@razor-x razor-x commented Aug 27, 2026

Copy link
Copy Markdown
Member

What this means for SDK users

Every action attempt now deserializes to a subclass for its exact (action_type, status) pair, so error and result have real types exactly where they exist and the literal null type everywhere else:

$attempt = $seam->locks->lock_door(device_id: $deviceId, wait_for_action_attempt: false);

// Narrow with instanceof — no null checks needed:
if ($attempt instanceof ActionAttempt\LockDoor\Success) {
    $attempt->result->was_confirmed_by_device; // result is a real object here
}
if ($attempt instanceof ActionAttempt\LockDoor\Error) {
    $attempt->error->message; // error is a real object here
}
if ($attempt instanceof ActionAttempt\LockDoor\Pending) {
    $attempt->error;  // declared as null — assigning anything else is a TypeError
    $attempt->result; // declared as null
}

Unknown discriminator values still fall back safely, preserving the raw value: an unknown action_type gives the base ActionAttempt, an unknown status gives the action-type class (e.g. ActionAttempt\LockDoor).

A failed attempt without an error object no longer crashes ActionAttemptFailedError — it falls back to the message "Action attempt failed".

Runtime behavior is unchanged — the API always sent null; the declared types just stopped lying about it.

How

Extends #479. Bumps @seamapi/blueprint to ^1.10.0, which annotates each action-attempt property with the statuses that populate it. Codegen nests a second discrimination level under each action type using the same conventions as #479 (backed enum, tryFrom + match, unrecognized fallback keeping raw values). Properties are placed per status from the annotation alone — nothing is keyed off the names error/result. The #479 blanket "error/result nullable everywhere" workaround is removed. Side benefit: the five distinct per-action-type error shapes are now preserved instead of collapsing into one shared class.

Verification

New ActionAttemptTest (10 tests) covers every behavior above. phpunit: 274 tests, 631 assertions green. psalm: 0 errors. Regeneration from a clean install reproduces the diff exactly; only src/Resources/ActionAttempt.php changed among generated files.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EdWS7o3htQ9cNxhCWL5Frp

claude and others added 5 commits August 27, 2026 01:14
Consume the actionAttemptStatuses property annotation from
@seamapi/blueprint 1.10.0: each action type class is now further
discriminated by status into one final subclass per status. A property
annotated with actionAttemptStatuses keeps its generated type on the
subclasses for the statuses it lists and is declared with the null type
everywhere else, so error is only readable on the error subclass and
result only on the success subclass. An unknown status falls back to
the action type class and retains the raw status value.

This replaces the blanket nullability workaround that forced error into
the shared base class and documented error and result as null while
pending, and it restores the per-action-type error shapes that the
shared error class had collapsed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EdWS7o3htQ9cNxhCWL5Frp
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EdWS7o3htQ9cNxhCWL5Frp
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EdWS7o3htQ9cNxhCWL5Frp
…otations-f216kn' into claude/action-attempt-status-annotations-f216kn
@razor-x
razor-x merged commit b2077f0 into main Aug 27, 2026
18 checks passed
@razor-x
razor-x deleted the claude/action-attempt-status-annotations-f216kn branch August 27, 2026 20:28
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.

2 participants