Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: WebexCommunity/WebexPythonSDK
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: ashjorda-patch
Choose a base ref
Loading
...
head repository: WebexCommunity/WebexPythonSDK
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
Loading
Checking mergeability… Don’t worry, you can still create the pull request.
  • 12 commits
  • 7 files changed
  • 4 contributors

Commits on Sep 17, 2025

  1. Fixes #256 with Thread-Aware Message Retrieval

    jozanini committed Sep 17, 2025
    Configuration menu
    Copy the full SHA
    c71fd77 View commit details
    Browse the repository at this point in the history

Commits on Oct 9, 2025

  1. Update containers.py

    Removed duplicate horizontalAlignment from simple_properties and descriptive comments in ColumnSet class. Added horizontalAlignment to simple_properties of Container class.
    guitarguy74 authored Oct 9, 2025
    Configuration menu
    Copy the full SHA
    415674b View commit details
    Browse the repository at this point in the history

Commits on Dec 10, 2025

  1. Update room.py

    ghpranav authored Dec 10, 2025
    Configuration menu
    Copy the full SHA
    89c5327 View commit details
    Browse the repository at this point in the history

Commits on Mar 24, 2026

  1. Fixes #256 with Thread-Aware Message Retrieval (#266)

    # Issue #256 Solution: Thread-Aware Message Retrieval
    
    ## Problem Description
    
    ### Original Issue
    The Webex Python SDK had a critical limitation where thread message
    retrieval worked correctly in 1:1 conversations but failed in spaces
    (group rooms) with the following errors:
    
    1. **404 Not Found Error**: `api.messages.get(parent_id)` worked for 1:1
    conversations but failed in spaces
    2. **403 Forbidden Error**: `api.messages.list(roomId=room_id,
    beforeMessage=parent_id)` worked for 1:1 but failed in spaces
    
    ### Root Cause Analysis
    The issue was caused by different permission models and API limitations
    between:
    - **Direct rooms (1:1 conversations)**: Messages are directly accessible
    via message ID
    - **Group rooms (spaces)**: Messages have different access controls and
    may require different retrieval strategies
    
    ### Impact
    This limitation prevented bots and applications from reliably retrieving
    thread context in spaces, making it impossible to:
    - Access the root message of a thread in spaces
    - Collect complete thread conversations for processing
    - Provide proper context to AI/LLM systems when responding to threaded
    messages
    
    ## Solution Overview
    
    ### Approach
    Implemented a **multi-strategy, room-type-aware message retrieval
    system** that:
    1. Detects room type (direct vs group) automatically
    2. Uses appropriate API endpoints based on room type
    3. Implements robust fallback mechanisms when direct retrieval fails
    4. Provides comprehensive error handling and user feedback
    
    ### Key Components
    
    #### 1. New API Methods (`src/webexpythonsdk/api/messages.py`)
    
    **Room Type Detection:**
    ```python
    def _is_direct_room(self, message):
        """Determine if a message is from a direct (1:1) room."""
    
    def _is_group_room(self, message):
        """Determine if a message is from a group room (space)."""
    ```
    
    **Thread Retrieval:**
    ```python
    def get_thread_messages(self, message, max_scan=500):
        """Retrieve all messages in a thread, including the root message."""
        # Returns: (thread_messages, root_message, error_message)
    
    def get_thread_context(self, message, max_scan=500):
        """Get comprehensive thread context information."""
        # Returns: dict with thread_messages, root_message, reply_count, etc.
    ```
    
    #### 2. Utility Function (`src/webexpythonsdk/thread_utils.py`)
    
    **Drop-in Replacement:**
    ```python
    def collect_thread_text_and_attachments(api, msg, max_scan=500, max_chars=60000):
        """Robustly collect thread text + attachments for both 1:1 and spaces."""
        # Returns: (thread_text, [attachment_text])
    ```
    
    #### 3. Multi-Strategy Retrieval
    
    **Strategy 1: Direct Retrieval**
    - Attempts `api.messages.get(parent_id)` first
    - Works for most cases when bot has proper permissions
    
    **Strategy 2: Room-Type-Aware Fallback**
    - **Direct rooms**: Uses `list_direct()` with `parentId` parameter
    - **Group rooms**: Scans recent messages to find parent by ID
    
    **Strategy 3: Reply Collection**
    - **Direct rooms**: Uses `list_direct()` for thread replies
    - **Group rooms**: Uses `list()` with `parentId` parameter
    
    **Strategy 4: Error Handling**
    - Provides clear error messages when retrieval fails
    - Graceful degradation to single message processing
    - Informative feedback about permission limitations
    
    ## Implementation Details
    
    ### File Structure
    ```
    src/webexpythonsdk/
    ├── api/
    │   └── messages.py          # Enhanced with thread-aware methods
    ├── thread_utils.py          # New utility functions
    └── __init__.py             # Updated exports
    
    tests/
    ├── api/
    │   └── test_messages.py     # Real integration tests
    └── (thread_utils tests integrated into test_messages.py)
    
    examples/
    └── thread_example.py        # Usage examples
    
    docs/
    └── THREAD_UTILS_README.md   # Comprehensive documentation
    ```
    
    ### API Method Details
    
    #### `get_thread_messages(message, max_scan=500)`
    **Purpose**: Core thread retrieval method with robust error handling
    
    **Parameters**:
    - `message`: Message object to get thread for
    - `max_scan`: Maximum messages to scan when searching for parent
    
    **Returns**:
    - `thread_messages`: List of all messages in thread (oldest to newest)
    - `root_message`: The root message of the thread (or None if not found)
    - `error_message`: Error description if any issues occurred
    
    #### `get_thread_context(message, max_scan=500)`
    **Purpose**: Convenience method returning structured thread information
    
    **Returns**:
    ```python
    {
        "thread_messages": [...],      # List of messages in thread
        "root_message": message,       # Root message object
        "reply_count": 5,              # Number of replies
        "is_thread": True,             # Boolean indicating if threaded
        "error": None,                 # Error message if any
        "room_type": "group"           # Type of room (direct/group)
    }
    ```
    
    ### Error Handling
    
    #### Common Error Scenarios
    1. **404 Not Found**: Parent message not accessible
       - **Cause**: Bot joined after thread started or lacks permission
       - **Handling**: Automatic fallback to scanning recent messages
    
    2. **403 Forbidden**: Insufficient permissions
       - **Cause**: Bot doesn't have access to space messages
       - **Handling**: Graceful degradation with informative error messages
    
    3. **API Exceptions**: Network or API errors
       - **Cause**: Temporary API issues
       - **Handling**: Fallback to single message processing
    
    #### Error Messages
    - `"Could not retrieve parent message {id}. Bot may have joined after
    thread started or lacks permission."`
    - `"Could not retrieve thread replies: {error}"`
    - `"Failed to retrieve thread context: {error}"`
    
    ## Usage Examples
    
    ### Basic Usage (Drop-in Replacement)
    ```python
    # Old way (user's original implementation)
    # thread_text, attachments = your_collect_thread_text_and_attachments(msg)
    
    # New way (using the SDK utility)
    from webexpythonsdk.thread_utils import collect_thread_text_and_attachments
    thread_text, attachments = collect_thread_text_and_attachments(api, msg)
    ```
    
    ### Advanced Usage (More Control)
    ```python
    # Get detailed thread information
    context = api.messages.get_thread_context(message)
    
    if context['error']:
        print(f"Error: {context['error']}")
    else:
        print(f"Thread has {len(context['thread_messages'])} messages")
        print(f"Room type: {context['room_type']}")
        print(f"Reply count: {context['reply_count']}")
    
    # Process each message in the thread
    for msg in context['thread_messages']:
        print(f"[{msg.personId}]: {msg.text}")
    ```
    
    ### Error Handling
    ```python
    try:
        context = api.messages.get_thread_context(message)
    
        if context['error']:
            if "permission" in context['error'].lower():
                print("Bot lacks permission to access thread root")
            elif "joined after" in context['error'].lower():
                print("Bot joined after thread started")
            else:
                print(f"Other error: {context['error']}")
        else:
            print("Thread retrieved successfully")
    
    except Exception as e:
        print(f"Unexpected error: {e}")
    ```
    
    ## Testing
    
    ### Test Coverage
    - **Unit Tests**: Mock-based tests integrated into `test_messages.py`
    - **Integration Tests**: Real API tests in `test_messages.py`
    - **Error Scenarios**: Comprehensive error handling validation
    - **Room Types**: Both direct and group room testing
    - **Edge Cases**: Single messages, invalid data, permission errors
    
    ### Test Categories
    1. **Room Type Detection**: Verifies correct identification of direct vs
    group rooms
    2. **Thread Context**: Tests comprehensive thread information retrieval
    3. **Thread Messages**: Tests core message collection functionality
    4. **Error Handling**: Validates graceful error handling and fallback
    behavior
    5. **Utility Functions**: Tests drop-in replacement functionality
    6. **Parameter Validation**: Tests custom parameters and limits
    
    ## Migration Guide
    
    ### For Existing Code
    1. **Import the new function**:
       ```python
    from webexpythonsdk.thread_utils import
    collect_thread_text_and_attachments
       ```
    
    2. **Replace your function call**:
       ```python
       # Old way
    # thread_text, attachments =
    your_collect_thread_text_and_attachments(msg)
    
       # New way
    thread_text, attachments = collect_thread_text_and_attachments(api, msg)
       ```
    
    3. **Update error handling** (optional):
    The new function provides better error messages and handles both room
    types automatically.
    
    ### For New Code
    Use the new API methods directly for more control:
    ```python
    # Get thread context
    context = api.messages.get_thread_context(message)
    
    # Check if it's a thread
    if context['is_thread']:
        print(f"Processing thread with {context['reply_count']} replies")
    
        # Process each message
        for msg in context['thread_messages']:
            process_message(msg)
    else:
        print("Single message, not a thread")
    ```
    
    ## Performance Considerations
    
    - **Max Scan Limit**: Default 500 messages to prevent excessive API
    calls
    - **Caching**: Author display names are cached to reduce API calls
    - **Pagination**: Uses efficient pagination for large threads
    - **Truncation**: Automatic text truncation to prevent memory issues
    - **Rate Limiting**: Respects Webex API rate limits
    
    ## Limitations
    
    1. **File Attachments**: The utility functions include placeholder
    implementations for file processing
    2. **Display Names**: Uses placeholder display names; integrate with
    People API for real names
    3. **Rate Limits**: Respects Webex API rate limits but doesn't implement
    backoff
    
    ## Future Enhancements
    
    Potential improvements for future versions:
    1. Real People API integration for display names
    2. File attachment processing
    3. Rate limiting and backoff strategies
    4. Thread analytics and metrics
    5. Real-time thread updates
    
    ## Files Modified/Created
    
    ### New Files
    - `src/webexpythonsdk/thread_utils.py` - Utility functions
    - `tests/api/test_messages.py` - Integration and unit tests
    - `examples/thread_example.py` - Usage examples
    - `THREAD_UTILS_README.md` - Comprehensive documentation
    - `ISSUE_256_SOLUTION.md` - This documentation
    
    ### Modified Files
    - `src/webexpythonsdk/api/messages.py` - Added thread-aware methods
    - `src/webexpythonsdk/__init__.py` - Updated exports
    - `tests/api/test_messages.py` - Added integration tests
    
    ## Conclusion
    
    This solution provides a robust, room-type-aware thread message
    retrieval system that resolves the original 404/403 errors while
    maintaining backward compatibility. The implementation includes
    comprehensive error handling, extensive testing, and clear documentation
    to ensure reliable operation in both 1:1 conversations and spaces.
    
    The solution is production-ready and provides a simple migration path
    for existing code while offering advanced features for new
    implementations.
    
    ---
    
    **Issue**: #256
    **Status**: ✅ Resolved
    **Implementation Date**: 2024
    **SDK Version**: Compatible with existing versions
    Joezanini authored Mar 24, 2026
    Configuration menu
    Copy the full SHA
    82c90f8 View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    9e09dcd View commit details
    Browse the repository at this point in the history
  3. updating ci to fix build issue

    jozanini committed Mar 24, 2026
    Configuration menu
    Copy the full SHA
    6e3cde2 View commit details
    Browse the repository at this point in the history
  4. Configuration menu
    Copy the full SHA
    26b6659 View commit details
    Browse the repository at this point in the history
  5. Configuration menu
    Copy the full SHA
    8f372f3 View commit details
    Browse the repository at this point in the history
  6. Update containers.py (#267)

    Removed duplicate horizontalAlignment from simple_properties and
    descriptive comments in ColumnSet class. Added horizontalAlignment to
    simple_properties of Container class.
    Joezanini authored Mar 24, 2026
    Configuration menu
    Copy the full SHA
    3478f34 View commit details
    Browse the repository at this point in the history
  7. Update room model (#268)

    This is a behavior fix (correct data binding), not a new feature. Anything that already called these properties will start getting different, correct values.
    Joezanini authored Mar 24, 2026
    Configuration menu
    Copy the full SHA
    f521100 View commit details
    Browse the repository at this point in the history

Commits on Apr 14, 2026

  1. Enhance room update functionality in tests

    Updated the room creation in `add_rooms` to store the created room object directly. Modified the `test_update_room_title` to include an `isLocked` parameter during the room update, ensuring the room's locked state is validated in the assertions.
    jozanini committed Apr 14, 2026
    Configuration menu
    Copy the full SHA
    e3193e5 View commit details
    Browse the repository at this point in the history
  2. Enhance room update functionality in tests (#272)

    Updated the room creation in `add_rooms` to store the created room
    object directly. Modified the `test_update_room_title` to include an
    `isLocked` parameter during the room update, ensuring the room's locked
    state is validated in the assertions.
    Joezanini authored Apr 14, 2026
    Configuration menu
    Copy the full SHA
    5aea148 View commit details
    Browse the repository at this point in the history
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.