Skip to content

Conversation

@danielchalef
Copy link
Member

Summary

Adds Conductor integration to automate workspace setup and testing, enabling parallel development workflows across multiple isolated workspaces.

Changes

  • conductor.json: Configuration defining setup and run scripts
  • conductor-setup.sh: Automated workspace initialization script

Features

Automated Setup Script

  • Verifies prerequisites (uv package manager, Python 3.10+)
  • Copies essential files (pyproject.toml, uv.lock, README.md, pytest.ini, conftest.py)
  • Creates symlinks to source code directories (graphiti_core, tests, examples)
  • Installs all 185 development dependencies using frozen lock file
  • Generates workspace-specific Makefile that uses virtualenv directly
  • Links .env file from root repository
  • Validates OPENAI_API_KEY is configured
  • Provides helpful error messages for missing prerequisites

Run Script

  • Executes unit test suite via make test
  • Configured as nonconcurrent to prevent overlapping test runs

Benefits

  • Fast workspace creation: ~1 second setup time after dependency installation
  • Isolated development: Each workspace has its own virtualenv
  • Consistent environments: Uses frozen lock file from root repo
  • Easy testing: One-click test execution via Run button
  • Fail-fast validation: Clear error messages guide developers through setup issues

Testing

  • ✅ Setup script tested successfully
  • ✅ All 199 unit tests can be collected and run
  • ✅ make test, make lint, make format, and make check commands verified

Once merged, all Conductor workspaces will automatically have access to these scripts.

🤖 Generated with Claude Code

danielchalef and others added 4 commits November 1, 2025 18:26
This adds Conductor integration to automate workspace setup and testing.

Configuration includes:
- Setup script that runs automatically when creating new workspaces
- Automated dependency installation using uv with frozen lock file
- Environment file linking from root repository
- Workspace-specific Makefile using virtualenv directly
- Run script for executing the test suite via "Run" button

The setup script:
- Verifies prerequisites (uv, Python 3.10+)
- Copies necessary files and creates symlinks to source code
- Installs all 185 development dependencies
- Links .env file and validates OPENAI_API_KEY
- Provides helpful error messages for missing prerequisites

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@claude
Copy link
Contributor

claude bot commented Nov 2, 2025

Critical Issues with PR Scope

This PR has significant scope creep that needs to be addressed before merging:

1. Unrelated Files Included

SUMMARY_PIPELINE_STATE.md - This is a 126-line design document about node summary pipeline optimizations that has nothing to do with Conductor integration. This appears to be accidentally committed and should be removed or moved to a separate PR.

.cursor/worktrees.json - This is Cursor IDE-specific configuration that should not be committed to the repository. This is IDE-specific and should be in .gitignore.

2. Major Unrelated Feature: FalkorDB Lite Support

The PR includes a substantial new feature adding FalkorDB Lite support (69 lines in falkordb_driver.py) that is completely unrelated to Conductor workspace configuration:

  • New lite and lite_db_path parameters
  • Import of redislite.falkordb_client
  • New _AsyncLiteGraphAdapter and _AsyncLiteClientAdapter classes
  • New _await_graph_query helper function
  • Changes to pyproject.toml adding falkordb-lite dependency

This feature should be in a separate PR with proper review focus on the FalkorDB integration.

3. PR Title Mismatch

The PR is titled "Add Conductor workspace configuration" but actually includes 3-4 distinct changes that should be separate PRs.

Recommendation

Split this into multiple PRs:

  1. Conductor integration (conductor.json, conductor-setup.sh only)
  2. FalkorDB Lite support (driver changes, pyproject.toml, tests)
  3. Remove SUMMARY_PIPELINE_STATE.md and .cursor/worktrees.json entirely (or create design doc PR if intentional)

fi

# Check Python version
python_version=$(python3 --version 2>&1 | awk '{print $2}')
Copy link
Contributor

Choose a reason for hiding this comment

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

The required_version variable is set but never used. Either remove it or use it in a more informative error message like:

echo "❌ Error: Python ${required_version}+ is required (found: $python_version)"


# Copy necessary files from root repo
echo "📄 Copying project files from root repo..."
cp "$CONDUCTOR_ROOT_PATH/pyproject.toml" .
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing validation that $CONDUCTOR_ROOT_PATH is set. The script will fail with confusing errors if this environment variable is not defined. Add at the start of the script:

if [ -z "$CONDUCTOR_ROOT_PATH" ]; then
    echo "❌ Error: CONDUCTOR_ROOT_PATH environment variable is not set"
    exit 1
fi


# Create symlink to source code instead of copying
echo "🔗 Creating symlinks to source code..."
ln -sf "$CONDUCTOR_ROOT_PATH/graphiti_core" graphiti_core
Copy link
Contributor

Choose a reason for hiding this comment

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

Using ln -sf will silently overwrite existing symlinks. If a workspace is re-setup, this could cause issues if the symlinks already exist. Consider checking first or adding validation that the symlinks point to the expected location.

# Internal helpers
# -----------------

async def _await_graph_query(graph: Any, cypher: str, params: dict[str, Any] | None):
Copy link
Contributor

Choose a reason for hiding this comment

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

This function calls query_callable twice when the result is not awaitable - once on line 365 to check if it's awaitable, and again on line 369 to actually run it. This executes the query twice for sync clients.

Fix:

async def _await_graph_query(graph: Any, cypher: str, params: dict[str, Any] | None):
    query_callable = getattr(graph, 'query')
    result = query_callable(cypher, params)
    if inspect.isawaitable(result):
        return await result
    # Result already executed for sync path, just return it
    return result

# Lazy import to avoid mandatory dependency when not using Lite
try:
from redislite.falkordb_client import FalkorDB as LiteFalkorDB # type: ignore
except Exception as e: # broad to surface helpful message
Copy link
Contributor

Choose a reason for hiding this comment

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

Catching bare Exception is too broad. This will catch KeyboardInterrupt, SystemExit, and other exceptions that should propagate. Use ImportError specifically since that's what you're trying to catch.

) from e

db_path = lite_db_path or '/tmp/falkordb.db'
lite_client = LiteFalkorDB(db_path)
Copy link
Contributor

Choose a reason for hiding this comment

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

Hardcoding /tmp/falkordb.db as the default is problematic:

  • /tmp may be cleared on reboot, losing data
  • No write permission guarantees in /tmp on all systems
  • No isolation between different processes/users

Consider using a more appropriate default like ~/.local/share/graphiti/falkordb.db or require the user to specify the path explicitly.

db_path = lite_db_path or '/tmp/falkordb.db'
lite_client = LiteFalkorDB(db_path)
self.client = _AsyncLiteClientAdapter(lite_client)
self._is_lite = True
Copy link
Contributor

Choose a reason for hiding this comment

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

The _is_lite instance variable is set but never used anywhere in the class. Either remove it or document why it's needed for future functionality.

from graphiti_core.driver.falkordb_driver import FalkorDriver as _FD

try:
_FD(lite=True, database='default_db')
Copy link
Contributor

Choose a reason for hiding this comment

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

This test only verifies that initialization doesn't raise an exception, but doesn't actually validate:

  • That the lite client adapter is used
  • That the adapter works correctly
  • That queries can be executed

The test should verify the actual behavior, not just that it doesn't crash. For example:

driver = _FD(lite=True, database='default_db')
assert isinstance(driver.client, _AsyncLiteClientAdapter)

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.

2 participants