(id: string)
| 355 | |
| 356 | type ProjectWithStoredGitCapability = { |
| 357 | repoPath: string; |
| 358 | isGitRepo: boolean | null; |
| 359 | worktreeReady: boolean | null; |
| 360 | gitCapabilityReason: string | null; |
| 361 | }; |
| 362 | |
| 363 | function withProjectGitMetadata<T extends { project: ProjectWithStoredGitCapability }>( |
| 364 | task: T |
| 365 | ): Omit<T, 'project'> & { project: T['project'] & ReturnType<typeof getStoredProjectGitCapability> } { |
| 366 | const capability = getStoredProjectGitCapability(task.project); |
| 367 | return withProjectGitCapability(task, capability); |
| 368 | } |
| 369 | |
| 370 | function withProjectGitCapability<T extends { project: ProjectWithStoredGitCapability }>( |
| 371 | task: T, |
| 372 | capability: ReturnType<typeof getStoredProjectGitCapability> |
| 373 | ): Omit<T, 'project'> & { project: T['project'] & ReturnType<typeof getStoredProjectGitCapability> } { |
| 374 | return { |
| 375 | ...task, |
| 376 | project: { |
| 377 | ...task.project, |
| 378 | ...capability, |
| 379 | }, |
| 380 | }; |
| 381 | } |
| 382 | |
| 383 | function buildProjectGitMetadata(project: ProjectWithStoredGitCapability) { |
| 384 | return getStoredProjectGitCapability(project); |
| 385 | } |
| 386 | |
| 387 | function buildTaskPrompt(task: { title: string; description?: string | null }): string { |
| 388 | const title = task.title.trim(); |
| 389 | const description = task.description; |
| 390 | return description?.trim() |
| 391 | ? [title, description].filter(Boolean).join('\n\n') |
| 392 | : title; |
| 393 | } |
| 394 | |
| 395 | export class TaskService { |
| 396 | constructor( |
| 397 | private readonly eventBus: EventBus, |
| 398 | private readonly sessionManager: SessionManager, |
| 399 | private readonly cleanupService: Pick<TaskCleanupService, 'trigger'> | undefined = undefined, |
no test coverage detected