@@ -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" ;
@@ -1364,6 +1366,35 @@ export class SessionService {
13641366 throw new Error ( "Authentication required for cloud commands" ) ;
13651367 }
13661368
1369+ const [ previousRun , task ] = await Promise . all ( [
1370+ client . getTaskRun ( session . taskId , session . taskRunId ) ,
1371+ client . getTask ( session . taskId ) ,
1372+ ] ) ;
1373+ const hasGitHubRepo = ! ! task . repository && ! ! task . github_integration ;
1374+ const previousState = previousRun . state as Record < string , unknown > ;
1375+ const previousOutput = ( previousRun . output ?? { } ) as Record <
1376+ string ,
1377+ unknown
1378+ > ;
1379+ // Prefer the actual working branch the agent last pushed to (synced by
1380+ // agent-server after each turn), then the run-level branch field, then
1381+ // the original base branch from state. This preserves unmerged work when
1382+ // the snapshot has expired and the sandbox is rebuilt from scratch.
1383+ const previousBaseBranch =
1384+ ( typeof previousOutput . head_branch === "string"
1385+ ? previousOutput . head_branch
1386+ : null ) ??
1387+ previousRun . branch ??
1388+ ( typeof previousState . pr_base_branch === "string"
1389+ ? previousState . pr_base_branch
1390+ : null ) ??
1391+ session . cloudBranch ;
1392+ const prAuthorshipMode = this . getCloudPrAuthorshipMode ( previousState ) ;
1393+ const githubUserToken =
1394+ prAuthorshipMode === "user" && hasGitHubRepo
1395+ ? await getGhUserTokenOrThrow ( )
1396+ : undefined ;
1397+
13671398 log . info ( "Creating resume run for terminal cloud task" , {
13681399 taskId : session . taskId ,
13691400 previousRunId : session . taskRunId ,
@@ -1375,11 +1406,21 @@ export class SessionService {
13751406 // The agent will load conversation history and restore the sandbox snapshot.
13761407 const updatedTask = await client . runTaskInCloud (
13771408 session . taskId ,
1378- session . cloudBranch ,
1409+ previousBaseBranch ,
13791410 {
13801411 resumeFromRunId : session . taskRunId ,
13811412 pendingUserMessage : promptText ,
13821413 } ,
1414+ undefined ,
1415+ {
1416+ prAuthorshipMode,
1417+ runSource : this . getCloudRunSource ( previousState ) ,
1418+ signalReportId :
1419+ typeof previousState . signal_report_id === "string"
1420+ ? previousState . signal_report_id
1421+ : undefined ,
1422+ githubUserToken,
1423+ } ,
13831424 ) ;
13841425 const newRun = updatedTask . latest_run ;
13851426 if ( ! newRun ?. id ) {
@@ -2102,6 +2143,20 @@ export class SessionService {
21022143 }
21032144 }
21042145
2146+ private getCloudPrAuthorshipMode (
2147+ state : Record < string , unknown > ,
2148+ ) : PrAuthorshipMode {
2149+ const explicitMode = state . pr_authorship_mode ;
2150+ if ( explicitMode === "user" || explicitMode === "bot" ) {
2151+ return explicitMode ;
2152+ }
2153+ return state . run_source === "signal_report" ? "bot" : "user" ;
2154+ }
2155+
2156+ private getCloudRunSource ( state : Record < string , unknown > ) : CloudRunSource {
2157+ return state . run_source === "signal_report" ? "signal_report" : "manual" ;
2158+ }
2159+
21052160 /**
21062161 * Filter out session/prompt events that should be skipped during resume.
21072162 * When resuming a cloud run, the initial session/prompt from the new run's
0 commit comments