Skip to content

Commit 2bb744a

Browse files
committed
fix(opencode): tighten retry and entrypoint guards
1 parent a8fb073 commit 2bb744a

File tree

4 files changed

+52
-5
lines changed

4 files changed

+52
-5
lines changed

apps/sim/app/api/tools/opencode/prompt/route.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,43 @@ describe('POST /api/tools/opencode/prompt', () => {
294294
})
295295
})
296296

297+
it('does not retry when a newly created session fails immediately', async () => {
298+
mockPromptOpenCodeSession.mockRejectedValueOnce(new Error('session not found'))
299+
mockShouldRetryWithFreshOpenCodeSession.mockReturnValue(true)
300+
mockCreateOpenCodeSession.mockResolvedValue({ id: 'fresh-session' })
301+
302+
const request = createMockRequest('POST', {
303+
repository: 'repo-a',
304+
providerId: 'provider-a',
305+
modelId: 'model-a',
306+
prompt: 'retry please',
307+
_context: {
308+
workspaceId: 'ws-1',
309+
workflowId: 'wf-1',
310+
userId: 'user-123',
311+
},
312+
})
313+
314+
const response = await POST(request as never)
315+
const data = await response.json()
316+
317+
expect(response.status).toBe(200)
318+
expect(mockCreateOpenCodeSession).toHaveBeenCalledTimes(1)
319+
expect(mockPromptOpenCodeSession).toHaveBeenCalledTimes(1)
320+
expect(mockLogOpenCodeFailure).toHaveBeenCalledWith(
321+
'Failed to execute OpenCode prompt',
322+
expect.objectContaining({ message: 'session not found' })
323+
)
324+
expect(data).toEqual({
325+
success: true,
326+
output: {
327+
content: '',
328+
threadId: 'fresh-session',
329+
error: 'session not found',
330+
},
331+
})
332+
})
333+
297334
it('stores and returns the fresh session id when the retry prompt fails', async () => {
298335
mockGetStoredOpenCodeSession.mockResolvedValue({
299336
sessionId: 'stale-session',

apps/sim/app/api/tools/opencode/prompt/route.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,9 @@ export async function POST(request: NextRequest) {
136136
const memoryKey = buildOpenCodeSessionMemoryKey(workflowId, sessionOwnerKey)
137137
const newThread = coerceOpenCodeBoolean(body.newThread)
138138
const storedThread = newThread ? null : await getStoredOpenCodeSession(workspaceId, memoryKey)
139+
const reusedStoredThread = Boolean(storedThread && storedThread.repository === repositoryId)
139140
let threadId =
140-
storedThread && storedThread.repository === repositoryId
141-
? storedThread.sessionId
142-
: undefined
141+
reusedStoredThread ? storedThread.sessionId : undefined
143142

144143
if (!threadId) {
145144
const session = await createOpenCodeSession(
@@ -177,7 +176,7 @@ export async function POST(request: NextRequest) {
177176

178177
return buildSuccessResponse(result.threadId, result.content, result.cost)
179178
} catch (error) {
180-
if (threadId && !newThread && shouldRetryWithFreshOpenCodeSession(error)) {
179+
if (reusedStoredThread && threadId && !newThread && shouldRetryWithFreshOpenCodeSession(error)) {
181180
let freshSessionId = threadId
182181

183182
try {

apps/sim/lib/opencode/service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ function getAssistantErrorMessage(error: AssistantMessage['error']): string | un
220220
return error.name
221221
}
222222

223-
export function extractOpenCodeText(parts: Part[]): string {
223+
function extractOpenCodeText(parts: Part[]): string {
224224
return parts
225225
.filter((part): part is Extract<Part, { type: 'text' }> => part.type === 'text')
226226
.map((part) => part.text.trim())

docker/opencode/entrypoint.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@ log() {
55
printf '[opencode-entrypoint] %s\n' "$*"
66
}
77

8+
validate_port() {
9+
local port="$1"
10+
11+
if [[ ! "$port" =~ ^[0-9]+$ ]]; then
12+
log "OPENCODE_PORT must be a numeric TCP port"
13+
exit 1
14+
fi
15+
}
16+
817
write_runtime_env() {
918
local env_file="/home/opencode/.config/opencode/runtime-env.sh"
1019
local vars=(
@@ -88,6 +97,8 @@ main() {
8897
export GOOGLE_GENERATIVE_AI_API_KEY="${GEMINI_API_KEY}"
8998
fi
9099

100+
validate_port "${OPENCODE_PORT}"
101+
91102
mkdir -p "${OPENCODE_REPOSITORY_ROOT}" /home/opencode/.config/opencode /home/opencode/.local/share/opencode /home/opencode/.local/state
92103
chown -R opencode:opencode "${OPENCODE_REPOSITORY_ROOT}" /home/opencode/.config /home/opencode/.local/share /home/opencode/.local/state
93104

0 commit comments

Comments
 (0)