mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-07-01 13:18:10 +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
82 lines
2.5 KiB
Python
82 lines
2.5 KiB
Python
from pathlib import Path
|
|
import subprocess
|
|
|
|
import click
|
|
from crewai_core.project import configured_project_definition, read_toml
|
|
|
|
from crewai_cli.deploy.validate import normalize_package_name
|
|
from crewai_cli.utils import build_env_with_all_tool_credentials
|
|
|
|
|
|
def _is_json_crew_project(project_root: Path | None = None) -> bool:
|
|
"""Return True for JSON crew projects that do not need package install."""
|
|
root = project_root or Path.cwd()
|
|
pyproject_path = root / "pyproject.toml"
|
|
if not pyproject_path.is_file():
|
|
return False
|
|
|
|
pyproject = read_toml(pyproject_path)
|
|
|
|
if (
|
|
configured_project_definition(
|
|
"crew", pyproject_data=pyproject, project_root=root
|
|
)
|
|
is None
|
|
):
|
|
return False
|
|
|
|
project_name = pyproject.get("project", {}).get("name", "")
|
|
package_name = normalize_package_name(project_name)
|
|
if package_name and (root / "src" / package_name / "crew.py").is_file():
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
# Be mindful about changing this.
|
|
# on some environments we don't use this command but instead uv sync directly
|
|
# so if you expect this to support more things you will need to replicate it there
|
|
# ask @joaomdmoura if you are unsure
|
|
def install_crew(
|
|
proxy_options: list[str],
|
|
*,
|
|
raise_on_error: bool = False,
|
|
install_project: bool | None = None,
|
|
) -> None:
|
|
"""
|
|
Install the crew by running the UV command to lock and install.
|
|
"""
|
|
try:
|
|
if install_project is None:
|
|
install_project = not _is_json_crew_project()
|
|
|
|
command = ["uv", "sync"]
|
|
if not install_project and "--no-install-project" not in proxy_options:
|
|
command.append("--no-install-project")
|
|
command.extend(proxy_options)
|
|
|
|
# Inject tool repository credentials so uv can authenticate
|
|
# against private package indexes (e.g. crewai tool repository).
|
|
# Without this, `uv sync` fails with 401 Unauthorized when the
|
|
# project depends on tools from a private index.
|
|
env = build_env_with_all_tool_credentials()
|
|
|
|
subprocess.run( # noqa: S603
|
|
command,
|
|
check=True,
|
|
capture_output=False,
|
|
text=True,
|
|
env=env,
|
|
)
|
|
|
|
except subprocess.CalledProcessError as e:
|
|
click.echo(f"An error occurred while running the crew: {e}", err=True)
|
|
click.echo(e.output, err=True)
|
|
if raise_on_error:
|
|
raise
|
|
|
|
except Exception as e:
|
|
click.echo(f"An unexpected error occurred: {e}", err=True)
|
|
if raise_on_error:
|
|
raise
|