Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 22 additions & 9 deletions src/agentpool_server/opencode_server/routes/session_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1167,7 +1167,7 @@ async def fork_session( # noqa: D417

# Copy messages in storage via SessionPool
if session_pool is not None:
with contextlib.suppress(KeyError, TypeError):
with contextlib.suppress(KeyError, TypeError, ValueError):
await session_pool.copy_messages(
session_id,
new_session_id,
Expand Down Expand Up @@ -1209,7 +1209,7 @@ async def fork_session( # noqa: D417


@router.post("/{session_id}/init")
async def init_session( # noqa: D417,PLR0915
async def init_session( # noqa: D417
session_id: str,
state: StateDep,
request: SessionInitRequest | None = None,
Expand All @@ -1230,6 +1230,25 @@ async def init_session( # noqa: D417,PLR0915
if session is None:
raise HTTPException(status_code=404, detail="Session not found")

# The entire init process (repo map generation, README reading, agent
# run) runs as a background task so the HTTP response returns
# immediately. This prevents timeouts on large repos in CI. (#260)
async def _run_init_background() -> None:
try:
await _do_init(state, session_id, request)
except Exception:
logger.exception("Init background task failed", session_id=session_id)

state.create_background_task(_run_init_background(), name=f"init_{session_id}")
return True


async def _do_init( # noqa: PLR0915
state: StateDep,
session_id: str,
request: SessionInitRequest | None,
) -> None:
"""Execute the full init workflow: repo map, README, agent run."""
fs = state.fs
working_dir = state.working_dir
try:
Expand Down Expand Up @@ -1290,10 +1309,8 @@ async def init_session( # noqa: D417,PLR0915
except Exception: # noqa: BLE001
pass

# Fire-and-forget through SessionPool; RunHandle is stored
# in SessionController._runs for cancellation tracking.
await session_pool.send_message(session_id, init_prompt)
return True
return

# Fallback: run the agent in the background directly
async def run_init() -> None:
Expand All @@ -1314,14 +1331,10 @@ async def run_init() -> None:

await agent.run(init_prompt)
finally:
# Per-session agent: model changes are session-local, no need
# to restore the original model.
pass

state.create_background_task(run_init(), name=f"init_{session_id}")

return True


@router.get("/{session_id}/todo")
async def get_session_todos(session_id: str, state: StateDep) -> list[Todo]:
Expand Down
Loading
Loading