Skip to main content

Official Python SDK for Mogu Workflow Management Platform

Project description

Mogu SDK

Official Python SDK for the Mogu Workflow Management Platform.

PyPI version Python 3.12+ License: MIT Code style: black

Features

  • 🔐 OAuth2 Authentication - Secure token-based authentication
  • 📝 Wiki Management - Create, update, search wiki pages in Git repositories
  • Async-First - Built on httpx for high-performance async operations
  • 🎯 Type-Safe - Full type hints with Pydantic models
  • 🧪 Well-Tested - Comprehensive test coverage
  • 📚 Great Documentation - Detailed API docs and examples

Installation

pip install mogu-sdk

Or with Poetry:

poetry add mogu-sdk

Quick Start

Environment Configuration

The SDK automatically reads configuration from environment variables or a .env file:

# Create a .env file
MOGU_BASE_URL=http://localhost:8000
MOGU_TOKEN=your-oauth-token
MOGU_WORKSPACE_ID=your-workspace-id

Basic Usage

import asyncio
from mogu_sdk import MoguClient

async def main():
    # Initialize client - automatically reads from environment variables
    client = MoguClient()
    
    # Or override specific values
    client = MoguClient(
        base_url="https://api.mogu.example.com",
        token="your-oauth-token"
    )
    
    # Access wiki client
    wiki = client.wiki
    
    # Create or update a wiki page
    result = await wiki.create_or_update_page(
        workspace_id="ws-123",
        path="docs/getting-started.md",
        content="# Getting Started\n\nWelcome to our wiki!",
        commit_message="Add getting started guide"
    )
    print(f"Committed: {result.commit_id}")
    
    # Search wiki with context
    results = await wiki.search(
        workspace_id="ws-123",
        query="authentication",
        max_results=10,
        context_lines=3
    )
    
    for result in results:
        print(f"\nFound in: {result.path}")
        for match in result.matches:
            print(f"  Line {match.line_number}: {match.line_content}")

if __name__ == "__main__":
    asyncio.run(main())

Wiki Client

Create or Update Wiki Page

Smart method that automatically detects if a file exists and creates or updates accordingly:

result = await wiki.create_or_update_page(
    workspace_id="ws-123",
    path="docs/api-reference.md",
    content="# API Reference\n\n## Authentication\n...",
    commit_message="Update API reference"
)

print(f"Success: {result.success}")
print(f"Commit ID: {result.commit_id}")
print(f"Message: {result.message}")

Search Wiki with Context

Search across all wiki files with configurable context extraction:

results = await wiki.search(
    workspace_id="ws-123",
    query="deployment kubernetes",
    max_results=20,
    context_lines=5  # Get 5 lines before/after each match
)

for result in results:
    print(f"\n📄 {result.path} (score: {result.score})")
    
    for match in result.matches:
        print(f"\n  Line {match.line_number}:")
        
        # Context before match
        if match.context_before:
            for line in match.context_before:
                print(f"    {line}")
        
        # The matched line (highlighted)
        print(f"  ➤ {match.line_content}")
        
        # Context after match
        if match.context_after:
            for line in match.context_after:
                print(f"    {line}")

Search with Character-Based Snippets (NEW!)

Extract text snippets of specific character length around matches - perfect for displaying search results in UIs:

results = await wiki.search(
    workspace_id="ws-123",
    query="authentication",
    max_results=10,
    snippet_chars=1000  # Extract ~1000 character snippet around each match
)

for result in results:
    for match in result.matches:
        if match.text_snippet:
            # Get the snippet with match position
            snippet = match.text_snippet
            start = match.snippet_match_start
            end = match.snippet_match_end
            
            # Highlight the match within snippet
            before = snippet[:start]
            matched = snippet[start:end]
            after = snippet[end:]
            
            print(f"{before}**{matched}**{after}")

Features:

  • Character-based extraction (e.g., 1000 chars) for consistent UI display
  • Smart word boundaries - avoids cutting words mid-character
  • Automatic ellipsis (...) for truncated text
  • Exact match position within snippet for highlighting
  • Works alongside line-based context (use both together!)

Combined context example:

# Get both line-based and character-based context
results = await wiki.search(
    workspace_id="ws-123",
    query="configuration",
    context_lines=2,      # 2 lines before/after (for code structure)
    snippet_chars=800     # 800 char snippet (for prose context)
)

# Now you have:
# - match.context_before / context_after (lines)
# - match.text_snippet (character-based snippet)

Search with Character-Based Snippets (NEW!)

Extract text snippets of specific character length around matches - perfect for displaying search results in UIs:

results = await wiki.search(
    workspace_id="ws-123",
    query="authentication",
    max_results=10,
    snippet_chars=1000  # Extract ~1000 character snippet around each match
)

for result in results:
    for match in result.matches:
        if match.text_snippet:
            # Get the snippet with match position
            snippet = match.text_snippet
            start = match.snippet_match_start
            end = match.snippet_match_end
            
            # Highlight the match within snippet
            before = snippet[:start]
            matched = snippet[start:end]
            after = snippet[end:]
            
            print(f"{before}**{matched}**{after}")

Features:

  • Character-based extraction (e.g., 1000 chars) for consistent UI display
  • Smart word boundaries - avoids cutting words mid-character
  • Automatic ellipsis (...) for truncated text
  • Exact match position within snippet for highlighting
  • Works alongside line-based context (use both together!)

Combined context example:

# Get both line-based and character-based context
results = await wiki.search(
    workspace_id="ws-123",
    query="configuration",
    context_lines=2,      # 2 lines before/after (for code structure)
    snippet_chars=800     # 800 char snippet (for prose context)
)

# Now you have:
# - match.context_before / context_after (lines)
# - match.text_snippet (character-based snippet)

List Wiki Files

files = await wiki.list_files(
    workspace_id="ws-123",
    folder_path="docs",  # Optional: filter by folder
    recursive=True
)

for file in files:
    icon = "📁" if file.is_folder else "📄"
    print(f"{icon} {file.path}")

Get File Content

content = await wiki.get_content(
    workspace_id="ws-123",
    path="docs/README.md"
)

print(f"Path: {content.path}")
print(f"Content:\n{content.content}")

Delete File

result = await wiki.delete_file(
    workspace_id="ws-123",
    path="docs/old-guide.md",
    commit_message="Remove outdated guide"
)

print(f"Deleted: {result.success}")

Configuration

The SDK supports multiple configuration methods with automatic environment variable loading.

Method 1: .env File (Recommended)

Create a .env file in your project root:

# .env
MOGU_BASE_URL=http://localhost:8000
MOGU_TOKEN=your-oauth-token
MOGU_WORKSPACE_ID=your-workspace-id
MOGU_TIMEOUT=30.0
MOGU_MAX_RETRIES=3
MOGU_VERIFY_SSL=true

Then simply initialize the client:

from mogu_sdk import MoguClient

# Automatically reads from .env file
client = MoguClient()

# Access default workspace_id
print(client.workspace_id)  # your-workspace-id

Method 2: Environment Variables

Set environment variables directly:

export MOGU_BASE_URL="https://api.mogu.example.com"
export MOGU_TOKEN="your-oauth-token"
export MOGU_WORKSPACE_ID="your-workspace-id"
from mogu_sdk import MoguClient

client = MoguClient()  # Reads from environment

Method 3: Direct Parameters

Override environment variables by passing parameters:

from mogu_sdk import MoguClient

client = MoguClient(
    base_url="https://api.mogu.example.com",
    token="your-oauth-token",
    workspace_id="your-workspace-id",
    timeout=30.0,  # Request timeout in seconds
    max_retries=3,  # Number of retry attempts
    verify_ssl=True  # SSL certificate verification
)

Error Handling

The SDK provides specific exceptions for different error scenarios:

from mogu_sdk.exceptions import (
    MoguAPIError,
    AuthenticationError,
    NotFoundError,
    PermissionDeniedError,
    ValidationError
)

try:
    result = await wiki.create_or_update_page(
        workspace_id="ws-123",
        path="docs/guide.md",
        content="# Guide",
        commit_message="Update guide"
    )
except AuthenticationError:
    print("Invalid or expired token")
except PermissionDeniedError:
    print("No permission to edit wiki")
except NotFoundError:
    print("Workspace not found")
except ValidationError as e:
    print(f"Invalid input: {e}")
except MoguAPIError as e:
    print(f"API error: {e.status_code} - {e.message}")

Advanced Usage

Context Manager

async with MoguClient(base_url="...", token="...") as client:
    result = await client.wiki.search(
        workspace_id="ws-123",
        query="deployment"
    )
    # Client automatically closed after context

Async Iteration

# Process search results as they arrive
async for result in wiki.search_stream(
    workspace_id="ws-123",
    query="api"
):
    print(f"Found: {result.path}")

Custom Headers

client = MoguClient(
    base_url="...",
    token="...",
    headers={
        "X-Custom-Header": "value",
        "User-Agent": "MyApp/1.0"
    }
)

Development

Setup Development Environment

# Clone the repository
git clone https://github.com/yourusername/mogu-sdk.git
cd mogu-sdk

# Install dependencies
poetry install

# Run tests
poetry run pytest

# Run linters
poetry run black mogu_sdk tests
poetry run ruff mogu_sdk tests
poetry run mypy mogu_sdk

Run Examples

# Set environment variables
export MOGU_BASE_URL="http://localhost:8000"
export MOGU_TOKEN="your-token"

# Run examples
poetry run python examples/wiki_basic.py
poetry run python examples/wiki_search.py

Contributing

Contributions are welcome! Please read our Contributing Guide for details.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Links

Support

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mogu_sdk-0.1.9.tar.gz (28.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mogu_sdk-0.1.9-py3-none-any.whl (32.2 kB view details)

Uploaded Python 3

File details

Details for the file mogu_sdk-0.1.9.tar.gz.

File metadata

  • Download URL: mogu_sdk-0.1.9.tar.gz
  • Upload date:
  • Size: 28.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.2.1 CPython/3.13.7 Darwin/25.1.0

File hashes

Hashes for mogu_sdk-0.1.9.tar.gz
Algorithm Hash digest
SHA256 d30852b4f9943746b1cfb0580b9945efad58d7d0274522bc6b0bbe4ffbe9ef60
MD5 49821eee4b538bef1fd9a07b58e6fb81
BLAKE2b-256 dd0273c8829fac0c7a13a5f6dc5f906597df13aa127b21b1e75162558ab3ae35

See more details on using hashes here.

File details

Details for the file mogu_sdk-0.1.9-py3-none-any.whl.

File metadata

  • Download URL: mogu_sdk-0.1.9-py3-none-any.whl
  • Upload date:
  • Size: 32.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.2.1 CPython/3.13.7 Darwin/25.1.0

File hashes

Hashes for mogu_sdk-0.1.9-py3-none-any.whl
Algorithm Hash digest
SHA256 3f67cf9dc876aa6480947f2f585067f2b2c03a798b3ceda5fe6cc4a147ca3b2f
MD5 c7f98a13d16c8172bc3660d098cf9208
BLAKE2b-256 2ba7ac66be2ca73747be891ff05b207338f68a545862e5e667309d09f72b711a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page