refactor: adopt graphs/runtime/providers shims + retarget langgraph.json

Part of the domain-reorg adoption (build plan step C3): fork content,
upstream layout. Adds agent/graphs/{agent,analyzer,chat,reviewer,
scheduler}.py as thin re-export shims delegating to the existing fork
graph factories (agent.server/analyzer/chat/reviewer/scheduler), plus
agent/providers/__init__.py re-exporting agent.utils.model's
make_model/provider_model_kwargs/fallback_model_id_for surface —
verbatim upstream content, verified each import resolves against fork
modules with no name changes needed.

agent/runtime/{constants,execution}.py deviate from upstream's
verbatim shim bodies: rather than duplicating DEFAULT_LLM_MODEL_ID/
DEFAULT_LLM_MAX_TOKENS/DEFAULT_RECURSION_LIMIT/MODEL_CALL_RECURSION_LIMIT
and graph_loaded_for_execution's logic (upstream's shims assume
agent/server.py already had these extracted into runtime/ modules,
which is out of this commit's scope — server.py is untouched), they
import the fork's existing agent.server attributes directly. This
keeps the values/logic single-sourced instead of forking a second
copy that could drift.

agent/runtime/sandbox.py's delegation targets also differ from
upstream: fork's sandbox lifecycle helpers are private
(_get_cached_sandbox_backend, _configure_git_identity,
_recreate_sandbox in agent/server.py) since the fork's sync
4-case `__creating__` sentinel design (AGENTS.md) never made them
public. get_cached_sandbox_backend() also drops upstream's
caller-supplied `reconnect` callback parameter — fork's
_get_cached_sandbox_backend is a plain cache lookup; reconnection is
handled internally by ensure_sandbox_for_thread/
check_or_recreate_sandbox, not via a passed-in callback. No other
signature changes.

Added fork-only agent/graphs/ci_monitor.py (delegates to
agent.ci_monitor:get_ci_monitor) for symmetry, since upstream deleted
its ci-autofix cluster and has no equivalent shim. langgraph.json's
five stock graph entrypoints plus the fork-only ci_monitor now all
point at agent.graphs.<name>; http.app stays agent.webapp:app
(unchanged, per plan).

Deliberately NOT included (owned by build plan step C4, the FastAPI
split, gated on /sh-security-review): agent/api/{__init__,app,
health}.py, agent/webhooks/common.py, and the three
agent/webhooks/{github,linear,slack}_routes.py files. Those aren't
thin structural shims like the 21-file list implies in isolation —
they carry the fork's actual webhook dispatch/verify logic split out
of the still-monolithic webapp.py, which hasn't happened yet.
Building them now against upstream's placeholder content would ship
incomplete auth surface that C4 would just discard and redo.

Pinned oven-sh/setup-bun's bun-version to 1.3.14 (the version
installed locally; ui/ has no .bun-version file or package.json
engines/packageManager field pinning one) across all three CI jobs
that install bun, removing the latest-resolution flake.

Gates: ruff check + ruff format --check (clean), pytest --co -q
(1637 collected, no import errors), a direct import smoke-test of
every new module's public symbols, and a make dev boot check —
langgraph dev registered all six graphs (agent, reviewer, analyzer,
chat, scheduler, ci_monitor) each importing from agent.graphs.*, and
loaded the custom app from agent.webapp:app, before the process was
killed. (The subsequent lifespan failure, "DEFAULT_SANDBOX_SNAPSHOT_ID
must be set when SANDBOX_TYPE=langsmith", is expected with no .env
secrets configured in this environment and unrelated to this commit.)
This commit is contained in:
Adam Moussa 2026-07-17 13:57:20 -04:00
parent 62d9945df4
commit 532788d409
No known key found for this signature in database
14 changed files with 140 additions and 6 deletions

View file

@ -45,6 +45,8 @@ jobs:
steps:
- uses: actions/checkout@v7
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with:
bun-version: "1.3.14"
- name: Install UI dependencies
working-directory: ui
run: bun install --frozen-lockfile
@ -74,6 +76,8 @@ jobs:
with:
node-version: "24"
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with:
bun-version: "1.3.14"
- name: Install Python deps (langgraph dev runtime)
run: uv sync --locked
- name: Install Playwright + Chromium
@ -132,6 +136,8 @@ jobs:
steps:
- uses: actions/checkout@v7
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with:
bun-version: "1.3.14"
- name: ui/package.json and ui/bun.lock agree
working-directory: ui
run: bun install --frozen-lockfile

1
agent/graphs/__init__.py Normal file
View file

@ -0,0 +1 @@
__all__: list[str] = []

3
agent/graphs/agent.py Normal file
View file

@ -0,0 +1,3 @@
from agent.server import get_agent, traced_agent
__all__ = ["get_agent", "traced_agent"]

3
agent/graphs/analyzer.py Normal file
View file

@ -0,0 +1,3 @@
from agent.analyzer import get_analyzer, traced_analyzer
__all__ = ["get_analyzer", "traced_analyzer"]

3
agent/graphs/chat.py Normal file
View file

@ -0,0 +1,3 @@
from agent.chat import get_chat_agent, traced_chat_agent
__all__ = ["get_chat_agent", "traced_chat_agent"]

View file

@ -0,0 +1,3 @@
from agent.ci_monitor import get_ci_monitor
__all__ = ["get_ci_monitor"]

3
agent/graphs/reviewer.py Normal file
View file

@ -0,0 +1,3 @@
from agent.reviewer import get_reviewer_agent, traced_reviewer_agent
__all__ = ["get_reviewer_agent", "traced_reviewer_agent"]

View file

@ -0,0 +1,3 @@
from agent.scheduler import get_scheduler
__all__ = ["get_scheduler"]

View file

@ -0,0 +1,15 @@
from agent.utils.model import (
DEFAULT_LLM_REASONING,
ModelKwargs,
fallback_model_id_for,
make_model,
provider_model_kwargs,
)
__all__ = [
"DEFAULT_LLM_REASONING",
"ModelKwargs",
"fallback_model_id_for",
"make_model",
"provider_model_kwargs",
]

25
agent/runtime/__init__.py Normal file
View file

@ -0,0 +1,25 @@
from .constants import (
DEFAULT_LLM_MAX_TOKENS,
DEFAULT_LLM_MODEL_ID,
DEFAULT_RECURSION_LIMIT,
MODEL_CALL_RECURSION_LIMIT,
)
from .execution import graph_loaded_for_execution
from .sandbox import (
configure_git_identity,
ensure_sandbox_for_thread,
get_cached_sandbox_backend,
recreate_sandbox,
)
__all__ = [
"DEFAULT_LLM_MAX_TOKENS",
"DEFAULT_LLM_MODEL_ID",
"DEFAULT_RECURSION_LIMIT",
"MODEL_CALL_RECURSION_LIMIT",
"configure_git_identity",
"ensure_sandbox_for_thread",
"get_cached_sandbox_backend",
"graph_loaded_for_execution",
"recreate_sandbox",
]

View file

@ -0,0 +1,13 @@
from agent.server import (
DEFAULT_LLM_MAX_TOKENS,
DEFAULT_LLM_MODEL_ID,
DEFAULT_RECURSION_LIMIT,
MODEL_CALL_RECURSION_LIMIT,
)
__all__ = [
"DEFAULT_LLM_MAX_TOKENS",
"DEFAULT_LLM_MODEL_ID",
"DEFAULT_RECURSION_LIMIT",
"MODEL_CALL_RECURSION_LIMIT",
]

View file

@ -0,0 +1,3 @@
from agent.server import graph_loaded_for_execution
__all__ = ["graph_loaded_for_execution"]

53
agent/runtime/sandbox.py Normal file
View file

@ -0,0 +1,53 @@
from collections.abc import Sequence
from deepagents.backends.protocol import SandboxBackendProtocol
async def ensure_sandbox_for_thread(
thread_id: str,
*,
github_proxy_token: str | None = None,
github_proxy_repositories: Sequence[str] | None = None,
repo: dict[str, str] | None = None,
) -> SandboxBackendProtocol:
from agent.server import ensure_sandbox_for_thread as ensure
return await ensure(
thread_id,
github_proxy_token=github_proxy_token,
github_proxy_repositories=github_proxy_repositories,
repo=repo,
)
def get_cached_sandbox_backend(thread_id: str) -> SandboxBackendProtocol:
# Fork's sync 4-case `__creating__` sentinel lifecycle (see AGENTS.md) handles
# reconnection internally in `ensure_sandbox_for_thread`/`check_or_recreate_sandbox`,
# so unlike upstream's shim there is no caller-supplied `reconnect` callback here:
# fork's `_get_cached_sandbox_backend` is a plain cache lookup.
from agent.server import _get_cached_sandbox_backend as get_backend
return get_backend(thread_id)
async def configure_git_identity(sandbox_backend: SandboxBackendProtocol) -> None:
from agent.server import _configure_git_identity as configure
await configure(sandbox_backend)
async def recreate_sandbox(
thread_id: str,
*,
github_proxy_token: str | None = None,
github_proxy_repositories: Sequence[str] | None = None,
repo: dict[str, str] | None = None,
) -> SandboxBackendProtocol:
from agent.server import _recreate_sandbox as recreate
return await recreate(
thread_id,
github_proxy_token=github_proxy_token,
github_proxy_repositories=github_proxy_repositories,
repo=repo,
)

View file

@ -3,12 +3,12 @@
"python_version": "3.12",
"api_version": "0.10.0rc3",
"graphs": {
"agent": "agent.server:traced_agent",
"reviewer": "agent.reviewer:traced_reviewer_agent",
"analyzer": "agent.analyzer:traced_analyzer",
"chat": "agent.chat:traced_chat_agent",
"scheduler": "agent.scheduler:get_scheduler",
"ci_monitor": "agent.ci_monitor:get_ci_monitor"
"agent": "agent.graphs.agent:traced_agent",
"reviewer": "agent.graphs.reviewer:traced_reviewer_agent",
"analyzer": "agent.graphs.analyzer:traced_analyzer",
"chat": "agent.graphs.chat:traced_chat_agent",
"scheduler": "agent.graphs.scheduler:get_scheduler",
"ci_monitor": "agent.graphs.ci_monitor:get_ci_monitor"
},
"dependencies": [
"."