Skip to content

Collapse vendor configs into pydantic models for IDE autocomplete#54

Merged
plutoless merged 12 commits into
mainfrom
vendor-config-ide-hints
Jul 2, 2026
Merged

Collapse vendor configs into pydantic models for IDE autocomplete#54
plutoless merged 12 commits into
mainfrom
vendor-config-ide-hints

Conversation

@plutoless

@plutoless plutoless commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

This PR has two related parts, both in service of IDE autocomplete for vendor configs.

Part 1 — Collapse vendor configs into pydantic models

Every STT/LLM/TTS/MLLM/avatar vendor config class (~63 across agentkit/vendors/) used def __init__(self, **kwargs: Any) and stashed a parallel *Options pydantic model, which erased all constructor type information — so VSCode/Pylance showed no autocomplete, no parameter types, and no hover docs when constructing e.g. DeepgramSTT(...).

This collapses each vendor class into its pydantic model: fields (with their Field(..., description=...), constraints, and validators) live directly on the class, and to_config() reads self.<field>. The *Options classes are deleted and the base classes become BaseModel + ABC. Result: full field autocomplete + hover docs + type-checking, with no new dependencies.

Behavior preservation

  • to_config() output is byte-identical for every vendor (guarded by golden-master snapshots + the full existing suite).
  • Two intentional changes:
    • FengmingSTT(**unexpected) now raises pydantic ValidationError instead of TypeError.
    • SenseTimeAvatar additionally accepts snake_case (app_id/scene_list) via populate_by_name=True; the wire output still emits appId/sceneList.

Notable design decisions

  • OpenAI/Gemini-compatible LLMs (Groq, CustomLLM, VertexAILLM, and the CN Aliyun/Bytedance/DeepSeek/Tencent LLMs) are standalone copies rather than inheriting/delegating — removes the old __init__ kwargs mutation and gives each clean per-class hints (accepted duplication over coupling).
  • TTS sample_rate: the base exposes resolved_sample_rate (reads getattr(self, "sample_rate", None)) to avoid a base member shadowing subclass sample_rate fields; agent.py's single consumer updated accordingly. Sarvam/Murf/CosyVoice keep their original accessor semantics via targeted overrides.
  • HeyGenAvatar is a standalone copy of LiveAvatarAvatar with its deprecation warning moved to model_post_init.

Part 2 — Top-level type exports + agora_agent.cn

Part 1 made the classes typed, but the most natural import — from agora_agent import DeepgramSTT — still resolved to Any (the top-level package uses a lazy __getattr__ fallback). This part gives the global vendors real static types at the top level, and puts CN vendors in a dedicated module:

  • Global vendors now autocomplete from the top level: from agora_agent import DeepgramSTT, OpenAI, MiniMaxTTS. Implemented by adding them to the top-level TYPE_CHECKING block only (they're already in agentkit.__all__, so runtime + __all__ are handled by the existing fallback/union — no _dynamic_imports/_ROOT_ALL churn).
  • CN vendors get a new agora_agent.cn module with natural names: from agora_agent.cn import AliyunLLM, MiniMaxTTS, TencentSTT. This also resolves the three name collisions cleanly — agora_agent.MiniMaxTTS is the global class, agora_agent.cn.MiniMaxTTS is the CN class.
  • Intentional change: SpatiusAvatar (a CN vendor previously exported top-level) is now cn-only — from agora_agent import SpatiusAvatar still runs (fallback → Any) but its typed path is from agora_agent.cn import SpatiusAvatar. XaiGrok/GenericAvatar were demoted to TYPE_CHECKING-only (behavior-neutral). One documented example in docs/guides/avatars.md updated; the broader CN-docs/alias-convention migration is a deliberate follow-up.

Test Plan

  • poetry run pytest -rP . — 235 passed, 1 skipped
  • poetry run mypy . — no new errors (only the 3 pre-existing core/ errors)
  • Golden-master snapshot tests lock to_config() output for the high-risk classes
  • Pyright (Cursor's engine): from agora_agent import DeepgramSTT and from agora_agent.cn import AliyunLLM resolve to real type[...] with 0 warnings; global vs CN MiniMaxTTS distinct
  • Reviewer: spot-check autocomplete in VSCode/Cursor for one class per family

🤖 Generated with Claude Code

plutoless and others added 12 commits July 2, 2026 05:48
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ulate_by_name

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Global vendor classes now resolve to real types via the top-level TYPE_CHECKING
block, so `from agora_agent import DeepgramSTT` gives IDE autocomplete (was Any).
CN vendors get a dedicated `agora_agent.cn` module (natural names), which also
resolves the MicrosoftSTT/MicrosoftTTS/MiniMaxTTS collisions. SpatiusAvatar (CN) is
now cn-only; XaiGrok/GenericAvatar demoted to TYPE_CHECKING-only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@plutoless plutoless merged commit cd5a222 into main Jul 2, 2026
8 checks passed
@plutoless plutoless deleted the vendor-config-ide-hints branch July 2, 2026 16:20
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