- Updated CI workflows to track poetry.lock instead of requirements.txt - Removed check-requirements-sync.py step from python-tests.yml - Updated dependency_scanner.py default from requirements.txt to pyproject.toml - Replaced all print() with click.echo() in deploy_edge_node.py (CLI script) - Replaced print() with logger.warning() in zk_cache.py - Updated setup.py files to read dependencies from pyproject.toml via tomli - Removed
15 KiB
CLI Packaging Restructuring Plan
Objective
Restructure the AITBC CLI into a proper installable Python package to eliminate sys.path manipulation debt and improve maintainability.
Current State
Entry Points
/opt/aitbc/cli/aitbc_cli.py- Main entrypoint (symlinked from/opt/aitbc/aitbc-cli)/opt/aitbc/cli/click_cli.py- Legacy Click entrypoint/opt/aitbc/cli/unified_cli.py- Unified nested command hierarchy/opt/aitbc/cli/miner_cli.py- Miner-specific CLI/opt/aitbc/cli/variants/main_minimal.py- Minimal variant
Package Structure
cli/
├── __init__.py
├── aitbc_cli.py (main entrypoint)
├── click_cli.py (legacy)
├── unified_cli.py (unified)
├── miner_cli.py (miner-specific)
├── variants/
│ └── main_minimal.py
├── handlers/
│ └── wallet.py
├── utils/
│ ├── wallet_daemon_client.py
│ └── dual_mode_wallet_adapter.py
├── core/
│ └── imports.py
├── aitbc_cli/
│ ├── __init__.py
│ ├── commands/
│ │ ├── wallet.py
│ │ ├── blockchain.py
│ │ ├── network.py
│ │ ├── market.py
│ │ ├── ai.py
│ │ ├── mining.py
│ │ ├── system.py
│ │ ├── agent.py
│ │ ├── openclaw.py
│ │ ├── workflow.py
│ │ ├── resource.py
│ │ ├── simulate.py
│ │ ├── node.py
│ │ ├── exchange.py
│ │ └── agent_sdk.py
│ ├── config.py
│ └── utils/
│ ├── __init__.py
│ ├── output.py
│ ├── error.py
│ ├── success.py
│ └── warning.py
└── build/
└── lib/
└── aitbc_cli/
└── main.py (generated)
Issues
- Multiple entrypoints with overlapping functionality
- sys.path manipulation in every entrypoint
- No proper package installation (run directly from source)
- Generated code in
cli/build/directory - Legacy files (cli/aitbc_cli.legacy.py at 3,257 lines)
- Mixed import patterns (absolute vs relative)
Target State
Package Structure
cli/
├── pyproject.toml (new)
├── setup.py (optional, for compatibility)
├── src/
│ └── aitbc_cli/
│ ├── __init__.py
│ ├── main.py (single entrypoint)
│ ├── commands/
│ │ ├── __init__.py
│ │ ├── wallet.py
│ │ ├── blockchain.py
│ │ ├── network.py
│ │ ├── market.py
│ │ ├── ai.py
│ │ ├── mining.py
│ │ ├── system.py
│ │ ├── agent.py
│ │ ├── openclaw.py
│ │ ├── workflow.py
│ │ ├── resource.py
│ │ ├── simulate.py
│ │ ├── node.py
│ │ ├── exchange.py
│ │ └── agent_sdk.py
│ ├── config.py
│ └── utils/
│ ├── __init__.py
│ ├── output.py
│ ├── error.py
│ ├── success.py
│ └── warning.py
├── tests/ (move from root tests/cli/)
└── README.md
Entry Points
- Single console script:
aitbc-clipointing toaitbc_cli.main:cli - Backward compatibility symlinks for legacy commands
Installation
cd /opt/aitbc/cli
pip install -e .
Implementation Plan
Phase 1: Create Package Structure
-
Create pyproject.toml
[build-system] requires = ["setuptools>=61.0", "wheel"] build-backend = "setuptools.build_meta" [project] name = "aitbc-cli" version = "0.1.0" description = "AITBC Command Line Interface" authors = [{name = "AITBC Team"}] license = {text = "MIT"} requires-python = ">=3.11" dependencies = [ "click>=8.0", "rich>=13.0", "PyYAML", "requests", "cryptography", ] [project.scripts] aitbc-cli = "aitbc_cli.main:cli" [tool.setuptools] package-dir = {"" = "src"} [tool.setuptools.packages.find] where = ["src"] -
Restructure directories
- Create
cli/src/aitbc_cli/ - Move
cli/aitbc_cli/commands/tocli/src/aitbc_cli/commands/ - Move
cli/aitbc_cli/config.pytocli/src/aitbc_cli/config.py - Move
cli/aitbc_cli/utils/tocli/src/aitbc_cli/utils/ - Create
cli/src/aitbc_cli/main.pyas single entrypoint
- Create
-
Update imports
- Change all imports to use relative imports within package
- Remove sys.path manipulation from all modules
- Use
from ..config import get_configinstead of absolute imports
Phase 2: Consolidate Entry Points
-
Create unified main.py
# cli/src/aitbc_cli/main.py import click from .commands import ( wallet, blockchain, network, market, ai, mining, system, agent, openclaw, workflow, resource, simulate, node, exchange, agent_sdk ) @click.group() @click.version_option(version="0.1.0") def cli(): """AITBC Command Line Interface""" pass # Add command groups cli.add_command(wallet.wallet) cli.add_command(blockchain.blockchain) cli.add_command(network.network) cli.add_command(market.market) cli.add_command(ai.ai) cli.add_command(mining.mining) cli.add_command(system.system) cli.add_command(agent.agent) cli.add_command(openclaw.openclaw) cli.add_command(workflow.workflow) cli.add_command(resource.resource) cli.add_command(simulate.simulate) cli.add_command(node.node) cli.add_command(exchange.exchange) cli.add_command(agent_sdk.agent_sdk) if __name__ == "__main__": cli() -
Deprecate legacy entrypoints
- Keep
cli/click_cli.pybut add deprecation warning - Keep
cli/miner_cli.pybut add deprecation warning - Keep
cli/unified_cli.pyas reference during migration - Document deprecation in README
- Keep
-
Update symlinks
/opt/aitbc/aitbc-clishould point to installed entrypoint- Or keep as symlink to
cli/src/aitbc_cli/main.pyduring transition
Phase 3: Remove sys.path Manipulation
-
CLI modules
- Remove sys.path.insert from
cli/src/aitbc_cli/main.py - Remove sys.path.insert from all command modules
- Remove sys.path.insert from utils modules
- Use PYTHONPATH environment variable for cross-package imports if needed
- Remove sys.path.insert from
-
Special cases
cli/core/imports.py- Keep as helper for coordinator-api imports, but make it optionalcli/handlers/wallet.py- Refactor to use proper imports or deprecatecli/utils/wallet_daemon_client.py- Refactor to use proper imports
-
Cross-package imports
- For imports from
aitbcpackage, use PYTHONPATH in environment - For imports from
apps/*, use PYTHONPATH in environment - Document required PYTHONPATH in README
- For imports from
Phase 4: Update Systemd Services
-
Update wrapper scripts
- Keep sys.path in wrappers for constants import (acceptable)
- Ensure PYTHONPATH includes installed CLI package
- Update exec commands to use installed
aitbc-cli
-
Update service files
- Change
ExecStart=/opt/aitbc/aitbc-clito use installed path - Or keep using
/opt/aitbc/aitbc-clisymlink for compatibility
- Change
Phase 5: Update Tests
-
Move CLI tests
- Move
tests/cli/tocli/tests/ - Update test imports to use package imports
- Remove sys.path manipulation from test conftest
- Move
-
Update test execution
- Run tests with
pytest cli/tests/ - Use PYTHONPATH for test isolation if needed
- Run tests with
Phase 6: Documentation
-
Update README
- Document installation process
- Document required PYTHONPATH
- Document backward compatibility
-
Update docs
- Update CLI usage documentation
- Document deprecated entrypoints
- Update development setup instructions
-
Update systemd docs
- Document wrapper script pattern
- Document acceptable sys.path usage
Migration Strategy
Step 1: Create New Package (Non-Breaking)
- Create
cli/src/aitbc_cli/structure alongside existing - Implement new entrypoint in parallel
- Test new package without affecting existing CLI
Step 2: Test New Package
- Install new package in venv:
pip install -e cli/ - Test
aitbc-clicommand - Verify all commands work
- Run test suite
Step 3: Update Symlinks
- Update
/opt/aitbc/aitbc-clito point to new entrypoint - Test with existing systemd services
- Rollback if issues
Step 4: Deprecate Old Files
- Add deprecation warnings to legacy entrypoints
- Document deprecation timeline
- Keep for 1-2 release cycles
Step 5: Remove Legacy Files
- Remove
cli/click_cli.py - Remove
cli/miner_cli.py - Remove
cli/unified_cli.py - Remove
cli/aitbc_cli.legacy.py - Remove
cli/build/directory - Remove old
cli/aitbc_cli/directory
Rollback Plan
If issues arise during migration:
-
Immediate rollback
- Restore
/opt/aitbc/aitbc-clisymlink to old entrypoint - Uninstall new package:
pip uninstall aitbc-cli - Old CLI continues to work
- Restore
-
Partial rollback
- Keep new package installed
- Use old entrypoint for critical services
- Fix issues in new package
-
Documentation rollback
- Document rollback procedure
- Keep legacy files until stable
Testing Checklist
- New package installs correctly
aitbc-clicommand works- All command groups work (wallet, blockchain, network, etc.)
- All subcommands work
- Backward compatibility maintained
- Systemd services work with new CLI
- Test suite passes
- No sys.path manipulation in new package
- Cross-package imports work with PYTHONPATH
- Documentation updated
Blocking Issue Discovered
During implementation, a critical architectural dependency was discovered:
The CLI has deep dependencies on the broader AITBC monorepo:
- aitbc package - CLI imports from
aitbc(get_logger, AITBCHTTPClient, NetworkError, KEYSTORE_DIR, etc.) - models.chain - Core modules import from
models.chain(ChainInfo, ChainType, ChainStatus, ConsensusAlgorithm) - Shared modules - CLI depends on shared modules across the monorepo
This means the CLI cannot be packaged as a standalone package without:
- Option A: Include all dependencies in CLI package (massive duplication, bad practice)
- Option B: Make CLI depend on aitbc package being installed (requires aitbc to be packaged first)
- Option C: Refactor CLI to remove these dependencies (major architectural change, high risk)
Current state: The CLI was designed to run from the monorepo with sys.path manipulation. It's not designed as a standalone package.
Revised Approach
Given this blocking issue, the CLI packaging approach needs reconsideration:
Option 1: Package aitbc first
- Package the
aitbcmodule as a standalone library - Then package CLI with aitbc as a dependency
- Requires significant refactoring of aitbc package structure
Option 2: Accept sys.path as necessary
- Keep CLI running from monorepo
- Accept sys.path manipulation as acceptable for monorepo CLI
- Focus on reducing but not eliminating sys.path usage
- Document as architectural decision
Option 3: Minimal CLI package
- Create a minimal CLI package that only contains command definitions
- Use PYTHONPATH environment variable for all imports
- CLI becomes a thin wrapper over monorepo code
- Still requires environment setup
Option 4: Abandon CLI packaging
- Accept that CLI is monorepo-specific
- Focus on other cleanup tasks
- Document CLI as requiring monorepo context
Estimated Effort (Original Plan)
- Phase 1: 4-6 hours (package structure, pyproject.toml) - COMPLETED
- Phase 2: 3-4 hours (consolidate entry points) - BLOCKED
- Phase 3: 4-6 hours (remove sys.path, fix imports) - BLOCKED by dependencies
- Phase 4: 2-3 hours (update systemd services)
- Phase 5: 2-3 hours (update tests)
- Phase 6: 2-3 hours (documentation)
- Testing: 4-6 hours
Status: BLOCKED on architectural dependency issue
Implementation Attempt Results
Attempted Option 1 (Package aitbc first, then CLI) but encountered additional blocking issues:
Issues Discovered During Implementation
-
CLI internal structure dependencies
- CLI commands import from
..configexpecting aConfigclass that doesn't exist - CLI has its own
coremodule with deployment, analytics, marketplace, etc. - These CLI-specific modules are not part of the aitbc package
- Moving them to aitbc would create circular dependencies
- CLI commands import from
-
CLI-specific modules
cli/core/deployment.py- Production deployment logiccli/core/analytics.py- Chain analyticscli/core/marketplace.py- Marketplace functionalitycli/core/chain_manager.py- Multi-chain management- These are CLI-specific, not shared library code
-
Import resolution complexity
- CLI uses relative imports (
..config,..core) - CLI expects specific internal structure
- Package structure breaks these assumptions
- Would require extensive refactoring of CLI internals
- CLI uses relative imports (
Current State
- aitbc package: Successfully installed with models.chain moved to aitbc.models
- CLI package: Depends on aitbc>=0.6.0
- Blocking issue: CLI internal structure incompatible with package layout
- Import errors: Multiple CLI commands fail due to missing internal modules
Recommendation
Switch to Option 2: Accept sys.path as necessary
The CLI was designed as a monorepo-specific tool with:
- Internal core modules
- Relative import structure
- Tight coupling to monorepo layout
Packaging it as a standalone package requires:
- Refactoring all internal imports
- Moving CLI-specific code to aitbc (inappropriate)
- Breaking backward compatibility
- High risk of introducing bugs
Accept sys.path manipulation as acceptable for monorepo CLI tools.
Dependencies
- None (can be done independently)
- Should be done before other CLI refactoring
- Should be done before removing legacy files
Risks
- Breaking changes - Mitigated by parallel implementation and rollback plan
- Systemd service failures - Mitigated by testing and rollback plan
- Import resolution issues - Mitigated by PYTHONPATH documentation
- Backward compatibility - Mitigated by keeping legacy files temporarily
Success Criteria
- CLI is installable as Python package
- No sys.path manipulation in CLI package
- Single entrypoint (
aitbc-cli) - All commands work correctly
- Systemd services work correctly
- Test suite passes
- Documentation updated
- Legacy files removed or deprecated