From 9f1c7e6aff97ed94479ee75fd42f9c242d44b7eb Mon Sep 17 00:00:00 2001 From: nrs <38722970+nrslib@users.noreply.github.com> Date: Wed, 11 Feb 2026 15:26:12 +0900 Subject: [PATCH] takt: github-issue-238-fix-opencode (#240) --- src/__tests__/opencode-client-cleanup.test.ts | 17 ++++++++-- src/__tests__/opencode-stream-handler.test.ts | 33 +++++++++++++++++++ src/infra/opencode/OpenCodeStreamHandler.ts | 24 ++++++++++++++ src/infra/opencode/client.ts | 4 +-- 4 files changed, 72 insertions(+), 6 deletions(-) diff --git a/src/__tests__/opencode-client-cleanup.test.ts b/src/__tests__/opencode-client-cleanup.test.ts index 5dc0705..af74d2c 100644 --- a/src/__tests__/opencode-client-cleanup.test.ts +++ b/src/__tests__/opencode-client-cleanup.test.ts @@ -218,7 +218,7 @@ describe('OpenCodeClient stream cleanup', () => { ); }); - it('should fail fast when question.asked is received without handler', async () => { + it('should reject question.asked without handler and continue processing', async () => { const { OpenCodeClient } = await import('../infra/opencode/client.js'); const stream = new MockEventStream([ { @@ -235,6 +235,17 @@ describe('OpenCodeClient stream cleanup', () => { ], }, }, + { + type: 'message.part.updated', + properties: { + part: { id: 'p-q1', type: 'text', text: 'continued response' }, + delta: 'continued response', + }, + }, + { + type: 'session.idle', + properties: { sessionID: 'session-4' }, + }, ]); const promptAsync = vi.fn().mockResolvedValue(undefined); @@ -260,8 +271,8 @@ describe('OpenCodeClient stream cleanup', () => { model: 'opencode/big-pickle', }); - expect(result.status).toBe('error'); - expect(result.content).toContain('no question handler'); + expect(result.status).toBe('done'); + expect(result.content).toBe('continued response'); expect(questionReject).toHaveBeenCalledWith( { requestID: 'q-1', diff --git a/src/__tests__/opencode-stream-handler.test.ts b/src/__tests__/opencode-stream-handler.test.ts index 2456f05..108fc10 100644 --- a/src/__tests__/opencode-stream-handler.test.ts +++ b/src/__tests__/opencode-stream-handler.test.ts @@ -12,6 +12,7 @@ import { emitToolResult, emitResult, handlePartUpdated, + type OpenCodeStreamEvent, type OpenCodeTextPart, type OpenCodeReasoningPart, type OpenCodeToolPart, @@ -351,3 +352,35 @@ describe('handlePartUpdated', () => { handlePartUpdated(part, 'Hello', undefined, state); }); }); + +describe('OpenCodeStreamEvent typing', () => { + it('should accept message.completed event shape', () => { + const event: OpenCodeStreamEvent = { + type: 'message.completed', + properties: { + info: { + sessionID: 'session-1', + role: 'assistant', + error: undefined, + }, + }, + }; + + expect(event.type).toBe('message.completed'); + }); + + it('should accept message.failed event shape', () => { + const event: OpenCodeStreamEvent = { + type: 'message.failed', + properties: { + info: { + sessionID: 'session-2', + role: 'assistant', + error: { message: 'failed' }, + }, + }, + }; + + expect(event.type).toBe('message.failed'); + }); +}); diff --git a/src/infra/opencode/OpenCodeStreamHandler.ts b/src/infra/opencode/OpenCodeStreamHandler.ts index f7c0e82..6b312ed 100644 --- a/src/infra/opencode/OpenCodeStreamHandler.ts +++ b/src/infra/opencode/OpenCodeStreamHandler.ts @@ -75,6 +75,28 @@ export interface OpenCodeMessageUpdatedEvent { }; } +export interface OpenCodeMessageCompletedEvent { + type: 'message.completed'; + properties: { + info: { + sessionID: string; + role: 'assistant' | 'user'; + error?: unknown; + }; + }; +} + +export interface OpenCodeMessageFailedEvent { + type: 'message.failed'; + properties: { + info: { + sessionID: string; + role: 'assistant' | 'user'; + error?: unknown; + }; + }; +} + export interface OpenCodePermissionAskedEvent { type: 'permission.asked'; properties: { @@ -107,6 +129,8 @@ export interface OpenCodeQuestionAskedEvent { export type OpenCodeStreamEvent = | OpenCodeMessagePartUpdatedEvent | OpenCodeMessageUpdatedEvent + | OpenCodeMessageCompletedEvent + | OpenCodeMessageFailedEvent | OpenCodeSessionStatusEvent | OpenCodeSessionIdleEvent | OpenCodeSessionErrorEvent diff --git a/src/infra/opencode/client.ts b/src/infra/opencode/client.ts index 5db6152..d853797 100644 --- a/src/infra/opencode/client.ts +++ b/src/infra/opencode/client.ts @@ -411,9 +411,7 @@ export class OpenCodeClient { OPENCODE_INTERACTION_TIMEOUT_MS, 'OpenCode question reject timed out', ); - success = false; - failureMessage = 'OpenCode asked a question, but no question handler is configured'; - break; + continue; } try {