Skip to content

[CHA-1578] refactor: code generated from openapi specs#205

Open
mogita wants to merge 9 commits intomainfrom
cha-1578_openapi-refactor-codegen
Open

[CHA-1578] refactor: code generated from openapi specs#205
mogita wants to merge 9 commits intomainfrom
cha-1578_openapi-refactor-codegen

Conversation

@mogita
Copy link

@mogita mogita commented Dec 16, 2025

Summary by CodeRabbit

  • New Features

    • Added comprehensive webhook handling with event parsing, type extraction, and HMAC-SHA256 signature verification.
    • Added moderation appeals API endpoints for creating, retrieving, and querying appeals.
    • Added video recording control endpoints (start/stop recording with external storage support).
    • Added call participant session metrics and query endpoints for detailed analytics.
    • Added Import V2 tasks API for bulk data operations.
    • Added future channel bans query endpoint.
  • Bug Fixes

    • Updated response types for message action methods to properly reflect action-oriented responses.
    • Improved datetime serialization in query parameters.

Note

Medium Risk
Large generated-client refactor that changes request/response typing and request serialization across many endpoints; main risk is subtle payload/query differences or type mismatches affecting API calls at runtime.

Overview
Regenerates OpenAPI-generated Python REST clients (sync + async) for chat and common to stop using build_body_dict and instead serialize strongly-typed *Request models via .to_dict(), while standardizing query param construction to build_query_param(**{...}).

Adds/extends API surface in the generated clients: query_future_channel_bans, new parameters like push_level (channel types), predefined_filter/filter_values/sort_values (channel query), and skip_push support for message partial/ephemeral updates; also updates several message-action-style endpoints to return MessageActionResponse.

Updates feeds wrapper to pass friend_reactions_options into get_or_create() and adds a Feed.query_pinned_activities() convenience method that delegates to the underlying client endpoint.

Written by Cursor Bugbot for commit 90e55bc. This will update automatically on new commits. Configure here.

Copilot AI review requested due to automatic review settings December 16, 2025 05:58
@coderabbitai
Copy link

coderabbitai bot commented Dec 16, 2025

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR refactors request payload construction across multiple modules using dictionary expansion patterns, introduces new API endpoints for recording, appeals, and data imports, launches a comprehensive webhook event handling system with constants and parsing utilities, and updates method return types and parameter types throughout chat, video, moderation, and feeds modules.

Changes

Cohort / File(s) Summary
Chat REST API Refactoring
getstream/chat/async_rest_client.py, getstream/chat/rest_client.py
Rewrote request payload construction using **{...} dictionary expansion; added query_future_channel_bans endpoint; changed return types for run_message_action, commit_message, translate_message to MessageActionResponse; added push_level parameter to channel type methods; updated numerous method signatures for improved parameter handling.
Video REST API Enhancement
getstream/video/async_rest_client.py, getstream/video/rest_client.py
Added new recording endpoints (start_recording, stop_recording); added call metrics endpoints (get_call_participant_session_metrics, query_call_participant_sessions); renamed SIP routing paths from /routing_rules to /inbound_routing_rules; updated notification settings type hints to Request variants; refactored query parameter construction to use dictionary expansion.
Video Call Wrapper Updates
getstream/video/async_call.py, getstream/video/call.py
Added four new public methods (start_recording, stop_recording, get_call_participant_session_metrics, query_call_participant_sessions); removed obsolete parameterless start_recording and stop_recording variants; delegated calls to updated client methods with proper response syncing.
Moderation API Expansion
getstream/moderation/async_rest_client.py, getstream/moderation/rest_client.py
Added appeal-related endpoints (appeal, get_appeal, query_appeals); updated payload type hints to use Request/Payload variants; refactored body construction with dictionary expansion; expanded submit_action with new action fields (appeal_id, reject_appeal, restore, unblock); updated sort parameter types.
Feeds API & Client Refactoring
getstream/feeds/rest_client.py, getstream/feeds/feeds.py
Added batch and restoration methods (update_activities_partial_batch, restore_activity); expanded activity, bookmark, follow, and feed operations with new optional parameters (copy_custom_to_notification, delete_notification_activity, skip_push, etc.); refactored all JSON/query body construction using dictionary expansion; added friend_reactions_options parameter to feed creation.
Common Client Updates
getstream/common/async_rest_client.py, getstream/common/rest_client.py
Added import v2 task endpoints (list_import_v2_tasks, create_import_v2_task, delete_import_v2_task, get_import_v2_task); updated upsert_push_provider parameter type to PushProviderRequest; refactored request body construction across multiple endpoints using dictionary expansion.
Webhook Module (New)
getstream/webhook.py, getstream/tests/test_webhook.py
Introduced comprehensive webhook handling: added 140+ EVENT_TYPE_* constants covering appeal, call, channel, feeds, message, moderation, reaction, and user events; implemented get_event_type(), parse_webhook_event(), and verify_webhook_signature() functions for event extraction, deserialization, and HMAC-SHA256 validation; added extensive test coverage for all webhook functionality.
Utilities & Misc
getstream/utils/__init__.py, getstream/video/rtc/coordinator/ws.py, tests/test_video_examples.py
Added datetime serialization support in build_query_param() with ISO 8601 formatting; updated WebSocket type annotation from WebSocketClientProtocol to ClientConnection with added null-safety assertion; updated video recording test to use explicit recording_type="composite" parameter.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes


🐰 Twitching whiskers with glee,
Dictionary unpacking, wild and free!
Webhooks dance, recordings shine,
Appeals and imports—code divine!
Stream's refactored, better designed,
A rabbit's work, exquisitely signed! 🎉

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Linked Issues check ❓ Inconclusive The PR addresses the core objective of CHA-1578 by regenerating code from OpenAPI specs across multiple files, though Kotlin support is not evident in the changes. Verify whether Kotlin support was added as a secondary objective, or confirm it's deferred to a separate PR or task.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly indicates this is a refactoring PR focused on code generation from OpenAPI specs, which aligns with the main objective of the changeset.
Out of Scope Changes check ✅ Passed The changes appear focused on code generation refactoring with payload construction updates and new API endpoints, which aligns with OpenAPI spec regeneration.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch cha-1578_openapi-refactor-codegen

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR contains code generated from refactored OpenAPI specifications, updating multiple REST client interfaces and model definitions across the GetStream SDK. The changes primarily involve type renames, new API endpoints, parameter additions, and model restructuring to align with updated API specifications.

Key changes:

  • Added new API methods and endpoints (e.g., get_call_stats_map, collections CRUD operations, mark_delivered)
  • Renamed types for clarity (e.g., NotificationSettingsNotificationSettingsRequest/Response, action request types now use Payload suffix)
  • Added telemetry decorators to feeds client methods
  • Expanded model definitions with new fields and response types

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated no comments.

Show a summary per file
File Description
getstream/video/rest_client.py Added get_call_stats_map method, added pagination params to query_call_session_participant_stats, updated type names for notification settings and SIP challenge
getstream/video/async_rest_client.py Mirror changes to sync client for async version
getstream/moderation/rest_client.py Updated type names for moderation payloads and action requests (added Payload suffix)
getstream/moderation/async_rest_client.py Mirror changes to sync client for async version
getstream/models/__init__.py Extensive model changes: renamed/restructured many dataclasses, added new models for collections, events, notifications; removed deprecated models
getstream/feeds/rest_client.py Added telemetry decorators, new collection endpoints, renamed add_reactionadd_activity_reaction, added new parameters to existing methods
getstream/feeds/feeds.py Updated method signatures to match client changes
getstream/chat/rest_client.py Added mark_delivered method, updated type names, added message_timestamp parameter
getstream/chat/async_rest_client.py Mirror changes to sync client for async version
getstream/chat/channel.py Updated method signatures to match client changes
getstream/chat/async_channel.py Mirror changes to sync client for async version

The changes appear to be auto-generated code with consistent patterns applied across sync and async versions of the clients. No issues were identified in the generated code structure.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 30dc844 and f9779b3.

📒 Files selected for processing (10)
  • getstream/chat/async_channel.py (3 hunks)
  • getstream/chat/async_rest_client.py (4 hunks)
  • getstream/chat/channel.py (3 hunks)
  • getstream/chat/rest_client.py (4 hunks)
  • getstream/feeds/feeds.py (2 hunks)
  • getstream/feeds/rest_client.py (51 hunks)
  • getstream/moderation/async_rest_client.py (4 hunks)
  • getstream/moderation/rest_client.py (4 hunks)
  • getstream/video/async_rest_client.py (5 hunks)
  • getstream/video/rest_client.py (5 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Plugins that work with audio, video, or WebRTC functionality should depend on getstream[webrtc] instead of just getstream to access WebRTC-related dependencies like aiortc, numpy, torch, torchaudio, soundfile, scipy, deepgram-sdk, and elevenlabs

Files:

  • getstream/chat/async_channel.py
  • getstream/chat/async_rest_client.py
  • getstream/moderation/rest_client.py
  • getstream/video/async_rest_client.py
  • getstream/chat/channel.py
  • getstream/moderation/async_rest_client.py
  • getstream/video/rest_client.py
  • getstream/chat/rest_client.py
  • getstream/feeds/rest_client.py
  • getstream/feeds/feeds.py
🧬 Code graph analysis (8)
getstream/chat/async_channel.py (1)
getstream/models/__init__.py (1)
  • ChannelInputRequest (4823-4851)
getstream/chat/async_rest_client.py (5)
getstream/common/telemetry.py (1)
  • operation_name (429-441)
getstream/chat/rest_client.py (1)
  • mark_delivered (145-157)
getstream/models/__init__.py (3)
  • DeliveredMessagePayload (7418-7420)
  • MarkDeliveredResponse (10927-10928)
  • ChannelInputRequest (4823-4851)
getstream/utils/__init__.py (2)
  • build_query_param (94-126)
  • build_body_dict (151-175)
getstream/base.py (2)
  • post (240-256)
  • post (429-445)
getstream/video/async_rest_client.py (3)
getstream/common/telemetry.py (1)
  • operation_name (429-441)
getstream/models/__init__.py (4)
  • QueryCallStatsMapResponse (14474-14538)
  • QueryCallSessionParticipantStatsResponse (14424-14457)
  • NotificationSettingsRequest (12890-12908)
  • SIPChallengeRequest (16585-16627)
getstream/utils/__init__.py (1)
  • build_query_param (94-126)
getstream/chat/channel.py (2)
getstream/stream_response.py (1)
  • data (22-24)
getstream/models/__init__.py (1)
  • ChannelInputRequest (4823-4851)
getstream/moderation/async_rest_client.py (4)
getstream/models/__init__.py (11)
  • ModerationPayloadRequest (12502-12514)
  • BanActionRequestPayload (1901-1919)
  • BlockActionRequestPayload (2040-2043)
  • DeleteActivityRequestPayload (7131-7137)
  • DeleteCommentRequestPayload (7226-7232)
  • DeleteMessageRequestPayload (7291-7297)
  • DeleteReactionRequestPayload (7322-7328)
  • DeleteUserRequestPayload (7369-7384)
  • MarkReviewedRequestPayload (10956-10963)
  • ShadowBlockActionRequestPayload (17303-17306)
  • UnbanActionRequestPayload (18368-18371)
getstream/moderation/rest_client.py (2)
  • ban (35-58)
  • unban (489-508)
getstream/chat/async_rest_client.py (1)
  • delete_message (969-987)
getstream/chat/rest_client.py (1)
  • delete_message (959-977)
getstream/video/rest_client.py (4)
getstream/common/telemetry.py (1)
  • operation_name (429-441)
getstream/video/async_rest_client.py (1)
  • get_call_stats_map (875-903)
getstream/models/__init__.py (4)
  • QueryCallStatsMapResponse (14474-14538)
  • QueryCallSessionParticipantStatsResponse (14424-14457)
  • NotificationSettingsRequest (12890-12908)
  • SIPChallengeRequest (16585-16627)
getstream/utils/__init__.py (1)
  • build_query_param (94-126)
getstream/feeds/rest_client.py (5)
getstream/common/telemetry.py (1)
  • operation_name (429-441)
getstream/base.py (6)
  • post (240-256)
  • post (429-445)
  • delete (276-292)
  • delete (465-481)
  • get (222-238)
  • get (411-427)
getstream/utils/__init__.py (2)
  • build_body_dict (151-175)
  • build_query_param (94-126)
getstream/feeds/feeds.py (1)
  • delete (17-24)
getstream/stream.py (2)
  • feeds (211-212)
  • feeds (316-328)
getstream/feeds/feeds.py (1)
getstream/models/__init__.py (2)
  • FeedInput (8341-8357)
  • EnrichmentOptions (7693-7744)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Upload results
  • GitHub Check: Tests (3.11)
  • GitHub Check: Tests (3.12)
  • GitHub Check: Tests (3.13)
  • GitHub Check: Tests (3.10)
🔇 Additional comments (35)
getstream/video/async_rest_client.py (3)

874-903: LGTM: New get_call_stats_map endpoint added.

The new method follows the established patterns in the codebase with proper telemetry decoration, path parameter handling, and query parameter construction for optional filters.


1028-1028: Breaking change: notification_settings type updated.

The parameter type changed from NotificationSettings to NotificationSettingsRequest. This is a breaking change for callers passing the old type. Ensure migration documentation is provided.


1096-1096: Breaking change: challenge parameter type updated.

The parameter type changed from SIPChallenge to SIPChallengeRequest. Callers using the old type will need to update their code.

getstream/moderation/async_rest_client.py (4)

213-213: Breaking change: moderation_payload type updated to ModerationPayloadRequest.

Callers using the previous ModerationPayload type will need to migrate.


249-249: Breaking change: config parameter type updated.

Type changed from FeedsModerationTemplateConfig to FeedsModerationTemplateConfigPayload.


288-288: Type alignment: sort uses SortParamRequest.

This aligns with other methods in the codebase that already use SortParamRequest for sort parameters.


460-470: Breaking changes: All action payload types updated to *Payload variants.

Multiple parameter types changed:

  • BanActionRequestBanActionRequestPayload
  • BlockActionRequestBlockActionRequestPayload
  • CustomActionRequestCustomActionRequestPayload
  • DeleteActivityRequestDeleteActivityRequestPayload
  • DeleteCommentRequestDeleteCommentRequestPayload
  • DeleteMessageRequestDeleteMessageRequestPayload
  • DeleteReactionRequestDeleteReactionRequestPayload
  • DeleteUserRequestDeleteUserRequestPayload
  • MarkReviewedRequestMarkReviewedRequestPayload
  • ShadowBlockActionRequestShadowBlockActionRequestPayload
  • UnbanActionRequestUnbanActionRequestPayload

Callers will need to update their code to use the new payload types.

getstream/chat/channel.py (2)

71-71: Breaking change: data parameter type updated to ChannelInputRequest.

The parameter type changed from ChannelInput to ChannelInputRequest. Existing callers passing ChannelInput will need to migrate.


329-348: New optional message_timestamp parameter added to mark_unread.

This is an additive, non-breaking change that extends the API to support marking unread by timestamp in addition to message ID.

getstream/chat/async_channel.py (2)

71-71: Breaking change consistent with sync version.

The data parameter type changed to ChannelInputRequest, matching the sync Channel class.


329-348: Async version mirrors sync changes for mark_unread.

The message_timestamp parameter addition is consistent with the sync Channel.mark_unread method.

getstream/feeds/feeds.py (1)

26-66: New optional parameters added to get_or_create.

Two new optional parameters added:

  • id_around: Optional[str] - for around-based pagination
  • enrichment_options: Optional[EnrichmentOptions] - for controlling enrichment behavior

These are additive, non-breaking changes that extend the API surface.

getstream/chat/rest_client.py (3)

144-157: New mark_delivered endpoint added.

This new method allows marking messages as delivered for a user. The implementation follows the established patterns with proper telemetry decoration and parameter handling.


260-260: Breaking change: data parameter type updated in update_channel.

Type changed from ChannelInput to ChannelInputRequest, consistent with the Channel wrapper classes.


627-654: Extended mark_unread with message_timestamp parameter.

The new optional message_timestamp parameter is properly included in the request body via build_body_dict. This is a non-breaking additive change.

getstream/video/rest_client.py (4)

870-899: New get_call_stats_map endpoint looks correct.

The implementation correctly mirrors the async counterpart, using query parameters for optional filters and path parameters for required identifiers. The return type QueryCallStatsMapResponse aligns with the model definition.


1024-1024: Type update to NotificationSettingsRequest is consistent.

The change from NotificationSettings to NotificationSettingsRequest aligns with the new payload variant types for request bodies, matching the async client changes.


1062-1062: Type update in update_call_type matches create_call_type.

Consistent use of NotificationSettingsRequest across both create and update operations.


1090-1090: SIPChallengeRequest type update is appropriate.

The challenge parameter now uses the dedicated request payload type, which is consistent with the API schema refactoring pattern applied throughout this PR.

getstream/chat/async_rest_client.py (4)

146-159: New mark_delivered method implementation is correct.

The async implementation properly mirrors the sync counterpart, using user_id as a query parameter and latest_delivered_messages in the request body. Telemetry decorator is correctly applied.


264-264: Type update to ChannelInputRequest in update_channel is correct.

This aligns with the PR's schema updates for request payload types.


631-658: mark_unread extended with message_timestamp parameter.

The new optional datetime parameter is correctly added to the method signature and included in the request body via build_body_dict. This enhancement allows marking unread by timestamp in addition to message ID.


175-204: Async and sync clients are consistent; type difference between methods appears intentional.

Both the async and sync clients use ChannelInput for get_or_create_distinct_channel and ChannelInputRequest for update_channel. The type difference is not an inconsistency between sync/async implementations but rather reflects intentional schema differences: ChannelInput includes created_by_id, truncated_by_id, and filter_tags fields that ChannelInputRequest omits, and their config_overrides fields reference different types (ChannelConfig vs ConfigOverridesRequest), suggesting the endpoints accept different request structures.

getstream/moderation/rest_client.py (5)

203-225: custom_check correctly updated to use ModerationPayloadRequest.

The type update for moderation_payload parameter aligns with the new payload variant types.


243-252: v2_upsert_template updated with FeedsModerationTemplateConfigPayload.

The config parameter type change is consistent with the schema refactoring.


278-292: query_moderation_flags updated to use SortParamRequest.

Consistent with other methods using the new request type for sort parameters.


448-486: submit_action correctly updated with new payload variant types.

All action parameters (ban, block, custom, delete_*, mark_reviewed, shadow_block, unban) now use their respective ...RequestPayload types, aligning with the schema updates.


254-276: Consider clarifying the intent of type inconsistency in moderation methods.

The flag method (line 263) uses ModerationPayload while custom_check (line 211) uses ModerationPayloadRequest. This pattern is consistent across the async client as well, where check and flag use ModerationPayload, while only custom_check uses ModerationPayloadRequest. Since both types have identical structure, clarify whether this distinction is intentional (e.g., to explicitly mark custom_check as request-only) or if the methods should be unified to use the same type for consistency.

getstream/feeds/rest_client.py (7)

3-3: Telemetry import added for instrumentation.

The addition of telemetry enables observability across all Feeds API methods.


34-80: add_activity extended with new parameters and telemetry.

New optional parameters restrict_replies, skip_enrich_url, and collection_refs expand the API capabilities. Telemetry decorator correctly applied.


505-560: New collection CRUD endpoints added.

The delete_collections, read_collections, update_collections, create_collections, and upsert_collections methods provide comprehensive collection management. Each uses appropriate HTTP methods and parameter handling.


799-808: list_feed_groups extended with include_soft_deleted filter.

Correctly passed as a query parameter for the GET request.


1299-1329: New feed visibility endpoints added.

list_feed_visibilities, get_feed_visibility, and update_feed_visibility provide visibility management capabilities with consistent patterns.


1375-1395: New get_feeds_rate_limits endpoint.

Provides rate limit introspection with platform-specific filters (android, ios, web, server_side).


1604-1617: delete_feed_user_data changed from DELETE to POST.

The method now uses POST with a request body containing hard_delete. This is a semantic change from the typical DELETE pattern but is appropriate when the operation requires request body parameters.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (6)
getstream/moderation/rest_client.py (1)

133-133: Use consistent payload type across check and custom_check methods.

The check method uses ModerationPayload (line 133), while custom_check uses ModerationPayloadRequest (line 258). Both classes are structurally identical, suggesting this naming inconsistency is likely unintentional. Standardize on a single type name for both methods.

getstream/video/async_call.py (1)

149-176: Avoid silent breaking changes from mid-signature parameter insertion (positional args).
go_live(...) and stop_live(...) add new optional parameters between existing ones, which can mis-bind existing positional calls without an exception. If positional args are supported for this public API, prefer appending new params at the end or make options keyword-only via * after self.

Also applies to: 427-453

getstream/video/rest_client.py (1)

951-980: Same sort: List[SortParamRequest] query-param encoding risk as async client.

getstream/video/call.py (1)

145-173: Public API: mid-signature param insertion can silently break positional callers.
Consider appending new options at the end or making them keyword-only (def go_live(self, *, ...)) to avoid wrong-parameter binding.

Also applies to: 407-433

getstream/feeds/feeds.py (1)

26-67: High-risk breaking change: id_around inserted before existing params may silently mis-bind positional calls.
If users call get_or_create(10) expecting limit=10, they’ll now pass id_around="10". Prefer keyword-only params or append new params at the end to preserve positional behavior.

getstream/video/async_rest_client.py (1)

955-984: Bug confirmed: sort: List[SortParamRequest] passed to build_query_param will be incorrectly encoded.
build_query_param converts list items with str(v) instead of calling to_json() on objects that have it. SortParamRequest has DataClassJsonMixin which provides to_json(), but the list branch at line 29 of getstream/utils/__init__.py bypasses it. This produces invalid wire format (e.g., "SortParamRequest(direction=1, ...)" instead of proper JSON).

The correct pattern is used elsewhere: pass sort to build_body_dict (as in getstream/common/rest_client.py:574-577). Other affected endpoints include getstream/feeds/rest_client.py and getstream/chat/rest_client.py.

🤖 Fix all issues with AI agents
In @getstream/feeds/rest_client.py:
- Around line 1592-1599: The current query_feeds_usage_stats method constructs
the request body with build_body_dict which yields {"_from": ...} but the API
expects the field mapped as "from"; fix by creating a
QueryFeedsUsageStatsRequest instance with _from and to, serialize that model for
the POST payload (replace the build_body_dict/json assignment with model
instantiation and model.dict()/serialize call per existing patterns), ensuring
the correct field name is sent; also apply the same change to the
query_aggregate_call_stats method in the video client.

In @getstream/video/async_rest_client.py:
- Around line 890-920: get_call_stats_map currently forwards start_time and
end_time datetime objects to build_query_param which json.dumps can't serialize;
convert start_time and end_time to ISO-8601 strings (e.g., via
start_time.isoformat()) before calling build_query_param, or add a small helper
to normalize datetimes to strings and use it in get_call_stats_map so
build_query_param only receives serializable values; keep the rest of the method
and path_params unchanged.

In @getstream/video/rest_client.py:
- Around line 749-766: The stop_recording method always sends an empty JSON body
because build_body_dict() returns {}; update stop_recording to avoid sending
'{}' when there are no fields by calling body = build_body_dict() and passing
json=body if body is truthy, otherwise pass json=None (or omit the json param)
to self.post; reference the stop_recording function and build_body_dict to
implement this conditional so the backend does not receive an unnecessary empty
object.
- Around line 886-916: The query builder is serializing datetime via json.dumps
and fails; update build_query_param to detect datetime (and datetime-like)
values and serialize them using the existing encode_datetime utility (or call
encode_datetime for the start_time/end_time before passing) so ISO strings are
produced; ensure build_query_param handles both naive and aware datetimes and
lists/dicts containing datetimes so calls from get_call_stats_map (and its async
counterpart) will no longer raise TypeError.

In @getstream/webhook.py:
- Around line 378-382: The code currently instantiates webhook event classes by
calling event_class(**data) which bypasses DataClassJsonMixin custom
deserialization (e.g., datetime_from_unix_ns); change the instantiation in the
function that calls _get_event_class to use the dataclass deserializer (call
event_class.from_dict(data) or the classmethod provided by DataClassJsonMixin)
so field mappings and datetime decoders are applied; ensure you import/handle
the from_dict method on the event classes and fall back to the current behavior
only if from_dict is not available.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f9779b3 and 03cad93.

📒 Files selected for processing (14)
  • getstream/chat/async_rest_client.py
  • getstream/chat/rest_client.py
  • getstream/common/async_rest_client.py
  • getstream/common/rest_client.py
  • getstream/feeds/feeds.py
  • getstream/feeds/rest_client.py
  • getstream/models/__init__.py
  • getstream/moderation/async_rest_client.py
  • getstream/moderation/rest_client.py
  • getstream/video/async_call.py
  • getstream/video/async_rest_client.py
  • getstream/video/call.py
  • getstream/video/rest_client.py
  • getstream/webhook.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Plugins that work with audio, video, or WebRTC functionality should depend on getstream[webrtc] instead of just getstream to access WebRTC-related dependencies like aiortc, numpy, torch, torchaudio, soundfile, scipy, deepgram-sdk, and elevenlabs

Files:

  • getstream/feeds/feeds.py
  • getstream/common/async_rest_client.py
  • getstream/common/rest_client.py
  • getstream/video/call.py
  • getstream/moderation/rest_client.py
  • getstream/chat/async_rest_client.py
  • getstream/video/async_call.py
  • getstream/chat/rest_client.py
  • getstream/moderation/async_rest_client.py
  • getstream/feeds/rest_client.py
  • getstream/video/rest_client.py
  • getstream/video/async_rest_client.py
  • getstream/webhook.py
🧬 Code graph analysis (12)
getstream/feeds/feeds.py (3)
getstream/stream_response.py (2)
  • data (22-24)
  • StreamResponse (11-36)
getstream/models/__init__.py (3)
  • FeedInput (8576-8592)
  • EnrichmentOptions (7921-7975)
  • UpdateFeedResponse (20025-20027)
getstream/feeds/rest_client.py (1)
  • update_feed (914-940)
getstream/common/async_rest_client.py (4)
getstream/common/telemetry.py (1)
  • operation_name (429-441)
getstream/models/__init__.py (6)
  • ListImportV2TasksResponse (11189-11195)
  • ImportV2TaskSettings (10750-10756)
  • UserRequest (21095-21119)
  • CreateImportV2TaskResponse (6949-6973)
  • DeleteImportV2TaskResponse (7505-7506)
  • GetImportV2TaskResponse (10066-10090)
getstream/utils/__init__.py (2)
  • build_query_param (94-126)
  • build_body_dict (151-175)
getstream/base.py (6)
  • get (222-238)
  • get (411-427)
  • post (240-256)
  • post (429-445)
  • delete (276-292)
  • delete (465-481)
getstream/common/rest_client.py (4)
getstream/common/async_rest_client.py (4)
  • list_import_v2_tasks (432-438)
  • create_import_v2_task (441-453)
  • delete_import_v2_task (456-466)
  • get_import_v2_task (469-477)
getstream/models/__init__.py (6)
  • ListImportV2TasksResponse (11189-11195)
  • ImportV2TaskSettings (10750-10756)
  • UserRequest (21095-21119)
  • CreateImportV2TaskResponse (6949-6973)
  • DeleteImportV2TaskResponse (7505-7506)
  • GetImportV2TaskResponse (10066-10090)
getstream/utils/__init__.py (2)
  • build_query_param (94-126)
  • build_body_dict (151-175)
getstream/base.py (6)
  • get (222-238)
  • get (411-427)
  • post (240-256)
  • post (429-445)
  • delete (276-292)
  • delete (465-481)
getstream/video/call.py (4)
getstream/video/async_call.py (1)
  • stop_recording (455-463)
getstream/video/async_rest_client.py (1)
  • stop_recording (754-769)
getstream/video/rest_client.py (1)
  • stop_recording (750-765)
getstream/models/__init__.py (1)
  • StopRecordingResponse (18228-18229)
getstream/moderation/rest_client.py (1)
getstream/models/__init__.py (19)
  • UserRequest (21095-21119)
  • AppealResponse (1562-1564)
  • GetAppealResponse (9727-9731)
  • ModerationPayloadRequest (12953-12965)
  • BanActionRequestPayload (2044-2062)
  • BlockActionRequestPayload (2183-2186)
  • CustomActionRequestPayload (7100-7104)
  • DeleteActivityRequestPayload (7345-7351)
  • DeleteCommentRequestPayload (7440-7446)
  • DeleteMessageRequestPayload (7510-7516)
  • DeleteReactionRequestPayload (7541-7547)
  • DeleteUserRequestPayload (7588-7603)
  • MarkReviewedRequestPayload (11382-11392)
  • RejectAppealRequestPayload (16404-16405)
  • RestoreActionRequestPayload (16681-16684)
  • ShadowBlockActionRequestPayload (17837-17840)
  • UnbanActionRequestPayload (18934-18940)
  • UnblockActionRequestPayload (18959-18962)
  • SubmitActionResponse (18352-18359)
getstream/chat/async_rest_client.py (4)
getstream/chat/rest_client.py (1)
  • mark_delivered (145-157)
getstream/models/__init__.py (4)
  • DeliveredMessagePayload (7637-7639)
  • MarkDeliveredResponse (11315-11316)
  • ChannelInputRequest (4990-5018)
  • MessageActionResponse (11676-11680)
getstream/utils/__init__.py (2)
  • build_query_param (94-126)
  • build_body_dict (151-175)
getstream/base.py (2)
  • post (240-256)
  • post (429-445)
getstream/video/async_call.py (5)
getstream/video/async_rest_client.py (1)
  • stop_recording (754-769)
getstream/video/call.py (1)
  • stop_recording (435-443)
getstream/video/rest_client.py (1)
  • stop_recording (750-765)
getstream/stream_response.py (1)
  • StreamResponse (11-36)
getstream/models/__init__.py (1)
  • StopRecordingResponse (18228-18229)
getstream/chat/rest_client.py (5)
getstream/chat/async_rest_client.py (1)
  • mark_delivered (147-159)
getstream/models/__init__.py (4)
  • DeliveredMessagePayload (7637-7639)
  • MarkDeliveredResponse (11315-11316)
  • ChannelInputRequest (4990-5018)
  • MessageActionResponse (11676-11680)
getstream/stream_response.py (2)
  • StreamResponse (11-36)
  • data (22-24)
getstream/utils/__init__.py (2)
  • build_query_param (94-126)
  • build_body_dict (151-175)
getstream/base.py (2)
  • post (240-256)
  • post (429-445)
getstream/moderation/async_rest_client.py (3)
getstream/moderation/rest_client.py (5)
  • appeal (35-52)
  • get_appeal (55-61)
  • query_appeals (64-83)
  • ban (86-109)
  • unban (548-567)
getstream/models/__init__.py (19)
  • UserRequest (21095-21119)
  • AppealResponse (1562-1564)
  • GetAppealResponse (9727-9731)
  • QueryAppealsResponse (14781-14785)
  • BanActionRequestPayload (2044-2062)
  • BlockActionRequestPayload (2183-2186)
  • CustomActionRequestPayload (7100-7104)
  • DeleteActivityRequestPayload (7345-7351)
  • DeleteCommentRequestPayload (7440-7446)
  • DeleteMessageRequestPayload (7510-7516)
  • DeleteReactionRequestPayload (7541-7547)
  • DeleteUserRequestPayload (7588-7603)
  • MarkReviewedRequestPayload (11382-11392)
  • RejectAppealRequestPayload (16404-16405)
  • RestoreActionRequestPayload (16681-16684)
  • ShadowBlockActionRequestPayload (17837-17840)
  • UnbanActionRequestPayload (18934-18940)
  • UnblockActionRequestPayload (18959-18962)
  • SubmitActionResponse (18352-18359)
getstream/utils/__init__.py (1)
  • build_body_dict (151-175)
getstream/feeds/rest_client.py (5)
getstream/common/telemetry.py (1)
  • operation_name (429-441)
getstream/base.py (6)
  • post (240-256)
  • post (429-445)
  • delete (276-292)
  • delete (465-481)
  • get (222-238)
  • get (411-427)
getstream/stream_response.py (2)
  • StreamResponse (11-36)
  • data (22-24)
getstream/utils/__init__.py (2)
  • build_body_dict (151-175)
  • build_query_param (94-126)
getstream/feeds/feeds.py (1)
  • delete (17-24)
getstream/video/rest_client.py (2)
getstream/models/__init__.py (4)
  • QueryCallStatsMapResponse (14968-15032)
  • SortParamRequest (17992-17999)
  • QueryCallSessionParticipantStatsResponse (14918-14951)
  • NotificationSettingsRequest (13341-13359)
getstream/utils/__init__.py (2)
  • build_body_dict (151-175)
  • build_query_param (94-126)
getstream/webhook.py (1)
getstream/models/__init__.py (9)
  • CustomEvent (7151-7170)
  • AppealAcceptedEvent (1425-1449)
  • CallAcceptedEvent (2608-2620)
  • BlockedUserEvent (2287-2303)
  • ClosedCaptionEvent (5975-5990)
  • CallCreatedEvent (2701-2713)
  • ChannelCreatedEvent (4728-4770)
  • ChannelUpdatedEvent (5695-5743)
  • ChannelVisibleEvent (5747-5789)
🔇 Additional comments (40)
getstream/moderation/rest_client.py (5)

34-83: LGTM - New appeal endpoints implemented correctly.

The three new appeal-related methods (appeal, get_appeal, query_appeals) follow the established patterns in this file with proper telemetry decorators, body construction, and return types matching the corresponding response models.


314-314: Inconsistent payload type: flag uses ModerationPayload while custom_check uses ModerationPayloadRequest.

Similar to check, the flag method's moderation_payload parameter still uses ModerationPayload rather than ModerationPayloadRequest. The AI summary indicates this should have been changed to ModerationPayloadRequest.


262-262: Type updated to ModerationPayloadRequest.

This aligns with the refactored OpenAPI specs using *Request payload variants.


296-296: Type updated to FeedsModerationTemplateConfigPayload.

This matches the payload type refactoring pattern.


499-545: submit_action expanded with new parameters and updated payload types.

The method signature changes look correct:

  • Added appeal_id parameter to support appeal actions
  • item_id changed to Optional[str] to accommodate appeal-based actions
  • Payload types renamed to *RequestPayload variants
  • New action payloads added: reject_appeal, restore, unblock

The body construction correctly includes all new fields.

getstream/moderation/async_rest_client.py (6)

34-85: LGTM - Async appeal endpoints implemented correctly.

The async versions of appeal, get_appeal, and query_appeals correctly mirror the synchronous implementations with proper async/await usage.


135-135: Same inconsistency: check uses ModerationPayload instead of ModerationPayloadRequest.

This mirrors the same issue in the synchronous client. If custom_check was updated to use ModerationPayloadRequest, check should likely be updated as well for consistency.


320-320: Same inconsistency: flag uses ModerationPayload instead of ModerationPayloadRequest.

Mirrors the sync client issue. The AI summary indicates this should have been changed.


266-266: Type updated to ModerationPayloadRequest.

Consistent with the sync client update.


302-302: Type updated to FeedsModerationTemplateConfigPayload.

Consistent with the sync client update.


507-553: submit_action async version correctly mirrors sync implementation.

All parameter and payload type changes align with the synchronous version:

  • appeal_id added
  • item_id now Optional[str]
  • Payload types use *RequestPayload variants
  • New actions: reject_appeal, restore, unblock
getstream/webhook.py (5)

1-7: LGTM on imports structure.

Standard library imports and typing are appropriate for webhook handling functionality.


170-326: LGTM on event type constants.

Comprehensive coverage of webhook event types with clear naming conventions.


329-348: LGTM on get_event_type implementation.

The function handles all input types correctly with appropriate exception handling and documented failure behavior.


385-543: Event mapping is comprehensive and correct.

The distinction between "*" (CustomEvent) and "custom" (CustomVideoEvent) is intentional. The event_map dictionary is recreated on each call, which is a minor inefficiency but acceptable for generated code.


546-565: LGTM on signature verification.

The use of hmac.compare_digest() for timing-safe comparison is correct security practice, preventing timing attacks on signature validation.

getstream/video/async_call.py (1)

454-463: stop_recording() wrapper wiring looks correct.
Pure formatting/refactor; still forwards type/id and syncs response.

getstream/video/async_rest_client.py (4)

308-344: go_live / stop_live request-body propagation looks consistent.
New recording flags are included in the request body via build_body_dict(...) and forwarded correctly.

Also applies to: 718-752


1038-1057: Payload type shift to NotificationSettingsRequest looks correct.
Using NotificationSettingsRequest aligns with request-body semantics (vs response-ish models).

Also applies to: 1078-1102


1107-1123: resolve_sip_inbound(... challenge: SIPChallengeRequest ...) looks consistent with request typing.
The request body uses build_body_dict(challenge=challenge) and should serialize via the model’s to_dict.


753-770: Empty JSON body is consistent with established codebase patterns, but backend contract verification still required.

Both sync and async stop_recording implementations use identical patterns—calling build_body_dict() with no arguments. This matches the standardized approach elsewhere in the codebase for endpoints without request parameters. However, explicit confirmation of the backend API contract expectations for this endpoint should be validated against the API specification or integration tests.

getstream/video/rest_client.py (3)

304-340: go_live / stop_live propagation looks consistent with the async variant.

Also applies to: 714-748


1034-1051: NotificationSettingsRequest usage looks correct for create/update call type.

Also applies to: 1072-1096


1101-1117: SIPChallengeRequest typing looks consistent for request payload.

getstream/video/call.py (1)

434-444: stop_recording() wrapper looks correct (formatting-only change).

getstream/feeds/feeds.py (1)

68-87: update(...) new fields are forwarded correctly.
description, name, and filter_tags are passed through to client.update_feed(...) as expected.

getstream/common/async_rest_client.py (1)

431-478: Import V2 task endpoints look consistent and correctly shaped.
Verb/path usage and request construction follow the existing client patterns.

getstream/common/rest_client.py (1)

423-466: Sync Import V2 task endpoints look consistent with async variant.

getstream/chat/rest_client.py (3)

144-157: New mark_delivered endpoint looks good.

The implementation correctly passes user_id as a query parameter and latest_delivered_messages in the request body. This aligns with the async version in async_rest_client.py.


627-654: Addition of message_timestamp parameter looks correct.

The new optional message_timestamp parameter is properly added to both the method signature and the request body, consistent with the async version.


1042-1059: Return type change to MessageActionResponse is a breaking change.

The return type changed from MessageResponse to MessageActionResponse for run_message_action. This is a breaking change for existing consumers. The same applies to commit_message and translate_message below.

Since this is generated code, please ensure that downstream consumers are aware of these breaking changes to:

  • run_message_action (line 1049)
  • commit_message (line 1065)
  • translate_message (line 1190)
getstream/chat/async_rest_client.py (4)

146-159: Async mark_delivered implementation is consistent with sync version.

The implementation correctly mirrors the sync version with proper await usage.


264-264: Same ChannelInput vs ChannelInputRequest inconsistency as sync version.

As noted in rest_client.py, update_channel uses ChannelInputRequest while get_or_create_distinct_channel (line 182) and get_or_create_channel (line 529) still use ChannelInput.

Please confirm this is intentional per the OpenAPI spec.


631-658: mark_unread changes are consistent with sync version.

The message_timestamp parameter addition is correctly implemented.


1052-1085: Return type changes to MessageActionResponse mirror sync version.

The async versions of run_message_action, commit_message, and translate_message correctly use the updated MessageActionResponse return type.

getstream/feeds/rest_client.py (5)

3-3: Telemetry integration looks good.

The telemetry import and decorator usage across all methods follows the established pattern in the codebase.


509-564: New collection methods follow established patterns.

The delete_collections, read_collections, update_collections, create_collections, and upsert_collections methods are correctly implemented with appropriate HTTP methods and telemetry decorators.


1314-1344: New feed visibility methods look correct.

The list_feed_visibilities, get_feed_visibility, and update_feed_visibility methods follow the established REST patterns.


1346-1373: New batch operations follow established patterns.

The create_feeds_batch, delete_feeds_batch, and own_batch methods are correctly implemented.


1619-1632: delete_feed_user_data changed from DELETE to POST.

The method now uses self.post instead of self.delete and includes hard_delete in the request body rather than as a query parameter. This appears intentional based on the endpoint path /users/{user_id}/delete.

@mogita mogita changed the title refactor: code generated from refactored openapi specs [CHA-1578] refactor: code generated from openapi specs Feb 16, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@getstream/tests/test_webhook.py`:
- Around line 77-716: Tests call parse_webhook_event with payloads that lack
required dataclass fields (e.g., CustomEvent requires created_at and custom;
MessageNewEvent requires message_id, watcher_count, message), causing TypeError
when event_class(**data) in parse_webhook_event is invoked; fix by updating the
test payloads passed to parse_webhook_event to include all mandatory fields for
each event class (populate created_at with an ISO datetime string or datetime
object, include a non-empty custom dict for CustomEvent, and add message_id,
watcher_count, message for MessageNewEvent, etc.) so that instantiation of the
dataclasses (via parse_webhook_event) succeeds.
🧹 Nitpick comments (1)
getstream/webhook.py (1)

387-550: event_map dict is rebuilt on every call.

_get_event_class allocates a ~130-entry dict each invocation. Since this is generated code the impact is low, but moving the map to module scope would be a trivial improvement.

♻️ Suggested refactor
+_EVENT_MAP = {
+    "*": CustomEvent,
+    "appeal.accepted": AppealAcceptedEvent,
+    # ... rest of entries ...
+}
+
 def _get_event_class(event_type: str):
     """Map event type to event class."""
-    event_map = {
-        "*": CustomEvent,
-        ...
-    }
-    return event_map.get(event_type)
+    return _EVENT_MAP.get(event_type)

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

This PR is being reviewed by Cursor Bugbot

Details

You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

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

Comments