celltype-cli 0.1.2__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- celltype_cli-0.2.0/.git +1 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.gitignore +1 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/PKG-INFO +20 -4
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/README.md +6 -1
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/install.sh +11 -8
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/pyproject.toml +16 -3
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/__init__.py +1 -1
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/agent/config.py +19 -2
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/agent/doctor.py +59 -5
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/agent/mcp_server.py +75 -1
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/agent/runner.py +24 -1
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/agent/sandbox.py +5 -2
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/agent/session.py +1 -1
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/agent/system_prompt.py +17 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/cli.py +674 -13
- celltype_cli-0.2.0/src/ct/cloud/__init__.py +3 -0
- celltype_cli-0.2.0/src/ct/cloud/auth.py +197 -0
- celltype_cli-0.2.0/src/ct/cloud/client.py +226 -0
- celltype_cli-0.2.0/src/ct/cloud/image_builder.py +152 -0
- celltype_cli-0.2.0/src/ct/cloud/local_runner.py +276 -0
- celltype_cli-0.2.0/src/ct/cloud/manifest.py +178 -0
- celltype_cli-0.2.0/src/ct/cloud/router.py +332 -0
- celltype_cli-0.2.0/src/ct/cloud/structure_inputs.py +49 -0
- celltype_cli-0.2.0/src/ct/cloud/tool_entrypoint.py +56 -0
- celltype_cli-0.2.0/src/ct/cloud/weight_downloader.py +217 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/models/llm.py +7 -4
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/__init__.py +57 -1
- celltype_cli-0.2.0/src/ct/tools/_container_tools.py +97 -0
- celltype_cli-0.2.0/src/ct/tools/alphafold2/Dockerfile +47 -0
- celltype_cli-0.2.0/src/ct/tools/alphafold2/implementation.py +200 -0
- celltype_cli-0.2.0/src/ct/tools/alphafold2/patch_jackhmmer.py +11 -0
- celltype_cli-0.2.0/src/ct/tools/alphafold2/tool.yaml +17 -0
- celltype_cli-0.2.0/src/ct/tools/alphafold2-multimer/Dockerfile +43 -0
- celltype_cli-0.2.0/src/ct/tools/alphafold2-multimer/implementation.py +184 -0
- celltype_cli-0.2.0/src/ct/tools/alphafold2-multimer/tool.yaml +17 -0
- celltype_cli-0.2.0/src/ct/tools/boltz2/Dockerfile +20 -0
- celltype_cli-0.2.0/src/ct/tools/boltz2/implementation.py +104 -0
- celltype_cli-0.2.0/src/ct/tools/boltz2/tool.yaml +19 -0
- celltype_cli-0.2.0/src/ct/tools/diffdock/Dockerfile +26 -0
- celltype_cli-0.2.0/src/ct/tools/diffdock/implementation.py +225 -0
- celltype_cli-0.2.0/src/ct/tools/diffdock/tool.yaml +20 -0
- celltype_cli-0.2.0/src/ct/tools/esm2/Dockerfile +17 -0
- celltype_cli-0.2.0/src/ct/tools/esm2/implementation.py +55 -0
- celltype_cli-0.2.0/src/ct/tools/esm2/tool.yaml +18 -0
- celltype_cli-0.2.0/src/ct/tools/esmfold/Dockerfile +18 -0
- celltype_cli-0.2.0/src/ct/tools/esmfold/implementation.py +98 -0
- celltype_cli-0.2.0/src/ct/tools/esmfold/tool.yaml +18 -0
- celltype_cli-0.2.0/src/ct/tools/evo2/Dockerfile +18 -0
- celltype_cli-0.2.0/src/ct/tools/evo2/implementation.py +63 -0
- celltype_cli-0.2.0/src/ct/tools/evo2/tool.yaml +19 -0
- celltype_cli-0.2.0/src/ct/tools/evo2-protein-design/Dockerfile +18 -0
- celltype_cli-0.2.0/src/ct/tools/evo2-protein-design/implementation.py +64 -0
- celltype_cli-0.2.0/src/ct/tools/evo2-protein-design/tool.yaml +19 -0
- celltype_cli-0.2.0/src/ct/tools/genmol/Dockerfile +13 -0
- celltype_cli-0.2.0/src/ct/tools/genmol/implementation.py +101 -0
- celltype_cli-0.2.0/src/ct/tools/genmol/tool.yaml +20 -0
- celltype_cli-0.2.0/src/ct/tools/molmim/Dockerfile +13 -0
- celltype_cli-0.2.0/src/ct/tools/molmim/implementation.py +97 -0
- celltype_cli-0.2.0/src/ct/tools/molmim/tool.yaml +19 -0
- celltype_cli-0.2.0/src/ct/tools/msa-search/Dockerfile +17 -0
- celltype_cli-0.2.0/src/ct/tools/msa-search/implementation.py +138 -0
- celltype_cli-0.2.0/src/ct/tools/msa-search/tool.yaml +18 -0
- celltype_cli-0.2.0/src/ct/tools/openfold2/Dockerfile +47 -0
- celltype_cli-0.2.0/src/ct/tools/openfold2/implementation.py +200 -0
- celltype_cli-0.2.0/src/ct/tools/openfold2/tool.yaml +17 -0
- celltype_cli-0.2.0/src/ct/tools/openfold3/Dockerfile +49 -0
- celltype_cli-0.2.0/src/ct/tools/openfold3/implementation.py +222 -0
- celltype_cli-0.2.0/src/ct/tools/openfold3/tool.yaml +19 -0
- celltype_cli-0.2.0/src/ct/tools/proteinmpnn/Dockerfile +24 -0
- celltype_cli-0.2.0/src/ct/tools/proteinmpnn/implementation.py +97 -0
- celltype_cli-0.2.0/src/ct/tools/proteinmpnn/tool.yaml +18 -0
- celltype_cli-0.2.0/src/ct/tools/rfdiffusion/Dockerfile +33 -0
- celltype_cli-0.2.0/src/ct/tools/rfdiffusion/implementation.py +151 -0
- celltype_cli-0.2.0/src/ct/tools/rfdiffusion/tool.yaml +19 -0
- celltype_cli-0.2.0/src/ct/tools/tool_entrypoint.py +27 -0
- celltype_cli-0.2.0/src/ct/update_checker.py +111 -0
- celltype_cli-0.2.0/tests/e2e/__init__.py +0 -0
- celltype_cli-0.2.0/tests/e2e/kras_g12c.fasta +6 -0
- celltype_cli-0.2.0/tests/e2e/sotorasib.smi +1 -0
- celltype_cli-0.2.0/tests/e2e/test_e2e_cloud.py +241 -0
- celltype_cli-0.2.0/tests/test_billing.py +133 -0
- celltype_cli-0.2.0/tests/test_cloud_auth.py +151 -0
- celltype_cli-0.2.0/tests/test_cloud_client.py +170 -0
- celltype_cli-0.2.0/tests/test_compute_router.py +332 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_config.py +21 -1
- celltype_cli-0.2.0/tests/test_e2e_local_gpu.py +260 -0
- celltype_cli-0.2.0/tests/test_extensibility.py +182 -0
- celltype_cli-0.2.0/tests/test_fallback_routing.py +172 -0
- celltype_cli-0.2.0/tests/test_gpu_registry.py +213 -0
- celltype_cli-0.2.0/tests/test_image_builder.py +132 -0
- celltype_cli-0.2.0/tests/test_local_runner.py +235 -0
- celltype_cli-0.2.0/tests/test_manifest.py +224 -0
- celltype_cli-0.2.0/tests/test_modal_generation.py +143 -0
- celltype_cli-0.2.0/tests/test_observability.py +118 -0
- celltype_cli-0.2.0/tests/test_security_mitigations.py +220 -0
- celltype_cli-0.2.0/tests/test_setup_gpu.py +114 -0
- celltype_cli-0.2.0/tests/test_stripe_integration.py +324 -0
- celltype_cli-0.2.0/tests/test_weight_management.py +138 -0
- celltype_cli-0.1.2/.claude/settings.local.json +0 -96
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.claude/commands/opsx/apply.md +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.claude/commands/opsx/archive.md +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.claude/commands/opsx/bulk-archive.md +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.claude/commands/opsx/continue.md +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.claude/commands/opsx/explore.md +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.claude/commands/opsx/ff.md +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.claude/commands/opsx/new.md +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.claude/commands/opsx/onboard.md +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.claude/commands/opsx/sync.md +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.claude/commands/opsx/verify.md +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.claude/skills/openspec-apply-change/SKILL.md +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.claude/skills/openspec-archive-change/SKILL.md +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.claude/skills/openspec-bulk-archive-change/SKILL.md +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.claude/skills/openspec-continue-change/SKILL.md +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.claude/skills/openspec-explore/SKILL.md +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.claude/skills/openspec-ff-change/SKILL.md +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.claude/skills/openspec-new-change/SKILL.md +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.claude/skills/openspec-onboard/SKILL.md +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.claude/skills/openspec-sync-specs/SKILL.md +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.claude/skills/openspec-verify-change/SKILL.md +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.dockerignore +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/.github/workflows/ci.yml +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/CLAUDE.md +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/Dockerfile +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/Dockerfile.api +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/LICENSE +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/assets/bixbench_benchmark.png +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/assets/ct2.gif +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/docker-compose.yml +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/openspec/config.yaml +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/scripts/prepare_datasets.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/scripts/prepare_l1000.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/settings.json +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/agent/__init__.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/agent/case_studies.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/agent/knowledge.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/agent/loop.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/agent/orchestrator.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/agent/trace_store.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/agent/trajectory.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/agent/types.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/agent/workflows.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/api/__init__.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/api/app.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/api/config.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/api/engine.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/data/__init__.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/data/compute_providers.json +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/data/cro_database.json +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/data/downloader.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/data/loaders.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/kb/__init__.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/kb/benchmarks.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/kb/governance.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/kb/ingest.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/kb/reasoning.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/kb/schema_monitor.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/kb/substrate.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/models/__init__.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/_compound_resolver.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/biomarker.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/cellxgene.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/chemistry.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/claude.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/clinical.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/clue.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/code.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/combination.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/compute.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/cro.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/data_api.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/design.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/dna.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/experiment.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/expression.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/files.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/genomics.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/http_client.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/imaging.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/intel.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/literature.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/network.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/notification.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/omics.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/ops.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/parity.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/pk.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/protein.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/regulatory.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/remote_data.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/report.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/repurposing.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/safety.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/shell.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/singlecell.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/statistics.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/structure.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/target.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/translational.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/tools/viability.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/ui/__init__.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/ui/markdown.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/ui/status.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/ui/suggestions.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/ui/terminal.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/src/ct/ui/traces.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/__init__.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/conftest.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/fixtures/plan_snapshot.txt +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/fixtures/trace_snapshot.txt +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_api_smoke.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_cellxgene.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_chemistry_new.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_claude.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_cli.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_clue.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_code.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_compute.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_cro.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_data_api.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_data_api_service.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_design.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_dna.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_doctor.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_downloader.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_engine.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_experiment.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_files.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_future_backends_todo.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_html_report.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_http_client.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_imaging.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_kb_benchmarks.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_kb_governance.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_kb_ingest.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_kb_reasoning.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_kb_schema_monitor.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_kb_substrate.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_knowledge.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_llm.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_mention_completer.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_network.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_notebook.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_notification.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_omics.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_ops.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_parity_tools.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_parkinsons_toolchain_smoke.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_patent_search.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_plan_display.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_protein.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_registry.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_remote_data.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_repurposing.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_sandbox.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_sdk_streaming.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_session.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_shell.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_singlecell.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_status.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_structure.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_target.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_terminal.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_terminal_integration.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_tools.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_trace_store.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_traces.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_trajectory.py +0 -0
- {celltype_cli-0.1.2 → celltype_cli-0.2.0}/tests/test_workflows.py +0 -0
celltype_cli-0.2.0/.git
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
gitdir: ../.git/modules/cli
|
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: celltype-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: CellType CLI — An autonomous agent for drug discovery research
|
|
5
5
|
Author: CellType Inc.
|
|
6
|
-
License
|
|
6
|
+
License: MIT
|
|
7
7
|
License-File: LICENSE
|
|
8
8
|
Requires-Python: >=3.10
|
|
9
|
-
Requires-Dist: anthropic>=0.
|
|
9
|
+
Requires-Dist: anthropic>=0.74.0
|
|
10
10
|
Requires-Dist: claude-agent-sdk>=0.1
|
|
11
11
|
Requires-Dist: httpx>=0.27
|
|
12
12
|
Requires-Dist: markdown>=3.5
|
|
13
|
+
Requires-Dist: matplotlib>=3.7
|
|
13
14
|
Requires-Dist: nbformat>=5.7
|
|
14
15
|
Requires-Dist: numpy>=1.24
|
|
15
16
|
Requires-Dist: openai>=1.0
|
|
16
17
|
Requires-Dist: pandas>=2.0
|
|
17
18
|
Requires-Dist: prompt-toolkit>=3.0
|
|
18
19
|
Requires-Dist: python-dotenv>=1.0
|
|
20
|
+
Requires-Dist: pyyaml>=6.0
|
|
19
21
|
Requires-Dist: rich>=13.0
|
|
20
22
|
Requires-Dist: scipy>=1.10
|
|
21
23
|
Requires-Dist: typer>=0.12
|
|
@@ -32,6 +34,12 @@ Requires-Dist: seaborn>=0.13; extra == 'all'
|
|
|
32
34
|
Requires-Dist: tiledbsoma>=1.0; extra == 'all'
|
|
33
35
|
Requires-Dist: torch>=2.0; extra == 'all'
|
|
34
36
|
Requires-Dist: transformers>=4.40; extra == 'all'
|
|
37
|
+
Provides-Extra: alpha
|
|
38
|
+
Requires-Dist: duckdb>=1.0; extra == 'alpha'
|
|
39
|
+
Requires-Dist: fastapi>=0.100; extra == 'alpha'
|
|
40
|
+
Requires-Dist: jinja2>=3.1; extra == 'alpha'
|
|
41
|
+
Requires-Dist: pydantic>=2.0; extra == 'alpha'
|
|
42
|
+
Requires-Dist: uvicorn[standard]>=0.20; extra == 'alpha'
|
|
35
43
|
Provides-Extra: analysis
|
|
36
44
|
Requires-Dist: scikit-learn>=1.3; extra == 'analysis'
|
|
37
45
|
Requires-Dist: seaborn>=0.13; extra == 'analysis'
|
|
@@ -43,6 +51,9 @@ Provides-Extra: biology
|
|
|
43
51
|
Requires-Dist: biopython>=1.81; extra == 'biology'
|
|
44
52
|
Provides-Extra: chemistry
|
|
45
53
|
Requires-Dist: rdkit>=2023.03; extra == 'chemistry'
|
|
54
|
+
Provides-Extra: cloud
|
|
55
|
+
Requires-Dist: modal>=1.0; extra == 'cloud'
|
|
56
|
+
Requires-Dist: pyjwt>=2.0; extra == 'cloud'
|
|
46
57
|
Provides-Extra: dev
|
|
47
58
|
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
|
|
48
59
|
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
@@ -63,6 +74,11 @@ Description-Content-Type: text/markdown
|
|
|
63
74
|
|
|
64
75
|
# celltype-cli
|
|
65
76
|
|
|
77
|
+
> **v0.2.0 is out** — Offload GPU-accelerated tools to CellType Cloud with no additional setup. ESMFold, Boltz-2, RFdiffusion, ProteinMPNN, and more. Update now:
|
|
78
|
+
> ```bash
|
|
79
|
+
> pip install --upgrade celltype-cli
|
|
80
|
+
> ```
|
|
81
|
+
|
|
66
82
|
An autonomous agent for drug discovery research. Like Claude Code, but for biology.
|
|
67
83
|
|
|
68
84
|
Ask questions in natural language. celltype-cli plans the analysis, selects the right tools, executes them, validates results, and returns data-backed conclusions.
|
|
@@ -71,7 +87,7 @@ Ask questions in natural language. celltype-cli plans the analysis, selects the
|
|
|
71
87
|
|
|
72
88
|
## Benchmark
|
|
73
89
|
|
|
74
|
-
CellType CLI achieves **90% accuracy** on [BixBench-Verified-50](https://
|
|
90
|
+
CellType CLI achieves **90% accuracy** on [BixBench-Verified-50](https://huggingface.co/datasets/phylobio/BixBench-Verified-50), outperforming all existing agentic systems for computational biology.
|
|
75
91
|
|
|
76
92
|

|
|
77
93
|
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# celltype-cli
|
|
2
2
|
|
|
3
|
+
> **v0.2.0 is out** — Offload GPU-accelerated tools to CellType Cloud with no additional setup. ESMFold, Boltz-2, RFdiffusion, ProteinMPNN, and more. Update now:
|
|
4
|
+
> ```bash
|
|
5
|
+
> pip install --upgrade celltype-cli
|
|
6
|
+
> ```
|
|
7
|
+
|
|
3
8
|
An autonomous agent for drug discovery research. Like Claude Code, but for biology.
|
|
4
9
|
|
|
5
10
|
Ask questions in natural language. celltype-cli plans the analysis, selects the right tools, executes them, validates results, and returns data-backed conclusions.
|
|
@@ -8,7 +13,7 @@ Ask questions in natural language. celltype-cli plans the analysis, selects the
|
|
|
8
13
|
|
|
9
14
|
## Benchmark
|
|
10
15
|
|
|
11
|
-
CellType CLI achieves **90% accuracy** on [BixBench-Verified-50](https://
|
|
16
|
+
CellType CLI achieves **90% accuracy** on [BixBench-Verified-50](https://huggingface.co/datasets/phylobio/BixBench-Verified-50), outperforming all existing agentic systems for computational biology.
|
|
12
17
|
|
|
13
18
|

|
|
14
19
|
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
set -euo pipefail
|
|
5
5
|
|
|
6
6
|
PACKAGE="celltype-cli"
|
|
7
|
+
REPO_URL="git+https://github.com/celltype/cli.git"
|
|
7
8
|
MIN_PYTHON="3.10"
|
|
8
9
|
|
|
9
10
|
# ── Helpers ────────────────────────────────────────────────────
|
|
@@ -45,17 +46,19 @@ esac
|
|
|
45
46
|
|
|
46
47
|
# ── Install package ────────────────────────────────────────────
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
ok "Installed with pipx"
|
|
52
|
-
elif command -v uv >/dev/null 2>&1; then
|
|
49
|
+
INSTALL_SPEC="${PACKAGE} @ ${REPO_URL}"
|
|
50
|
+
|
|
51
|
+
if command -v uv >/dev/null 2>&1; then
|
|
53
52
|
info "Installing ${PACKAGE} via uv..."
|
|
54
|
-
uv tool install "$
|
|
53
|
+
uv tool install "$INSTALL_SPEC" || uv tool install --force "$INSTALL_SPEC"
|
|
55
54
|
ok "Installed with uv"
|
|
55
|
+
elif command -v pipx >/dev/null 2>&1; then
|
|
56
|
+
info "Installing ${PACKAGE} via pipx..."
|
|
57
|
+
pipx install "$REPO_URL" || pipx install --force "$REPO_URL"
|
|
58
|
+
ok "Installed with pipx"
|
|
56
59
|
else
|
|
57
|
-
warn "pipx
|
|
58
|
-
"$PYTHON" -m pip install --user --upgrade "$
|
|
60
|
+
warn "uv/pipx not found — falling back to pip install --user"
|
|
61
|
+
"$PYTHON" -m pip install --user --upgrade "$INSTALL_SPEC"
|
|
59
62
|
ok "Installed with pip"
|
|
60
63
|
|
|
61
64
|
# Check if user bin is on PATH
|
|
@@ -4,10 +4,10 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "celltype-cli"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.2.0"
|
|
8
8
|
description = "CellType CLI — An autonomous agent for drug discovery research"
|
|
9
9
|
readme = "README.md"
|
|
10
|
-
license = "MIT"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
11
|
requires-python = ">=3.10"
|
|
12
12
|
authors = [
|
|
13
13
|
{ name = "CellType Inc." },
|
|
@@ -17,16 +17,18 @@ dependencies = [
|
|
|
17
17
|
"typer>=0.12",
|
|
18
18
|
"rich>=13.0",
|
|
19
19
|
"prompt-toolkit>=3.0",
|
|
20
|
-
"anthropic>=0.
|
|
20
|
+
"anthropic>=0.74.0",
|
|
21
21
|
"openai>=1.0",
|
|
22
22
|
"claude-agent-sdk>=0.1",
|
|
23
23
|
"httpx>=0.27",
|
|
24
24
|
"pandas>=2.0",
|
|
25
25
|
"numpy>=1.24",
|
|
26
26
|
"scipy>=1.10",
|
|
27
|
+
"matplotlib>=3.7",
|
|
27
28
|
"python-dotenv>=1.0",
|
|
28
29
|
"markdown>=3.5",
|
|
29
30
|
"nbformat>=5.7",
|
|
31
|
+
"pyyaml>=6.0",
|
|
30
32
|
]
|
|
31
33
|
|
|
32
34
|
[project.optional-dependencies]
|
|
@@ -60,6 +62,17 @@ api = [
|
|
|
60
62
|
"uvicorn[standard]>=0.20",
|
|
61
63
|
"duckdb>=1.0",
|
|
62
64
|
]
|
|
65
|
+
alpha = [
|
|
66
|
+
"fastapi>=0.100",
|
|
67
|
+
"uvicorn[standard]>=0.20",
|
|
68
|
+
"duckdb>=1.0",
|
|
69
|
+
"jinja2>=3.1",
|
|
70
|
+
"pydantic>=2.0",
|
|
71
|
+
]
|
|
72
|
+
cloud = [
|
|
73
|
+
"modal>=1.0",
|
|
74
|
+
"pyjwt>=2.0",
|
|
75
|
+
]
|
|
63
76
|
all = [
|
|
64
77
|
"rdkit>=2023.03",
|
|
65
78
|
"biopython>=1.81",
|
|
@@ -29,7 +29,7 @@ logger = logging.getLogger("ct.config")
|
|
|
29
29
|
|
|
30
30
|
DEFAULTS = {
|
|
31
31
|
"llm.provider": "anthropic",
|
|
32
|
-
"llm.model": "claude-
|
|
32
|
+
"llm.model": "claude-opus-4-6",
|
|
33
33
|
"llm.api_key": None,
|
|
34
34
|
"llm.openai_api_key": None,
|
|
35
35
|
"llm.temperature": 0.1,
|
|
@@ -67,6 +67,14 @@ DEFAULTS = {
|
|
|
67
67
|
"compute.lambda_api_key": None,
|
|
68
68
|
"compute.runpod_api_key": None,
|
|
69
69
|
"compute.default_provider": "lambda",
|
|
70
|
+
"compute.mode": "cloud",
|
|
71
|
+
|
|
72
|
+
"cloud.endpoint": "https://api.celltype.com",
|
|
73
|
+
"cloud.dashboard_url": "https://cloud.celltype.com",
|
|
74
|
+
|
|
75
|
+
"gpu.name": None,
|
|
76
|
+
"gpu.vram_mb": None,
|
|
77
|
+
"gpu.setup_completed": False,
|
|
70
78
|
|
|
71
79
|
"sandbox.timeout": 30,
|
|
72
80
|
"sandbox.output_dir": str(Path.cwd() / "outputs"),
|
|
@@ -456,6 +464,13 @@ class Config:
|
|
|
456
464
|
if self.llm_api_key(provider):
|
|
457
465
|
return None
|
|
458
466
|
|
|
467
|
+
# Azure AI Foundry: Foundry-specific env vars are valid Anthropic auth
|
|
468
|
+
if provider == "anthropic" and (
|
|
469
|
+
os.environ.get("ANTHROPIC_FOUNDRY_API_KEY")
|
|
470
|
+
or os.environ.get("ANTHROPIC_FOUNDRY_RESOURCE")
|
|
471
|
+
):
|
|
472
|
+
return None
|
|
473
|
+
|
|
459
474
|
if provider == "openai":
|
|
460
475
|
return (
|
|
461
476
|
"OpenAI API key not configured. Set OPENAI_API_KEY or run:\n"
|
|
@@ -464,7 +479,9 @@ class Config:
|
|
|
464
479
|
|
|
465
480
|
return (
|
|
466
481
|
"Anthropic API key not configured. Set ANTHROPIC_API_KEY or run:\n"
|
|
467
|
-
" ct config set llm.api_key <key
|
|
482
|
+
" ct config set llm.api_key <key>\n"
|
|
483
|
+
"For Azure AI Foundry: set ANTHROPIC_FOUNDRY_API_KEY and "
|
|
484
|
+
"ANTHROPIC_FOUNDRY_RESOURCE"
|
|
468
485
|
)
|
|
469
486
|
|
|
470
487
|
def keys_table(self) -> Table:
|
|
@@ -6,6 +6,7 @@ Used by `ct doctor` and interactive `/doctor` to surface actionable setup issues
|
|
|
6
6
|
|
|
7
7
|
from dataclasses import dataclass
|
|
8
8
|
import logging
|
|
9
|
+
import os
|
|
9
10
|
from pathlib import Path
|
|
10
11
|
|
|
11
12
|
from rich.table import Table
|
|
@@ -67,12 +68,12 @@ def run_checks(config: Config | None = None, session=None) -> list[DoctorCheck]:
|
|
|
67
68
|
if llm_issue:
|
|
68
69
|
checks.append(DoctorCheck(name="llm", status="error", detail=llm_issue))
|
|
69
70
|
else:
|
|
71
|
+
if os.environ.get("ANTHROPIC_FOUNDRY_API_KEY") or os.environ.get("ANTHROPIC_FOUNDRY_RESOURCE"):
|
|
72
|
+
detail = f"provider=anthropic (Azure Foundry), model={model}"
|
|
73
|
+
else:
|
|
74
|
+
detail = f"provider={provider}, model={model}"
|
|
70
75
|
checks.append(
|
|
71
|
-
DoctorCheck(
|
|
72
|
-
name="llm",
|
|
73
|
-
status="ok",
|
|
74
|
-
detail=f"provider={provider}, model={model}",
|
|
75
|
-
)
|
|
76
|
+
DoctorCheck(name="llm", status="ok", detail=detail)
|
|
76
77
|
)
|
|
77
78
|
|
|
78
79
|
# 3) Output directory availability
|
|
@@ -339,6 +340,59 @@ def run_checks(config: Config | None = None, session=None) -> list[DoctorCheck]:
|
|
|
339
340
|
)
|
|
340
341
|
)
|
|
341
342
|
|
|
343
|
+
# GPU compute readiness
|
|
344
|
+
compute_mode = str(cfg.get("compute.mode", "cloud")).lower()
|
|
345
|
+
if compute_mode == "cloud":
|
|
346
|
+
try:
|
|
347
|
+
from ct.cloud.auth import is_logged_in
|
|
348
|
+
if is_logged_in():
|
|
349
|
+
checks.append(DoctorCheck(
|
|
350
|
+
name="gpu_compute",
|
|
351
|
+
status="ok",
|
|
352
|
+
detail="compute.mode=cloud, logged in to CellType Cloud",
|
|
353
|
+
))
|
|
354
|
+
else:
|
|
355
|
+
checks.append(DoctorCheck(
|
|
356
|
+
name="gpu_compute",
|
|
357
|
+
status="warn",
|
|
358
|
+
detail="compute.mode=cloud but not logged in. Run `ct login`.",
|
|
359
|
+
))
|
|
360
|
+
except Exception:
|
|
361
|
+
checks.append(DoctorCheck(
|
|
362
|
+
name="gpu_compute",
|
|
363
|
+
status="warn",
|
|
364
|
+
detail="compute.mode=cloud, could not check login status",
|
|
365
|
+
))
|
|
366
|
+
elif compute_mode == "local":
|
|
367
|
+
try:
|
|
368
|
+
from ct.cloud.router import _detect_local_gpu_info
|
|
369
|
+
gpus = _detect_local_gpu_info()
|
|
370
|
+
if gpus:
|
|
371
|
+
best = max(gpus, key=lambda g: g.vram_mb)
|
|
372
|
+
checks.append(DoctorCheck(
|
|
373
|
+
name="gpu_compute",
|
|
374
|
+
status="ok",
|
|
375
|
+
detail=f"compute.mode=local, GPU: {best.name} ({best.vram_gb}GB)",
|
|
376
|
+
))
|
|
377
|
+
else:
|
|
378
|
+
checks.append(DoctorCheck(
|
|
379
|
+
name="gpu_compute",
|
|
380
|
+
status="error",
|
|
381
|
+
detail="compute.mode=local but no GPU detected. Run `ct setup-gpu`.",
|
|
382
|
+
))
|
|
383
|
+
except Exception:
|
|
384
|
+
checks.append(DoctorCheck(
|
|
385
|
+
name="gpu_compute",
|
|
386
|
+
status="warn",
|
|
387
|
+
detail="compute.mode=local, could not detect GPU",
|
|
388
|
+
))
|
|
389
|
+
else:
|
|
390
|
+
checks.append(DoctorCheck(
|
|
391
|
+
name="gpu_compute",
|
|
392
|
+
status="ok",
|
|
393
|
+
detail="compute.mode=auto (will detect at runtime)",
|
|
394
|
+
))
|
|
395
|
+
|
|
342
396
|
return checks
|
|
343
397
|
|
|
344
398
|
|
|
@@ -132,7 +132,21 @@ def _make_tool_handler(tool_obj, session):
|
|
|
132
132
|
call_args[key] = val.lower() == "true"
|
|
133
133
|
|
|
134
134
|
try:
|
|
135
|
-
|
|
135
|
+
# Route GPU tools through compute router
|
|
136
|
+
if getattr(tool_obj, "requires_gpu", False):
|
|
137
|
+
from ct.cloud.router import ComputeRouter
|
|
138
|
+
router = ComputeRouter(config=getattr(session, "config", None))
|
|
139
|
+
result = await asyncio.to_thread(router.route, tool_obj, **call_args)
|
|
140
|
+
|
|
141
|
+
# Handle "needs_user_prompt" — the router couldn't run locally
|
|
142
|
+
# and needs the user to decide about cloud fallback.
|
|
143
|
+
# We prompt here on the main thread where input() works.
|
|
144
|
+
if isinstance(result, dict) and result.get("needs_user_prompt"):
|
|
145
|
+
result = await _prompt_cloud_fallback(
|
|
146
|
+
router, tool_obj, result, call_args, session,
|
|
147
|
+
)
|
|
148
|
+
else:
|
|
149
|
+
result = await asyncio.to_thread(tool_obj.run, **call_args)
|
|
136
150
|
text = _format_tool_result(result)
|
|
137
151
|
except Exception as e:
|
|
138
152
|
logger.warning("Tool %s raised: %s", tool_obj.name, e)
|
|
@@ -147,6 +161,66 @@ def _make_tool_handler(tool_obj, session):
|
|
|
147
161
|
return handler
|
|
148
162
|
|
|
149
163
|
|
|
164
|
+
async def _prompt_cloud_fallback(router, tool_obj, prompt_result, call_args, session):
|
|
165
|
+
"""Prompt the user on the main thread about switching to CellType Cloud.
|
|
166
|
+
|
|
167
|
+
Called when compute.mode=local but the tool can't run locally.
|
|
168
|
+
Runs on the event loop (main thread) so input() works correctly.
|
|
169
|
+
|
|
170
|
+
Options:
|
|
171
|
+
y — run this tool on CellType Cloud (one-time)
|
|
172
|
+
n — skip this tool
|
|
173
|
+
n! — skip and don't ask again for this session
|
|
174
|
+
"""
|
|
175
|
+
from rich.console import Console
|
|
176
|
+
console = getattr(session, "console", None) or Console()
|
|
177
|
+
|
|
178
|
+
# Stop the spinner so it doesn't interfere with the prompt
|
|
179
|
+
spinner = getattr(session, "_active_spinner", None)
|
|
180
|
+
if spinner is not None:
|
|
181
|
+
spinner.stop()
|
|
182
|
+
session._active_spinner = None
|
|
183
|
+
|
|
184
|
+
msg = prompt_result.get("prompt_message", "GPU tool cannot run locally.")
|
|
185
|
+
|
|
186
|
+
console.print(f"\n [yellow]{msg}[/yellow]")
|
|
187
|
+
|
|
188
|
+
try:
|
|
189
|
+
answer = input(
|
|
190
|
+
" Use CellType Cloud for this tool call?\n"
|
|
191
|
+
" [y] yes [y!] yes for all (switch to cloud mode) [n] no (skip this tool call): "
|
|
192
|
+
).strip().lower()
|
|
193
|
+
except (EOFError, KeyboardInterrupt):
|
|
194
|
+
answer = "n"
|
|
195
|
+
|
|
196
|
+
if answer in ("y", "yes"):
|
|
197
|
+
# One-time cloud dispatch for this tool call
|
|
198
|
+
result = await asyncio.to_thread(router.route_cloud_for_tool, tool_obj, **call_args)
|
|
199
|
+
return result
|
|
200
|
+
elif answer in ("y!", "yes!"):
|
|
201
|
+
# Switch to cloud mode permanently — no more prompts
|
|
202
|
+
try:
|
|
203
|
+
from ct.agent.config import Config
|
|
204
|
+
cfg = Config.load()
|
|
205
|
+
cfg.set("compute.mode", "cloud")
|
|
206
|
+
cfg.save()
|
|
207
|
+
console.print(" [green]compute.mode switched to cloud[/green]")
|
|
208
|
+
except Exception:
|
|
209
|
+
pass
|
|
210
|
+
result = await asyncio.to_thread(router.route_cloud_for_tool, tool_obj, **call_args)
|
|
211
|
+
return result
|
|
212
|
+
else:
|
|
213
|
+
# n / anything else — skip this tool call
|
|
214
|
+
return {
|
|
215
|
+
"summary": (
|
|
216
|
+
f"[Skipped] {tool_obj.name} — {msg} "
|
|
217
|
+
"User chose to skip this tool call."
|
|
218
|
+
),
|
|
219
|
+
"skipped": True,
|
|
220
|
+
"reason": "user_skipped",
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
|
|
150
224
|
# ---------------------------------------------------------------------------
|
|
151
225
|
# run_python sandbox tool
|
|
152
226
|
# ---------------------------------------------------------------------------
|
|
@@ -101,6 +101,8 @@ async def process_messages(
|
|
|
101
101
|
thinking_status = None
|
|
102
102
|
if runner is not None:
|
|
103
103
|
runner._active_spinner = None
|
|
104
|
+
if hasattr(runner, "session"):
|
|
105
|
+
runner.session._active_spinner = None
|
|
104
106
|
|
|
105
107
|
text = block.text or ""
|
|
106
108
|
full_text.append(text)
|
|
@@ -130,6 +132,9 @@ async def process_messages(
|
|
|
130
132
|
thinking_status.start_async_refresh()
|
|
131
133
|
if runner is not None:
|
|
132
134
|
runner._active_spinner = thinking_status
|
|
135
|
+
# Also store on session so MCP prompt can stop it
|
|
136
|
+
if runner is not None and hasattr(runner, "session"):
|
|
137
|
+
runner.session._active_spinner = thinking_status
|
|
133
138
|
except ImportError:
|
|
134
139
|
pass
|
|
135
140
|
|
|
@@ -337,7 +342,7 @@ class AgentRunner:
|
|
|
337
342
|
)
|
|
338
343
|
|
|
339
344
|
# ----- Configure Agent SDK -----
|
|
340
|
-
model = config.get("llm.model") or "claude-
|
|
345
|
+
model = config.get("llm.model") or "claude-opus-4-6"
|
|
341
346
|
max_turns = int(config.get("agent.max_sdk_turns", 30))
|
|
342
347
|
|
|
343
348
|
allowed_tools = [f"mcp__ct-tools__{name}" for name in tool_names]
|
|
@@ -357,6 +362,24 @@ class AgentRunner:
|
|
|
357
362
|
# Suppress warnings in SDK subprocess (matplotlib, pydeseq2, numpy, etc.)
|
|
358
363
|
clean_env["PYTHONWARNINGS"] = "ignore"
|
|
359
364
|
|
|
365
|
+
# Enable Foundry mode for Agent SDK subprocess if Foundry env vars present
|
|
366
|
+
if any(clean_env.get(v) for v in (
|
|
367
|
+
"ANTHROPIC_FOUNDRY_API_KEY",
|
|
368
|
+
"ANTHROPIC_FOUNDRY_RESOURCE",
|
|
369
|
+
"ANTHROPIC_FOUNDRY_BASE_URL",
|
|
370
|
+
)):
|
|
371
|
+
clean_env["CLAUDE_CODE_USE_FOUNDRY"] = "1"
|
|
372
|
+
# Pin model names for Foundry deployments
|
|
373
|
+
clean_env.setdefault(
|
|
374
|
+
"ANTHROPIC_DEFAULT_SONNET_MODEL", model
|
|
375
|
+
)
|
|
376
|
+
clean_env.setdefault(
|
|
377
|
+
"ANTHROPIC_DEFAULT_OPUS_MODEL", model
|
|
378
|
+
)
|
|
379
|
+
clean_env.setdefault(
|
|
380
|
+
"ANTHROPIC_DEFAULT_HAIKU_MODEL", model
|
|
381
|
+
)
|
|
382
|
+
|
|
360
383
|
# Plan mode: use SDK's built-in plan permission mode.
|
|
361
384
|
# In plan mode, Claude outputs a plan then calls ExitPlanMode.
|
|
362
385
|
# We intercept that to show the plan and ask for approval.
|
|
@@ -20,8 +20,11 @@ warnings.filterwarnings("ignore", message="Unable to import Axes3D")
|
|
|
20
20
|
warnings.filterwarnings("ignore", category=UserWarning, module="matplotlib")
|
|
21
21
|
|
|
22
22
|
# Force non-interactive matplotlib backend before any import
|
|
23
|
-
|
|
24
|
-
matplotlib
|
|
23
|
+
try:
|
|
24
|
+
import matplotlib
|
|
25
|
+
matplotlib.use("Agg")
|
|
26
|
+
except ImportError:
|
|
27
|
+
pass # matplotlib is a required dep; deferred error in _setup_namespace()
|
|
25
28
|
|
|
26
29
|
|
|
27
30
|
# Modules blocked from import inside the sandbox
|
|
@@ -54,7 +54,7 @@ class Session:
|
|
|
54
54
|
"""Return the current model name."""
|
|
55
55
|
if self._llm:
|
|
56
56
|
return self._llm.model
|
|
57
|
-
return self.config.get("llm.model") or "claude-
|
|
57
|
+
return self.config.get("llm.model") or "claude-opus-4-6"
|
|
58
58
|
|
|
59
59
|
def log(self, message: str):
|
|
60
60
|
"""Log to scratchpad (for debugging/transparency)."""
|
|
@@ -69,6 +69,20 @@ BANNED PHRASES — never write these:
|
|
|
69
69
|
If tools failed, pivot to answering from your knowledge instead.
|
|
70
70
|
"""
|
|
71
71
|
|
|
72
|
+
_STRUCTURE_INPUT_GUIDANCE = """\
|
|
73
|
+
|
|
74
|
+
## Structure File Inputs
|
|
75
|
+
|
|
76
|
+
For tools that accept `target_pdb`, `backbone_pdb`, or `protein_pdb`, you may
|
|
77
|
+
provide either:
|
|
78
|
+
- inline PDB/mmCIF text, or
|
|
79
|
+
- a local filesystem path to a `.pdb`, `.cif`, `.mmcif`, or `.ent` file.
|
|
80
|
+
|
|
81
|
+
If the structure is already saved locally, prefer passing the file path instead
|
|
82
|
+
of pasting the full structure text. The local runner and CellType Cloud client
|
|
83
|
+
will inline the file contents automatically before dispatch.
|
|
84
|
+
"""
|
|
85
|
+
|
|
72
86
|
|
|
73
87
|
# ---------------------------------------------------------------------------
|
|
74
88
|
# Builder
|
|
@@ -167,6 +181,9 @@ def build_system_prompt(
|
|
|
167
181
|
# 8. Synthesis instructions
|
|
168
182
|
parts.append(_SYNTHESIS_INSTRUCTIONS)
|
|
169
183
|
|
|
184
|
+
# 8b. Structure input guidance
|
|
185
|
+
parts.append(_STRUCTURE_INPUT_GUIDANCE)
|
|
186
|
+
|
|
170
187
|
# 9. Dynamic data context
|
|
171
188
|
if data_context:
|
|
172
189
|
parts.append("\n## Data Context\n")
|