@@ -29,6 +29,7 @@ import { taskViewedApi } from "@features/sidebar/hooks/useTaskViewed";
2929import { DEFAULT_GATEWAY_MODEL } from "@posthog/agent/gateway-models" ;
3030import { getIsOnline } from "@renderer/stores/connectivityStore" ;
3131import { trpcClient } from "@renderer/trpc/client" ;
32+ import { getGhUserTokenOrThrow } from "@renderer/utils/github" ;
3233import { toast } from "@renderer/utils/toast" ;
3334import { getCloudUrlFromRegion } from "@shared/constants/oauth" ;
3435import {
@@ -39,6 +40,7 @@ import {
3940 type Task ,
4041} from "@shared/types" ;
4142import { ANALYTICS_EVENTS } from "@shared/types/analytics" ;
43+ import type { CloudRunSource , PrAuthorshipMode } from "@shared/types/cloud" ;
4244import type { AcpMessage , StoredLogEntry } from "@shared/types/session-events" ;
4345import { isJsonRpcRequest } from "@shared/types/session-events" ;
4446import { buildPermissionToolMetadata , track } from "@utils/analytics" ;
@@ -1388,6 +1390,35 @@ export class SessionService {
13881390 throw new Error ( "Authentication required for cloud commands" ) ;
13891391 }
13901392
1393+ const [ previousRun , task ] = await Promise . all ( [
1394+ client . getTaskRun ( session . taskId , session . taskRunId ) ,
1395+ client . getTask ( session . taskId ) ,
1396+ ] ) ;
1397+ const hasGitHubRepo = ! ! task . repository && ! ! task . github_integration ;
1398+ const previousState = previousRun . state as Record < string , unknown > ;
1399+ const previousOutput = ( previousRun . output ?? { } ) as Record <
1400+ string ,
1401+ unknown
1402+ > ;
1403+ // Prefer the actual working branch the agent last pushed to (synced by
1404+ // agent-server after each turn), then the run-level branch field, then
1405+ // the original base branch from state. This preserves unmerged work when
1406+ // the snapshot has expired and the sandbox is rebuilt from scratch.
1407+ const previousBaseBranch =
1408+ ( typeof previousOutput . head_branch === "string"
1409+ ? previousOutput . head_branch
1410+ : null ) ??
1411+ previousRun . branch ??
1412+ ( typeof previousState . pr_base_branch === "string"
1413+ ? previousState . pr_base_branch
1414+ : null ) ??
1415+ session . cloudBranch ;
1416+ const prAuthorshipMode = this . getCloudPrAuthorshipMode ( previousState ) ;
1417+ const githubUserToken =
1418+ prAuthorshipMode === "user" && hasGitHubRepo
1419+ ? await getGhUserTokenOrThrow ( )
1420+ : undefined ;
1421+
13911422 log . info ( "Creating resume run for terminal cloud task" , {
13921423 taskId : session . taskId ,
13931424 previousRunId : session . taskRunId ,
@@ -1399,11 +1430,21 @@ export class SessionService {
13991430 // The agent will load conversation history and restore the sandbox snapshot.
14001431 const updatedTask = await client . runTaskInCloud (
14011432 session . taskId ,
1402- session . cloudBranch ,
1433+ previousBaseBranch ,
14031434 {
14041435 resumeFromRunId : session . taskRunId ,
14051436 pendingUserMessage : promptText ,
14061437 } ,
1438+ undefined ,
1439+ {
1440+ prAuthorshipMode,
1441+ runSource : this . getCloudRunSource ( previousState ) ,
1442+ signalReportId :
1443+ typeof previousState . signal_report_id === "string"
1444+ ? previousState . signal_report_id
1445+ : undefined ,
1446+ githubUserToken,
1447+ } ,
14071448 ) ;
14081449 const newRun = updatedTask . latest_run ;
14091450 if ( ! newRun ?. id ) {
@@ -2126,6 +2167,20 @@ export class SessionService {
21262167 }
21272168 }
21282169
2170+ private getCloudPrAuthorshipMode (
2171+ state : Record < string , unknown > ,
2172+ ) : PrAuthorshipMode {
2173+ const explicitMode = state . pr_authorship_mode ;
2174+ if ( explicitMode === "user" || explicitMode === "bot" ) {
2175+ return explicitMode ;
2176+ }
2177+ return state . run_source === "signal_report" ? "bot" : "user" ;
2178+ }
2179+
2180+ private getCloudRunSource ( state : Record < string , unknown > ) : CloudRunSource {
2181+ return state . run_source === "signal_report" ? "signal_report" : "manual" ;
2182+ }
2183+
21292184 /**
21302185 * Filter out session/prompt events that should be skipped during resume.
21312186 * When resuming a cloud run, the initial session/prompt from the new run's
0 commit comments