Skip to content

Fix OpenCode adapter timeout and event handling#88

Merged
gricha merged 1 commit intomainfrom
fix/opencode-async-endpoint
Jan 11, 2026
Merged

Fix OpenCode adapter timeout and event handling#88
gricha merged 1 commit intomainfrom
fix/opencode-async-endpoint

Conversation

@gricha
Copy link
Copy Markdown
Owner

@gricha gricha commented Jan 11, 2026

Summary

  • Use async endpoint (prompt_async) instead of sync - prevents timeout on long-running operations
  • Increase SSE timeout to 10 minutes for complex tool-use operations
  • Filter SSE events by sessionID to prevent cross-session interference
  • Remove duplicate error emission
  • Verify session exists before using saved agentSessionId

Root Cause

The sync /session/:id/message endpoint blocks until the AI completes processing. Our curl had a 30-second timeout, so any operation taking longer would fail with "Connection failed". The async endpoint returns 204 immediately and we rely on SSE for the response.

Test plan

  • Multi-message conversation test passes
  • Long-running operation with tool calls completes without timeout
  • Invalid session ID gracefully creates new session
  • Manual testing in web/mobile UI

🤖 Generated with Claude Code

@gricha gricha force-pushed the fix/opencode-async-endpoint branch from 33f4095 to 6392606 Compare January 11, 2026 00:53
Comment on lines +522 to +524
if (idleSessionId && idleSessionId !== this.agentSessionId) {
continue;
}

This comment was marked as outdated.

- Use async endpoint (prompt_async) instead of sync endpoint
  The sync /message endpoint blocks until AI completes, causing
  curl to timeout on long-running operations (>30s)

- Increase SSE timeout from 2 minutes to 10 minutes for long ops

- Filter SSE events by sessionID to prevent cross-session interference
  Events from other sessions could cause premature session.idle detection

- Remove duplicate error emission (was sending error twice to clients)

- Add sessionExists() check before using saved agentSessionId
  Prevents "Connection failed" when restored session doesn't exist on server

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@gricha gricha force-pushed the fix/opencode-async-endpoint branch from 6392606 to daf2fa9 Compare January 11, 2026 01:17
@gricha gricha merged commit 48a4652 into main Jan 11, 2026
8 checks passed
@gricha gricha deleted the fix/opencode-async-endpoint branch January 11, 2026 01:21
Comment on lines +521 to +524
const idleSessionId = event.properties?.sessionID;
if (!idleSessionId || idleSessionId !== this.agentSessionId) {
continue;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The new filtering logic discards SSE events if the optional sessionID field is missing, which could lead to timeouts or silently dropped messages.
Severity: CRITICAL

🔍 Detailed Analysis

The filtering logic for session.idle and message.part.updated events assumes the sessionID field will always be present. However, the OpenCodeServerEvent interface defines sessionID as optional. If the OpenCode service sends a valid event for the current session but omits the sessionID, this code will incorrectly discard it. This can lead to two failure modes: a 10-minute stream timeout if a session.idle event is dropped, or silent loss of AI responses if a message.part.updated event is dropped.

💡 Suggested Fix

Modify the filtering logic to correctly handle events where sessionID is undefined. The logic should only filter out events that have a sessionID that does not match the current agentSessionId. Events without a sessionID should be processed, assuming they are relevant to the current session.

🤖 Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: src/session-manager/adapters/opencode.ts#L521-L524

Potential issue: The filtering logic for `session.idle` and `message.part.updated`
events assumes the `sessionID` field will always be present. However, the
`OpenCodeServerEvent` interface defines `sessionID` as optional. If the OpenCode service
sends a valid event for the current session but omits the `sessionID`, this code will
incorrectly discard it. This can lead to two failure modes: a 10-minute stream timeout
if a `session.idle` event is dropped, or silent loss of AI responses if a
`message.part.updated` event is dropped.

Did we get this right? 👍 / 👎 to inform future reviews.
Reference ID: 8438808

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant