Skip to content

Commit 9d652c5

Browse files
feat(cloud): Add plan mode support for cloud runs (#1645)
1 parent 9418447 commit 9d652c5

13 files changed

Lines changed: 493 additions & 31 deletions

File tree

apps/code/src/main/services/cloud-task/schemas.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,13 @@ export const sendCommandInput = z.object({
5050
runId: z.string(),
5151
apiHost: z.string(),
5252
teamId: z.number(),
53-
method: z.enum(["user_message", "cancel", "close"]),
53+
method: z.enum([
54+
"user_message",
55+
"cancel",
56+
"close",
57+
"permission_response",
58+
"set_config_option",
59+
]),
5460
params: z.record(z.string(), z.unknown()).optional(),
5561
});
5662

apps/code/src/main/services/cloud-task/service.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { CloudTaskPermissionRequestUpdate } from "@shared/types";
12
import type { StoredLogEntry } from "@shared/types/session-events";
23
import { net } from "electron";
34
import { inject, injectable, preDestroy } from "inversify";
@@ -122,6 +123,24 @@ function isSseErrorEvent(data: unknown): data is SseErrorEventData {
122123
);
123124
}
124125

126+
interface PermissionRequestEventData {
127+
type: "permission_request";
128+
requestId: string;
129+
toolCall: CloudTaskPermissionRequestUpdate["toolCall"];
130+
options: CloudTaskPermissionRequestUpdate["options"];
131+
}
132+
133+
function isPermissionRequestEvent(
134+
data: unknown,
135+
): data is PermissionRequestEventData {
136+
return (
137+
typeof data === "object" &&
138+
data !== null &&
139+
(data as { type?: string }).type === "permission_request" &&
140+
typeof (data as { requestId?: string }).requestId === "string"
141+
);
142+
}
143+
125144
function createStreamStatusError(status: number): CloudTaskStreamError {
126145
switch (status) {
127146
case 401:
@@ -682,6 +701,18 @@ export class CloudTaskService extends TypedEventEmitter<CloudTaskEvents> {
682701
return;
683702
}
684703

704+
if (isPermissionRequestEvent(event.data)) {
705+
this.emit(CloudTaskEvent.Update, {
706+
taskId: watcher.taskId,
707+
runId: watcher.runId,
708+
kind: "permission_request" as const,
709+
requestId: event.data.requestId,
710+
toolCall: event.data.toolCall,
711+
options: event.data.options,
712+
});
713+
return;
714+
}
715+
685716
watcher.pendingLogEntries.push(event.data as StoredLogEntry);
686717
if (watcher.pendingLogEntries.length >= EVENT_BATCH_MAX_SIZE) {
687718
this.flushLogBatch(key);

apps/code/src/renderer/api/posthogClient.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,7 @@ export class PostHogAPIClient {
746746
runSource?: CloudRunSource;
747747
signalReportId?: string;
748748
githubUserToken?: string;
749+
initialPermissionMode?: string;
749750
},
750751
): Promise<Task> {
751752
const teamId = await this.getTeamId();
@@ -774,6 +775,9 @@ export class PostHogAPIClient {
774775
if (options?.githubUserToken) {
775776
body.github_user_token = options.githubUserToken;
776777
}
778+
if (options?.initialPermissionMode) {
779+
body.initial_permission_mode = options.initialPermissionMode;
780+
}
777781

778782
const data = await this.api.post(
779783
`/api/projects/{project_id}/tasks/{id}/run/`,

apps/code/src/renderer/features/sessions/hooks/useSessionConnection.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ export function useSessionConnection({
7272
if (!cloudAuthState.projectId || !cloudAuthState.cloudRegion) return;
7373

7474
const runId = task.latest_run.id;
75+
const initialMode =
76+
typeof task.latest_run.state?.initial_permission_mode === "string"
77+
? task.latest_run.state.initial_permission_mode
78+
: undefined;
7579
const cleanup = getSessionService().watchCloudTask(
7680
task.id,
7781
runId,
@@ -81,6 +85,7 @@ export function useSessionConnection({
8185
queryClient.invalidateQueries({ queryKey: ["tasks"] });
8286
},
8387
task.latest_run?.log_url,
88+
initialMode,
8489
);
8590
return cleanup;
8691
}, [
@@ -93,6 +98,7 @@ export function useSessionConnection({
9398
task.id,
9499
task.latest_run?.id,
95100
task.latest_run?.log_url,
101+
task.latest_run?.state?.initial_permission_mode,
96102
]);
97103

98104
useEffect(() => {

0 commit comments

Comments
 (0)