From e61de49743dba807f513aad5b3ddd26513b92dbc Mon Sep 17 00:00:00 2001 From: Matt Rubens <2600+mrubens@users.noreply.github.com> Date: Tue, 28 Jul 2026 19:40:10 +0000 Subject: [PATCH 1/4] fix(cloud-agents): quote web follow-ups on GitHub --- .../server/__tests__/github-message-instructions.test.ts | 6 ++++++ .../cloud-agents/src/server/github-message-instructions.ts | 1 + 2 files changed, 7 insertions(+) diff --git a/packages/cloud-agents/src/server/__tests__/github-message-instructions.test.ts b/packages/cloud-agents/src/server/__tests__/github-message-instructions.test.ts index b1fb3fedd..866e6d8d8 100644 --- a/packages/cloud-agents/src/server/__tests__/github-message-instructions.test.ts +++ b/packages/cloud-agents/src/server/__tests__/github-message-instructions.test.ts @@ -23,6 +23,12 @@ describe('GitHub message instructions', () => { expect(instructions).toContain( 'For lightweight clarification, satisfy the `input_needed` milestone on GitHub.', ); + expect(instructions).toContain( + 'begin the next GitHub reply with a Markdown blockquote of that follow-up', + ); + expect(instructions).toContain('not injected out-of-band context'); + expect(instructions).toContain('keep it to 280 characters'); + expect(instructions).toContain('public-reply policy prohibits disclosing'); expect(instructions).toContain('plain GitHub issue'); }); }); diff --git a/packages/cloud-agents/src/server/github-message-instructions.ts b/packages/cloud-agents/src/server/github-message-instructions.ts index 0e2f1ba96..5ec900e53 100644 --- a/packages/cloud-agents/src/server/github-message-instructions.ts +++ b/packages/cloud-agents/src/server/github-message-instructions.ts @@ -9,6 +9,7 @@ export function buildGitHubMessageInstructions(): string { For that non-actionable mention case, leave one brief GitHub reply on the same conversation surface if a reply is still useful, then conclude with a no-op result. Do not treat short verification asks such as "is this addressed?" or "did we fix everything from the last round?" as no-op; those are actionable follow-up. Keep GitHub replies brief, relevant to the request, and free of internal reasoning or raw logs. + When answering a follow-up sent from the web UI, begin the next GitHub reply with a Markdown blockquote of that follow-up so other participants can see what the reply addresses. Use the user's message only, not injected out-of-band context; keep it to 280 characters. Omit or summarize any portion that the public-reply policy prohibits disclosing. If the active workflow already owns a dedicated GitHub comment lifecycle, let that workflow satisfy the relevant communication milestones instead of duplicating generic thread updates. For lightweight clarification, satisfy the \`input_needed\` milestone on GitHub. Use \`request_user_input\` only when the task needs structured or private input outside the public thread. From 5957d7ed11d5baf58a445d125e9ff1a42f66b9aa Mon Sep 17 00:00:00 2001 From: Daniel Riccio <57051444+daniel-lxs@users.noreply.github.com> Date: Tue, 28 Jul 2026 20:02:41 +0000 Subject: [PATCH 2/4] fix: mark web follow-ups in task prompts --- .../src/trpc/commands/sandbox-session/index.ts | 15 ++++++++++++--- .../commands/sandbox-session/send-prompt.test.ts | 12 ++++++------ .../__tests__/github-message-instructions.test.ts | 1 + .../src/server/github-message-instructions.ts | 2 +- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/apps/web/src/trpc/commands/sandbox-session/index.ts b/apps/web/src/trpc/commands/sandbox-session/index.ts index fd3f505bc..e11d560e5 100644 --- a/apps/web/src/trpc/commands/sandbox-session/index.ts +++ b/apps/web/src/trpc/commands/sandbox-session/index.ts @@ -72,6 +72,10 @@ function getAuthenticatedPromptUserName( ); } +function buildModelVisibleWebPrompt(prompt: string): string { + return `\n${prompt}\n`; +} + async function assertSandboxRpcEndpointReachable(sandboxServerUrl: string) { const controller = new AbortController(); const timeoutId = setTimeout( @@ -296,11 +300,16 @@ export async function sendSandboxPromptCommand( ], }); + const prompt = + parsed.source === 'web' && typeof parsed.prompt === 'string' + ? buildModelVisibleWebPrompt(parsed.prompt) + : parsed.prompt; + return await client.commands.sendPrompt.mutate({ prompt: - outOfBandContext && typeof parsed.prompt === 'string' - ? withOutOfBandContext(outOfBandContext, parsed.prompt) - : parsed.prompt, + outOfBandContext && typeof prompt === 'string' + ? withOutOfBandContext(outOfBandContext, prompt) + : prompt, quoteText: parsed.prompt, taskTool: parsed.taskTool, images: parsed.images, diff --git a/apps/web/src/trpc/commands/sandbox-session/send-prompt.test.ts b/apps/web/src/trpc/commands/sandbox-session/send-prompt.test.ts index c1607cd26..27297fca4 100644 --- a/apps/web/src/trpc/commands/sandbox-session/send-prompt.test.ts +++ b/apps/web/src/trpc/commands/sandbox-session/send-prompt.test.ts @@ -150,7 +150,7 @@ describe('sendSandboxPromptCommand', () => { expect(mockSendPromptMutate).toHaveBeenCalledWith( expect.objectContaining({ - prompt: 'keep going', + prompt: '\nkeep going\n', quoteText: 'keep going', source: 'web', userName: 'Auth Fallback Name', @@ -183,7 +183,7 @@ describe('sendSandboxPromptCommand', () => { expect(mockSendPromptMutate).toHaveBeenCalledWith( expect.objectContaining({ prompt: - '\nnotice\n\n\nPlease fix it.', + '\nnotice\n\n\n\nPlease fix it.\n', quoteText: 'Please fix it.', }), ); @@ -217,7 +217,7 @@ describe('sendSandboxPromptCommand', () => { expect(mockSendPromptMutate).toHaveBeenCalledWith( expect.objectContaining({ - prompt: 'change direction', + prompt: '\nchange direction\n', autoSteerWhenQueued: true, }), ); @@ -255,7 +255,7 @@ describe('sendSandboxPromptCommand', () => { expect(mockSendPromptMutate).toHaveBeenCalledWith( expect.objectContaining({ - prompt: 'keep going', + prompt: '\nkeep going\n', source: 'web', userName: 'casey', }), @@ -335,7 +335,7 @@ describe('sendSandboxPromptCommand', () => { expect(updatedRun?.actingUserId).toBe(user.id); expect(mockSendPromptMutate).toHaveBeenCalledWith( expect.objectContaining({ - prompt: 'keep going', + prompt: '\nkeep going\n', // Actor handoffs steer so the previous actor's turn does not keep // running after the credential identity changes. autoSteerWhenQueued: true, @@ -370,7 +370,7 @@ describe('sendSandboxPromptCommand', () => { expect(mockSendPromptMutate).toHaveBeenCalledWith( expect.objectContaining({ - prompt: 'keep going', + prompt: '\nkeep going\n', autoSteerWhenQueued: undefined, }), ); diff --git a/packages/cloud-agents/src/server/__tests__/github-message-instructions.test.ts b/packages/cloud-agents/src/server/__tests__/github-message-instructions.test.ts index 866e6d8d8..068b5159a 100644 --- a/packages/cloud-agents/src/server/__tests__/github-message-instructions.test.ts +++ b/packages/cloud-agents/src/server/__tests__/github-message-instructions.test.ts @@ -26,6 +26,7 @@ describe('GitHub message instructions', () => { expect(instructions).toContain( 'begin the next GitHub reply with a Markdown blockquote of that follow-up', ); + expect(instructions).toContain(''); expect(instructions).toContain('not injected out-of-band context'); expect(instructions).toContain('keep it to 280 characters'); expect(instructions).toContain('public-reply policy prohibits disclosing'); diff --git a/packages/cloud-agents/src/server/github-message-instructions.ts b/packages/cloud-agents/src/server/github-message-instructions.ts index 5ec900e53..4719bf598 100644 --- a/packages/cloud-agents/src/server/github-message-instructions.ts +++ b/packages/cloud-agents/src/server/github-message-instructions.ts @@ -9,7 +9,7 @@ export function buildGitHubMessageInstructions(): string { For that non-actionable mention case, leave one brief GitHub reply on the same conversation surface if a reply is still useful, then conclude with a no-op result. Do not treat short verification asks such as "is this addressed?" or "did we fix everything from the last round?" as no-op; those are actionable follow-up. Keep GitHub replies brief, relevant to the request, and free of internal reasoning or raw logs. - When answering a follow-up sent from the web UI, begin the next GitHub reply with a Markdown blockquote of that follow-up so other participants can see what the reply addresses. Use the user's message only, not injected out-of-band context; keep it to 280 characters. Omit or summarize any portion that the public-reply policy prohibits disclosing. + When answering a , begin the next GitHub reply with a Markdown blockquote of that follow-up so other participants can see what the reply addresses. Use only the message inside that boundary, not injected out-of-band context; keep it to 280 characters. Omit or summarize any portion that the public-reply policy prohibits disclosing. If the active workflow already owns a dedicated GitHub comment lifecycle, let that workflow satisfy the relevant communication milestones instead of duplicating generic thread updates. For lightweight clarification, satisfy the \`input_needed\` milestone on GitHub. Use \`request_user_input\` only when the task needs structured or private input outside the public thread. From dfe9de54620446ae4808dc827f4f6784cfa1c8e2 Mon Sep 17 00:00:00 2001 From: Daniel Riccio <57051444+daniel-lxs@users.noreply.github.com> Date: Tue, 28 Jul 2026 21:06:14 +0000 Subject: [PATCH 3/4] fix: quote web replies in GitHub comments --- .../src/handlers/tasks/manageSourceControl.ts | 79 ++++++++++++++++--- .../trpc/commands/sandbox-session/index.ts | 34 +++++--- .../sandbox-session/send-prompt.test.ts | 12 +-- .../github-message-instructions.test.ts | 7 -- .../src/server/github-message-instructions.ts | 1 - .../src/__tests__/messages.test.ts | 18 +++++ packages/communication/src/messages.ts | 16 ++-- 7 files changed, 121 insertions(+), 46 deletions(-) diff --git a/apps/api/src/handlers/tasks/manageSourceControl.ts b/apps/api/src/handlers/tasks/manageSourceControl.ts index c7ce752f5..58b7d6a37 100644 --- a/apps/api/src/handlers/tasks/manageSourceControl.ts +++ b/apps/api/src/handlers/tasks/manageSourceControl.ts @@ -1,6 +1,11 @@ import type { Context } from 'hono'; import type { ContentfulStatusCode } from 'hono/utils/http-status'; import { z } from 'zod'; +import { + clearLatestUserMessageForReplyQuoteIfId, + getLatestUserMessageForReplyQuote, +} from '@roomote/communication/messages'; +import { resolveSourceControlProviderFromPayload } from '@roomote/types'; import { createOrUpdateSourceControlPullRequestForTaskRun, @@ -27,6 +32,27 @@ import { } from '../mcp/proxy-utils'; import { logHandlerError } from '../utils'; +const GITHUB_REPLY_QUOTE_MAX_LENGTH = 280; + +function formatGitHubReplyQuote(params: { + userName: string; + text: string; +}): string | null { + const userName = params.userName.replace(/\s+/g, ' ').trim(); + const text = params.text.trim(); + + if (!userName || !text) { + return null; + } + + const truncated = + text.length <= GITHUB_REPLY_QUOTE_MAX_LENGTH + ? text + : `${text.slice(0, GITHUB_REPLY_QUOTE_MAX_LENGTH - 3).trimEnd()}...`; + + return `> **${userName}:** ${truncated.replaceAll('\n', '\n> ')}`; +} + /** * POST /api/mcp/tasks/:taskId/source_control * @@ -66,6 +92,35 @@ export async function manageSourceControl( runId: auth.authContext.runId, taskId, }); + const isGitHubTask = + resolveSourceControlProviderFromPayload(taskRun.payload) === 'github'; + const bodyInput = 'body' in input ? input : null; + const shouldQuote = + isGitHubTask && + (input.action === 'reply_to_pull_request_comment' || + input.action === 'create_pull_request_comment' || + input.action === 'create_issue_comment') && + typeof bodyInput?.body === 'string'; + const pendingQuote = shouldQuote + ? await getLatestUserMessageForReplyQuote('github', taskRun.id) + : null; + + if (pendingQuote && typeof bodyInput?.body === 'string') { + const quote = formatGitHubReplyQuote(pendingQuote); + if (quote) { + bodyInput.body = `${quote}\n\n${bodyInput.body}`; + } + } + + const clearQuoteAfterSuccess = async () => { + if (pendingQuote) { + await clearLatestUserMessageForReplyQuoteIfId( + 'github', + taskRun.id, + pendingQuote.id, + ); + } + }; switch (input.action) { case 'create_or_update_pull_request': @@ -89,21 +144,21 @@ export async function manageSourceControl( case 'resolve_pull_request_thread': case 'submit_pull_request_review': case 'update_pull_request_comment': - return c.json( - await writeSourceControlPullRequestForTaskRun({ - taskRun, - input, - }), - ); + const writeResult = await writeSourceControlPullRequestForTaskRun({ + taskRun, + input, + }); + await clearQuoteAfterSuccess(); + return c.json(writeResult); case 'get_issue': case 'list_issue_comments': case 'create_issue_comment': - return c.json( - await manageSourceControlIssueForTaskRun({ - taskRun, - input, - }), - ); + const issueResult = await manageSourceControlIssueForTaskRun({ + taskRun, + input, + }); + await clearQuoteAfterSuccess(); + return c.json(issueResult); } } catch (error) { if (error instanceof z.ZodError) { diff --git a/apps/web/src/trpc/commands/sandbox-session/index.ts b/apps/web/src/trpc/commands/sandbox-session/index.ts index e11d560e5..82928fc61 100644 --- a/apps/web/src/trpc/commands/sandbox-session/index.ts +++ b/apps/web/src/trpc/commands/sandbox-session/index.ts @@ -5,9 +5,11 @@ import { getEnvironmentDefinitionIdFromPayload, isBootingRunStatus, isExitedRunStatus, + resolveSourceControlProviderFromPayload, taskToolDispatchPayloadSchema, } from '@roomote/types'; import { createRunToken } from '@roomote/auth'; +import { trackLatestUserMessageForReplyQuote } from '@roomote/communication/messages'; import { and, compareAndSetTrustedRunActingUser, @@ -72,10 +74,6 @@ function getAuthenticatedPromptUserName( ); } -function buildModelVisibleWebPrompt(prompt: string): string { - return `\n${prompt}\n`; -} - async function assertSandboxRpcEndpointReachable(sandboxServerUrl: string) { const controller = new AbortController(); const timeoutId = setTimeout( @@ -300,16 +298,11 @@ export async function sendSandboxPromptCommand( ], }); - const prompt = - parsed.source === 'web' && typeof parsed.prompt === 'string' - ? buildModelVisibleWebPrompt(parsed.prompt) - : parsed.prompt; - - return await client.commands.sendPrompt.mutate({ + const result = await client.commands.sendPrompt.mutate({ prompt: - outOfBandContext && typeof prompt === 'string' - ? withOutOfBandContext(outOfBandContext, prompt) - : prompt, + outOfBandContext && typeof parsed.prompt === 'string' + ? withOutOfBandContext(outOfBandContext, parsed.prompt) + : parsed.prompt, quoteText: parsed.prompt, taskTool: parsed.taskTool, images: parsed.images, @@ -323,6 +316,21 @@ export async function sendSandboxPromptCommand( ? true : parsed.autoSteerWhenQueued, }); + + if ( + parsed.source === 'web' && + typeof parsed.prompt === 'string' && + resolveSourceControlProviderFromPayload(taskRun.payload) === 'github' + ) { + await trackLatestUserMessageForReplyQuote({ + provider: 'github', + runId: taskRun.id, + text: parsed.prompt, + userName: getAuthenticatedPromptUserName(auth) ?? 'Someone', + }); + } + + return result; } catch (error) { await releaseOutOfBandContext(outOfBandContext); diff --git a/apps/web/src/trpc/commands/sandbox-session/send-prompt.test.ts b/apps/web/src/trpc/commands/sandbox-session/send-prompt.test.ts index 27297fca4..c1607cd26 100644 --- a/apps/web/src/trpc/commands/sandbox-session/send-prompt.test.ts +++ b/apps/web/src/trpc/commands/sandbox-session/send-prompt.test.ts @@ -150,7 +150,7 @@ describe('sendSandboxPromptCommand', () => { expect(mockSendPromptMutate).toHaveBeenCalledWith( expect.objectContaining({ - prompt: '\nkeep going\n', + prompt: 'keep going', quoteText: 'keep going', source: 'web', userName: 'Auth Fallback Name', @@ -183,7 +183,7 @@ describe('sendSandboxPromptCommand', () => { expect(mockSendPromptMutate).toHaveBeenCalledWith( expect.objectContaining({ prompt: - '\nnotice\n\n\n\nPlease fix it.\n', + '\nnotice\n\n\nPlease fix it.', quoteText: 'Please fix it.', }), ); @@ -217,7 +217,7 @@ describe('sendSandboxPromptCommand', () => { expect(mockSendPromptMutate).toHaveBeenCalledWith( expect.objectContaining({ - prompt: '\nchange direction\n', + prompt: 'change direction', autoSteerWhenQueued: true, }), ); @@ -255,7 +255,7 @@ describe('sendSandboxPromptCommand', () => { expect(mockSendPromptMutate).toHaveBeenCalledWith( expect.objectContaining({ - prompt: '\nkeep going\n', + prompt: 'keep going', source: 'web', userName: 'casey', }), @@ -335,7 +335,7 @@ describe('sendSandboxPromptCommand', () => { expect(updatedRun?.actingUserId).toBe(user.id); expect(mockSendPromptMutate).toHaveBeenCalledWith( expect.objectContaining({ - prompt: '\nkeep going\n', + prompt: 'keep going', // Actor handoffs steer so the previous actor's turn does not keep // running after the credential identity changes. autoSteerWhenQueued: true, @@ -370,7 +370,7 @@ describe('sendSandboxPromptCommand', () => { expect(mockSendPromptMutate).toHaveBeenCalledWith( expect.objectContaining({ - prompt: '\nkeep going\n', + prompt: 'keep going', autoSteerWhenQueued: undefined, }), ); diff --git a/packages/cloud-agents/src/server/__tests__/github-message-instructions.test.ts b/packages/cloud-agents/src/server/__tests__/github-message-instructions.test.ts index 068b5159a..b1fb3fedd 100644 --- a/packages/cloud-agents/src/server/__tests__/github-message-instructions.test.ts +++ b/packages/cloud-agents/src/server/__tests__/github-message-instructions.test.ts @@ -23,13 +23,6 @@ describe('GitHub message instructions', () => { expect(instructions).toContain( 'For lightweight clarification, satisfy the `input_needed` milestone on GitHub.', ); - expect(instructions).toContain( - 'begin the next GitHub reply with a Markdown blockquote of that follow-up', - ); - expect(instructions).toContain(''); - expect(instructions).toContain('not injected out-of-band context'); - expect(instructions).toContain('keep it to 280 characters'); - expect(instructions).toContain('public-reply policy prohibits disclosing'); expect(instructions).toContain('plain GitHub issue'); }); }); diff --git a/packages/cloud-agents/src/server/github-message-instructions.ts b/packages/cloud-agents/src/server/github-message-instructions.ts index 4719bf598..0e2f1ba96 100644 --- a/packages/cloud-agents/src/server/github-message-instructions.ts +++ b/packages/cloud-agents/src/server/github-message-instructions.ts @@ -9,7 +9,6 @@ export function buildGitHubMessageInstructions(): string { For that non-actionable mention case, leave one brief GitHub reply on the same conversation surface if a reply is still useful, then conclude with a no-op result. Do not treat short verification asks such as "is this addressed?" or "did we fix everything from the last round?" as no-op; those are actionable follow-up. Keep GitHub replies brief, relevant to the request, and free of internal reasoning or raw logs. - When answering a , begin the next GitHub reply with a Markdown blockquote of that follow-up so other participants can see what the reply addresses. Use only the message inside that boundary, not injected out-of-band context; keep it to 280 characters. Omit or summarize any portion that the public-reply policy prohibits disclosing. If the active workflow already owns a dedicated GitHub comment lifecycle, let that workflow satisfy the relevant communication milestones instead of duplicating generic thread updates. For lightweight clarification, satisfy the \`input_needed\` milestone on GitHub. Use \`request_user_input\` only when the task needs structured or private input outside the public thread. diff --git a/packages/communication/src/__tests__/messages.test.ts b/packages/communication/src/__tests__/messages.test.ts index d7b0d930a..7479dbcbe 100644 --- a/packages/communication/src/__tests__/messages.test.ts +++ b/packages/communication/src/__tests__/messages.test.ts @@ -314,6 +314,24 @@ describe('communication message queues', () => { ); }); + it('supports GitHub reply quotes without adding GitHub as a chat provider', async () => { + await setLatestUserMessageForReplyQuote('github', 44, { + text: 'ship it', + userName: 'Ada', + }); + + expect(setMock).toHaveBeenCalledWith( + 'github:latest_user_message:44', + JSON.stringify({ + id: 'quote-id-fixed', + text: 'ship it', + userName: 'Ada', + }), + 'EX', + 30 * 24 * 60 * 60, + ); + }); + it('reads the latest user message', async () => { getMock.mockResolvedValueOnce( JSON.stringify({ diff --git a/packages/communication/src/messages.ts b/packages/communication/src/messages.ts index f7e746bfe..31ee41131 100644 --- a/packages/communication/src/messages.ts +++ b/packages/communication/src/messages.ts @@ -7,6 +7,8 @@ import { queuedCommunicationMessageSchema, } from '@roomote/types'; +type ReplyQuoteProvider = CommunicationProvider | 'github'; + const COMMUNICATION_MESSAGE_TTL_SECONDS = 60 * 60; const COMMUNICATION_MESSAGE_DEDUPE_TTL_SECONDS = 24 * 60 * 60; const LATEST_INBOUND_MESSAGE_ID_TTL_SECONDS = 60 * 60 * 24; @@ -20,7 +22,7 @@ export interface LatestUserMessageForReplyQuote { } type TrackLatestUserMessageForReplyQuoteParams = { - provider: CommunicationProvider; + provider: ReplyQuoteProvider; runId: number; text: string; userName: string; @@ -72,7 +74,7 @@ function getLatestInboundMessageIdKey( } function getLatestUserMessageForReplyQuoteKey( - provider: CommunicationProvider, + provider: ReplyQuoteProvider, runId: number, ): string { return `${provider}:latest_user_message:${runId}`; @@ -108,7 +110,7 @@ function parseLatestUserMessageForReplyQuote( } function getCommunicationMessageDedupeKey( - provider: CommunicationProvider, + provider: ReplyQuoteProvider, runId: number, messageId: string, ): string { @@ -350,7 +352,7 @@ export async function getLatestInboundMessageId( * quote it back into the originating chat thread (Discord parity with Slack). */ export async function setLatestUserMessageForReplyQuote( - provider: CommunicationProvider, + provider: ReplyQuoteProvider, runId: number, message: Omit & { id?: string }, ): Promise { @@ -399,7 +401,7 @@ export async function trackLatestUserMessageForReplyQuote({ } export async function getLatestUserMessageForReplyQuote( - provider: CommunicationProvider, + provider: ReplyQuoteProvider, runId: number, ): Promise { const redis = getRedis(); @@ -410,7 +412,7 @@ export async function getLatestUserMessageForReplyQuote( } export async function clearLatestUserMessageForReplyQuote( - provider: CommunicationProvider, + provider: ReplyQuoteProvider, runId: number, ): Promise { try { @@ -430,7 +432,7 @@ export async function clearLatestUserMessageForReplyQuote( * was quoted on this delivery. Prevents clearing a newer same-text follow-up. */ export async function clearLatestUserMessageForReplyQuoteIfId( - provider: CommunicationProvider, + provider: ReplyQuoteProvider, runId: number, id: string, ): Promise { From 6aaff4a0937aa4d7c9216c26295a46ba42dc1df8 Mon Sep 17 00:00:00 2001 From: Daniel Riccio <57051444+daniel-lxs@users.noreply.github.com> Date: Tue, 28 Jul 2026 21:06:35 +0000 Subject: [PATCH 4/4] fix: scope source control write cases --- apps/api/src/handlers/tasks/manageSourceControl.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/api/src/handlers/tasks/manageSourceControl.ts b/apps/api/src/handlers/tasks/manageSourceControl.ts index 58b7d6a37..099a79116 100644 --- a/apps/api/src/handlers/tasks/manageSourceControl.ts +++ b/apps/api/src/handlers/tasks/manageSourceControl.ts @@ -143,22 +143,24 @@ export async function manageSourceControl( case 'create_pull_request_comment': case 'resolve_pull_request_thread': case 'submit_pull_request_review': - case 'update_pull_request_comment': + case 'update_pull_request_comment': { const writeResult = await writeSourceControlPullRequestForTaskRun({ taskRun, input, }); await clearQuoteAfterSuccess(); return c.json(writeResult); + } case 'get_issue': case 'list_issue_comments': - case 'create_issue_comment': + case 'create_issue_comment': { const issueResult = await manageSourceControlIssueForTaskRun({ taskRun, input, }); await clearQuoteAfterSuccess(); return c.json(issueResult); + } } } catch (error) { if (error instanceof z.ZodError) {