From d744b37723ed001aa22da5e05328e78339fe1b63 Mon Sep 17 00:00:00 2001 From: alex-clawd Date: Wed, 13 May 2026 01:31:52 -0700 Subject: [PATCH] fix: deduplicate JSONC stripping, guard progress callback, and fix _read_config - Extract `_strip_jsonc` as the single shared helper in `create_agent.py`, replacing the three duplicate implementations in `agent_tui.py`, `benchmark.py`, and the inline regex in `cli.py::_read_config`. - Apply `_strip_jsonc` (including trailing-comma removal) inside `_read_config` so JSONC config.json files are parsed correctly. - Add `if progress is not None:` guard inside `_make_progress_cb._cb` to prevent a `NoneType` call when running in verbose mode. Co-Authored-By: Claude Sonnet 4.6 --- lib/cli/src/crewai_cli/agent_tui.py | 8 ++------ lib/cli/src/crewai_cli/benchmark.py | 9 ++------- lib/cli/src/crewai_cli/cli.py | 16 +++++++--------- lib/cli/src/crewai_cli/create_agent.py | 4 ++-- 4 files changed, 13 insertions(+), 24 deletions(-) diff --git a/lib/cli/src/crewai_cli/agent_tui.py b/lib/cli/src/crewai_cli/agent_tui.py index 7cbac7c32..c9564a49b 100644 --- a/lib/cli/src/crewai_cli/agent_tui.py +++ b/lib/cli/src/crewai_cli/agent_tui.py @@ -39,6 +39,8 @@ from textual.widgets import ( TextArea, ) +from crewai_cli.create_agent import _strip_jsonc + try: from textual.suggester import Suggester @@ -115,12 +117,6 @@ def _safe_render(text: str) -> str: return _rich_escape(text) -def _strip_jsonc(text: str) -> str: - text = re.sub(r"(? list[dict[str, Any]]: """Load all agent definitions from agents/ directory.""" agents: list[dict[str, Any]] = [] diff --git a/lib/cli/src/crewai_cli/benchmark.py b/lib/cli/src/crewai_cli/benchmark.py index 9025a42cb..0f1f7493a 100644 --- a/lib/cli/src/crewai_cli/benchmark.py +++ b/lib/cli/src/crewai_cli/benchmark.py @@ -12,6 +12,8 @@ from typing import Any from pydantic import BaseModel +from crewai_cli.create_agent import _strip_jsonc as _strip_jsonc_comments + class BenchmarkCase(BaseModel): """A single benchmark test case.""" @@ -109,13 +111,6 @@ def load_benchmark_cases(path: str | Path) -> LoadedCases: return LoadedCases(cases, threshold) -def _strip_jsonc_comments(text: str) -> str: - """Strip // and /* */ comments and trailing commas from JSONC text.""" - result = re.sub(r"(? tuple[bool, float]: """Check if expected output is found in actual (case-insensitive substring match). diff --git a/lib/cli/src/crewai_cli/cli.py b/lib/cli/src/crewai_cli/cli.py index edce5610b..10cf002f3 100644 --- a/lib/cli/src/crewai_cli/cli.py +++ b/lib/cli/src/crewai_cli/cli.py @@ -11,7 +11,7 @@ from crewai_core.token_manager import TokenManager from crewai_cli.add_crew_to_flow import add_crew_to_flow from crewai_cli.authentication.main import AuthenticationCommand from crewai_cli.config import Settings -from crewai_cli.create_agent import create_agent +from crewai_cli.create_agent import _strip_jsonc, create_agent from crewai_cli.create_crew import create_crew from crewai_cli.create_flow import create_flow from crewai_cli.crew_chat import run_chat @@ -613,10 +613,7 @@ def _read_config(*keys: str) -> Any: return None try: raw = config_path.read_text(encoding="utf-8") - import re - - clean = re.sub(r"(? None: - prefixed = dict(event) - if "model" in prefixed: - prefixed["model"] = f"{agent_name}/{prefixed['model']}" - progress.on_progress(prefixed) + if progress is not None: + prefixed = dict(event) + if "model" in prefixed: + prefixed["model"] = f"{agent_name}/{prefixed['model']}" + progress.on_progress(prefixed) return _cb diff --git a/lib/cli/src/crewai_cli/create_agent.py b/lib/cli/src/crewai_cli/create_agent.py index 88e9a0236..65e4e929c 100644 --- a/lib/cli/src/crewai_cli/create_agent.py +++ b/lib/cli/src/crewai_cli/create_agent.py @@ -812,7 +812,7 @@ def _prompt_agent_name() -> str: ) -def _strip_comments(text: str) -> str: +def _strip_jsonc(text: str) -> str: """Strip // and /* */ comments from JSONC text, then fix trailing commas.""" result = re.sub(r"(? None: try: raw = config_path.read_text(encoding="utf-8") - clean = _strip_comments(raw) + clean = _strip_jsonc(raw) config = json.loads(clean) rooms = config.get("rooms", {})