Skip to content

feat: 실질 Python SDK — 핵심 플로우 + 게시 파이프라인 (#230) - #1

Merged
bluelucifer merged 1 commit into
mainfrom
feat/sdk-real-230
Jun 14, 2026
Merged

feat: 실질 Python SDK — 핵심 플로우 + 게시 파이프라인 (#230)#1
bluelucifer merged 1 commit into
mainfrom
feat/sdk-real-230

Conversation

@bluelucifer

@bluelucifer bluelucifer commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

요약

loftbox-sdk-python 스켈레톤(헤더만 있던 상태)을 실동작 SDK로 실질화. 메인 레포 이슈 TheMagicTower/loftbox#230.

구현

  • httpx 동기 클라이언트 + 리소스 네임스페이스: auth / agents / mailboxes / messages / threads / webhooks / domains / suppressions / attachments
  • 핵심 플로우: signup·verify / agent·mailbox 생성 / messages.send(멱등키·예약 send_at·첨부·cc·답장) / inbox list_inbox+ack_inbox / 라벨 add_labels·remove_label / 전문검색 list(q=...) / threads / approve·reject / webhook 생성
  • pydantic v2 모델(extra="allow" — 서버 필드 추가에 강건), Page 커서 페이지네이션
  • 오류 매핑: LoftBox wire shape {"error":{message,retry_after,...}} 파싱 → AuthenticationError/PermissionError/NotFoundError/ConflictError/RateLimitError/ValidationError, RateLimitError.retry_after_secs
  • README: 미구현 LangChain/CrewAI extras 제거(미구현 광고 금지 원칙)
  • examples/quickstart.py, httpx MockTransport 단위테스트 13

CI / 게시

  • .github/workflows/ci.yml — ruff(check+format) + mypy + pytest (Python 3.9, 3.12)
  • .github/workflows/publish.ymlv* 태그 푸시 시 PyPI 게시. 태그-버전 일치 검증 + twine check + permissions: contents: read. 게시 권한은 PYPI_API_TOKEN 시크릿(레포 설정에서 주입).

리뷰 (codex 적대적 코드리뷰 반영)

  • verify_signup body 수정(email+verification_token — 라이브 스펙 대조)
  • nested 오류 shape 파싱
  • domain.status() 전용 DomainStatus 모델(id 없음)
  • 라벨 경로 quote(label, safe="") 인코딩 + 특수문자 테스트
  • webhook secret 명시 필드(1회 반환, 로그 금지 주석)
  • 422 → ValidationError 매핑

참고: codex 가 1차에 send_at/labels/q "미지원" Critical 을 제기했으나, 이는 stale core 서브모듈(#236/#238/#241 머지 전) 기준 오판이었음. 라이브 OpenAPI(api.loftbox.net) 에 모두 존재함을 확인.

설계 결정

  • 코드젠(Fern/openapi-generator) 대신 OpenAPI 대조 수작성 idiomatic 클라이언트 — 핵심 ~20개 엔드포인트로 표면이 작고, admin 표면 제외·ergonomic 우선이 best-case.

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Comprehensive API client with full support for agents, mailboxes, messages, threads, webhooks, domains, suppressions, and attachments management
    • Structured error handling with specific exception types (RateLimitError, NotFoundError, ValidationError, etc.)
    • Pagination support for list operations
    • Context manager support for automatic resource cleanup
  • Documentation

    • Expanded documentation with quickstart guide and practical usage examples
    • Error handling semantics documentation
  • Tests

    • Comprehensive unit test suite for API client operations
  • Chores

    • CI/CD pipeline configuration
    • Updated project metadata and dependency management (Pydantic v2, httpx)

스켈레톤(헤더만)을 실동작 클라이언트로 실질화.

- httpx 동기 클라이언트 + 리소스 네임스페이스(auth/agents/mailboxes/messages/
  threads/webhooks/domains/suppressions/attachments)
- 핵심 플로우: signup·verify / agent·mailbox / send(멱등키·예약 send_at·첨부)
  / inbox poll+ack / 라벨 add·remove / 전문검색 q / threads / approve·reject / webhook
- pydantic v2 모델(extra=allow), Page 커서 페이지네이션
- 오류 매핑: LoftBox wire shape {"error":{message,retry_after,...}} 파싱,
  401/403/404/409/429/400·422 → 구체 예외, RateLimitError.retry_after_secs
- README: 미구현 langchain/crewai extras 제거(미구현 광고 금지)
- examples/quickstart.py, httpx MockTransport 단위테스트 13
- CI(ruff/mypy/pytest, py3.9+3.12) + 태그푸시 PyPI 게시(twine check, 버전검증)

codex 코드리뷰 반영: verify_signup body(email+verification_token), nested 오류
shape, domain status 전용 모델, 라벨 경로 인코딩(quote), webhook secret 명시 필드.

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

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Review Change Stack

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Free

Run ID: 65290007-a89c-4038-ad29-8340b2f4b824

📥 Commits

Reviewing files that changed from the base of the PR and between 80b8ab9 and 50db102.

📒 Files selected for processing (11)
  • .github/workflows/ci.yml
  • .github/workflows/publish.yml
  • README.md
  • examples/.gitkeep
  • examples/quickstart.py
  • loftbox/__init__.py
  • loftbox/client.py
  • loftbox/errors.py
  • loftbox/models.py
  • pyproject.toml
  • tests/test_client.py

📝 Walkthrough

Walkthrough

This PR introduces the initial LoftBox Python SDK: Pydantic v2 data models, a typed error hierarchy with error_for_status, a full synchronous httpx-based LoftBox client with nine resource namespaces, an expanded public __all__, 13 mock-transport unit tests, updated pyproject.toml packaging/tooling, CI and PyPI publish workflows, and Korean README documentation with a quickstart example.

Changes

LoftBox Python SDK — Initial Implementation

Layer / File(s) Summary
Pydantic models and error hierarchy
loftbox/models.py, loftbox/errors.py
Rewrites models from dataclasses to Pydantic v2 with shared _Base(extra="allow"); adds Attachment, Thread, Webhook, Domain, DomainStatus, Suppression, Page[T]. Introduces error module with LoftBoxError base, six typed subclasses, and error_for_status factory.
Client init, _request machinery, and lifecycle
loftbox/client.py
Replaces stub client with full __init__ (timeout, optional external httpx.Client, ownership tracking, resource namespace wiring), centralized _request (header construction, None-param pruning, network error wrapping, error-body/Retry-After parsing), _page helper, and close()/context-manager methods.
Resource endpoint namespaces
loftbox/client.py
Implements nine _Resource subclasses: _Auth, _Agents, _Mailboxes, _Messages (idempotency key, scheduling, URL-encoded label path), _Threads, _Webhooks, _Domains, _Suppressions, _Attachments.
Public package surface and packaging
loftbox/__init__.py, pyproject.toml
Expands __all__ from 4 to full model and error symbol set. Updates pyproject.toml with metadata, httpx+pydantic dependencies, reworked dev extras, Hatch wheel target, Ruff, and MyPy config.
Client test suite
tests/test_client.py
Adds make_client helper over httpx.MockTransport and 13 tests covering request shape, pagination, bare-array responses, inbox ack, label URL encoding, error mapping, Retry-After parsing, nested error body, signup verification, and context-manager lifecycle.
CI workflows, docs, and quickstart
.github/workflows/ci.yml, .github/workflows/publish.yml, README.md, examples/quickstart.py
Adds lint/type-check/test CI on Python 3.9+3.12 and a tag-triggered PyPI publish workflow with version verification. Rewrites README with Korean SDK docs (quickstart, features, error handling, pagination). Adds a runnable examples/quickstart.py.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant LoftBox
  participant httpx.Client
  participant LoftBoxAPI

  User->>LoftBox: with LoftBox(api_key) as client
  User->>LoftBox: client.messages.send(mailbox_id, to, subject, body, idempotency_key)
  LoftBox->>httpx.Client: POST /v1/messages (Authorization, Idempotency-Key headers)
  httpx.Client->>LoftBoxAPI: HTTP request
  LoftBoxAPI-->>httpx.Client: 200 JSON or 4xx/429
  httpx.Client-->>LoftBox: response
  alt success
    LoftBox-->>User: Message model
  else 429 Rate Limit
    LoftBox->>LoftBox: read Retry-After header / body
    LoftBox-->>User: raise RateLimitError(retry_after_secs)
  else 4xx other
    LoftBox-->>User: raise typed LoftBoxError subclass
  end
  User->>LoftBox: client.mailboxes.poll_inbox(mailbox_id)
  LoftBox->>httpx.Client: GET /v1/mailboxes/{id}/inbox
  httpx.Client->>LoftBoxAPI: HTTP request
  LoftBoxAPI-->>httpx.Client: {data, next_cursor}
  LoftBox-->>User: Page[Message]
  User->>LoftBox: client.mailboxes.ack_inbox(mailbox_id, message_ids)
  LoftBox->>httpx.Client: POST /v1/mailboxes/{id}/inbox/ack
  httpx.Client->>LoftBoxAPI: HTTP request
  LoftBoxAPI-->>httpx.Client: 204
  LoftBox-->>User: None
  User->>LoftBox: exit context manager
  LoftBox->>httpx.Client: close()
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐇 A mailbox was empty, a client was bare,
Now agents and webhooks are floating through air.
With Pydantic models and errors in place,
The SDK hops forward at wonderful pace!
pip install loftbox — go on, give it a try,
This bunny ships features right up to the sky. 🚀


Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login.

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

@bluelucifer
bluelucifer merged commit 19918dd into main Jun 14, 2026
3 checks passed
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