-
Notifications
You must be signed in to change notification settings - Fork 41
Add StateManager and TriggerState classes to Python SDK #213
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Introduced the `StateManager` class for managing workflow states and triggering graph executions. - Added the `TriggerState` class to represent trigger states with identifiers and input parameters. - Updated the README.md to include documentation for the new classes and their usage. - Created a new example script in `temp.py` demonstrating the usage of `StateManager` and `TriggerState`. - Bumped version to 0.0.7b6 to reflect the new features.
📝 WalkthroughSummary by CodeRabbit
WalkthroughIntroduces a new StateManager client and TriggerState model for programmatic graph execution, integrates them into the exospherehost public API, documents usage in README (with a duplicated section), and bumps the package version to 0.0.7b6. Changes
Sequence Diagram(s)sequenceDiagram
actor Developer
participant SDK as StateManager (SDK)
participant HTTP as aiohttp Client
participant Svc as State Manager Service
Developer->>SDK: trigger(graph_name, state|states)
SDK->>SDK: Validate inputs / build payload
SDK->>HTTP: POST {uri/version/namespace/graph/graph_name/trigger}\nHeaders: x-api-key
HTTP->>Svc: HTTP POST /trigger
Svc-->>HTTP: 200 JSON or error
HTTP-->>SDK: Response
alt 200 OK
SDK-->>Developer: Return response JSON (dict)
else Non-200
SDK-->>Developer: Raise Exception(status, text)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary of Changes
Hello @NiveditJain, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request significantly enhances the Python SDK by introducing robust state management capabilities. It adds StateManager and TriggerState classes, enabling programmatic control over workflow states and the ability to trigger graph executions with specific input parameters. The changes include new core logic, updated documentation, and a version bump, providing developers with powerful tools for integrating and orchestrating ExosphereHost workflows within their applications.
Highlights
- New Core Classes for State Management: Two new classes,
StateManagerandTriggerState, have been introduced to the Python SDK.StateManagerfacilitates programmatic triggering of graph executions and managing workflow states, whileTriggerStateencapsulates the identifier and input parameters for these triggers. - Asynchronous Graph Triggering: The
StateManagerclass provides anasync triggermethod, allowing users to initiate graph executions by sending either a singleTriggerStateobject or a list of them. This enables flexible integration with existing applications and custom orchestration logic. - Updated Documentation: The
README.mdhas been significantly updated to include comprehensive documentation for the newStateManagerandTriggerStateclasses. This includes detailed explanations of their initialization, parameters, and usage examples, ensuring developers can easily adopt these new features. - Version Bump: The SDK's version has been incremented to
0.0.7b6to reflect the addition of these new state management capabilities.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.
| Feature | Command | Description |
|---|---|---|
| Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
| Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
| Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
| Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces StateManager and TriggerState classes to the Python SDK, enabling programmatic triggering of graph executions. The changes are well-documented in the README. My review focuses on improving the robustness and conciseness of the new StateManager class. I've suggested adding configuration validation to prevent runtime errors, refactoring for more idiomatic Python, and using custom exceptions for better error handling. I also pointed out a minor style issue.
| def _set_config_from_env(self): | ||
| """ | ||
| Set configuration from environment variables if not provided. | ||
| """ | ||
| if self._state_manager_uri is None: | ||
| self._state_manager_uri = os.environ.get("EXOSPHERE_STATE_MANAGER_URI") | ||
| if self._key is None: | ||
| self._key = os.environ.get("EXOSPHERE_API_KEY") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The configuration values _state_manager_uri and _key are fetched from environment variables if not provided, but there's no check to ensure they are actually set. This can lead to runtime errors later when API calls are made. It's crucial to validate that these have values after attempting to load from the environment, similar to how it's done in the Runtime class.
| def _set_config_from_env(self): | |
| """ | |
| Set configuration from environment variables if not provided. | |
| """ | |
| if self._state_manager_uri is None: | |
| self._state_manager_uri = os.environ.get("EXOSPHERE_STATE_MANAGER_URI") | |
| if self._key is None: | |
| self._key = os.environ.get("EXOSPHERE_API_KEY") | |
| def _set_config_from_env(self): | |
| """ | |
| Set configuration from environment variables if not provided. | |
| """ | |
| if self._state_manager_uri is None: | |
| self._state_manager_uri = os.environ.get("EXOSPHERE_STATE_MANAGER_URI") | |
| if self._key is None: | |
| self._key = os.environ.get("EXOSPHERE_API_KEY") | |
| if self._state_manager_uri is None: | |
| raise ValueError("State manager URI is not set. Provide it as an argument or set the EXOSPHERE_STATE_MANAGER_URI environment variable.") | |
| if self._key is None: | |
| raise ValueError("API key is not set. Provide it as an argument or set the EXOSPHERE_API_KEY environment variable.") |
| states_list = [] | ||
| if state is not None: | ||
| states_list.append(state) | ||
| if states is not None: | ||
| states_list.extend(states) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic for constructing states_list is correct but can be expressed more concisely using a conditional expression. This improves readability.
| states_list = [] | |
| if state is not None: | |
| states_list.append(state) | |
| if states is not None: | |
| states_list.extend(states) | |
| states_list = [state] if state is not None else states |
| } | ||
| endpoint = self._get_trigger_state_endpoint(graph_name) | ||
| async with aiohttp.ClientSession() as session: | ||
| async with session.post(endpoint, json=body, headers=headers) as response: # type: ignore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The # type: ignore comment suppresses a potential type error. The validation I suggested for _state_manager_uri and _key should ensure they are not None, which will likely resolve the underlying type issue for the endpoint and headers parameters. Once the validation is in place, please check if this type: ignore can be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 10
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
python-sdk/README.md(1 hunks)python-sdk/exospherehost/__init__.py(1 hunks)python-sdk/exospherehost/_version.py(1 hunks)python-sdk/exospherehost/statemanager.py(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
python-sdk/exospherehost/statemanager.py (5)
state-manager/app/models/create_models.py (4)
TriggerGraphResponseModel(36-39)TriggerGraphRequestModel(32-33)ResponseStateModel(12-19)RequestStateModel(7-9)state-manager/app/controller/create_states.py (1)
trigger_graph(24-48)state-manager/tests/unit/controller/test_trigger_graph.py (2)
test_trigger_graph_success(28-80)test_trigger_graph_create_states_error(84-99)state-manager/app/models/db/state.py (1)
State(8-18)state-manager/app/routes.py (1)
trigger_graph_route(72-82)
python-sdk/exospherehost/__init__.py (1)
python-sdk/exospherehost/statemanager.py (2)
StateManager(38-123)TriggerState(6-35)
python-sdk/README.md (4)
state-manager/app/controller/create_states.py (1)
trigger_graph(24-48)state-manager/app/models/create_models.py (2)
TriggerGraphResponseModel(36-39)TriggerGraphRequestModel(32-33)state-manager/tests/unit/controller/test_trigger_graph.py (1)
test_trigger_graph_success(28-80)state-manager/app/models/db/state.py (1)
State(8-18)
🪛 Gitleaks (8.27.2)
python-sdk/exospherehost/statemanager.py
28-28: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
python-sdk/README.md
239-239: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🪛 LanguageTool
python-sdk/README.md
[grammar] ~198-~198: Use correct spacing
Context: ...andle them manually ## State Management The SDK provides a StateManager class ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~200-~200: Use correct spacing
Context: ...for building custom orchestration logic. ### StateManager Class The StateManager c...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~202-~202: Use correct spacing
Context: ...estration logic. ### StateManager Class The StateManager class allows you to t...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~204-~204: Use correct spacing
Context: ...the ExosphereHost state manager service. #### Initialization ```python from exosphere...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~206-~206: Use correct spacing
Context: ...te manager service. #### Initialization python from exospherehost import StateManager # Initialize with explicit configuration state_manager = StateManager( namespace="MyProject", state_manager_uri="https://your-state-manager.exosphere.host", key="your-api-key", state_manager_version="v0" ) # Or initialize with environment variables state_manager = StateManager(namespace="MyProject") Parameters: - namespace (str): The n...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~223-~223: Use correct spacing
Context: ...amespace="MyProject") ``` Parameters: - namespace (str): The namespace for your project - ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~224-~224: Use correct spacing
Context: ...e(str): The namespace for your project -state_manager_uri` (str, optional): The URI of the state ma...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~225-~225: Use articles correctly
Context: ...manager service. If not provided, reads from EXOSPHERE_STATE_MANAGER_URI environme...
(QB_NEW_EN_OTHER_ERROR_IDS_11)
[grammar] ~225-~225: There might be a mistake here.
Context: ..._STATE_MANAGER_URIenvironment variable -key` (str, optional): Your API key. If not pr...
(QB_NEW_EN_OTHER)
[grammar] ~226-~226: Use articles correctly
Context: ...): Your API key. If not provided, reads from EXOSPHERE_API_KEY environment variabl...
(QB_NEW_EN_OTHER_ERROR_IDS_11)
[grammar] ~226-~226: There might be a mistake here.
Context: ...EXOSPHERE_API_KEY environment variable - state_manager_version (str): The API version to use (default: ...
(QB_NEW_EN_OTHER)
[grammar] ~227-~227: Use correct spacing
Context: ...: The API version to use (default: "v0") #### Triggering Graph Execution ```python fr...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~229-~229: Use correct spacing
Context: ...: "v0") #### Triggering Graph Execution python from exospherehost import StateManager, TriggerState # Create a single trigger state trigger_state = TriggerState( identifier="user-login", inputs={ "user_id": "12345", "session_token": "abc123def456", "timestamp": "2024-01-15T10:30:00Z" } ) # Trigger a single state result = await state_manager.trigger("my-graph", state=trigger_state) # Or trigger multiple states trigger_states = [ TriggerState(identifier="trigger1", inputs={"key1": "value1"}), TriggerState(identifier="trigger2", inputs={"key2": "value2"}) ] result = await state_manager.trigger("my-graph", states=trigger_states) Parameters: - graph_name (str): The ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~256-~256: Use correct spacing
Context: ...tates=trigger_states) ``` Parameters: - graph_name (str): The name of the graph to trigger ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~257-~257: Use correct spacing
Context: ... (str): The name of the graph to trigger - state (TriggerState, optional): A single trigg...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~258-~258: Use correct spacing
Context: ...State, optional): A single trigger state - states (list[TriggerState], optional): A list o...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~259-~259: Use correct spacing
Context: ...te], optional): A list of trigger states Returns: - dict: The JSON response f...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~261-~261: There might be a mistake here.
Context: ...l): A list of trigger states Returns: - dict: The JSON response from the state manag...
(QB_NEW_EN)
[grammar] ~262-~262: Use correct spacing
Context: ...JSON response from the state manager API Raises: - ValueError: If neither `st...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~264-~264: There might be a mistake here.
Context: ...se from the state manager API Raises: - ValueError: If neither state nor states is pro...
(QB_NEW_EN)
[grammar] ~265-~265: There might be a mistake here.
Context: ...rovided, or if states is an empty list - Exception: If the API request fails with a non-20...
(QB_NEW_EN)
[grammar] ~266-~266: Use correct spacing
Context: ...request fails with a non-200 status code ### TriggerState Class The TriggerState c...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~268-~268: Use correct spacing
Context: ...-200 status code ### TriggerState Class The TriggerState class represents a tr...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~270-~270: Use correct spacing
Context: ...assed to the graph when it is triggered. #### Creating Trigger States ```python from ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~272-~272: Use correct spacing
Context: ...triggered. #### Creating Trigger States python from exospherehost import TriggerState # Basic trigger state trigger_state = TriggerState( identifier="data-processing", inputs={ "file_path": "/path/to/data.csv", "batch_size": "1000", "priority": "high" } ) # Trigger state with complex data (serialized as JSON) import json complex_data = { "filters": ["active", "verified"], "date_range": {"start": "2024-01-01", "end": "2024-01-31"}, "options": {"include_metadata": True, "format": "json"} } trigger_state = TriggerState( identifier="complex-processing", inputs={ "config": json.dumps(complex_data), "user_id": "12345" } ) Attributes: - identifier (str): A un...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~305-~305: Use correct spacing
Context: ..._id": "12345" } ) ``` Attributes: - identifier (str): A unique identifier for this trig...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~306-~306: Use correct spacing
Context: ... to determine how to process the trigger - inputs (dict[str, str]): A dictionary of input ...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~307-~307: There might be a problem here.
Context: ...ed to the graph. The keys are parameter names and values are parameter values, both as st...
(QB_NEW_EN_MERGED_MATCH)
[grammar] ~307-~307: There might be a mistake here.
Context: ...es are parameter values, both as strings ## Integration with ExosphereHost Platform ...
(QB_NEW_EN_OTHER)
🪛 markdownlint-cli2 (0.17.2)
python-sdk/README.md
224-224: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
257-257: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
262-262: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
265-265: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
306-306: Lists should be surrounded by blank lines
(MD032, blanks-around-lists)
🔇 Additional comments (4)
python-sdk/exospherehost/_version.py (1)
1-1: Version bump aligns with new public API exposure.The version update to 0.0.7b6 is appropriate for introducing StateManager and TriggerState.
python-sdk/exospherehost/__init__.py (1)
40-40: Public re-export of StateManager and TriggerState looks good.This makes the new API available via exospherehost.StateManager and exospherehost.TriggerState.
python-sdk/exospherehost/statemanager.py (2)
99-105: Input validation for mutually exclusive arguments looks correct.Covers all invalid combinations, including empty list.
1-3: aiohttp already declared in python-sdk dependenciesThe python-sdk/pyproject.toml includes:
- Line 9:
"aiohttp>=3.12.15"No changes needed for runtime dependency declaration.
nk-ag
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
StateManagerclass for managing workflow states and triggering graph executions.TriggerStateclass to represent trigger states with identifiers and input parameters.temp.pydemonstrating the usage ofStateManagerandTriggerState.