Skip to content

feat(sdk): implement zoom sdk integration#8

Merged
CyberwizD merged 5 commits into
mainfrom
feat/zoom-sdk-integration
May 16, 2026
Merged

feat(sdk): implement zoom sdk integration#8
CyberwizD merged 5 commits into
mainfrom
feat/zoom-sdk-integration

Conversation

@CyberwizD
Copy link
Copy Markdown
Collaborator

@CyberwizD CyberwizD commented May 16, 2026

Description

Adds the first Zoom RTMS-backed SDK prototype for MeetMind. This introduces a separate sdk/ package that lets developers create Zoom meeting agent sessions, configure wake words, receive Zoom RTMS webhook events, persist transcript/provider data, and prepare the boundary for future Zoom speaking support.

Type of Change

  • feat — New feature
  • fix — Bug fix
  • refactor — Code refactoring (no functional change)
  • docs — Documentation update
  • test — Adding or updating tests
  • chore — Maintenance (dependencies, CI, tooling)

Related Issue

Closes #

Changes Made

  • Added sdk/ package with SDK config, database setup, SQLAlchemy models, repositories, wake-word detection, and developer-facing SDK service.
  • Added Zoom RTMS webhook handling for OAuth callback, URL validation, RTMS started/stopped events, and transcript/audio event persistence.
  • Added SDK API routes for creating sessions, fetching sessions, retrieving transcripts, and preparing the /speak boundary.
  • Added configurable SDK database settings using SDK_DATABASE_URL, SQLite fallback, or Postgres/MySQL env vars.
  • Added configurable wake words through ZOOM_DEFAULT_WAKE_WORDS and per-session overrides.
  • Added SDK docs and tests for config, persistence, wake-word detection, and Zoom webhook security/event mapping.
  • Added rtms and python-decouple dependencies and ignored local SDK SQLite folders/files.

Proof of Work

API Response / Screenshots
POST /api/v1/sdk/sessions
Status: 201 Created

{
  "status": true,
  "message": "SDK session created",
  "data": {
    "id": "17a16bbe-a976-4f24-9113-f10e3c5b0939",
    "platform": "zoom",
    "meeting_id": "test-meeting-123",
    "meeting_url": "https://zoom.us/j/test-meeting-123",
    "agent_name": "MeetMind",
    "context": null,
    "wake_words": [
      "MeetMind",
      "Hey MeetMind"
    ],
    "status": "created",
    "provider_session_id": null,
    "created_at": "2026-05-16T11:54:31.260837",
    "updated_at": "2026-05-16T11:54:31.260846"
  }
}

Test Cases

  • Test case 1: test_database_url_prefers_explicit_override
  • Test case 2: test_database_url_uses_sqlite_path_for_local
  • Test case 3: test_database_url_builds_postgres_from_discrete_env
  • Test case 4: test_default_wake_words_are_configurable
  • Test case 5: test_session_and_transcript_persist_in_sqlite
  • Test case 6: test_detect_wake_word_respects_configured_phrases
  • Test case 7: test_verify_zoom_signature_accepts_valid_signed_body
  • Test case 8: test_rtms_event_mapping_supports_zoom_payload_shapes
Test output uv run pytest tests/sdk -q

============================= test session starts =============================
platform win32 -- Python 3.13.0, pytest-9.0.3, pluggy-1.6.0
rootdir: C:\Users\WISDOM\Documents\Python Codes\HNG\MeetMind\meetmind-api
configfile: pyproject.toml
plugins: anyio-4.13.0, asyncio-1.3.0
asyncio: mode=Mode.AUTO, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function
collected 10 items

tests\sdk\test_config.py .... [ 40%]
tests\sdk\test_repository.py . [ 50%]
tests\sdk\test_wake_words.py .. [ 70%]
tests\sdk\test_zoom_webhook.py ... [100%]

============================= 10 passed in 8.37s ==============================

Checklist

  • My branch follows the naming convention (/)
  • My commits follow Conventional Commits
  • I have added meaningful tests that cover success and failure paths
  • All new and existing tests pass locally (uv run pytest)
  • I have included proof of work (JSON responses or screenshots)
  • I have updated documentation if needed
  • My code follows the project's style guidelines

Summary by CodeRabbit

Release Notes

  • New Features

    • Added SDK API endpoints for creating and managing sessions with transcript storage and retrieval.
    • Added Zoom RTMS webhook integration for real-time meeting data capture.
    • Added OAuth callback support for authentication flows.
  • Documentation

    • Added SDK prototype documentation and setup guide.
  • Tests

    • Added comprehensive test coverage for SDK functionality.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 16, 2026

Warning

Rate limit exceeded

@CyberwizD has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 24 minutes and 18 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9b1552c0-9be7-48b0-9a8e-afc01f7a4e67

📥 Commits

Reviewing files that changed from the base of the PR and between 1cb2e70 and 497cad6.

📒 Files selected for processing (17)
  • .env.example
  • app/api/v1/routes/zoom_sdk.py
  • docs/sdk/zoom-rtms-sdk-prototype.md
  • sdk/config.py
  • sdk/models.py
  • sdk/providers/zoom_rtms/events.py
  • sdk/providers/zoom_rtms/manager.py
  • sdk/providers/zoom_rtms/webhook.py
  • sdk/providers/zoom_rtms/webhook_security.py
  • sdk/repositories.py
  • sdk/schemas.py
  • sdk/wake_words.py
  • tests/sdk/test_config.py
  • tests/sdk/test_repository.py
  • tests/sdk/test_schemas.py
  • tests/sdk/test_wake_words.py
  • tests/sdk/test_zoom_webhook.py
📝 Walkthrough

Walkthrough

This pull request introduces the MeetMind SDK v0.1.0 with complete Zoom RTMS integration. It adds environment-based configuration, SQLAlchemy persistence models for sessions and transcripts, a public Python SDK service class, Zoom webhook security validation, real-time meeting session management with callback wiring, and FastAPI HTTP endpoints for session lifecycle and transcript access.

Changes

MeetMind SDK and Zoom RTMS Integration

Layer / File(s) Summary
SDK Core Infrastructure
sdk/__init__.py, sdk/config.py, sdk/db.py, sdk/models.py, sdk/repositories.py, pyproject.toml
Environment-backed SDKSettings loads Zoom credentials and database URLs (SQLite or Postgres). SDKBase and session factory manage database lifecycle. SDKSession, SDKTranscriptTurn, and SDKProviderEvent ORM models store session metadata, transcript turns, and provider events as JSON. SDKRepository provides create, retrieve, update, and list operations with proper session/transcript sequencing and provider event recording.
SDK Public Service and Schemas
sdk/sdk.py, sdk/schemas.py, tests/sdk/test_config.py
MeetMindSDK service class wraps the repository and exposes thin delegating methods for Zoom session creation, retrieval, and transcript listing. Pydantic models define CreateSDKSessionRequest, SpeakRequest, and OAuthCallbackResponse. Configuration tests validate database URL construction and wake-word parsing.
Wake Word Detection
sdk/wake_words.py, tests/sdk/test_wake_words.py
normalize_wake_words performs case-insensitive deduplication while preserving first-seen casing. detect_wake_word scans text using word-boundary regexes, prioritizing longer phrases. Tests assert normalization and detection behavior.
Zoom RTMS Security and Events
sdk/providers/zoom_rtms/webhook_security.py, sdk/providers/zoom_rtms/events.py, tests/sdk/test_zoom_webhook.py
verify_zoom_signature validates webhook signatures using the v0:{timestamp}:{body} format and constant-time HMAC comparison. zoom_url_validation_response returns HMAC-SHA256 tokens. Event helpers normalize meeting.rtms.* event names and extract meeting_id, rtms_stream_id, and event metadata from multiple key variants. Tests verify signature validation and event mapping.
Zoom RTMS Manager and Webhook Handler
sdk/providers/zoom_rtms/manager.py, sdk/providers/zoom_rtms/webhook.py, sdk/providers/zoom_meeting_bridge/bridge.py, tests/sdk/test_repository.py
ZoomRTMSManager joins RTMS streams, registers transcript/audio callbacks, persists turns with wake-word detection, and tracks clients by stream ID. handle_zoom_webhook routes started/stopped events to the manager and records all events. MeetingOutputBridge defines a v0.2 speaking interface stub. Integration test verifies session and transcript persistence.
HTTP Endpoints and Registration
app/api/v1/routes/sdk.py, app/api/v1/routes/zoom_sdk.py, app/api/v1/router.py
Four SDK session endpoints (create, get, list transcript, speak) use MeetMindSDK and return session.to_dict(). Zoom webhook endpoint validates signature and dispatches to handle_zoom_webhook. OAuth callback endpoint echoes code and state. Routes mount under /sdk and /zoom prefixes.
Configuration and Documentation
.env.example, .gitignore, docs/sdk/zoom-rtms-sdk-prototype.md
Example environment variables for SDK database configuration (SQLite defaults, optional Postgres), Zoom credentials, webhook secrets, and RTMS feature toggles. Ignore patterns added for .sdk/ and *.sqlite* files. Comprehensive prototype documentation describes separation from main app, local/staging setup, end-to-end flow, and v0.1/v0.2 scope boundaries.

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically summarizes the main change: implementing Zoom SDK integration.
Description check ✅ Passed The description follows the template with all required sections completed: clear description, type of change marked, changes listed, proof of work provided with API response example, comprehensive test cases documented with output, and checklist fully completed.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/zoom-sdk-integration

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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
Copy Markdown

@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: 20

Caution

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

⚠️ Outside diff range comments (1)
tests/sdk/test_wake_words.py (1)

11-16: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Add a regression test for blank/whitespace wake words.

Current tests don’t protect against false matches when configured phrases contain empty values. Add a case like ["", " ", "Atlas"] and assert only "Atlas" can trigger.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/sdk/test_wake_words.py` around lines 11 - 16, Add a regression test to
tests/sdk/test_wake_words.py that verifies detect_wake_word ignores empty or
whitespace-only configured phrases: update the
test_detect_wake_word_respects_configured_phrases case to include wake_words =
["", "  ", "Atlas"] and assert detect_wake_word("Can you help here, Hey Atlas?",
wake_words) == "Atlas" while detect_wake_word("MeetMind should not trigger",
wake_words) is None (and optionally assert that inputs matching only whitespace
entries do not trigger).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.env.example:
- Line 41: Wrap the ZOOM_DEFAULT_WAKE_WORDS value in quotes in the .env.example
to avoid ambiguous parsing of comma-separated values with spaces (e.g., change
ZOOM_DEFAULT_WAKE_WORDS=MeetMind,Hey MeetMind to use quotes around the whole
value); update the ZOOM_DEFAULT_WAKE_WORDS entry so dotenv parsers treat the
comma and internal space as part of the value rather than tokenizing it.

In `@app/api/v1/routes/zoom_sdk.py`:
- Around line 16-31: The async endpoint zoom_rtms_webhook currently calls the
synchronous handle_zoom_webhook directly and will block the event loop; update
zoom_rtms_webhook to run the blocking handler in a worker thread by importing
and using run_in_threadpool (or asyncio.to_thread) and awaiting
run_in_threadpool(handle_zoom_webhook, db, payload) instead of calling
handle_zoom_webhook(db=db, payload=payload); keep signature and verification
logic as-is and ensure the call passes the same db and payload parameters to
handle_zoom_webhook so database operations (record_provider_event,
create_session, update_session_status) execute off the event loop.

In `@docs/sdk/zoom-rtms-sdk-prototype.md`:
- Around line 44-60: Fix the ordered-list nesting in the "Prototype Flow"
section by indenting the HTTP request code block so it is a child of the "1.
Create an SDK session:" list item (or alternatively restart numbering at 1 for
the code block), i.e., ensure the triple-backtick fenced block and its contents
are prefixed with three spaces (or otherwise indented) under the "Create an SDK
session" line so the code block is part of that list item and avoids MD029 lint
errors.

In `@sdk/config.py`:
- Line 45: The code hardcodes a single default port (5432) for DB ports (e.g.,
self.sdk_db_port), causing MySQL to fall back to the wrong port; change the
logic to pick a DB-type-specific default by reading the DB type env var (e.g.,
SDK_DB_TYPE) and mapping common types to their default ports (e.g.,
postgres/postgresql -> 5432, mysql/mariadb -> 3306, mssql -> 1433) before
calling config(..., default=...); apply the same conditional/default mapping to
the other DB port assignments in this file so each port attribute uses the
correct default for the configured DB type.

In `@sdk/models.py`:
- Line 33: The failing Ruff line-lengths are caused by overly long single-line
declarations (e.g., the field declaration "created_at: Mapped[datetime] =
mapped_column(DateTime(timezone=True), default=utc_now") and two other long
lines at positions reported (around lines 76 and 107); fix by wrapping long
arguments across multiple lines or extracting long expressions to short-named
temporaries so each source line is ≤88 chars—for example, split mapped_column
parameters onto separate indented lines or assign the DateTime(...) or default
value to a short variable and reference that variable in the field definition
(apply the same wrapping/extraction to the symbols at the other reported
locations).
- Line 65: SDKTranscriptTurn.session_id and SDKProviderEvent.session_id are
missing foreign key constraints; import ForeignKey from sqlalchemy and change
both mapped_column declarations to include ForeignKey("sdk_sessions.id") (e.g.,
session_id: Mapped[str] = mapped_column(ForeignKey("sdk_sessions.id"), String,
index=True, nullable=False)) so the columns reference sdk_sessions.id and
enforce referential integrity.

In `@sdk/providers/zoom_rtms/events.py`:
- Around line 1-3: The import block in sdk/providers/zoom_rtms/events.py is
misformatted for ruff (I001); ensure the "from __future__ import annotations"
and "from typing import Any" follow ruff's import ordering by separating the
future import from other imports with a blank line (or simply run `ruff check
--fix` in this file) so the __future__ import sits alone and the typing import
is on the next block.
- Around line 43-49: The meeting-id extraction currently builds variable `value`
from `obj` but omits the `meeting_uuid` (and possibly `meetingUuid`) keys;
update the `value = (...)` expression in the events extraction code to also
check for `obj.get("meeting_uuid")` (and `obj.get("meetingUuid")` if camelCase
variants are expected) alongside the existing keys (`meeting_id`, `meetingId`,
`meeting_number`, `meetingNumber`, `uuid`) so payloads using `meeting_uuid`
correctly resolve to a meeting id/uuid.

In `@sdk/providers/zoom_rtms/manager.py`:
- Line 35: Several raise statements and long expressions in
sdk/providers/zoom_rtms/manager.py (notably uses of ZoomRTMSRuntimeError and
long function calls/strings) exceed the 88-char Ruff E501 limit; wrap these by
breaking long strings or calls across lines using parentheses, implicit
concatenation, or by assigning parts to intermediate variables and then raising
ZoomRTMSRuntimeError(msg). Update each offending expression (the raise lines and
the other long expressions referenced) to use line breaks so no logical line
exceeds 88 chars while preserving the exact message and exception type.
- Around line 27-29: Make client lifecycle idempotent and thread-safe: add a
lock (e.g., self.clients_lock = threading.Lock()) in __init__ alongside
self.clients and self.executor, then wrap all reads/writes to self.clients
(including the handlers that process "started" and "stopped" events) with the
lock; on a "started" event check under the lock whether a live client for that
stream_id already exists and reuse it, otherwise create and register a new
client, and on a "stopped"/cleanup path ensure you close/shutdown the client and
remove it from self.clients while holding the lock so repeated events don’t leak
or duplicate clients.
- Around line 49-76: The call to client.join(...) can raise and currently leaves
the persisted session marked "listening" and the runtime client not tracked;
wrap client.join(...) in a try/except to catch join failures, and in the except
block: remove any partial runtime state (do not add self.clients[stream_id] or
pop it if added), attempt to shut down the created client (e.g., call
client.close() / client.destroy() if available on rtms.Client), and call
repo.update_session_status(session, "<rollback_status>") to revert the session
(use a stable status such as "idle" or "failed"); finally re-raise a
ZoomRTMSRuntimeError (or the original exception) so callers see the failure.
Ensure these changes are applied around the client.join(...) call and touch
symbols: client.join, self.clients, client (rtms.Client), and
repo.update_session_status.

In `@sdk/providers/zoom_rtms/webhook_security.py`:
- Around line 25-27: The current logic returns True when secret_token is missing
(checking secret_token) which effectively disables signature verification;
change this to fail-closed by returning False (or raising an error) when
secret_token is falsy, and ensure the subsequent check for timestamp and
signature also returns False if either is missing; update the function that uses
secret_token/timestamp/signature (referencing the secret_token, timestamp,
signature checks in webhook_security.py) so missing secrets or missing
timestamp/signature cause rejection rather than allowing the webhook.

In `@sdk/providers/zoom_rtms/webhook.py`:
- Around line 27-29: The URL validation branch currently casts a missing
plainToken to "None" and the line is too long; in the handler where you check if
raw_event == URL_VALIDATION_EVENT (use payload_object and URL_VALIDATION_EVENT),
extract the token into a local variable (e.g., plain_token =
payload_object(payload).get("plainToken") or
payload_object(payload).get("plain_token")), then explicitly guard that
plain_token is present and handle the invalid payload (return an appropriate
error/raise or log and return a bad-request response) instead of casting to str;
finally call zoom_url_validation_response(plain_token,
settings.zoom_webhook_secret_token) and reflow the statements so each line stays
within style limits (avoiding an inline cast and long expressions).

In `@sdk/repositories.py`:
- Around line 82-83: The current pattern of calling next_sequence(session.id)
separately then creating SDKTranscriptTurn risks duplicate sequence_no under
concurrent inserts; change sequence allocation to an atomic, transactional
operation: implement next_sequence to allocate the next sequence number inside
the same DB transaction that inserts the SDKTranscriptTurn (e.g., SELECT
MAX(sequence_no) FROM transcripts WHERE session_id = :id FOR UPDATE then use
max+1, or maintain a per-session sequence table and use UPDATE ... RETURNING or
a DB sequence), or alternatively add a unique (session_id, sequence_no)
constraint and perform the insert in a retry loop catching IntegrityError and
re-reading the next sequence; update the code paths that call next_sequence (the
caller that constructs SDKTranscriptTurn at the noted spots) to use the new
transactional allocation API so sequence assignment is atomic.
- Around line 27-29: The current expression uses "wake_words or
get_sdk_settings().zoom_default_wake_words" which treats an explicit empty list
as falsy and falls back to defaults; change the logic so configured_wake_words
is set from wake_words when the caller provided a value (including empty list)
and only use get_sdk_settings().zoom_default_wake_words when wake_words is None
(e.g., use a conditional like "wake_words if wake_words is not None else
get_sdk_settings().zoom_default_wake_words") before passing into
normalize_wake_words; update the assignment around configured_wake_words,
normalize_wake_words, wake_words, and get_sdk_settings()/zoom_default_wake_words
accordingly.
- Around line 49-55: find_zoom_session can raise MultipleResultsFound because
SDKSession.meeting_id isn't unique; modify the query in find_zoom_session to
restrict to a single row—either append .limit(1) to the select(...) before
executing or switch to using .scalars().first() on the result—so the latest
SDKSession (ordered by SDKSession.created_at.desc()) is returned safely when
multiple records exist.
- Around line 120-131: The SDKProviderEvent creation currently commits blindly
and raises IntegrityError on duplicate (provider, event_id); wrap the DB
add/commit/refresh in a try/except that catches sqlalchemy.exc.IntegrityError,
calls self.db.rollback(), then query and return the existing SDKProviderEvent by
provider and event_id (e.g., via
self.db.query(SDKProviderEvent).filter_by(provider=provider,
event_id=event_id).one()), and re-raise any other exceptions; ensure you import
IntegrityError and keep the original successful path unchanged (create event,
add, commit, refresh, return).

In `@sdk/schemas.py`:
- Line 16: Add a Pydantic field validator for SpeakRequest.text (similar to
ResetPasswordRequest.token) that strips whitespace and raises ValueError if the
result is empty so whitespace-only strings are rejected; update imports to
include pydantic.validator if missing and implement a method named e.g.
validate_text(cls, v) on the SpeakRequest model that returns the original value
when non-empty after strip and raises a ValueError with an explanatory message
otherwise.

In `@sdk/wake_words.py`:
- Around line 22-25: The detect_wake_word loop currently builds regexes from
wake_words that may be empty or whitespace; filter and strip entries before
matching so blank strings don't become boundary-only patterns. In
detect_wake_word, sanitize the input list by trimming each wake_word (e.g.,
wake_word = wake_word.strip()) and skip any empty results (or pre-filter the
wake_words iterable) before creating pattern =
rf"\b{re.escape(wake_word.lower())}\b" and running re.search; preserve the
existing sort-by-length behavior on the sanitized list.

In `@tests/sdk/test_zoom_webhook.py`:
- Around line 28-60: Add two tests: one to ensure verify_zoom_signature rejects
when secret_token is empty by calling verify_zoom_signature with secret_token=""
and asserting it returns False (or raises the expected rejection behavior), and
another to assert that meeting_id(payload) falls back to the meeting_uuid when
the payload only contains "meeting_uuid" (create a payload like
{"event":"meeting.rtms.started","payload":{"meeting_uuid":"uuid-only"}} and
assert normalize_event_name(...) == "meeting.rtms_started" and
meeting_id(payload) == "uuid-only" while rtms_stream_id(payload) remains handled
as before); reference the existing test functions verify_zoom_signature,
normalize_event_name, meeting_id, and rtms_stream_id when adding these cases.

---

Outside diff comments:
In `@tests/sdk/test_wake_words.py`:
- Around line 11-16: Add a regression test to tests/sdk/test_wake_words.py that
verifies detect_wake_word ignores empty or whitespace-only configured phrases:
update the test_detect_wake_word_respects_configured_phrases case to include
wake_words = ["", "  ", "Atlas"] and assert detect_wake_word("Can you help here,
Hey Atlas?", wake_words) == "Atlas" while detect_wake_word("MeetMind should not
trigger", wake_words) is None (and optionally assert that inputs matching only
whitespace entries do not trigger).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5fd24bcf-995c-418c-a7e0-9d4ec5a8120d

📥 Commits

Reviewing files that changed from the base of the PR and between 349024e and 1cb2e70.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (27)
  • .env.example
  • .gitignore
  • app/api/v1/router.py
  • app/api/v1/routes/sdk.py
  • app/api/v1/routes/zoom_sdk.py
  • docs/sdk/zoom-rtms-sdk-prototype.md
  • pyproject.toml
  • sdk/__init__.py
  • sdk/config.py
  • sdk/db.py
  • sdk/models.py
  • sdk/providers/__init__.py
  • sdk/providers/zoom_meeting_bridge/__init__.py
  • sdk/providers/zoom_meeting_bridge/bridge.py
  • sdk/providers/zoom_rtms/__init__.py
  • sdk/providers/zoom_rtms/events.py
  • sdk/providers/zoom_rtms/manager.py
  • sdk/providers/zoom_rtms/webhook.py
  • sdk/providers/zoom_rtms/webhook_security.py
  • sdk/repositories.py
  • sdk/schemas.py
  • sdk/sdk.py
  • sdk/wake_words.py
  • tests/sdk/test_config.py
  • tests/sdk/test_repository.py
  • tests/sdk/test_wake_words.py
  • tests/sdk/test_zoom_webhook.py

Comment thread .env.example Outdated
Comment thread app/api/v1/routes/zoom_sdk.py Outdated
Comment thread docs/sdk/zoom-rtms-sdk-prototype.md
Comment thread sdk/config.py Outdated
Comment thread sdk/models.py Outdated
Comment thread sdk/repositories.py Outdated
Comment thread sdk/repositories.py
Comment thread sdk/schemas.py
Comment thread sdk/wake_words.py Outdated
Comment thread tests/sdk/test_zoom_webhook.py
@CyberwizD CyberwizD merged commit 3b2e97c into main May 16, 2026
6 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