mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-09-22 19:06:25 +00:00
feat(cli): prioritize platform integrations
This commit is contained in:
@@ -234,9 +234,9 @@ _FLAT_TOOLS: list[tuple[str, str]] = [
|
||||
_COMMON_TOOL_ORDER = [
|
||||
"SerperDevTool",
|
||||
"ScrapeWebsiteTool",
|
||||
"DirectoryReadTool",
|
||||
"FileReadTool",
|
||||
"FileWriterTool",
|
||||
"platform:gmail",
|
||||
"platform:whatsapp",
|
||||
]
|
||||
|
||||
_ANSI_SEQUENCE_RE = re.compile(r"\x1b\[[0-?]*[ -/]*[@-~]")
|
||||
@@ -898,19 +898,19 @@ def _platform_app_name(app: str) -> str:
|
||||
|
||||
|
||||
def _prompt_platform_token() -> str:
|
||||
"""Explain how to obtain and securely prompt for an AMP integration token."""
|
||||
"""Explain how to securely prompt for an AMP Enterprise Action Auth Token."""
|
||||
click.secho(
|
||||
" To use CrewAI Platform tools, you need a CrewAI Platform Integration Token.",
|
||||
" To use CrewAI Platform tools, you need a CrewAI Platform Enterprise Action Auth Token.",
|
||||
fg="yellow",
|
||||
)
|
||||
click.secho(
|
||||
" Get your token from CrewAI AMP: https://app.crewai.com "
|
||||
"→ Settings → Integration Tokens.",
|
||||
"→ Settings → Account → Enterprise Action Auth Token.",
|
||||
fg="cyan",
|
||||
)
|
||||
return str(
|
||||
click.prompt(
|
||||
click.style(" CREWAI_PLATFORM_INTEGRATION_TOKEN", fg="cyan"),
|
||||
click.style(" CREWAI_ENTERPRISE_ACTION_AUTH_TOKEN", fg="cyan"),
|
||||
hide_input=True,
|
||||
prompt_suffix=click.style(" > ", fg="bright_white"),
|
||||
)
|
||||
@@ -954,7 +954,7 @@ def _report_platform_app_validation(
|
||||
status_code = getattr(getattr(error, "response", None), "status_code", None)
|
||||
if status_code in {401, 403}:
|
||||
click.secho(
|
||||
" ✘ CrewAI Platform Integration Token is invalid or expired",
|
||||
" ✘ CrewAI Platform Enterprise Action Auth Token is invalid or expired",
|
||||
fg="red",
|
||||
)
|
||||
return True
|
||||
@@ -1008,7 +1008,7 @@ def _validate_platform_apps(
|
||||
app_name = _platform_app_name(app)
|
||||
click.echo()
|
||||
click.secho(
|
||||
" Checking CrewAI Platform Integration Token and "
|
||||
" Checking CrewAI Platform Enterprise Action Auth Token and "
|
||||
f"{app_name} integration on AMP...",
|
||||
fg="cyan",
|
||||
)
|
||||
@@ -1027,7 +1027,7 @@ def _show_platform_validation_guidance(
|
||||
click.echo()
|
||||
if token_invalid:
|
||||
click.secho(
|
||||
" Check your CrewAI Platform Integration Token in AMP.",
|
||||
" Check your CrewAI Platform Enterprise Action Auth Token in AMP.",
|
||||
fg="yellow",
|
||||
)
|
||||
return
|
||||
@@ -1037,7 +1037,7 @@ def _show_platform_validation_guidance(
|
||||
" Check the "
|
||||
f"{', '.join(failed_app_names)} integration"
|
||||
f"{'s' if len(failed_app_names) != 1 else ''} and your CrewAI "
|
||||
"Platform Integration Token in AMP.",
|
||||
"Platform Enterprise Action Auth Token in AMP.",
|
||||
fg="yellow",
|
||||
)
|
||||
|
||||
@@ -1082,19 +1082,21 @@ def _setup_platform_auth(agents: list[dict[str, Any]]) -> str | None:
|
||||
"`pip install 'crewai[tools]'`."
|
||||
) from error
|
||||
|
||||
token = os.environ.get("CREWAI_PLATFORM_INTEGRATION_TOKEN", "")
|
||||
token = os.environ.get("CREWAI_ENTERPRISE_ACTION_AUTH_TOKEN") or os.environ.get(
|
||||
"CREWAI_PLATFORM_INTEGRATION_TOKEN", ""
|
||||
)
|
||||
while True:
|
||||
if not token:
|
||||
token = _prompt_platform_token()
|
||||
if not token:
|
||||
click.secho(
|
||||
" A CrewAI Platform Integration Token is required to validate "
|
||||
" A CrewAI Platform Enterprise Action Auth Token is required to validate "
|
||||
"the selected integrations.",
|
||||
fg="yellow",
|
||||
)
|
||||
continue
|
||||
|
||||
os.environ["CREWAI_PLATFORM_INTEGRATION_TOKEN"] = token
|
||||
os.environ["CREWAI_ENTERPRISE_ACTION_AUTH_TOKEN"] = token
|
||||
failed_apps, token_invalid = _validate_platform_apps(
|
||||
apps, ApplicationSelector, client_for_selector
|
||||
)
|
||||
@@ -1110,7 +1112,7 @@ def _setup_platform_auth(agents: list[dict[str, Any]]) -> str | None:
|
||||
replacement_token = _prompt_platform_revalidation_token()
|
||||
if replacement_token:
|
||||
token = replacement_token
|
||||
os.environ["CREWAI_PLATFORM_INTEGRATION_TOKEN"] = token
|
||||
os.environ["CREWAI_ENTERPRISE_ACTION_AUTH_TOKEN"] = token
|
||||
|
||||
|
||||
# ── Main ────────────────────────────────────────────────────────
|
||||
@@ -1178,11 +1180,11 @@ def create_json_crew(
|
||||
copy_assistant_instructions(folder_path)
|
||||
|
||||
if platform_token:
|
||||
os.environ["CREWAI_PLATFORM_INTEGRATION_TOKEN"] = platform_token
|
||||
os.environ["CREWAI_ENTERPRISE_ACTION_AUTH_TOKEN"] = platform_token
|
||||
env_vars = load_env_vars(folder_path)
|
||||
env_vars["CREWAI_PLATFORM_INTEGRATION_TOKEN"] = platform_token
|
||||
env_vars["CREWAI_ENTERPRISE_ACTION_AUTH_TOKEN"] = platform_token
|
||||
write_env_file(folder_path, env_vars)
|
||||
_success("CrewAI Platform integration token saved to .env")
|
||||
_success("CrewAI Platform Enterprise Action Auth Token saved to .env")
|
||||
|
||||
for agent in agents:
|
||||
_write_jsonc(
|
||||
|
||||
@@ -6,20 +6,27 @@ from crewai_core.platform_apps import PLATFORM_APPS
|
||||
PLATFORM_TOOL_PREFIX = "platform:"
|
||||
|
||||
_APP_DESCRIPTIONS: dict[str, str] = {
|
||||
"gmail": "Gmail Integration",
|
||||
"github": "GitHub Integration",
|
||||
"google_drive": "Google Drive Integration",
|
||||
"google_sheets": "Google Sheets Integration",
|
||||
"slack": "Slack Integration",
|
||||
"google_calendar": "Google Calendar Integration",
|
||||
"whatsapp": "WhatsApp Integration",
|
||||
"youtube": "YouTube Integration",
|
||||
"instagram": "Instagram Integration",
|
||||
"outlook": "Outlook Integration",
|
||||
"google_docs": "Google Docs Integration",
|
||||
"linkedin": "LinkedIn Integration",
|
||||
"asana": "Asana Integration",
|
||||
"box": "Box Integration",
|
||||
"clickup": "ClickUp Integration",
|
||||
"github": "GitHub Integration",
|
||||
"gmail": "Gmail Integration",
|
||||
"google_calendar": "Google Calendar Integration",
|
||||
"google_sheets": "Google Sheets Integration",
|
||||
"hubspot": "HubSpot Integration",
|
||||
"jira": "Jira Integration",
|
||||
"linear": "Linear Integration",
|
||||
"notion": "Notion Integration",
|
||||
"salesforce": "Salesforce Integration",
|
||||
"shopify": "Shopify Integration",
|
||||
"slack": "Slack Integration",
|
||||
"stripe": "Stripe Integration",
|
||||
"zendesk": "Zendesk Integration",
|
||||
}
|
||||
|
||||
@@ -470,16 +470,18 @@ def test_json_wizard_tool_picker_prioritizes_common_tools(monkeypatch):
|
||||
|
||||
tools = json_crew._select_tools()
|
||||
|
||||
assert tools == ["SerperDevTool", "DirectoryReadTool"]
|
||||
assert tools == ["SerperDevTool", "FileReadTool"]
|
||||
assert len(picker_calls) == 1
|
||||
labels = picker_calls[0][1]
|
||||
assert 0 in picker_calls[0][2]["separator_indices"]
|
||||
assert labels[0] == "── Common tools ──"
|
||||
assert labels[1].strip().endswith("SerperDevTool")
|
||||
assert labels[2].strip().endswith("ScrapeWebsiteTool")
|
||||
assert labels[3].strip().endswith("DirectoryReadTool")
|
||||
assert labels[4].strip().endswith("FileReadTool")
|
||||
assert labels[5].strip().endswith("FileWriterTool")
|
||||
assert labels[3].strip().endswith("FileReadTool")
|
||||
assert labels[4].startswith("Gmail Integration")
|
||||
assert labels[4].endswith("Platform: GmailIntegration")
|
||||
assert labels[5].startswith("WhatsApp Integration")
|
||||
assert labels[5].endswith("Platform: WhatsAppIntegration")
|
||||
assert labels[1].index("Google search") < labels[1].index("SerperDevTool")
|
||||
assert "More tools" not in labels
|
||||
|
||||
@@ -749,7 +751,7 @@ def test_platform_validation_announces_concurrent_apps_together(capsys):
|
||||
output = capsys.readouterr().out
|
||||
assert (failed_apps, token_invalid) == ([], False)
|
||||
assert "Checking GitHub, Gmail, Google Calendar integrations together on AMP" in output
|
||||
assert "Checking CrewAI Platform Integration Token and GitHub" not in output
|
||||
assert "Checking CrewAI Platform Enterprise Action Auth Token and GitHub" not in output
|
||||
|
||||
|
||||
def test_platform_validation_falls_back_to_sequential_checks(monkeypatch, capsys):
|
||||
@@ -779,8 +781,8 @@ def test_platform_validation_falls_back_to_sequential_checks(monkeypatch, capsys
|
||||
assert (failed_apps, token_invalid) == ([], False)
|
||||
assert checked_apps == ["github", "gmail"]
|
||||
output = capsys.readouterr().out
|
||||
assert "Checking CrewAI Platform Integration Token and GitHub integration" in output
|
||||
assert "Checking CrewAI Platform Integration Token and Gmail integration" in output
|
||||
assert "Checking CrewAI Platform Enterprise Action Auth Token and GitHub integration" in output
|
||||
assert "Checking CrewAI Platform Enterprise Action Auth Token and Gmail integration" in output
|
||||
|
||||
|
||||
def test_multi_picker_skips_separator_on_initial_cursor(monkeypatch):
|
||||
@@ -1040,7 +1042,7 @@ def test_json_create_saves_platform_token_to_env_file(tmp_path, monkeypatch):
|
||||
json_crew.create_json_crew("Platform Crew", skip_provider=True)
|
||||
|
||||
env_file = tmp_path / "platform_crew" / ".env"
|
||||
assert "CREWAI_PLATFORM_INTEGRATION_TOKEN=token" in env_file.read_text()
|
||||
assert "CREWAI_ENTERPRISE_ACTION_AUTH_TOKEN=token" in env_file.read_text()
|
||||
|
||||
|
||||
def test_json_crew_uses_template_files():
|
||||
|
||||
@@ -4,20 +4,27 @@ from typing import Final, Literal, get_args
|
||||
|
||||
|
||||
PlatformApp = Literal[
|
||||
"gmail",
|
||||
"github",
|
||||
"google_drive",
|
||||
"google_sheets",
|
||||
"slack",
|
||||
"google_calendar",
|
||||
"whatsapp",
|
||||
"youtube",
|
||||
"instagram",
|
||||
"outlook",
|
||||
"google_docs",
|
||||
"linkedin",
|
||||
"asana",
|
||||
"box",
|
||||
"clickup",
|
||||
"github",
|
||||
"gmail",
|
||||
"google_calendar",
|
||||
"google_sheets",
|
||||
"hubspot",
|
||||
"jira",
|
||||
"linear",
|
||||
"notion",
|
||||
"salesforce",
|
||||
"shopify",
|
||||
"slack",
|
||||
"stripe",
|
||||
"zendesk",
|
||||
]
|
||||
|
||||
@@ -2,10 +2,15 @@ import os
|
||||
|
||||
|
||||
def get_platform_integration_token() -> str:
|
||||
"""Get the platform integration token from the environment."""
|
||||
token = os.getenv("CREWAI_PLATFORM_INTEGRATION_TOKEN") or ""
|
||||
"""Get the Platform Enterprise Action Auth Token from the environment."""
|
||||
token = (
|
||||
os.getenv("CREWAI_ENTERPRISE_ACTION_AUTH_TOKEN")
|
||||
or os.getenv("CREWAI_PLATFORM_INTEGRATION_TOKEN")
|
||||
or ""
|
||||
)
|
||||
if not token:
|
||||
raise ValueError(
|
||||
"No platform integration token found, please set the CREWAI_PLATFORM_INTEGRATION_TOKEN environment variable"
|
||||
"No Platform Enterprise Action Auth Token found, please set the "
|
||||
"CREWAI_ENTERPRISE_ACTION_AUTH_TOKEN environment variable"
|
||||
)
|
||||
return token # TODO: Use context manager to get token
|
||||
|
||||
@@ -3,20 +3,27 @@ from crewai_core.platform_apps import PLATFORM_APPS
|
||||
|
||||
def test_platform_apps_contains_supported_application_catalog() -> None:
|
||||
assert PLATFORM_APPS == (
|
||||
"gmail",
|
||||
"github",
|
||||
"google_drive",
|
||||
"google_sheets",
|
||||
"slack",
|
||||
"google_calendar",
|
||||
"whatsapp",
|
||||
"youtube",
|
||||
"instagram",
|
||||
"outlook",
|
||||
"google_docs",
|
||||
"linkedin",
|
||||
"asana",
|
||||
"box",
|
||||
"clickup",
|
||||
"github",
|
||||
"gmail",
|
||||
"google_calendar",
|
||||
"google_sheets",
|
||||
"hubspot",
|
||||
"jira",
|
||||
"linear",
|
||||
"notion",
|
||||
"salesforce",
|
||||
"shopify",
|
||||
"slack",
|
||||
"stripe",
|
||||
"zendesk",
|
||||
)
|
||||
|
||||
@@ -367,7 +367,7 @@ def test_clipper_client_requires_platform_integration_token(
|
||||
parameters={},
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError, match="CREWAI_PLATFORM_INTEGRATION_TOKEN"):
|
||||
with pytest.raises(ValueError, match="CREWAI_ENTERPRISE_ACTION_AUTH_TOKEN"):
|
||||
ClipperClient().execute_action(tool, {})
|
||||
|
||||
mock_post.assert_not_called()
|
||||
|
||||
Reference in New Issue
Block a user