mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-07-01 05:08:12 +00:00
* Require explicit CrewAI project definitions
JSON crews and declarative flows now resolve from `[tool.crewai]`
metadata instead of implicit filename discovery. This makes project type
selection deterministic, prevents stray `crew.json(c)` files from changing
CLI behavior, and centralizes definition path validation for run, install,
deploy validation, plotting, and memory reset paths.
`[tool.crewai].definition` must be a project-local file path. Absolute
paths, `~`, missing files, directories, and paths escaping the project root
are rejected so deploy and runtime commands use the same contract.
Breaking changes and migration paths:
* JSON crew projects are no longer discovered from `crew.json` or
`crew.jsonc` alone. Add explicit metadata:
```toml
[tool.crewai]
type = "crew"
definition = "crew.jsonc"
```
* Declarative flow projects must use a valid project-local definition path:
```toml
[tool.crewai]
type = "flow"
definition = "flows/research.yaml"
```
* `Flow.from_definition(definition)` is removed. Use:
```python
Flow.from_declaration(contents=definition)
```
* `FlowDefinition.to_json()` and `FlowDefinition.to_yaml()` are removed.
Use `FlowDefinition.to_dict()` and serialize with the caller's JSON or
YAML library.
* `FlowDefinition.from_dict()` is removed. Use:
```python
FlowDefinition.from_declaration(contents=data)
```
* `FlowDefinition.json_schema()` is removed. Use Pydantic's schema API only
where schema generation is intentionally needed:
```python
FlowDefinition.model_json_schema(by_alias=True)
```
* `crewai_cli.run_crew.find_crew_json_file()` and `_has_json_crew()` are
removed. Use `configured_project_json_crew()` or the shared
`crewai_core.project.configured_project_definition("crew")` helper.
* `crewai reset-memories` now only loads JSON crews declared through
`[tool.crewai].definition`, and invalid declared JSON crew definitions
fail instead of silently falling back to classic crew discovery.
* Address code review comments
105 lines
2.7 KiB
Python
105 lines
2.7 KiB
Python
from pathlib import Path
|
|
import subprocess
|
|
|
|
import pytest
|
|
|
|
import crewai_cli.install_crew as install_crew_module
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _tool_credentials(monkeypatch):
|
|
monkeypatch.setattr(
|
|
install_crew_module,
|
|
"build_env_with_all_tool_credentials",
|
|
lambda: {"CREWAI_TEST": "1"},
|
|
)
|
|
|
|
|
|
def test_install_crew_json_project_skips_project_install(
|
|
fp, monkeypatch, tmp_path: Path
|
|
):
|
|
monkeypatch.chdir(tmp_path)
|
|
(tmp_path / "pyproject.toml").write_text(
|
|
"""
|
|
[project]
|
|
name = "json_crew"
|
|
|
|
[tool.crewai]
|
|
type = "crew"
|
|
definition = "crew.jsonc"
|
|
""".strip()
|
|
)
|
|
(tmp_path / "crew.jsonc").write_text("{}\n")
|
|
fp.register(["uv", "sync", "--no-install-project"], stdout="")
|
|
|
|
install_crew_module.install_crew([])
|
|
|
|
|
|
def test_install_crew_json_project_with_python_package_installs_project(
|
|
fp, monkeypatch, tmp_path: Path
|
|
):
|
|
monkeypatch.chdir(tmp_path)
|
|
(tmp_path / "pyproject.toml").write_text(
|
|
"""
|
|
[project]
|
|
name = "hybrid-crew"
|
|
|
|
[tool.crewai]
|
|
type = "crew"
|
|
definition = "crew.jsonc"
|
|
""".strip()
|
|
)
|
|
(tmp_path / "crew.jsonc").write_text("{}\n")
|
|
package_dir = tmp_path / "src" / "hybrid_crew"
|
|
package_dir.mkdir(parents=True)
|
|
(package_dir / "crew.py").write_text("class HybridCrew: ...\n")
|
|
fp.register(["uv", "sync"], stdout="")
|
|
|
|
install_crew_module.install_crew([])
|
|
|
|
|
|
def test_install_crew_flow_project_installs_project(fp, monkeypatch, tmp_path: Path):
|
|
monkeypatch.chdir(tmp_path)
|
|
(tmp_path / "pyproject.toml").write_text(
|
|
"""
|
|
[project]
|
|
name = "flow_project"
|
|
|
|
[tool.crewai]
|
|
type = "flow"
|
|
""".strip()
|
|
)
|
|
(tmp_path / "crew.jsonc").write_text("{}\n")
|
|
fp.register(["uv", "sync"], stdout="")
|
|
|
|
install_crew_module.install_crew([])
|
|
|
|
|
|
def test_install_crew_classic_project_installs_project(
|
|
fp, monkeypatch, tmp_path: Path
|
|
):
|
|
monkeypatch.chdir(tmp_path)
|
|
(tmp_path / "pyproject.toml").write_text("[project]\nname = 'classic'\n")
|
|
fp.register(["uv", "sync"], stdout="")
|
|
|
|
install_crew_module.install_crew([])
|
|
|
|
|
|
def test_install_crew_install_project_false_adds_no_install_project(fp):
|
|
fp.register(["uv", "sync", "--no-install-project", "--frozen"], stdout="")
|
|
|
|
install_crew_module.install_crew(["--frozen"], install_project=False)
|
|
|
|
|
|
def test_install_crew_reraises_sync_failure_when_requested(fp):
|
|
fp.register(["uv", "sync"], returncode=1, stderr="sync failed\n")
|
|
|
|
with pytest.raises(subprocess.CalledProcessError):
|
|
install_crew_module.install_crew([], raise_on_error=True)
|
|
|
|
|
|
def test_install_crew_swallows_sync_failure_by_default(fp):
|
|
fp.register(["uv", "sync"], returncode=1, stderr="sync failed\n")
|
|
|
|
install_crew_module.install_crew([])
|