This commit is contained in:
@@ -368,7 +368,7 @@ def _build_project_backend(ctx: BuilderContext, *, settings: Settings) -> Any |
|
|||||||
except Exception: # noqa: BLE001
|
except Exception: # noqa: BLE001
|
||||||
return _with_builder_skills(StateBackend())
|
return _with_builder_skills(StateBackend())
|
||||||
return _with_builder_skills(
|
return _with_builder_skills(
|
||||||
WorkspaceBackend(ctx.workspace),
|
_workspace_backend_with_grep_compat(WorkspaceBackend, ctx.workspace),
|
||||||
artifacts_root=f"/{prefix}/{_BUILDER_ARTIFACT_DIR}",
|
artifacts_root=f"/{prefix}/{_BUILDER_ARTIFACT_DIR}",
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
@@ -404,11 +404,41 @@ def _build_project_backend(ctx: BuilderContext, *, settings: Settings) -> Any |
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
return _with_builder_skills(
|
return _with_builder_skills(
|
||||||
WorkspaceBackend(workspace),
|
_workspace_backend_with_grep_compat(WorkspaceBackend, workspace),
|
||||||
artifacts_root=f"/{prefix}/{_BUILDER_ARTIFACT_DIR}",
|
artifacts_root=f"/{prefix}/{_BUILDER_ARTIFACT_DIR}",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _workspace_backend_with_grep_compat(workspace_backend_cls: Any, workspace: Any) -> Any:
|
||||||
|
"""Patch older a2a-pack WorkspaceBackend grep glob behavior.
|
||||||
|
|
||||||
|
Older ``WorkspaceBackend.grep`` only matched ``glob`` against the full
|
||||||
|
workspace key. DeepAgents commonly calls ``grep(path="/agents/name",
|
||||||
|
glob="agent.py")``, which should match ``agents/name/agent.py``.
|
||||||
|
"""
|
||||||
|
|
||||||
|
class BuilderWorkspaceBackend(workspace_backend_cls): # type: ignore[misc, valid-type]
|
||||||
|
def grep(
|
||||||
|
self,
|
||||||
|
pattern: str,
|
||||||
|
path: str | None = None,
|
||||||
|
glob: str | None = None,
|
||||||
|
) -> Any:
|
||||||
|
result = super().grep(pattern, path=path, glob=glob)
|
||||||
|
if not glob or not path or getattr(result, "matches", None):
|
||||||
|
return result
|
||||||
|
norm = getattr(self, "_norm", None)
|
||||||
|
base = norm(path) if callable(norm) else path.strip("/")
|
||||||
|
if not base:
|
||||||
|
return result
|
||||||
|
scoped_glob = f"{base.rstrip('/')}/{glob.lstrip('/')}"
|
||||||
|
if scoped_glob == glob:
|
||||||
|
return result
|
||||||
|
return super().grep(pattern, path=path, glob=scoped_glob)
|
||||||
|
|
||||||
|
return BuilderWorkspaceBackend(workspace)
|
||||||
|
|
||||||
|
|
||||||
def _with_builder_skills(default_backend: Any, *, artifacts_root: str = "/") -> Any:
|
def _with_builder_skills(default_backend: Any, *, artifacts_root: str = "/") -> Any:
|
||||||
skill_store = InMemoryStore()
|
skill_store = InMemoryStore()
|
||||||
for path, content in _builder_skill_files().items():
|
for path, content in _builder_skill_files().items():
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ from agent_builder.builder import (
|
|||||||
_build_project_backend,
|
_build_project_backend,
|
||||||
_builder_skill_files,
|
_builder_skill_files,
|
||||||
_with_builder_skills,
|
_with_builder_skills,
|
||||||
|
_workspace_backend_with_grep_compat,
|
||||||
)
|
)
|
||||||
from agent_builder.config import Settings
|
from agent_builder.config import Settings
|
||||||
from agent_builder.tools import A2A_PACK_MIN_VERSION, _strip_unsupported_pricing_fields
|
from agent_builder.tools import A2A_PACK_MIN_VERSION, _strip_unsupported_pricing_fields
|
||||||
@@ -209,3 +210,49 @@ inline = Pricing(price_per_call_usd=0.01, compute={"runtime_seconds": 600}, tota
|
|||||||
backend.artifacts_root,
|
backend.artifacts_root,
|
||||||
"/agents/svgwrite-agent/.agent-builder",
|
"/agents/svgwrite-agent/.agent-builder",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_project_backend_grep_compat_qualifies_relative_glob(self) -> None:
|
||||||
|
class _LegacyBackend:
|
||||||
|
def __init__(self, workspace: object) -> None:
|
||||||
|
self.workspace = workspace
|
||||||
|
self.calls: list[tuple[str | None, str | None]] = []
|
||||||
|
|
||||||
|
def _norm(self, path: str | None) -> str:
|
||||||
|
return (path or "").strip("/")
|
||||||
|
|
||||||
|
def grep(
|
||||||
|
self,
|
||||||
|
pattern: str,
|
||||||
|
path: str | None = None,
|
||||||
|
glob: str | None = None,
|
||||||
|
):
|
||||||
|
self.calls.append((path, glob))
|
||||||
|
matches = (
|
||||||
|
[{"path": "/agents/github-repo-inspector/agent.py"}]
|
||||||
|
if glob == "agents/github-repo-inspector/agent.py"
|
||||||
|
else []
|
||||||
|
)
|
||||||
|
return type("GrepResult", (), {"error": None, "matches": matches})()
|
||||||
|
|
||||||
|
backend = _workspace_backend_with_grep_compat(_LegacyBackend, object())
|
||||||
|
|
||||||
|
result = backend.grep(
|
||||||
|
"_github_client",
|
||||||
|
path="/agents/github-repo-inspector",
|
||||||
|
glob="agent.py",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
backend.calls,
|
||||||
|
[
|
||||||
|
("/agents/github-repo-inspector", "agent.py"),
|
||||||
|
(
|
||||||
|
"/agents/github-repo-inspector",
|
||||||
|
"agents/github-repo-inspector/agent.py",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
result.matches,
|
||||||
|
[{"path": "/agents/github-repo-inspector/agent.py"}],
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user