diff --git a/packages/a2a-server/Dockerfile b/packages/a2a-server/Dockerfile index c5014281e6..0d4fd8f7b1 100644 --- a/packages/a2a-server/Dockerfile +++ b/packages/a2a-server/Dockerfile @@ -22,6 +22,9 @@ USER node ENV CODER_AGENT_WORKSPACE_PATH=/workspace ENV CODER_AGENT_PORT=8080 ENV NODE_ENV=production +# Prevent git from prompting for credentials interactively — fails fast instead of hanging +ENV GIT_TERMINAL_PROMPT=0 +ENV CODER_AGENT_HOST=0.0.0.0 EXPOSE 8080 diff --git a/packages/a2a-server/src/chat-bridge/handler.ts b/packages/a2a-server/src/chat-bridge/handler.ts index a6ffdacd65..483ed9fb2b 100644 --- a/packages/a2a-server/src/chat-bridge/handler.ts +++ b/packages/a2a-server/src/chat-bridge/handler.ts @@ -162,7 +162,7 @@ export class ChatBridgeHandler { this.sessionStore.updateTaskId(threadName, newTaskId); const threadKey = message.thread.threadKey || threadName; - return renderResponse(response, threadKey); + return renderResponse(response, threadKey, threadName); } catch (error) { const errorMsg = error instanceof Error ? error.message : 'Unknown error'; @@ -205,7 +205,7 @@ export class ChatBridgeHandler { // Convert A2A response to Chat format const threadKey = message.thread.threadKey || threadName; - return renderResponse(response, threadKey); + return renderResponse(response, threadKey, threadName); } catch (error) { const errorMsg = error instanceof Error ? error.message : 'Unknown error'; logger.error(`[ChatBridge] Error handling message: ${errorMsg}`, error); diff --git a/packages/a2a-server/src/chat-bridge/response-renderer.ts b/packages/a2a-server/src/chat-bridge/response-renderer.ts index e299ccba18..31148fa68f 100644 --- a/packages/a2a-server/src/chat-bridge/response-renderer.ts +++ b/packages/a2a-server/src/chat-bridge/response-renderer.ts @@ -71,6 +71,7 @@ export function extractToolApprovals( export function renderResponse( response: A2AResponse, threadKey?: string, + threadName?: string, ): ChatResponse { const parts = extractAllParts(response); const textContent = extractTextFromParts(parts); @@ -145,8 +146,10 @@ export function renderResponse( chatResponse.cardsV2 = cards; } - if (threadKey) { - chatResponse.thread = { threadKey }; + if (threadKey || threadName) { + chatResponse.thread = {}; + if (threadKey) chatResponse.thread.threadKey = threadKey; + if (threadName) chatResponse.thread.name = threadName; } // Ensure we always return something diff --git a/packages/a2a-server/src/chat-bridge/routes.ts b/packages/a2a-server/src/chat-bridge/routes.ts index c3547bb3a1..b259f2205d 100644 --- a/packages/a2a-server/src/chat-bridge/routes.ts +++ b/packages/a2a-server/src/chat-bridge/routes.ts @@ -253,6 +253,15 @@ function wrapAddOnsResponse(response: ChatResponse): Record { if (response.cardsV2) { message['cardsV2'] = response.cardsV2; } + // Include thread info so the reply goes to the user's thread + // instead of appearing as a top-level message + if (response.thread) { + const thread: Record = {}; + if (response.thread.name) thread['name'] = response.thread.name; + if (response.thread.threadKey) + thread['threadKey'] = response.thread.threadKey; + message['thread'] = thread; + } // For action responses (like CARD_CLICKED acknowledgments), use updateMessageAction if (response.actionResponse?.type === 'UPDATE_MESSAGE') { diff --git a/packages/a2a-server/src/chat-bridge/types.ts b/packages/a2a-server/src/chat-bridge/types.ts index b38ee90991..adfeaa85ad 100644 --- a/packages/a2a-server/src/chat-bridge/types.ts +++ b/packages/a2a-server/src/chat-bridge/types.ts @@ -121,7 +121,7 @@ export interface ChatOnClick { export interface ChatResponse { text?: string; cardsV2?: ChatCardV2[]; - thread?: { threadKey: string }; + thread?: { threadKey?: string; name?: string }; actionResponse?: { type: 'NEW_MESSAGE' | 'UPDATE_MESSAGE' | 'REQUEST_CONFIG'; };