Skip to content
Closed
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
21 changes: 13 additions & 8 deletions src/core/checkpoints/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ import { CheckpointServiceOptions, RepoPerTaskCheckpointService } from "../../se

export async function getCheckpointService(
task: Task,
{ interval = 250, timeout = 15_000 }: { interval?: number; timeout?: number } = {},
{
interval = 250,
timeout = 15_000,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 15-second timeout is still hardcoded for subsequent calls. Would it be beneficial to make this configurable through settings? Users with varying repository sizes might need different timeout values.

isInitialCall = false,
}: { interval?: number; timeout?: number; isInitialCall?: boolean } = {},
) {
if (!task.enableCheckpoints) {
return undefined
Expand Down Expand Up @@ -67,13 +71,14 @@ export async function getCheckpointService(
}

if (task.checkpointServiceInitializing) {
await pWaitFor(
() => {
console.log("[Task#getCheckpointService] waiting for service to initialize")
return !!task.checkpointService && !!task?.checkpointService?.isInitialized
},
{ interval, timeout },
)
// If this is the initial call from initiateTaskLoop, don't apply a timeout
// to allow large repositories to complete initialization
const waitOptions = isInitialCall ? { interval } : { interval, timeout }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this approach thread-safe? While the isInitialCall flag correctly removes the timeout for initial initialization, there might be a race condition if multiple operations try to get the checkpoint service simultaneously. Consider adding a mutex or lock mechanism to prevent concurrent initialization attempts.


await pWaitFor(() => {
console.log("[Task#getCheckpointService] waiting for service to initialize")
return !!task.checkpointService && !!task?.checkpointService?.isInitialized
}, waitOptions)
if (!task?.checkpointService) {
task.enableCheckpoints = false
return undefined
Expand Down
3 changes: 2 additions & 1 deletion src/core/task/Task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1661,7 +1661,8 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {

private async initiateTaskLoop(userContent: Anthropic.Messages.ContentBlockParam[]): Promise<void> {
// Kicks off the checkpoints initialization process in the background.
getCheckpointService(this)
// Pass isInitialCall=true to avoid timeout for large repositories
getCheckpointService(this, { isInitialCall: true })
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we expand this comment to be more descriptive? Consider adding more context about why isInitialCall=true is important and what problem it solves (e.g., preventing checkpoints from being disabled in large repos due to timeout during git add operations).


let nextUserContent = userContent
let includeFileDetails = true
Expand Down
4 changes: 3 additions & 1 deletion src/services/checkpoints/ShadowCheckpointService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,9 @@ export abstract class ShadowCheckpointService extends EventEmitter {

private async stageAll(git: SimpleGit) {
try {
await git.add(".")
// Use --ignore-errors to continue even if some files can't be added (e.g., permission issues)
// This prevents the operation from failing in large repositories with problematic files
await git.add([".", "--ignore-errors"])
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good addition of the --ignore-errors flag! However, when errors are caught, we're not logging which specific files failed to be added. Could we enhance the error logging to help users identify and fix permission issues?

} catch (error) {
this.log(
`[${this.constructor.name}#stageAll] failed to add files to git: ${error instanceof Error ? error.message : String(error)}`,
Expand Down
Loading