Skip to content

Commit 241b55a

Browse files
committed
Implement fetch and pull logic on task creation
1 parent c170f21 commit 241b55a

File tree

5 files changed

+61
-2
lines changed

5 files changed

+61
-2
lines changed

apps/array/src/main/services/workspace/schemas.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export const createWorkspaceInput = z.object({
5858
folderPath: z.string().min(2, "Folder path must be a valid directory path"),
5959
mode: workspaceModeSchema,
6060
branch: z.string().optional(),
61+
fetchLatest: z.boolean().optional(),
6162
});
6263

6364
export const deleteWorkspaceInput = z.object({

apps/array/src/main/services/workspace/service.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,15 @@ export class WorkspaceService extends TypedEventEmitter<WorkspaceServiceEvents>
9999
}
100100

101101
async createWorkspace(options: CreateWorkspaceInput): Promise<WorkspaceInfo> {
102-
const { taskId, mainRepoPath, folderId, folderPath, mode, branch } =
103-
options;
102+
const {
103+
taskId,
104+
mainRepoPath,
105+
folderId,
106+
folderPath,
107+
mode,
108+
branch,
109+
fetchLatest,
110+
} = options;
104111
log.info(
105112
`Creating workspace for task ${taskId} in ${mainRepoPath} (mode: ${mode})`,
106113
);
@@ -276,6 +283,30 @@ export class WorkspaceService extends TypedEventEmitter<WorkspaceServiceEvents>
276283
);
277284
}
278285
}
286+
287+
// Fetch latest from origin if requested - pull from the base branch the user selected
288+
if (fetchLatest) {
289+
const baseBranch = branch ?? worktree.baseBranch;
290+
if (baseBranch) {
291+
try {
292+
log.info(
293+
`Fetching latest from origin/${baseBranch} for task ${taskId}`,
294+
);
295+
await execAsync("git fetch origin", { cwd: worktree.worktreePath });
296+
await execAsync(`git pull origin ${baseBranch}`, {
297+
cwd: worktree.worktreePath,
298+
});
299+
log.info(`Successfully fetched latest for task ${taskId}`);
300+
} catch (error) {
301+
log.warn(`Failed to fetch latest for task ${taskId}:`, error);
302+
// Don't fail workspace creation, just warn
303+
}
304+
} else {
305+
log.info(
306+
`Skipping fetch latest for task ${taskId}: no base branch specified`,
307+
);
308+
}
309+
}
279310
} catch (error) {
280311
log.error(`Failed to create worktree for task ${taskId}:`, error);
281312
throw new Error(`Failed to create worktree: ${String(error)}`);

apps/array/src/renderer/features/settings/components/SettingsView.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,12 @@ export function SettingsView() {
5757
defaultRunMode,
5858
createPR,
5959
desktopNotifications,
60+
fetchLatestOnNewTask,
6061
setAutoRunTasks,
6162
setDefaultRunMode,
6263
setCreatePR,
6364
setDesktopNotifications,
65+
setFetchLatestOnNewTask,
6466
} = useSettingsStore();
6567
const terminalLayoutMode = useTerminalLayoutStore(
6668
(state) => state.terminalLayoutMode,
@@ -337,6 +339,23 @@ export function SettingsView() {
337339
size="1"
338340
/>
339341
</Flex>
342+
343+
<Flex align="center" justify="between">
344+
<Flex direction="column" gap="1">
345+
<Text size="1" weight="medium">
346+
Fetch latest on new task
347+
</Text>
348+
<Text size="1" color="gray">
349+
Pull the latest changes from origin after creating a
350+
workspace
351+
</Text>
352+
</Flex>
353+
<Switch
354+
checked={fetchLatestOnNewTask}
355+
onCheckedChange={setFetchLatestOnNewTask}
356+
size="1"
357+
/>
358+
</Flex>
340359
</Flex>
341360
</Card>
342361
</Flex>

apps/array/src/renderer/features/settings/stores/settingsStore.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ interface SettingsStore {
2020
defaultModel: string;
2121
defaultFramework: AgentFramework;
2222
desktopNotifications: boolean;
23+
fetchLatestOnNewTask: boolean;
2324

2425
setAutoRunTasks: (autoRun: boolean) => void;
2526
setDefaultRunMode: (mode: DefaultRunMode) => void;
@@ -30,6 +31,7 @@ interface SettingsStore {
3031
setDefaultModel: (model: string) => void;
3132
setDefaultFramework: (framework: AgentFramework) => void;
3233
setDesktopNotifications: (enabled: boolean) => void;
34+
setFetchLatestOnNewTask: (enabled: boolean) => void;
3335
}
3436

3537
export const useSettingsStore = create<SettingsStore>()(
@@ -44,6 +46,7 @@ export const useSettingsStore = create<SettingsStore>()(
4446
defaultModel: DEFAULT_MODEL,
4547
defaultFramework: DEFAULT_FRAMEWORK,
4648
desktopNotifications: true,
49+
fetchLatestOnNewTask: true,
4750

4851
setAutoRunTasks: (autoRun) => set({ autoRunTasks: autoRun }),
4952
setDefaultRunMode: (mode) => set({ defaultRunMode: mode }),
@@ -56,6 +59,8 @@ export const useSettingsStore = create<SettingsStore>()(
5659
setDefaultFramework: (framework) => set({ defaultFramework: framework }),
5760
setDesktopNotifications: (enabled) =>
5861
set({ desktopNotifications: enabled }),
62+
setFetchLatestOnNewTask: (enabled) =>
63+
set({ fetchLatestOnNewTask: enabled }),
5964
}),
6065
{
6166
name: "settings-storage",

apps/array/src/renderer/sagas/task/task-creation.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { PostHogAPIClient } from "@api/posthogClient";
22
import { buildPromptBlocks } from "@features/editor/utils/prompt-builder";
33
import { getSessionActions } from "@features/sessions/stores/sessionStore";
4+
import { useSettingsStore } from "@features/settings/stores/settingsStore";
45
import { useWorkspaceStore } from "@features/workspace/stores/workspaceStore";
56
import { logger } from "@renderer/lib/logger";
67
import { useTaskDirectoryStore } from "@renderer/stores/taskDirectoryStore";
@@ -108,6 +109,7 @@ export class TaskCreationSaga extends Saga<
108109
});
109110
}
110111

112+
const fetchLatest = useSettingsStore.getState().fetchLatestOnNewTask;
111113
const workspaceInfo = await this.step({
112114
name: "workspace_creation",
113115
execute: async () => {
@@ -118,6 +120,7 @@ export class TaskCreationSaga extends Saga<
118120
folderPath: repoPath,
119121
mode: workspaceMode,
120122
branch: branch ?? undefined,
123+
fetchLatest,
121124
});
122125
},
123126
rollback: async () => {

0 commit comments

Comments
 (0)