Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 64 additions & 8 deletions apps/api/src/handlers/github/__tests__/handlePrComment.test.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 27 additions & 12 deletions apps/api/src/handlers/github/handlePrComment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
enqueueTask,
getTaskUrl,
routeGitHubTask,
SnapshotResumeAlreadyExistsError,
} from '@roomote/cloud-agents/server';
import {
findActiveGitHubPrReviewTask,
Expand Down Expand Up @@ -931,7 +932,7 @@ async function deliverFollowUpToExistingTask({
});
}

async function resumeExistingTaskAndDeliverFollowUp({
export async function resumeExistingTaskAndDeliverFollowUp({
taskId,
userId,
sourceRunId,
Expand Down Expand Up @@ -1048,18 +1049,32 @@ async function resumeExistingTaskAndDeliverFollowUp({

// Resumes never create tasks and never re-attribute; the resuming human
// becomes the new run's acting user.
const resumeLaunch = await enqueueTask(
{
task: {
type: TaskPayloadKind.SnapshotResume,
sourceSnapshotId: sourceRun.snapshotId,
sourceRunId: sourceRun.id,
payload: resumePayload,
let resumeLaunch: Awaited<ReturnType<typeof enqueueTask>>;
try {
resumeLaunch = await enqueueTask(
{
task: {
type: TaskPayloadKind.SnapshotResume,
sourceSnapshotId: sourceRun.snapshotId,
sourceRunId: sourceRun.id,
payload: resumePayload,
},
actingUserId: senderUserId,
},
actingUserId: senderUserId,
},
{},
);
{},
);
} catch (error) {
if (error instanceof SnapshotResumeAlreadyExistsError) {
// Continue through the normal fallback path so this distinct instruction
// gets its own linked follow-up task and response instead of being lost.
return {
success: false as const,
error: 'Reusable PR owner is already resuming',
status: 409,
};
}
throw error;
}

const accepted = await waitForResumeRunToAcceptDeferredPrompt({
taskId,
Expand Down
63 changes: 63 additions & 0 deletions apps/api/src/handlers/tasks/__tests__/sendMessageToTask.test.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

67 changes: 55 additions & 12 deletions apps/api/src/handlers/tasks/sendMessageToTask.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { TRPCClientError } from '@trpc/client';
import { enqueueTask } from '@roomote/cloud-agents/server';
import {
enqueueTask,
SnapshotResumeAlreadyExistsError,
} from '@roomote/cloud-agents/server';
import {
notifyFastAgentParentOnPrFeedback,
withSandboxServerRpcClient,
Expand Down Expand Up @@ -593,18 +596,30 @@ async function resumeTaskFromSnapshot({

// Resumes never create tasks and never re-attribute; the follow-up sender
// becomes the new run's acting user.
const resumeLaunch = await enqueueTask(
{
task: {
type: TaskPayloadKind.SnapshotResume,
sourceSnapshotId: sourceRun.snapshotId,
sourceRunId: sourceRun.id,
payload,
let resumeLaunch: Awaited<ReturnType<typeof enqueueTask>>;
try {
resumeLaunch = await enqueueTask(
{
task: {
type: TaskPayloadKind.SnapshotResume,
sourceSnapshotId: sourceRun.snapshotId,
sourceRunId: sourceRun.id,
payload,
},
actingUserId: userId,
},
actingUserId: userId,
},
{},
);
{},
);
} catch (error) {
if (error instanceof SnapshotResumeAlreadyExistsError) {
return {
success: false,
error: 'Task continuation is already in progress. Try again shortly.',
status: 409,
};
}
throw error;
}

await maybeCreateSlackReplyQuoteContext({
runId: resumeLaunch.id,
Expand Down Expand Up @@ -1266,6 +1281,34 @@ export async function steerMessageToTask({
});
}

const latestRun = await findLatestTaskRun(taskId, {
id: true,
status: true,
sandboxServerUrl: true,
actingUserId: true,
snapshotId: true,
snapshotCreatedAt: true,
sourceRunId: true,
payload: true,
port: true,
result: true,
});
if (latestRun?.id === run.id && isExitedRunStatus(latestRun.status)) {
Comment thread
roomote-roomote[bot] marked this conversation as resolved.
const resumeResult = await resumeTaskFromSnapshot({
taskId,
userId,
message,
quoteText,
images,
sourceRun: latestRun as LatestTaskRun,
channelBindings,
senderMode,
});
if (resumeResult) {
return resumeResult;
}
}

if (error instanceof SandboxNotReadyError) {
return {
success: false,
Expand Down
Loading
Loading